1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! This module contains the "cleaned" pieces of the AST, and the functions
14 pub use self::Type
::*;
15 pub use self::Mutability
::*;
16 pub use self::ItemEnum
::*;
17 pub use self::TyParamBound
::*;
18 pub use self::SelfTy
::*;
19 pub use self::FunctionRetTy
::*;
20 pub use self::Visibility
::*;
23 use syntax
::ast
::{self, AttrStyle}
;
25 use syntax
::codemap
::Spanned
;
26 use syntax
::feature_gate
::UnstableFeatures
;
28 use syntax
::symbol
::keywords
;
29 use syntax_pos
::{self, DUMMY_SP, Pos, FileName}
;
31 use rustc
::middle
::const_val
::ConstVal
;
32 use rustc
::middle
::privacy
::AccessLevels
;
33 use rustc
::middle
::resolve_lifetime
as rl
;
34 use rustc
::middle
::lang_items
;
35 use rustc
::hir
::def
::{Def, CtorKind}
;
36 use rustc
::hir
::def_id
::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}
;
37 use rustc
::ty
::subst
::Substs
;
38 use rustc
::ty
::{self, Ty, AdtKind}
;
39 use rustc
::middle
::stability
;
40 use rustc
::util
::nodemap
::{FxHashMap, FxHashSet}
;
41 use rustc_typeck
::hir_ty_to_ty
;
45 use rustc_const_math
::ConstInt
;
46 use std
::default::Default
;
47 use std
::{mem, slice, vec}
;
48 use std
::iter
::FromIterator
;
56 use html
::item_type
::ItemType
;
57 use html
::markdown
::markdown_links
;
65 // extract the stability index for a node from tcx, if possible
66 fn get_stability(cx
: &DocContext
, def_id
: DefId
) -> Option
<Stability
> {
67 cx
.tcx
.lookup_stability(def_id
).clean(cx
)
70 fn get_deprecation(cx
: &DocContext
, def_id
: DefId
) -> Option
<Deprecation
> {
71 cx
.tcx
.lookup_deprecation(def_id
).clean(cx
)
75 fn clean(&self, cx
: &DocContext
) -> T
;
78 impl<T
: Clean
<U
>, U
> Clean
<Vec
<U
>> for [T
] {
79 fn clean(&self, cx
: &DocContext
) -> Vec
<U
> {
80 self.iter().map(|x
| x
.clean(cx
)).collect()
84 impl<T
: Clean
<U
>, U
> Clean
<U
> for P
<T
> {
85 fn clean(&self, cx
: &DocContext
) -> U
{
90 impl<T
: Clean
<U
>, U
> Clean
<U
> for Rc
<T
> {
91 fn clean(&self, cx
: &DocContext
) -> U
{
96 impl<T
: Clean
<U
>, U
> Clean
<Option
<U
>> for Option
<T
> {
97 fn clean(&self, cx
: &DocContext
) -> Option
<U
> {
98 self.as_ref().map(|v
| v
.clean(cx
))
102 impl<T
, U
> Clean
<U
> for ty
::Binder
<T
> where T
: Clean
<U
> {
103 fn clean(&self, cx
: &DocContext
) -> U
{
108 impl<T
: Clean
<U
>, U
> Clean
<Vec
<U
>> for P
<[T
]> {
109 fn clean(&self, cx
: &DocContext
) -> Vec
<U
> {
110 self.iter().map(|x
| x
.clean(cx
)).collect()
114 #[derive(Clone, Debug)]
117 pub version
: Option
<String
>,
119 pub module
: Option
<Item
>,
120 pub externs
: Vec
<(CrateNum
, ExternalCrate
)>,
121 pub primitives
: Vec
<(DefId
, PrimitiveType
, Attributes
)>,
122 pub access_levels
: Arc
<AccessLevels
<DefId
>>,
123 // These are later on moved into `CACHEKEY`, leaving the map empty.
124 // Only here so that they can be filtered through the rustdoc passes.
125 pub external_traits
: FxHashMap
<DefId
, Trait
>,
126 pub masked_crates
: FxHashSet
<CrateNum
>,
129 impl<'a
, 'tcx
, 'rcx
> Clean
<Crate
> for visit_ast
::RustdocVisitor
<'a
, 'tcx
, 'rcx
> {
130 fn clean(&self, cx
: &DocContext
) -> Crate
{
131 use ::visit_lib
::LibEmbargoVisitor
;
134 let mut r
= cx
.renderinfo
.borrow_mut();
135 r
.deref_trait_did
= cx
.tcx
.lang_items().deref_trait();
136 r
.deref_mut_trait_did
= cx
.tcx
.lang_items().deref_mut_trait();
137 r
.owned_box_did
= cx
.tcx
.lang_items().owned_box();
140 let mut externs
= Vec
::new();
141 for &cnum
in cx
.tcx
.crates().iter() {
142 externs
.push((cnum
, cnum
.clean(cx
)));
143 // Analyze doc-reachability for extern items
144 LibEmbargoVisitor
::new(cx
).visit_lib(cnum
);
146 externs
.sort_by(|&(a
, _
), &(b
, _
)| a
.cmp(&b
));
148 // Clean the crate, translating the entire libsyntax AST to one that is
149 // understood by rustdoc.
150 let mut module
= self.module
.clean(cx
);
151 let mut masked_crates
= FxHashSet();
154 ModuleItem(ref module
) => {
155 for it
in &module
.items
{
156 if it
.is_extern_crate() && it
.attrs
.has_doc_flag("masked") {
157 masked_crates
.insert(it
.def_id
.krate
);
164 let ExternalCrate { name, src, primitives, .. }
= LOCAL_CRATE
.clean(cx
);
166 let m
= match module
.inner
{
167 ModuleItem(ref mut m
) => m
,
170 m
.items
.extend(primitives
.iter().map(|&(def_id
, prim
, ref attrs
)| {
172 source
: Span
::empty(),
173 name
: Some(prim
.to_url_str().to_string()),
174 attrs
: attrs
.clone(),
175 visibility
: Some(Public
),
176 stability
: get_stability(cx
, def_id
),
177 deprecation
: get_deprecation(cx
, def_id
),
179 inner
: PrimitiveItem(prim
),
184 let mut access_levels
= cx
.access_levels
.borrow_mut();
185 let mut external_traits
= cx
.external_traits
.borrow_mut();
191 module
: Some(module
),
194 access_levels
: Arc
::new(mem
::replace(&mut access_levels
, Default
::default())),
195 external_traits
: mem
::replace(&mut external_traits
, Default
::default()),
201 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
202 pub struct ExternalCrate
{
205 pub attrs
: Attributes
,
206 pub primitives
: Vec
<(DefId
, PrimitiveType
, Attributes
)>,
209 impl Clean
<ExternalCrate
> for CrateNum
{
210 fn clean(&self, cx
: &DocContext
) -> ExternalCrate
{
211 let root
= DefId { krate: *self, index: CRATE_DEF_INDEX }
;
212 let krate_span
= cx
.tcx
.def_span(root
);
213 let krate_src
= cx
.sess().codemap().span_to_filename(krate_span
);
215 // Collect all inner modules which are tagged as implementations of
218 // Note that this loop only searches the top-level items of the crate,
219 // and this is intentional. If we were to search the entire crate for an
220 // item tagged with `#[doc(primitive)]` then we would also have to
221 // search the entirety of external modules for items tagged
222 // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
223 // all that metadata unconditionally).
225 // In order to keep the metadata load under control, the
226 // `#[doc(primitive)]` feature is explicitly designed to only allow the
227 // primitive tags to show up as the top level items in a crate.
229 // Also note that this does not attempt to deal with modules tagged
230 // duplicately for the same primitive. This is handled later on when
231 // rendering by delegating everything to a hash map.
232 let as_primitive
= |def
: Def
| {
233 if let Def
::Mod(def_id
) = def
{
234 let attrs
= cx
.tcx
.get_attrs(def_id
).clean(cx
);
236 for attr
in attrs
.lists("doc") {
237 if let Some(v
) = attr
.value_str() {
238 if attr
.check_name("primitive") {
239 prim
= PrimitiveType
::from_str(&v
.as_str());
243 // FIXME: should warn on unknown primitives?
247 return prim
.map(|p
| (def_id
, p
, attrs
));
251 let primitives
= if root
.is_local() {
252 cx
.tcx
.hir
.krate().module
.item_ids
.iter().filter_map(|&id
| {
253 let item
= cx
.tcx
.hir
.expect_item(id
.id
);
256 as_primitive(Def
::Mod(cx
.tcx
.hir
.local_def_id(id
.id
)))
258 hir
::ItemUse(ref path
, hir
::UseKind
::Single
)
259 if item
.vis
== hir
::Visibility
::Public
=> {
260 as_primitive(path
.def
).map(|(_
, prim
, attrs
)| {
261 // Pretend the primitive is local.
262 (cx
.tcx
.hir
.local_def_id(id
.id
), prim
, attrs
)
269 cx
.tcx
.item_children(root
).iter().map(|item
| item
.def
)
270 .filter_map(as_primitive
).collect()
274 name
: cx
.tcx
.crate_name(*self).to_string(),
276 attrs
: cx
.tcx
.get_attrs(root
).clean(cx
),
282 /// Anything with a source location and set of attributes and, optionally, a
283 /// name. That is, anything that can be documented. This doesn't correspond
284 /// directly to the AST's concept of an item; it's a strict superset.
285 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
289 /// Not everything has a name. E.g., impls
290 pub name
: Option
<String
>,
291 pub attrs
: Attributes
,
293 pub visibility
: Option
<Visibility
>,
295 pub stability
: Option
<Stability
>,
296 pub deprecation
: Option
<Deprecation
>,
300 /// Finds the `doc` attribute as a NameValue and returns the corresponding
302 pub fn doc_value
<'a
>(&'a
self) -> Option
<&'a
str> {
303 self.attrs
.doc_value()
305 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
307 pub fn collapsed_doc_value(&self) -> Option
<String
> {
308 self.attrs
.collapsed_doc_value()
311 pub fn links(&self) -> Vec
<(String
, String
)> {
315 pub fn is_crate(&self) -> bool
{
317 StrippedItem(box ModuleItem(Module { is_crate: true, ..}
)) |
318 ModuleItem(Module { is_crate: true, ..}
) => true,
322 pub fn is_mod(&self) -> bool
{
323 self.type_() == ItemType
::Module
325 pub fn is_trait(&self) -> bool
{
326 self.type_() == ItemType
::Trait
328 pub fn is_struct(&self) -> bool
{
329 self.type_() == ItemType
::Struct
331 pub fn is_enum(&self) -> bool
{
332 self.type_() == ItemType
::Enum
334 pub fn is_fn(&self) -> bool
{
335 self.type_() == ItemType
::Function
337 pub fn is_associated_type(&self) -> bool
{
338 self.type_() == ItemType
::AssociatedType
340 pub fn is_associated_const(&self) -> bool
{
341 self.type_() == ItemType
::AssociatedConst
343 pub fn is_method(&self) -> bool
{
344 self.type_() == ItemType
::Method
346 pub fn is_ty_method(&self) -> bool
{
347 self.type_() == ItemType
::TyMethod
349 pub fn is_typedef(&self) -> bool
{
350 self.type_() == ItemType
::Typedef
352 pub fn is_primitive(&self) -> bool
{
353 self.type_() == ItemType
::Primitive
355 pub fn is_union(&self) -> bool
{
356 self.type_() == ItemType
::Union
358 pub fn is_import(&self) -> bool
{
359 self.type_() == ItemType
::Import
361 pub fn is_extern_crate(&self) -> bool
{
362 self.type_() == ItemType
::ExternCrate
365 pub fn is_stripped(&self) -> bool
{
366 match self.inner { StrippedItem(..) => true, _ => false }
368 pub fn has_stripped_fields(&self) -> Option
<bool
> {
370 StructItem(ref _struct
) => Some(_struct
.fields_stripped
),
371 UnionItem(ref union) => Some(union.fields_stripped
),
372 VariantItem(Variant { kind: VariantKind::Struct(ref vstruct)}
) => {
373 Some(vstruct
.fields_stripped
)
379 pub fn stability_class(&self) -> Option
<String
> {
380 self.stability
.as_ref().and_then(|ref s
| {
381 let mut classes
= Vec
::with_capacity(2);
383 if s
.level
== stability
::Unstable
{
384 classes
.push("unstable");
387 if !s
.deprecated_since
.is_empty() {
388 classes
.push("deprecated");
391 if classes
.len() != 0 {
392 Some(classes
.join(" "))
399 pub fn stable_since(&self) -> Option
<&str> {
400 self.stability
.as_ref().map(|s
| &s
.since
[..])
403 /// Returns a documentation-level item type from the item.
404 pub fn type_(&self) -> ItemType
{
409 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
411 ExternCrateItem(String
, Option
<String
>),
416 FunctionItem(Function
),
418 TypedefItem(Typedef
, bool
/* is associated type */),
420 ConstantItem(Constant
),
423 /// A method signature only. Used for required methods in traits (ie,
424 /// non-default-methods).
425 TyMethodItem(TyMethod
),
426 /// A method with a body.
428 StructFieldItem(Type
),
429 VariantItem(Variant
),
430 /// `fn`s from an extern block
431 ForeignFunctionItem(Function
),
432 /// `static`s from an extern block
433 ForeignStaticItem(Static
),
434 /// `type`s from an extern block
437 PrimitiveItem(PrimitiveType
),
438 AssociatedConstItem(Type
, Option
<String
>),
439 AssociatedTypeItem(Vec
<TyParamBound
>, Option
<Type
>),
440 /// An item that has been stripped by a rustdoc pass
441 StrippedItem(Box
<ItemEnum
>),
445 pub fn generics(&self) -> Option
<&Generics
> {
447 ItemEnum
::StructItem(ref s
) => &s
.generics
,
448 ItemEnum
::EnumItem(ref e
) => &e
.generics
,
449 ItemEnum
::FunctionItem(ref f
) => &f
.generics
,
450 ItemEnum
::TypedefItem(ref t
, _
) => &t
.generics
,
451 ItemEnum
::TraitItem(ref t
) => &t
.generics
,
452 ItemEnum
::ImplItem(ref i
) => &i
.generics
,
453 ItemEnum
::TyMethodItem(ref i
) => &i
.generics
,
454 ItemEnum
::MethodItem(ref i
) => &i
.generics
,
455 ItemEnum
::ForeignFunctionItem(ref f
) => &f
.generics
,
461 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
463 pub items
: Vec
<Item
>,
467 impl Clean
<Item
> for doctree
::Module
{
468 fn clean(&self, cx
: &DocContext
) -> Item
{
469 let name
= if self.name
.is_some() {
470 self.name
.unwrap().clean(cx
)
475 // maintain a stack of mod ids, for doc comment path resolution
476 // but we also need to resolve the module's own docs based on whether its docs were written
477 // inside or outside the module, so check for that
478 let attrs
= if self.attrs
.iter()
479 .filter(|a
| a
.check_name("doc"))
481 .map_or(true, |a
| a
.style
== AttrStyle
::Inner
) {
482 // inner doc comment, use the module's own scope for resolution
483 cx
.mod_ids
.borrow_mut().push(self.id
);
486 // outer doc comment, use its parent's scope
487 let attrs
= self.attrs
.clean(cx
);
488 cx
.mod_ids
.borrow_mut().push(self.id
);
492 let mut items
: Vec
<Item
> = vec
![];
493 items
.extend(self.extern_crates
.iter().map(|x
| x
.clean(cx
)));
494 items
.extend(self.imports
.iter().flat_map(|x
| x
.clean(cx
)));
495 items
.extend(self.structs
.iter().map(|x
| x
.clean(cx
)));
496 items
.extend(self.unions
.iter().map(|x
| x
.clean(cx
)));
497 items
.extend(self.enums
.iter().map(|x
| x
.clean(cx
)));
498 items
.extend(self.fns
.iter().map(|x
| x
.clean(cx
)));
499 items
.extend(self.foreigns
.iter().flat_map(|x
| x
.clean(cx
)));
500 items
.extend(self.mods
.iter().map(|x
| x
.clean(cx
)));
501 items
.extend(self.typedefs
.iter().map(|x
| x
.clean(cx
)));
502 items
.extend(self.statics
.iter().map(|x
| x
.clean(cx
)));
503 items
.extend(self.constants
.iter().map(|x
| x
.clean(cx
)));
504 items
.extend(self.traits
.iter().map(|x
| x
.clean(cx
)));
505 items
.extend(self.impls
.iter().flat_map(|x
| x
.clean(cx
)));
506 items
.extend(self.macros
.iter().map(|x
| x
.clean(cx
)));
508 cx
.mod_ids
.borrow_mut().pop();
510 // determine if we should display the inner contents or
511 // the outer `mod` item for the source code.
513 let cm
= cx
.sess().codemap();
514 let outer
= cm
.lookup_char_pos(self.where_outer
.lo());
515 let inner
= cm
.lookup_char_pos(self.where_inner
.lo());
516 if outer
.file
.start_pos
== inner
.file
.start_pos
{
520 // mod foo; (and a separate FileMap for the contents)
528 source
: whence
.clean(cx
),
529 visibility
: self.vis
.clean(cx
),
530 stability
: self.stab
.clean(cx
),
531 deprecation
: self.depr
.clean(cx
),
532 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
533 inner
: ModuleItem(Module
{
534 is_crate
: self.is_crate
,
541 pub struct ListAttributesIter
<'a
> {
542 attrs
: slice
::Iter
<'a
, ast
::Attribute
>,
543 current_list
: vec
::IntoIter
<ast
::NestedMetaItem
>,
547 impl<'a
> Iterator
for ListAttributesIter
<'a
> {
548 type Item
= ast
::NestedMetaItem
;
550 fn next(&mut self) -> Option
<Self::Item
> {
551 if let Some(nested
) = self.current_list
.next() {
555 for attr
in &mut self.attrs
{
556 if let Some(list
) = attr
.meta_item_list() {
557 if attr
.check_name(self.name
) {
558 self.current_list
= list
.into_iter();
559 if let Some(nested
) = self.current_list
.next() {
570 pub trait AttributesExt
{
571 /// Finds an attribute as List and returns the list of attributes nested inside.
572 fn lists
<'a
>(&'a
self, name
: &'a
str) -> ListAttributesIter
<'a
>;
575 impl AttributesExt
for [ast
::Attribute
] {
576 fn lists
<'a
>(&'a
self, name
: &'a
str) -> ListAttributesIter
<'a
> {
579 current_list
: Vec
::new().into_iter(),
585 pub trait NestedAttributesExt
{
586 /// Returns whether the attribute list contains a specific `Word`
587 fn has_word(self, word
: &str) -> bool
;
590 impl<I
: IntoIterator
<Item
=ast
::NestedMetaItem
>> NestedAttributesExt
for I
{
591 fn has_word(self, word
: &str) -> bool
{
592 self.into_iter().any(|attr
| attr
.is_word() && attr
.check_name(word
))
596 /// A portion of documentation, extracted from a `#[doc]` attribute.
598 /// Each variant contains the line number within the complete doc-comment where the fragment
599 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
601 /// Included files are kept separate from inline doc comments so that proper line-number
602 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
603 /// kept separate because of issue #42760.
604 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
605 pub enum DocFragment
{
606 // FIXME #44229 (misdreavus): sugared and raw doc comments can be brought back together once
607 // hoedown is completely removed from rustdoc.
608 /// A doc fragment created from a `///` or `//!` doc comment.
609 SugaredDoc(usize, syntax_pos
::Span
, String
),
610 /// A doc fragment created from a "raw" `#[doc=""]` attribute.
611 RawDoc(usize, syntax_pos
::Span
, String
),
612 /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
613 /// given filename and the file contents.
614 Include(usize, syntax_pos
::Span
, String
, String
),
618 pub fn as_str(&self) -> &str {
620 DocFragment
::SugaredDoc(_
, _
, ref s
) => &s
[..],
621 DocFragment
::RawDoc(_
, _
, ref s
) => &s
[..],
622 DocFragment
::Include(_
, _
, _
, ref s
) => &s
[..],
626 pub fn span(&self) -> syntax_pos
::Span
{
628 DocFragment
::SugaredDoc(_
, span
, _
) |
629 DocFragment
::RawDoc(_
, span
, _
) |
630 DocFragment
::Include(_
, span
, _
, _
) => span
,
635 impl<'a
> FromIterator
<&'a DocFragment
> for String
{
636 fn from_iter
<T
>(iter
: T
) -> Self
638 T
: IntoIterator
<Item
= &'a DocFragment
>
640 iter
.into_iter().fold(String
::new(), |mut acc
, frag
| {
645 DocFragment
::SugaredDoc(_
, _
, ref docs
)
646 | DocFragment
::RawDoc(_
, _
, ref docs
)
647 | DocFragment
::Include(_
, _
, _
, ref docs
) =>
656 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug, Default)]
657 pub struct Attributes
{
658 pub doc_strings
: Vec
<DocFragment
>,
659 pub other_attrs
: Vec
<ast
::Attribute
>,
660 pub cfg
: Option
<Rc
<Cfg
>>,
661 pub span
: Option
<syntax_pos
::Span
>,
662 /// map from Rust paths to resolved defs and potential URL fragments
663 pub links
: Vec
<(String
, DefId
, Option
<String
>)>,
667 /// Extracts the content from an attribute `#[doc(cfg(content))]`.
668 fn extract_cfg(mi
: &ast
::MetaItem
) -> Option
<&ast
::MetaItem
> {
669 use syntax
::ast
::NestedMetaItemKind
::MetaItem
;
671 if let ast
::MetaItemKind
::List(ref nmis
) = mi
.node
{
673 if let MetaItem(ref cfg_mi
) = nmis
[0].node
{
674 if cfg_mi
.check_name("cfg") {
675 if let ast
::MetaItemKind
::List(ref cfg_nmis
) = cfg_mi
.node
{
676 if cfg_nmis
.len() == 1 {
677 if let MetaItem(ref content_mi
) = cfg_nmis
[0].node
{
678 return Some(content_mi
);
690 /// Reads a `MetaItem` from within an attribute, looks for whether it is a
691 /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
693 fn extract_include(mi
: &ast
::MetaItem
)
694 -> Option
<(String
, String
)>
696 mi
.meta_item_list().and_then(|list
| {
698 if meta
.check_name("include") {
699 // the actual compiled `#[doc(include="filename")]` gets expanded to
700 // `#[doc(include(file="filename", contents="file contents")]` so we need to
701 // look for that instead
702 return meta
.meta_item_list().and_then(|list
| {
703 let mut filename
: Option
<String
> = None
;
704 let mut contents
: Option
<String
> = None
;
707 if it
.check_name("file") {
708 if let Some(name
) = it
.value_str() {
709 filename
= Some(name
.to_string());
711 } else if it
.check_name("contents") {
712 if let Some(docs
) = it
.value_str() {
713 contents
= Some(docs
.to_string());
718 if let (Some(filename
), Some(contents
)) = (filename
, contents
) {
719 Some((filename
, contents
))
731 pub fn has_doc_flag(&self, flag
: &str) -> bool
{
732 for attr
in &self.other_attrs
{
733 if !attr
.check_name("doc") { continue; }
735 if let Some(items
) = attr
.meta_item_list() {
736 if items
.iter().filter_map(|i
| i
.meta_item()).any(|it
| it
.check_name(flag
)) {
745 pub fn from_ast(diagnostic
: &::errors
::Handler
,
746 attrs
: &[ast
::Attribute
]) -> Attributes
{
747 let mut doc_strings
= vec
![];
749 let mut cfg
= Cfg
::True
;
750 let mut doc_line
= 0;
752 let other_attrs
= attrs
.iter().filter_map(|attr
| {
753 attr
.with_desugared_doc(|attr
| {
754 if attr
.check_name("doc") {
755 if let Some(mi
) = attr
.meta() {
756 if let Some(value
) = mi
.value_str() {
757 // Extracted #[doc = "..."]
758 let value
= value
.to_string();
760 doc_line
+= value
.lines().count();
762 if attr
.is_sugared_doc
{
763 doc_strings
.push(DocFragment
::SugaredDoc(line
, attr
.span
, value
));
765 doc_strings
.push(DocFragment
::RawDoc(line
, attr
.span
, value
));
769 sp
= Some(attr
.span
);
772 } else if let Some(cfg_mi
) = Attributes
::extract_cfg(&mi
) {
773 // Extracted #[doc(cfg(...))]
774 match Cfg
::parse(cfg_mi
) {
775 Ok(new_cfg
) => cfg
&= new_cfg
,
776 Err(e
) => diagnostic
.span_err(e
.span
, e
.msg
),
779 } else if let Some((filename
, contents
)) = Attributes
::extract_include(&mi
)
782 doc_line
+= contents
.lines().count();
783 doc_strings
.push(DocFragment
::Include(line
,
797 cfg
: if cfg
== Cfg
::True { None }
else { Some(Rc::new(cfg)) }
,
803 /// Finds the `doc` attribute as a NameValue and returns the corresponding
805 pub fn doc_value
<'a
>(&'a
self) -> Option
<&'a
str> {
806 self.doc_strings
.first().map(|s
| s
.as_str())
809 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
811 pub fn collapsed_doc_value(&self) -> Option
<String
> {
812 if !self.doc_strings
.is_empty() {
813 Some(self.doc_strings
.iter().collect())
819 /// Get links as a vector
821 /// Cache must be populated before call
822 pub fn links(&self) -> Vec
<(String
, String
)> {
823 use html
::format
::href
;
824 self.links
.iter().filter_map(|&(ref s
, did
, ref fragment
)| {
825 if let Some((mut href
, ..)) = href(did
) {
826 if let Some(ref fragment
) = *fragment
{
828 href
.push_str(fragment
);
830 Some((s
.clone(), href
))
838 impl AttributesExt
for Attributes
{
839 fn lists
<'a
>(&'a
self, name
: &'a
str) -> ListAttributesIter
<'a
> {
840 self.other_attrs
.lists(name
)
844 /// Given a def, returns its name and disambiguator
845 /// for a value namespace
847 /// Returns None for things which cannot be ambiguous since
848 /// they exist in both namespaces (structs and modules)
849 fn value_ns_kind(def
: Def
, path_str
: &str) -> Option
<(&'
static str, String
)> {
851 // structs, variants, and mods exist in both namespaces. skip them
852 Def
::StructCtor(..) | Def
::Mod(..) | Def
::Variant(..) | Def
::VariantCtor(..) => None
,
854 => Some(("function", format
!("{}()", path_str
))),
856 => Some(("method", format
!("{}()", path_str
))),
858 => Some(("const", format
!("const@{}", path_str
))),
860 => Some(("static", format
!("static@{}", path_str
))),
861 _
=> Some(("value", format
!("value@{}", path_str
))),
865 /// Given a def, returns its name, the article to be used, and a disambiguator
866 /// for the type namespace
867 fn type_ns_kind(def
: Def
, path_str
: &str) -> (&'
static str, &'
static str, String
) {
868 let (kind
, article
) = match def
{
869 // we can still have non-tuple structs
870 Def
::Struct(..) => ("struct", "a"),
871 Def
::Enum(..) => ("enum", "an"),
872 Def
::Trait(..) => ("trait", "a"),
873 Def
::Union(..) => ("union", "a"),
876 (kind
, article
, format
!("{}@{}", kind
, path_str
))
879 fn ambiguity_error(cx
: &DocContext
, attrs
: &Attributes
,
881 article1
: &str, kind1
: &str, disambig1
: &str,
882 article2
: &str, kind2
: &str, disambig2
: &str) {
883 let sp
= attrs
.doc_strings
.first()
884 .map_or(DUMMY_SP
, |a
| a
.span());
886 .struct_span_warn(sp
,
887 &format
!("`{}` is both {} {} and {} {}",
888 path_str
, article1
, kind1
,
890 .help(&format
!("try `{}` if you want to select the {}, \
891 or `{}` if you want to \
893 disambig1
, kind1
, disambig2
,
898 /// Given an enum variant's def, return the def of its enum and the associated fragment
899 fn handle_variant(cx
: &DocContext
, def
: Def
) -> Result
<(Def
, Option
<String
>), ()> {
900 use rustc
::ty
::DefIdTree
;
902 let parent
= if let Some(parent
) = cx
.tcx
.parent(def
.def_id()) {
907 let parent_def
= Def
::Enum(parent
);
908 let variant
= cx
.tcx
.expect_variant_def(def
);
909 Ok((parent_def
, Some(format
!("{}.v", variant
.name
))))
912 /// Resolve a given string as a path, along with whether or not it is
913 /// in the value namespace. Also returns an optional URL fragment in the case
914 /// of variants and methods
915 fn resolve(cx
: &DocContext
, path_str
: &str, is_val
: bool
) -> Result
<(Def
, Option
<String
>), ()> {
916 // In case we're in a module, try to resolve the relative
918 if let Some(id
) = cx
.mod_ids
.borrow().last() {
919 let result
= cx
.resolver
.borrow_mut()
922 resolver
.resolve_str_path_error(DUMMY_SP
,
926 if let Ok(result
) = result
{
927 // In case this is a trait item, skip the
928 // early return and try looking for the trait
929 let value
= match result
.def
{
930 Def
::Method(_
) | Def
::AssociatedConst(_
) => true,
931 Def
::AssociatedTy(_
) => false,
932 Def
::Variant(_
) => return handle_variant(cx
, result
.def
),
933 // not a trait item, just return what we found
934 _
=> return Ok((result
.def
, None
))
941 // If resolution failed, it may still be a method
942 // because methods are not handled by the resolver
943 // If so, bail when we're not looking for a value
949 // Try looking for methods and associated items
950 let mut split
= path_str
.rsplitn(2, "::");
951 let mut item_name
= if let Some(first
) = split
.next() {
957 let mut path
= if let Some(second
) = split
.next() {
963 let ty
= cx
.resolver
.borrow_mut()
966 resolver
.resolve_str_path_error(DUMMY_SP
,
970 Def
::Struct(did
) | Def
::Union(did
) | Def
::Enum(did
) | Def
::TyAlias(did
) => {
971 let item
= cx
.tcx
.inherent_impls(did
).iter()
972 .flat_map(|imp
| cx
.tcx
.associated_items(*imp
))
973 .find(|item
| item
.name
== item_name
);
974 if let Some(item
) = item
{
975 if item
.kind
== ty
::AssociatedKind
::Method
&& is_val
{
976 Ok((ty
.def
, Some(format
!("method.{}", item_name
))))
985 let item
= cx
.tcx
.associated_item_def_ids(did
).iter()
986 .map(|item
| cx
.tcx
.associated_item(*item
))
987 .find(|item
| item
.name
== item_name
);
988 if let Some(item
) = item
{
989 let kind
= match item
.kind
{
990 ty
::AssociatedKind
::Const
if is_val
=> "associatedconstant",
991 ty
::AssociatedKind
::Type
if !is_val
=> "associatedtype",
992 ty
::AssociatedKind
::Method
if is_val
=> "tymethod",
996 Ok((ty
.def
, Some(format
!("{}.{}", kind
, item_name
))))
1009 /// Resolve a string as a macro
1010 fn macro_resolve(cx
: &DocContext
, path_str
: &str) -> Option
<Def
> {
1011 use syntax
::ext
::base
::MacroKind
;
1012 use syntax
::ext
::hygiene
::Mark
;
1013 let segment
= ast
::PathSegment
{
1014 identifier
: ast
::Ident
::from_str(path_str
),
1018 let path
= ast
::Path
{
1020 segments
: vec
![segment
],
1023 let mut resolver
= cx
.resolver
.borrow_mut();
1024 let mark
= Mark
::root();
1026 .resolve_macro_to_def_inner(mark
, &path
, MacroKind
::Bang
, false);
1027 if let Ok(def
) = res
{
1029 } else if let Some(def
) = resolver
.all_macros
.get(&path_str
.into()) {
1037 /// can be either value or type, not a macro
1041 /// values, functions, consts, statics, everything in the value namespace
1043 /// types, traits, everything in the type namespace
1047 impl Clean
<Attributes
> for [ast
::Attribute
] {
1048 fn clean(&self, cx
: &DocContext
) -> Attributes
{
1049 let mut attrs
= Attributes
::from_ast(cx
.sess().diagnostic(), self);
1051 if UnstableFeatures
::from_environment().is_nightly_build() {
1052 let dox
= attrs
.collapsed_doc_value().unwrap_or_else(String
::new
);
1053 for link
in markdown_links(&dox
, cx
.render_type
) {
1054 // bail early for real links
1055 if link
.contains('
/'
) {
1058 let (def
, fragment
) = {
1059 let mut kind
= PathKind
::Unknown
;
1060 let path_str
= if let Some(prefix
) =
1061 ["struct@", "enum@", "type@",
1062 "trait@", "union@"].iter()
1063 .find(|p
| link
.starts_with(**p
)) {
1064 kind
= PathKind
::Type
;
1065 link
.trim_left_matches(prefix
)
1066 } else if let Some(prefix
) =
1067 ["const@", "static@",
1068 "value@", "function@", "mod@",
1069 "fn@", "module@", "method@"]
1070 .iter().find(|p
| link
.starts_with(**p
)) {
1071 kind
= PathKind
::Value
;
1072 link
.trim_left_matches(prefix
)
1073 } else if link
.ends_with("()") {
1074 kind
= PathKind
::Value
;
1075 link
.trim_right_matches("()")
1076 } else if link
.starts_with("macro@") {
1077 kind
= PathKind
::Macro
;
1078 link
.trim_left_matches("macro@")
1079 } else if link
.ends_with('
!'
) {
1080 kind
= PathKind
::Macro
;
1081 link
.trim_right_matches('
!'
)
1086 // avoid resolving things (i.e. regular links) which aren't like paths
1087 // FIXME(Manishearth) given that most links have slashes in them might be worth
1088 // doing a check for slashes first
1089 if path_str
.contains(|ch
: char| !(ch
.is_alphanumeric() ||
1090 ch
== '
:'
|| ch
== '_'
)) {
1096 PathKind
::Value
=> {
1097 if let Ok(def
) = resolve(cx
, path_str
, true) {
1100 // this could just be a normal link or a broken link
1101 // we could potentially check if something is
1102 // "intra-doc-link-like" and warn in that case
1107 if let Ok(def
) = resolve(cx
, path_str
, false) {
1110 // this could just be a normal link
1114 PathKind
::Unknown
=> {
1116 if let Some(macro_def
) = macro_resolve(cx
, path_str
) {
1117 if let Ok(type_def
) = resolve(cx
, path_str
, false) {
1118 let (type_kind
, article
, type_disambig
)
1119 = type_ns_kind(type_def
.0, path_str
);
1120 ambiguity_error(cx
, &attrs
, path_str
,
1121 article
, type_kind
, &type_disambig
,
1122 "a", "macro", &format
!("macro@{}", path_str
));
1124 } else if let Ok(value_def
) = resolve(cx
, path_str
, true) {
1125 let (value_kind
, value_disambig
)
1126 = value_ns_kind(value_def
.0, path_str
)
1127 .expect("struct and mod cases should have been \
1128 caught in previous branch");
1129 ambiguity_error(cx
, &attrs
, path_str
,
1130 "a", value_kind
, &value_disambig
,
1131 "a", "macro", &format
!("macro@{}", path_str
));
1134 } else if let Ok(type_def
) = resolve(cx
, path_str
, false) {
1135 // It is imperative we search for not-a-value first
1136 // Otherwise we will find struct ctors for when we are looking
1137 // for structs, and the link won't work.
1138 // if there is something in both namespaces
1139 if let Ok(value_def
) = resolve(cx
, path_str
, true) {
1140 let kind
= value_ns_kind(value_def
.0, path_str
);
1141 if let Some((value_kind
, value_disambig
)) = kind
{
1142 let (type_kind
, article
, type_disambig
)
1143 = type_ns_kind(type_def
.0, path_str
);
1144 ambiguity_error(cx
, &attrs
, path_str
,
1145 article
, type_kind
, &type_disambig
,
1146 "a", value_kind
, &value_disambig
);
1151 } else if let Ok(value_def
) = resolve(cx
, path_str
, true) {
1154 // this could just be a normal link
1158 PathKind
::Macro
=> {
1159 if let Some(def
) = macro_resolve(cx
, path_str
) {
1169 let id
= register_def(cx
, def
);
1170 attrs
.links
.push((link
, id
, fragment
));
1173 cx
.sess().abort_if_errors();
1180 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1181 pub struct TyParam
{
1184 pub bounds
: Vec
<TyParamBound
>,
1185 pub default: Option
<Type
>,
1188 impl Clean
<TyParam
> for hir
::TyParam
{
1189 fn clean(&self, cx
: &DocContext
) -> TyParam
{
1191 name
: self.name
.clean(cx
),
1192 did
: cx
.tcx
.hir
.local_def_id(self.id
),
1193 bounds
: self.bounds
.clean(cx
),
1194 default: self.default.clean(cx
),
1199 impl<'tcx
> Clean
<TyParam
> for ty
::TypeParameterDef
{
1200 fn clean(&self, cx
: &DocContext
) -> TyParam
{
1201 cx
.renderinfo
.borrow_mut().external_typarams
.insert(self.def_id
, self.name
.clean(cx
));
1203 name
: self.name
.clean(cx
),
1205 bounds
: vec
![], // these are filled in from the where-clauses
1206 default: if self.has_default
{
1207 Some(cx
.tcx
.type_of(self.def_id
).clean(cx
))
1215 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1216 pub enum TyParamBound
{
1217 RegionBound(Lifetime
),
1218 TraitBound(PolyTrait
, hir
::TraitBoundModifier
)
1222 fn maybe_sized(cx
: &DocContext
) -> TyParamBound
{
1223 let did
= cx
.tcx
.require_lang_item(lang_items
::SizedTraitLangItem
);
1224 let empty
= cx
.tcx
.intern_substs(&[]);
1225 let path
= external_path(cx
, &cx
.tcx
.item_name(did
),
1226 Some(did
), false, vec
![], empty
);
1227 inline
::record_extern_fqn(cx
, did
, TypeKind
::Trait
);
1228 TraitBound(PolyTrait
{
1229 trait_
: ResolvedPath
{
1235 generic_params
: Vec
::new(),
1236 }, hir
::TraitBoundModifier
::Maybe
)
1239 fn is_sized_bound(&self, cx
: &DocContext
) -> bool
{
1240 use rustc
::hir
::TraitBoundModifier
as TBM
;
1241 if let TyParamBound
::TraitBound(PolyTrait { ref trait_, .. }
, TBM
::None
) = *self {
1242 if trait_
.def_id() == cx
.tcx
.lang_items().sized_trait() {
1250 impl Clean
<TyParamBound
> for hir
::TyParamBound
{
1251 fn clean(&self, cx
: &DocContext
) -> TyParamBound
{
1253 hir
::RegionTyParamBound(lt
) => RegionBound(lt
.clean(cx
)),
1254 hir
::TraitTyParamBound(ref t
, modifier
) => TraitBound(t
.clean(cx
), modifier
),
1259 fn external_path_params(cx
: &DocContext
, trait_did
: Option
<DefId
>, has_self
: bool
,
1260 bindings
: Vec
<TypeBinding
>, substs
: &Substs
) -> PathParameters
{
1261 let lifetimes
= substs
.regions().filter_map(|v
| v
.clean(cx
)).collect();
1262 let types
= substs
.types().skip(has_self
as usize).collect
::<Vec
<_
>>();
1265 // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
1266 Some(did
) if cx
.tcx
.lang_items().fn_trait_kind(did
).is_some() => {
1267 assert_eq
!(types
.len(), 1);
1268 let inputs
= match types
[0].sty
{
1269 ty
::TyTuple(ref tys
, _
) => tys
.iter().map(|t
| t
.clean(cx
)).collect(),
1271 return PathParameters
::AngleBracketed
{
1273 types
: types
.clean(cx
),
1279 // FIXME(#20299) return type comes from a projection now
1280 // match types[1].sty {
1281 // ty::TyTuple(ref v, _) if v.is_empty() => None, // -> ()
1282 // _ => Some(types[1].clean(cx))
1284 PathParameters
::Parenthesized
{
1290 PathParameters
::AngleBracketed
{
1292 types
: types
.clean(cx
),
1299 // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
1300 // from Fn<(A, B,), C> to Fn(A, B) -> C
1301 fn external_path(cx
: &DocContext
, name
: &str, trait_did
: Option
<DefId
>, has_self
: bool
,
1302 bindings
: Vec
<TypeBinding
>, substs
: &Substs
) -> Path
{
1306 segments
: vec
![PathSegment
{
1307 name
: name
.to_string(),
1308 params
: external_path_params(cx
, trait_did
, has_self
, bindings
, substs
)
1313 impl<'tcx
> Clean
<TyParamBound
> for ty
::TraitRef
<'tcx
> {
1314 fn clean(&self, cx
: &DocContext
) -> TyParamBound
{
1315 inline
::record_extern_fqn(cx
, self.def_id
, TypeKind
::Trait
);
1316 let path
= external_path(cx
, &cx
.tcx
.item_name(self.def_id
),
1317 Some(self.def_id
), true, vec
![], self.substs
);
1319 debug
!("ty::TraitRef\n subst: {:?}\n", self.substs
);
1321 // collect any late bound regions
1322 let mut late_bounds
= vec
![];
1323 for ty_s
in self.input_types().skip(1) {
1324 if let ty
::TyTuple(ts
, _
) = ty_s
.sty
{
1326 if let ty
::TyRef(ref reg
, _
) = ty_s
.sty
{
1327 if let &ty
::RegionKind
::ReLateBound(..) = *reg
{
1328 debug
!(" hit an ReLateBound {:?}", reg
);
1329 if let Some(lt
) = reg
.clean(cx
) {
1330 late_bounds
.push(GenericParam
::Lifetime(lt
));
1340 trait_
: ResolvedPath
{
1346 generic_params
: late_bounds
,
1348 hir
::TraitBoundModifier
::None
1353 impl<'tcx
> Clean
<Option
<Vec
<TyParamBound
>>> for Substs
<'tcx
> {
1354 fn clean(&self, cx
: &DocContext
) -> Option
<Vec
<TyParamBound
>> {
1355 let mut v
= Vec
::new();
1356 v
.extend(self.regions().filter_map(|r
| r
.clean(cx
))
1358 v
.extend(self.types().map(|t
| TraitBound(PolyTrait
{
1359 trait_
: t
.clean(cx
),
1360 generic_params
: Vec
::new(),
1361 }, hir
::TraitBoundModifier
::None
)));
1362 if !v
.is_empty() {Some(v)}
else {None}
1366 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1367 pub struct Lifetime(String
);
1370 pub fn get_ref
<'a
>(&'a
self) -> &'a
str {
1371 let Lifetime(ref s
) = *self;
1376 pub fn statik() -> Lifetime
{
1377 Lifetime("'static".to_string())
1381 impl Clean
<Lifetime
> for hir
::Lifetime
{
1382 fn clean(&self, cx
: &DocContext
) -> Lifetime
{
1383 let hir_id
= cx
.tcx
.hir
.node_to_hir_id(self.id
);
1384 let def
= cx
.tcx
.named_region(hir_id
);
1386 Some(rl
::Region
::EarlyBound(_
, node_id
, _
)) |
1387 Some(rl
::Region
::LateBound(_
, node_id
, _
)) |
1388 Some(rl
::Region
::Free(_
, node_id
)) => {
1389 if let Some(lt
) = cx
.lt_substs
.borrow().get(&node_id
).cloned() {
1395 Lifetime(self.name
.name().to_string())
1399 impl Clean
<Lifetime
> for hir
::LifetimeDef
{
1400 fn clean(&self, _
: &DocContext
) -> Lifetime
{
1401 if self.bounds
.len() > 0 {
1402 let mut s
= format
!("{}: {}",
1403 self.lifetime
.name
.name(),
1404 self.bounds
[0].name
.name());
1405 for bound
in self.bounds
.iter().skip(1) {
1406 s
.push_str(&format
!(" + {}", bound
.name
.name()));
1410 Lifetime(self.lifetime
.name
.name().to_string())
1415 impl Clean
<Lifetime
> for ty
::RegionParameterDef
{
1416 fn clean(&self, _
: &DocContext
) -> Lifetime
{
1417 Lifetime(self.name
.to_string())
1421 impl Clean
<Option
<Lifetime
>> for ty
::RegionKind
{
1422 fn clean(&self, cx
: &DocContext
) -> Option
<Lifetime
> {
1424 ty
::ReStatic
=> Some(Lifetime
::statik()),
1425 ty
::ReLateBound(_
, ty
::BrNamed(_
, name
)) => Some(Lifetime(name
.to_string())),
1426 ty
::ReEarlyBound(ref data
) => Some(Lifetime(data
.name
.clean(cx
))),
1428 ty
::ReLateBound(..) |
1432 ty
::ReSkolemized(..) |
1434 ty
::ReClosureBound(_
) |
1435 ty
::ReErased
=> None
1440 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1441 pub enum WherePredicate
{
1442 BoundPredicate { ty: Type, bounds: Vec<TyParamBound> }
,
1443 RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>}
,
1444 EqPredicate { lhs: Type, rhs: Type }
,
1447 impl Clean
<WherePredicate
> for hir
::WherePredicate
{
1448 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
1450 hir
::WherePredicate
::BoundPredicate(ref wbp
) => {
1451 WherePredicate
::BoundPredicate
{
1452 ty
: wbp
.bounded_ty
.clean(cx
),
1453 bounds
: wbp
.bounds
.clean(cx
)
1457 hir
::WherePredicate
::RegionPredicate(ref wrp
) => {
1458 WherePredicate
::RegionPredicate
{
1459 lifetime
: wrp
.lifetime
.clean(cx
),
1460 bounds
: wrp
.bounds
.clean(cx
)
1464 hir
::WherePredicate
::EqPredicate(ref wrp
) => {
1465 WherePredicate
::EqPredicate
{
1466 lhs
: wrp
.lhs_ty
.clean(cx
),
1467 rhs
: wrp
.rhs_ty
.clean(cx
)
1474 impl<'a
> Clean
<WherePredicate
> for ty
::Predicate
<'a
> {
1475 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
1476 use rustc
::ty
::Predicate
;
1479 Predicate
::Trait(ref pred
) => pred
.clean(cx
),
1480 Predicate
::Equate(ref pred
) => pred
.clean(cx
),
1481 Predicate
::Subtype(ref pred
) => pred
.clean(cx
),
1482 Predicate
::RegionOutlives(ref pred
) => pred
.clean(cx
),
1483 Predicate
::TypeOutlives(ref pred
) => pred
.clean(cx
),
1484 Predicate
::Projection(ref pred
) => pred
.clean(cx
),
1485 Predicate
::WellFormed(_
) => panic
!("not user writable"),
1486 Predicate
::ObjectSafe(_
) => panic
!("not user writable"),
1487 Predicate
::ClosureKind(..) => panic
!("not user writable"),
1488 Predicate
::ConstEvaluatable(..) => panic
!("not user writable"),
1493 impl<'a
> Clean
<WherePredicate
> for ty
::TraitPredicate
<'a
> {
1494 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
1495 WherePredicate
::BoundPredicate
{
1496 ty
: self.trait_ref
.self_ty().clean(cx
),
1497 bounds
: vec
![self.trait_ref
.clean(cx
)]
1502 impl<'tcx
> Clean
<WherePredicate
> for ty
::EquatePredicate
<'tcx
> {
1503 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
1504 let ty
::EquatePredicate(ref lhs
, ref rhs
) = *self;
1505 WherePredicate
::EqPredicate
{
1512 impl<'tcx
> Clean
<WherePredicate
> for ty
::SubtypePredicate
<'tcx
> {
1513 fn clean(&self, _cx
: &DocContext
) -> WherePredicate
{
1514 panic
!("subtype predicates are an internal rustc artifact \
1515 and should not be seen by rustdoc")
1519 impl<'tcx
> Clean
<WherePredicate
> for ty
::OutlivesPredicate
<ty
::Region
<'tcx
>, ty
::Region
<'tcx
>> {
1520 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
1521 let ty
::OutlivesPredicate(ref a
, ref b
) = *self;
1522 WherePredicate
::RegionPredicate
{
1523 lifetime
: a
.clean(cx
).unwrap(),
1524 bounds
: vec
![b
.clean(cx
).unwrap()]
1529 impl<'tcx
> Clean
<WherePredicate
> for ty
::OutlivesPredicate
<Ty
<'tcx
>, ty
::Region
<'tcx
>> {
1530 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
1531 let ty
::OutlivesPredicate(ref ty
, ref lt
) = *self;
1533 WherePredicate
::BoundPredicate
{
1535 bounds
: vec
![TyParamBound
::RegionBound(lt
.clean(cx
).unwrap())]
1540 impl<'tcx
> Clean
<WherePredicate
> for ty
::ProjectionPredicate
<'tcx
> {
1541 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
1542 WherePredicate
::EqPredicate
{
1543 lhs
: self.projection_ty
.clean(cx
),
1544 rhs
: self.ty
.clean(cx
)
1549 impl<'tcx
> Clean
<Type
> for ty
::ProjectionTy
<'tcx
> {
1550 fn clean(&self, cx
: &DocContext
) -> Type
{
1551 let trait_
= match self.trait_ref(cx
.tcx
).clean(cx
) {
1552 TyParamBound
::TraitBound(t
, _
) => t
.trait_
,
1553 TyParamBound
::RegionBound(_
) => {
1554 panic
!("cleaning a trait got a region")
1558 name
: cx
.tcx
.associated_item(self.item_def_id
).name
.clean(cx
),
1559 self_type
: box self.self_ty().clean(cx
),
1565 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1566 pub enum GenericParam
{
1571 impl Clean
<GenericParam
> for hir
::GenericParam
{
1572 fn clean(&self, cx
: &DocContext
) -> GenericParam
{
1574 hir
::GenericParam
::Lifetime(ref l
) => GenericParam
::Lifetime(l
.clean(cx
)),
1575 hir
::GenericParam
::Type(ref t
) => GenericParam
::Type(t
.clean(cx
)),
1580 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug, Default)]
1581 pub struct Generics
{
1582 pub params
: Vec
<GenericParam
>,
1583 pub where_predicates
: Vec
<WherePredicate
>,
1586 impl Clean
<Generics
> for hir
::Generics
{
1587 fn clean(&self, cx
: &DocContext
) -> Generics
{
1588 let mut g
= Generics
{
1589 params
: self.params
.clean(cx
),
1590 where_predicates
: self.where_clause
.predicates
.clean(cx
)
1593 // Some duplicates are generated for ?Sized bounds between type params and where
1594 // predicates. The point in here is to move the bounds definitions from type params
1595 // to where predicates when such cases occur.
1596 for where_pred
in &mut g
.where_predicates
{
1598 WherePredicate
::BoundPredicate { ty: Generic(ref name), ref mut bounds }
=> {
1599 if bounds
.is_empty() {
1600 for param
in &mut g
.params
{
1601 if let GenericParam
::Type(ref mut type_param
) = *param
{
1602 if &type_param
.name
== name
{
1603 mem
::swap(bounds
, &mut type_param
.bounds
);
1617 impl<'a
, 'tcx
> Clean
<Generics
> for (&'a ty
::Generics
,
1618 &'a ty
::GenericPredicates
<'tcx
>) {
1619 fn clean(&self, cx
: &DocContext
) -> Generics
{
1620 use self::WherePredicate
as WP
;
1622 let (gens
, preds
) = *self;
1624 // Bounds in the type_params and lifetimes fields are repeated in the
1625 // predicates field (see rustc_typeck::collect::ty_generics), so remove
1627 let stripped_typarams
= gens
.types
.iter().filter_map(|tp
| {
1628 if tp
.name
== keywords
::SelfType
.name() {
1629 assert_eq
!(tp
.index
, 0);
1634 }).collect
::<Vec
<_
>>();
1636 let mut where_predicates
= preds
.predicates
.to_vec().clean(cx
);
1638 // Type parameters and have a Sized bound by default unless removed with
1639 // ?Sized. Scan through the predicates and mark any type parameter with
1640 // a Sized bound, removing the bounds as we find them.
1642 // Note that associated types also have a sized bound by default, but we
1643 // don't actually know the set of associated types right here so that's
1644 // handled in cleaning associated types
1645 let mut sized_params
= FxHashSet();
1646 where_predicates
.retain(|pred
| {
1648 WP
::BoundPredicate { ty: Generic(ref g), ref bounds }
=> {
1649 if bounds
.iter().any(|b
| b
.is_sized_bound(cx
)) {
1650 sized_params
.insert(g
.clone());
1660 // Run through the type parameters again and insert a ?Sized
1661 // unbound for any we didn't find to be Sized.
1662 for tp
in &stripped_typarams
{
1663 if !sized_params
.contains(&tp
.name
) {
1664 where_predicates
.push(WP
::BoundPredicate
{
1665 ty
: Type
::Generic(tp
.name
.clone()),
1666 bounds
: vec
![TyParamBound
::maybe_sized(cx
)],
1671 // It would be nice to collect all of the bounds on a type and recombine
1672 // them if possible, to avoid e.g. `where T: Foo, T: Bar, T: Sized, T: 'a`
1673 // and instead see `where T: Foo + Bar + Sized + 'a`
1676 params
: gens
.regions
1679 .map(|lp
| GenericParam
::Lifetime(lp
))
1681 simplify
::ty_params(stripped_typarams
)
1683 .map(|tp
| GenericParam
::Type(tp
))
1686 where_predicates
: simplify
::where_clauses(cx
, where_predicates
),
1691 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1693 pub generics
: Generics
,
1694 pub unsafety
: hir
::Unsafety
,
1695 pub constness
: hir
::Constness
,
1700 impl<'a
> Clean
<Method
> for (&'a hir
::MethodSig
, &'a hir
::Generics
, hir
::BodyId
) {
1701 fn clean(&self, cx
: &DocContext
) -> Method
{
1703 generics
: self.1.clean(cx
),
1704 unsafety
: self.0.unsafety
,
1705 constness
: self.0.constness
,
1706 decl
: (&*self.0.decl
, self.2).clean(cx
),
1712 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1713 pub struct TyMethod
{
1714 pub unsafety
: hir
::Unsafety
,
1716 pub generics
: Generics
,
1720 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1721 pub struct Function
{
1723 pub generics
: Generics
,
1724 pub unsafety
: hir
::Unsafety
,
1725 pub constness
: hir
::Constness
,
1729 impl Clean
<Item
> for doctree
::Function
{
1730 fn clean(&self, cx
: &DocContext
) -> Item
{
1732 name
: Some(self.name
.clean(cx
)),
1733 attrs
: self.attrs
.clean(cx
),
1734 source
: self.whence
.clean(cx
),
1735 visibility
: self.vis
.clean(cx
),
1736 stability
: self.stab
.clean(cx
),
1737 deprecation
: self.depr
.clean(cx
),
1738 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
1739 inner
: FunctionItem(Function
{
1740 decl
: (&self.decl
, self.body
).clean(cx
),
1741 generics
: self.generics
.clean(cx
),
1742 unsafety
: self.unsafety
,
1743 constness
: self.constness
,
1750 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1752 pub inputs
: Arguments
,
1753 pub output
: FunctionRetTy
,
1755 pub attrs
: Attributes
,
1759 pub fn has_self(&self) -> bool
{
1760 self.inputs
.values
.len() > 0 && self.inputs
.values
[0].name
== "self"
1763 pub fn self_type(&self) -> Option
<SelfTy
> {
1764 self.inputs
.values
.get(0).and_then(|v
| v
.to_self())
1768 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1769 pub struct Arguments
{
1770 pub values
: Vec
<Argument
>,
1773 impl<'a
> Clean
<Arguments
> for (&'a
[P
<hir
::Ty
>], &'a
[Spanned
<ast
::Name
>]) {
1774 fn clean(&self, cx
: &DocContext
) -> Arguments
{
1776 values
: self.0.iter
().enumerate().map(|(i
, ty
)| {
1777 let mut name
= self.1.get(i
).map(|n
| n
.node
.to_string())
1778 .unwrap_or(String
::new());
1779 if name
.is_empty() {
1780 name
= "_".to_string();
1784 type_
: ty
.clean(cx
),
1791 impl<'a
> Clean
<Arguments
> for (&'a
[P
<hir
::Ty
>], hir
::BodyId
) {
1792 fn clean(&self, cx
: &DocContext
) -> Arguments
{
1793 let body
= cx
.tcx
.hir
.body(self.1);
1796 values
: self.0.iter
().enumerate().map(|(i
, ty
)| {
1798 name
: name_from_pat(&body
.arguments
[i
].pat
),
1799 type_
: ty
.clean(cx
),
1806 impl<'a
, A
: Copy
> Clean
<FnDecl
> for (&'a hir
::FnDecl
, A
)
1807 where (&'a
[P
<hir
::Ty
>], A
): Clean
<Arguments
>
1809 fn clean(&self, cx
: &DocContext
) -> FnDecl
{
1811 inputs
: (&self.0.inputs
[..], self.1).clean(cx
),
1812 output
: self.0.output
.clean(cx
),
1813 variadic
: self.0.variadic
,
1814 attrs
: Attributes
::default()
1819 impl<'a
, 'tcx
> Clean
<FnDecl
> for (DefId
, ty
::PolyFnSig
<'tcx
>) {
1820 fn clean(&self, cx
: &DocContext
) -> FnDecl
{
1821 let (did
, sig
) = *self;
1822 let mut names
= if cx
.tcx
.hir
.as_local_node_id(did
).is_some() {
1825 cx
.tcx
.fn_arg_names(did
).into_iter()
1828 output
: Return(sig
.skip_binder().output().clean(cx
)),
1829 attrs
: Attributes
::default(),
1830 variadic
: sig
.skip_binder().variadic
,
1832 values
: sig
.skip_binder().inputs().iter().map(|t
| {
1835 name
: names
.next().map_or("".to_string(), |name
| name
.to_string()),
1843 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1844 pub struct Argument
{
1849 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1852 SelfBorrowed(Option
<Lifetime
>, Mutability
),
1857 pub fn to_self(&self) -> Option
<SelfTy
> {
1858 if self.name
!= "self" {
1861 if self.type_
.is_self_type() {
1862 return Some(SelfValue
);
1865 BorrowedRef{ref lifetime, mutability, ref type_}
if type_
.is_self_type() => {
1866 Some(SelfBorrowed(lifetime
.clone(), mutability
))
1868 _
=> Some(SelfExplicit(self.type_
.clone()))
1873 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1874 pub enum FunctionRetTy
{
1879 impl Clean
<FunctionRetTy
> for hir
::FunctionRetTy
{
1880 fn clean(&self, cx
: &DocContext
) -> FunctionRetTy
{
1882 hir
::Return(ref typ
) => Return(typ
.clean(cx
)),
1883 hir
::DefaultReturn(..) => DefaultReturn
,
1888 impl GetDefId
for FunctionRetTy
{
1889 fn def_id(&self) -> Option
<DefId
> {
1891 Return(ref ty
) => ty
.def_id(),
1892 DefaultReturn
=> None
,
1897 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1899 pub unsafety
: hir
::Unsafety
,
1900 pub items
: Vec
<Item
>,
1901 pub generics
: Generics
,
1902 pub bounds
: Vec
<TyParamBound
>,
1903 pub is_spotlight
: bool
,
1907 impl Clean
<Item
> for doctree
::Trait
{
1908 fn clean(&self, cx
: &DocContext
) -> Item
{
1909 let attrs
= self.attrs
.clean(cx
);
1910 let is_spotlight
= attrs
.has_doc_flag("spotlight");
1912 name
: Some(self.name
.clean(cx
)),
1914 source
: self.whence
.clean(cx
),
1915 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
1916 visibility
: self.vis
.clean(cx
),
1917 stability
: self.stab
.clean(cx
),
1918 deprecation
: self.depr
.clean(cx
),
1919 inner
: TraitItem(Trait
{
1920 unsafety
: self.unsafety
,
1921 items
: self.items
.clean(cx
),
1922 generics
: self.generics
.clean(cx
),
1923 bounds
: self.bounds
.clean(cx
),
1924 is_spotlight
: is_spotlight
,
1925 is_auto
: self.is_auto
.clean(cx
),
1931 impl Clean
<bool
> for hir
::IsAuto
{
1932 fn clean(&self, _
: &DocContext
) -> bool
{
1934 hir
::IsAuto
::Yes
=> true,
1935 hir
::IsAuto
::No
=> false,
1940 impl Clean
<Type
> for hir
::TraitRef
{
1941 fn clean(&self, cx
: &DocContext
) -> Type
{
1942 resolve_type(cx
, self.path
.clean(cx
), self.ref_id
)
1946 impl Clean
<PolyTrait
> for hir
::PolyTraitRef
{
1947 fn clean(&self, cx
: &DocContext
) -> PolyTrait
{
1949 trait_
: self.trait_ref
.clean(cx
),
1950 generic_params
: self.bound_generic_params
.clean(cx
)
1955 impl Clean
<Item
> for hir
::TraitItem
{
1956 fn clean(&self, cx
: &DocContext
) -> Item
{
1957 let inner
= match self.node
{
1958 hir
::TraitItemKind
::Const(ref ty
, default) => {
1959 AssociatedConstItem(ty
.clean(cx
),
1960 default.map(|e
| print_const_expr(cx
, e
)))
1962 hir
::TraitItemKind
::Method(ref sig
, hir
::TraitMethod
::Provided(body
)) => {
1963 MethodItem((sig
, &self.generics
, body
).clean(cx
))
1965 hir
::TraitItemKind
::Method(ref sig
, hir
::TraitMethod
::Required(ref names
)) => {
1966 TyMethodItem(TyMethod
{
1967 unsafety
: sig
.unsafety
.clone(),
1968 decl
: (&*sig
.decl
, &names
[..]).clean(cx
),
1969 generics
: self.generics
.clean(cx
),
1973 hir
::TraitItemKind
::Type(ref bounds
, ref default) => {
1974 AssociatedTypeItem(bounds
.clean(cx
), default.clean(cx
))
1978 name
: Some(self.name
.clean(cx
)),
1979 attrs
: self.attrs
.clean(cx
),
1980 source
: self.span
.clean(cx
),
1981 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
1983 stability
: get_stability(cx
, cx
.tcx
.hir
.local_def_id(self.id
)),
1984 deprecation
: get_deprecation(cx
, cx
.tcx
.hir
.local_def_id(self.id
)),
1990 impl Clean
<Item
> for hir
::ImplItem
{
1991 fn clean(&self, cx
: &DocContext
) -> Item
{
1992 let inner
= match self.node
{
1993 hir
::ImplItemKind
::Const(ref ty
, expr
) => {
1994 AssociatedConstItem(ty
.clean(cx
),
1995 Some(print_const_expr(cx
, expr
)))
1997 hir
::ImplItemKind
::Method(ref sig
, body
) => {
1998 MethodItem((sig
, &self.generics
, body
).clean(cx
))
2000 hir
::ImplItemKind
::Type(ref ty
) => TypedefItem(Typedef
{
2001 type_
: ty
.clean(cx
),
2002 generics
: Generics
::default(),
2006 name
: Some(self.name
.clean(cx
)),
2007 source
: self.span
.clean(cx
),
2008 attrs
: self.attrs
.clean(cx
),
2009 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
2010 visibility
: self.vis
.clean(cx
),
2011 stability
: get_stability(cx
, cx
.tcx
.hir
.local_def_id(self.id
)),
2012 deprecation
: get_deprecation(cx
, cx
.tcx
.hir
.local_def_id(self.id
)),
2018 impl<'tcx
> Clean
<Item
> for ty
::AssociatedItem
{
2019 fn clean(&self, cx
: &DocContext
) -> Item
{
2020 let inner
= match self.kind
{
2021 ty
::AssociatedKind
::Const
=> {
2022 let ty
= cx
.tcx
.type_of(self.def_id
);
2023 let default = if self.defaultness
.has_value() {
2024 Some(inline
::print_inlined_const(cx
, self.def_id
))
2028 AssociatedConstItem(ty
.clean(cx
), default)
2030 ty
::AssociatedKind
::Method
=> {
2031 let generics
= (cx
.tcx
.generics_of(self.def_id
),
2032 &cx
.tcx
.predicates_of(self.def_id
)).clean(cx
);
2033 let sig
= cx
.tcx
.fn_sig(self.def_id
);
2034 let mut decl
= (self.def_id
, sig
).clean(cx
);
2036 if self.method_has_self_argument
{
2037 let self_ty
= match self.container
{
2038 ty
::ImplContainer(def_id
) => {
2039 cx
.tcx
.type_of(def_id
)
2041 ty
::TraitContainer(_
) => cx
.tcx
.mk_self_type()
2043 let self_arg_ty
= *sig
.input(0).skip_binder();
2044 if self_arg_ty
== self_ty
{
2045 decl
.inputs
.values
[0].type_
= Generic(String
::from("Self"));
2046 } else if let ty
::TyRef(_
, mt
) = self_arg_ty
.sty
{
2047 if mt
.ty
== self_ty
{
2048 match decl
.inputs
.values
[0].type_
{
2049 BorrowedRef{ref mut type_, ..}
=> {
2050 **type_
= Generic(String
::from("Self"))
2052 _
=> unreachable
!(),
2058 let provided
= match self.container
{
2059 ty
::ImplContainer(_
) => true,
2060 ty
::TraitContainer(_
) => self.defaultness
.has_value()
2063 let constness
= if cx
.tcx
.is_const_fn(self.def_id
) {
2064 hir
::Constness
::Const
2066 hir
::Constness
::NotConst
2069 unsafety
: sig
.unsafety(),
2076 TyMethodItem(TyMethod
{
2077 unsafety
: sig
.unsafety(),
2084 ty
::AssociatedKind
::Type
=> {
2085 let my_name
= self.name
.clean(cx
);
2087 if let ty
::TraitContainer(did
) = self.container
{
2088 // When loading a cross-crate associated type, the bounds for this type
2089 // are actually located on the trait/impl itself, so we need to load
2090 // all of the generics from there and then look for bounds that are
2091 // applied to this associated type in question.
2092 let predicates
= cx
.tcx
.predicates_of(did
);
2093 let generics
= (cx
.tcx
.generics_of(did
), &predicates
).clean(cx
);
2094 let mut bounds
= generics
.where_predicates
.iter().filter_map(|pred
| {
2095 let (name
, self_type
, trait_
, bounds
) = match *pred
{
2096 WherePredicate
::BoundPredicate
{
2097 ty
: QPath { ref name, ref self_type, ref trait_ }
,
2099 } => (name
, self_type
, trait_
, bounds
),
2102 if *name
!= my_name { return None }
2104 ResolvedPath { did, .. }
if did
== self.container
.id() => {}
2108 Generic(ref s
) if *s
== "Self" => {}
2112 }).flat_map(|i
| i
.iter().cloned()).collect
::<Vec
<_
>>();
2113 // Our Sized/?Sized bound didn't get handled when creating the generics
2114 // because we didn't actually get our whole set of bounds until just now
2115 // (some of them may have come from the trait). If we do have a sized
2116 // bound, we remove it, and if we don't then we add the `?Sized` bound
2118 match bounds
.iter().position(|b
| b
.is_sized_bound(cx
)) {
2119 Some(i
) => { bounds.remove(i); }
2120 None
=> bounds
.push(TyParamBound
::maybe_sized(cx
)),
2123 let ty
= if self.defaultness
.has_value() {
2124 Some(cx
.tcx
.type_of(self.def_id
))
2129 AssociatedTypeItem(bounds
, ty
.clean(cx
))
2131 TypedefItem(Typedef
{
2132 type_
: cx
.tcx
.type_of(self.def_id
).clean(cx
),
2133 generics
: Generics
{
2135 where_predicates
: Vec
::new(),
2142 let visibility
= match self.container
{
2143 ty
::ImplContainer(_
) => self.vis
.clean(cx
),
2144 ty
::TraitContainer(_
) => None
,
2148 name
: Some(self.name
.clean(cx
)),
2150 stability
: get_stability(cx
, self.def_id
),
2151 deprecation
: get_deprecation(cx
, self.def_id
),
2152 def_id
: self.def_id
,
2153 attrs
: inline
::load_attrs(cx
, self.def_id
),
2154 source
: cx
.tcx
.def_span(self.def_id
).clean(cx
),
2160 /// A trait reference, which may have higher ranked lifetimes.
2161 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2162 pub struct PolyTrait
{
2164 pub generic_params
: Vec
<GenericParam
>,
2167 /// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
2168 /// type out of the AST/TyCtxt given one of these, if more information is needed. Most importantly
2169 /// it does not preserve mutability or boxes.
2170 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2172 /// structs/enums/traits (most that'd be an hir::TyPath)
2175 typarams
: Option
<Vec
<TyParamBound
>>,
2177 /// true if is a `T::Name` path for associated types
2180 /// For parameterized types, so the consumer of the JSON don't go
2181 /// looking for types which don't exist anywhere.
2183 /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
2184 /// arrays, slices, and tuples.
2185 Primitive(PrimitiveType
),
2187 BareFunction(Box
<BareFunctionDecl
>),
2190 Array(Box
<Type
>, String
),
2193 RawPointer(Mutability
, Box
<Type
>),
2195 lifetime
: Option
<Lifetime
>,
2196 mutability
: Mutability
,
2200 // <Type as Trait>::Name
2203 self_type
: Box
<Type
>,
2210 // impl TraitA+TraitB
2211 ImplTrait(Vec
<TyParamBound
>),
2214 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
2215 pub enum PrimitiveType
{
2216 Isize
, I8
, I16
, I32
, I64
, I128
,
2217 Usize
, U8
, U16
, U32
, U64
, U128
,
2232 #[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
2248 pub trait GetDefId
{
2249 fn def_id(&self) -> Option
<DefId
>;
2252 impl<T
: GetDefId
> GetDefId
for Option
<T
> {
2253 fn def_id(&self) -> Option
<DefId
> {
2254 self.as_ref().and_then(|d
| d
.def_id())
2259 pub fn primitive_type(&self) -> Option
<PrimitiveType
> {
2261 Primitive(p
) | BorrowedRef { type_: box Primitive(p), ..}
=> Some(p
),
2262 Slice(..) | BorrowedRef { type_: box Slice(..), .. }
=> Some(PrimitiveType
::Slice
),
2263 Array(..) | BorrowedRef { type_: box Array(..), .. }
=> Some(PrimitiveType
::Array
),
2264 Tuple(ref tys
) => if tys
.is_empty() {
2265 Some(PrimitiveType
::Unit
)
2267 Some(PrimitiveType
::Tuple
)
2269 RawPointer(..) => Some(PrimitiveType
::RawPointer
),
2270 BorrowedRef { type_: box Generic(..), .. }
=> Some(PrimitiveType
::Reference
),
2271 BareFunction(..) => Some(PrimitiveType
::Fn
),
2272 Never
=> Some(PrimitiveType
::Never
),
2277 pub fn is_generic(&self) -> bool
{
2279 ResolvedPath { is_generic, .. }
=> is_generic
,
2284 pub fn is_self_type(&self) -> bool
{
2286 Generic(ref name
) => name
== "Self",
2291 pub fn generics(&self) -> Option
<&[Type
]> {
2293 ResolvedPath { ref path, .. }
=> {
2294 path
.segments
.last().and_then(|seg
| {
2295 if let PathParameters
::AngleBracketed { ref types, .. }
= seg
.params
{
2307 impl GetDefId
for Type
{
2308 fn def_id(&self) -> Option
<DefId
> {
2310 ResolvedPath { did, .. }
=> Some(did
),
2311 Primitive(p
) => ::html
::render
::cache().primitive_locations
.get(&p
).cloned(),
2312 BorrowedRef { type_: box Generic(..), .. }
=>
2313 Primitive(PrimitiveType
::Reference
).def_id(),
2314 BorrowedRef { ref type_, .. }
=> type_
.def_id(),
2315 Tuple(ref tys
) => if tys
.is_empty() {
2316 Primitive(PrimitiveType
::Unit
).def_id()
2318 Primitive(PrimitiveType
::Tuple
).def_id()
2320 BareFunction(..) => Primitive(PrimitiveType
::Fn
).def_id(),
2321 Never
=> Primitive(PrimitiveType
::Never
).def_id(),
2322 Slice(..) => Primitive(PrimitiveType
::Slice
).def_id(),
2323 Array(..) => Primitive(PrimitiveType
::Array
).def_id(),
2324 RawPointer(..) => Primitive(PrimitiveType
::RawPointer
).def_id(),
2325 QPath { ref self_type, .. }
=> self_type
.def_id(),
2331 impl PrimitiveType
{
2332 fn from_str(s
: &str) -> Option
<PrimitiveType
> {
2334 "isize" => Some(PrimitiveType
::Isize
),
2335 "i8" => Some(PrimitiveType
::I8
),
2336 "i16" => Some(PrimitiveType
::I16
),
2337 "i32" => Some(PrimitiveType
::I32
),
2338 "i64" => Some(PrimitiveType
::I64
),
2339 "i128" => Some(PrimitiveType
::I128
),
2340 "usize" => Some(PrimitiveType
::Usize
),
2341 "u8" => Some(PrimitiveType
::U8
),
2342 "u16" => Some(PrimitiveType
::U16
),
2343 "u32" => Some(PrimitiveType
::U32
),
2344 "u64" => Some(PrimitiveType
::U64
),
2345 "u128" => Some(PrimitiveType
::U128
),
2346 "bool" => Some(PrimitiveType
::Bool
),
2347 "char" => Some(PrimitiveType
::Char
),
2348 "str" => Some(PrimitiveType
::Str
),
2349 "f32" => Some(PrimitiveType
::F32
),
2350 "f64" => Some(PrimitiveType
::F64
),
2351 "array" => Some(PrimitiveType
::Array
),
2352 "slice" => Some(PrimitiveType
::Slice
),
2353 "tuple" => Some(PrimitiveType
::Tuple
),
2354 "unit" => Some(PrimitiveType
::Unit
),
2355 "pointer" => Some(PrimitiveType
::RawPointer
),
2356 "reference" => Some(PrimitiveType
::Reference
),
2357 "fn" => Some(PrimitiveType
::Fn
),
2358 "never" => Some(PrimitiveType
::Never
),
2363 pub fn as_str(&self) -> &'
static str {
2364 use self::PrimitiveType
::*;
2387 RawPointer
=> "pointer",
2388 Reference
=> "reference",
2394 pub fn to_url_str(&self) -> &'
static str {
2399 impl From
<ast
::IntTy
> for PrimitiveType
{
2400 fn from(int_ty
: ast
::IntTy
) -> PrimitiveType
{
2402 ast
::IntTy
::Isize
=> PrimitiveType
::Isize
,
2403 ast
::IntTy
::I8
=> PrimitiveType
::I8
,
2404 ast
::IntTy
::I16
=> PrimitiveType
::I16
,
2405 ast
::IntTy
::I32
=> PrimitiveType
::I32
,
2406 ast
::IntTy
::I64
=> PrimitiveType
::I64
,
2407 ast
::IntTy
::I128
=> PrimitiveType
::I128
,
2412 impl From
<ast
::UintTy
> for PrimitiveType
{
2413 fn from(uint_ty
: ast
::UintTy
) -> PrimitiveType
{
2415 ast
::UintTy
::Usize
=> PrimitiveType
::Usize
,
2416 ast
::UintTy
::U8
=> PrimitiveType
::U8
,
2417 ast
::UintTy
::U16
=> PrimitiveType
::U16
,
2418 ast
::UintTy
::U32
=> PrimitiveType
::U32
,
2419 ast
::UintTy
::U64
=> PrimitiveType
::U64
,
2420 ast
::UintTy
::U128
=> PrimitiveType
::U128
,
2425 impl From
<ast
::FloatTy
> for PrimitiveType
{
2426 fn from(float_ty
: ast
::FloatTy
) -> PrimitiveType
{
2428 ast
::FloatTy
::F32
=> PrimitiveType
::F32
,
2429 ast
::FloatTy
::F64
=> PrimitiveType
::F64
,
2434 impl Clean
<Type
> for hir
::Ty
{
2435 fn clean(&self, cx
: &DocContext
) -> Type
{
2439 TyPtr(ref m
) => RawPointer(m
.mutbl
.clean(cx
), box m
.ty
.clean(cx
)),
2440 TyRptr(ref l
, ref m
) => {
2441 let lifetime
= if l
.is_elided() {
2446 BorrowedRef
{lifetime
: lifetime
, mutability
: m
.mutbl
.clean(cx
),
2447 type_
: box m
.ty
.clean(cx
)}
2449 TySlice(ref ty
) => Slice(box ty
.clean(cx
)),
2450 TyArray(ref ty
, n
) => {
2451 let def_id
= cx
.tcx
.hir
.body_owner_def_id(n
);
2452 let param_env
= cx
.tcx
.param_env(def_id
);
2453 let substs
= Substs
::identity_for_item(cx
.tcx
, def_id
);
2454 let n
= cx
.tcx
.const_eval(param_env
.and((def_id
, substs
))).unwrap_or_else(|_
| {
2455 cx
.tcx
.mk_const(ty
::Const
{
2456 val
: ConstVal
::Unevaluated(def_id
, substs
),
2457 ty
: cx
.tcx
.types
.usize
2460 let n
= if let ConstVal
::Integral(ConstInt
::Usize(n
)) = n
.val
{
2462 } else if let ConstVal
::Unevaluated(def_id
, _
) = n
.val
{
2463 if let Some(node_id
) = cx
.tcx
.hir
.as_local_node_id(def_id
) {
2464 print_const_expr(cx
, cx
.tcx
.hir
.body_owned_by(node_id
))
2466 inline
::print_inlined_const(cx
, def_id
)
2471 Array(box ty
.clean(cx
), n
)
2473 TyTup(ref tys
) => Tuple(tys
.clean(cx
)),
2474 TyPath(hir
::QPath
::Resolved(None
, ref path
)) => {
2475 if let Some(new_ty
) = cx
.ty_substs
.borrow().get(&path
.def
).cloned() {
2479 let mut alias
= None
;
2480 if let Def
::TyAlias(def_id
) = path
.def
{
2481 // Substitute private type aliases
2482 if let Some(node_id
) = cx
.tcx
.hir
.as_local_node_id(def_id
) {
2483 if !cx
.access_levels
.borrow().is_exported(def_id
) {
2484 alias
= Some(&cx
.tcx
.hir
.expect_item(node_id
).node
);
2489 if let Some(&hir
::ItemTy(ref ty
, ref generics
)) = alias
{
2490 let provided_params
= &path
.segments
.last().unwrap();
2491 let mut ty_substs
= FxHashMap();
2492 let mut lt_substs
= FxHashMap();
2493 provided_params
.with_parameters(|provided_params
| {
2494 for (i
, ty_param
) in generics
.ty_params().enumerate() {
2495 let ty_param_def
= Def
::TyParam(cx
.tcx
.hir
.local_def_id(ty_param
.id
));
2496 if let Some(ty
) = provided_params
.types
.get(i
).cloned() {
2497 ty_substs
.insert(ty_param_def
, ty
.into_inner().clean(cx
));
2498 } else if let Some(default) = ty_param
.default.clone() {
2499 ty_substs
.insert(ty_param_def
, default.into_inner().clean(cx
));
2503 for (i
, lt_param
) in generics
.lifetimes().enumerate() {
2504 if let Some(lt
) = provided_params
.lifetimes
.get(i
).cloned() {
2505 if !lt
.is_elided() {
2506 let lt_def_id
= cx
.tcx
.hir
.local_def_id(lt_param
.lifetime
.id
);
2507 lt_substs
.insert(lt_def_id
, lt
.clean(cx
));
2512 return cx
.enter_alias(ty_substs
, lt_substs
, || ty
.clean(cx
));
2514 resolve_type(cx
, path
.clean(cx
), self.id
)
2516 TyPath(hir
::QPath
::Resolved(Some(ref qself
), ref p
)) => {
2517 let mut segments
: Vec
<_
> = p
.segments
.clone().into();
2519 let trait_path
= hir
::Path
{
2521 def
: Def
::Trait(cx
.tcx
.associated_item(p
.def
.def_id()).container
.id()),
2522 segments
: segments
.into(),
2525 name
: p
.segments
.last().unwrap().name
.clean(cx
),
2526 self_type
: box qself
.clean(cx
),
2527 trait_
: box resolve_type(cx
, trait_path
.clean(cx
), self.id
)
2530 TyPath(hir
::QPath
::TypeRelative(ref qself
, ref segment
)) => {
2531 let mut def
= Def
::Err
;
2532 let ty
= hir_ty_to_ty(cx
.tcx
, self);
2533 if let ty
::TyProjection(proj
) = ty
.sty
{
2534 def
= Def
::Trait(proj
.trait_ref(cx
.tcx
).def_id
);
2536 let trait_path
= hir
::Path
{
2539 segments
: vec
![].into(),
2542 name
: segment
.name
.clean(cx
),
2543 self_type
: box qself
.clean(cx
),
2544 trait_
: box resolve_type(cx
, trait_path
.clean(cx
), self.id
)
2547 TyTraitObject(ref bounds
, ref lifetime
) => {
2548 match bounds
[0].clean(cx
).trait_
{
2549 ResolvedPath { path, typarams: None, did, is_generic }
=> {
2550 let mut bounds
: Vec
<_
> = bounds
[1..].iter().map(|bound
| {
2551 TraitBound(bound
.clean(cx
), hir
::TraitBoundModifier
::None
)
2553 if !lifetime
.is_elided() {
2554 bounds
.push(RegionBound(lifetime
.clean(cx
)));
2558 typarams
: Some(bounds
),
2563 _
=> Infer
// shouldn't happen
2566 TyBareFn(ref barefn
) => BareFunction(box barefn
.clean(cx
)),
2567 TyImplTraitExistential(ref exist_ty
, ref _lts
) => ImplTrait(exist_ty
.bounds
.clean(cx
)),
2568 TyInfer
| TyErr
=> Infer
,
2569 TyTypeof(..) => panic
!("Unimplemented type {:?}", self.node
),
2574 impl<'tcx
> Clean
<Type
> for Ty
<'tcx
> {
2575 fn clean(&self, cx
: &DocContext
) -> Type
{
2577 ty
::TyNever
=> Never
,
2578 ty
::TyBool
=> Primitive(PrimitiveType
::Bool
),
2579 ty
::TyChar
=> Primitive(PrimitiveType
::Char
),
2580 ty
::TyInt(int_ty
) => Primitive(int_ty
.into()),
2581 ty
::TyUint(uint_ty
) => Primitive(uint_ty
.into()),
2582 ty
::TyFloat(float_ty
) => Primitive(float_ty
.into()),
2583 ty
::TyStr
=> Primitive(PrimitiveType
::Str
),
2584 ty
::TySlice(ty
) => Slice(box ty
.clean(cx
)),
2585 ty
::TyArray(ty
, n
) => {
2586 let mut n
= cx
.tcx
.lift(&n
).unwrap();
2587 if let ConstVal
::Unevaluated(def_id
, substs
) = n
.val
{
2588 let param_env
= cx
.tcx
.param_env(def_id
);
2589 if let Ok(new_n
) = cx
.tcx
.const_eval(param_env
.and((def_id
, substs
))) {
2593 let n
= if let ConstVal
::Integral(ConstInt
::Usize(n
)) = n
.val
{
2595 } else if let ConstVal
::Unevaluated(def_id
, _
) = n
.val
{
2596 if let Some(node_id
) = cx
.tcx
.hir
.as_local_node_id(def_id
) {
2597 print_const_expr(cx
, cx
.tcx
.hir
.body_owned_by(node_id
))
2599 inline
::print_inlined_const(cx
, def_id
)
2604 Array(box ty
.clean(cx
), n
)
2606 ty
::TyRawPtr(mt
) => RawPointer(mt
.mutbl
.clean(cx
), box mt
.ty
.clean(cx
)),
2607 ty
::TyRef(r
, mt
) => BorrowedRef
{
2608 lifetime
: r
.clean(cx
),
2609 mutability
: mt
.mutbl
.clean(cx
),
2610 type_
: box mt
.ty
.clean(cx
),
2614 let ty
= cx
.tcx
.lift(self).unwrap();
2615 let sig
= ty
.fn_sig(cx
.tcx
);
2616 BareFunction(box BareFunctionDecl
{
2617 unsafety
: sig
.unsafety(),
2618 generic_params
: Vec
::new(),
2619 decl
: (cx
.tcx
.hir
.local_def_id(ast
::CRATE_NODE_ID
), sig
).clean(cx
),
2623 ty
::TyAdt(def
, substs
) => {
2625 let kind
= match def
.adt_kind() {
2626 AdtKind
::Struct
=> TypeKind
::Struct
,
2627 AdtKind
::Union
=> TypeKind
::Union
,
2628 AdtKind
::Enum
=> TypeKind
::Enum
,
2630 inline
::record_extern_fqn(cx
, did
, kind
);
2631 let path
= external_path(cx
, &cx
.tcx
.item_name(did
),
2632 None
, false, vec
![], substs
);
2640 ty
::TyForeign(did
) => {
2641 inline
::record_extern_fqn(cx
, did
, TypeKind
::Foreign
);
2642 let path
= external_path(cx
, &cx
.tcx
.item_name(did
),
2643 None
, false, vec
![], Substs
::empty());
2651 ty
::TyDynamic(ref obj
, ref reg
) => {
2652 if let Some(principal
) = obj
.principal() {
2653 let did
= principal
.def_id();
2654 inline
::record_extern_fqn(cx
, did
, TypeKind
::Trait
);
2656 let mut typarams
= vec
![];
2657 reg
.clean(cx
).map(|b
| typarams
.push(RegionBound(b
)));
2658 for did
in obj
.auto_traits() {
2659 let empty
= cx
.tcx
.intern_substs(&[]);
2660 let path
= external_path(cx
, &cx
.tcx
.item_name(did
),
2661 Some(did
), false, vec
![], empty
);
2662 inline
::record_extern_fqn(cx
, did
, TypeKind
::Trait
);
2663 let bound
= TraitBound(PolyTrait
{
2664 trait_
: ResolvedPath
{
2670 generic_params
: Vec
::new(),
2671 }, hir
::TraitBoundModifier
::None
);
2672 typarams
.push(bound
);
2675 let mut bindings
= vec
![];
2676 for ty
::Binder(ref pb
) in obj
.projection_bounds() {
2677 bindings
.push(TypeBinding
{
2678 name
: cx
.tcx
.associated_item(pb
.item_def_id
).name
.clean(cx
),
2683 let path
= external_path(cx
, &cx
.tcx
.item_name(did
), Some(did
),
2684 false, bindings
, principal
.0.substs
);
2687 typarams
: Some(typarams
),
2695 ty
::TyTuple(ref t
, _
) => Tuple(t
.clean(cx
)),
2697 ty
::TyProjection(ref data
) => data
.clean(cx
),
2699 ty
::TyParam(ref p
) => Generic(p
.name
.to_string()),
2701 ty
::TyAnon(def_id
, substs
) => {
2702 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
2703 // by looking up the projections associated with the def_id.
2704 let predicates_of
= cx
.tcx
.predicates_of(def_id
);
2705 let substs
= cx
.tcx
.lift(&substs
).unwrap();
2706 let bounds
= predicates_of
.instantiate(cx
.tcx
, substs
);
2707 ImplTrait(bounds
.predicates
.into_iter().filter_map(|predicate
| {
2708 predicate
.to_opt_poly_trait_ref().clean(cx
)
2712 ty
::TyClosure(..) | ty
::TyGenerator(..) => Tuple(vec
![]), // FIXME(pcwalton)
2714 ty
::TyGeneratorWitness(..) => panic
!("TyGeneratorWitness"),
2715 ty
::TyInfer(..) => panic
!("TyInfer"),
2716 ty
::TyError
=> panic
!("TyError"),
2721 impl Clean
<Item
> for hir
::StructField
{
2722 fn clean(&self, cx
: &DocContext
) -> Item
{
2724 name
: Some(self.name
).clean(cx
),
2725 attrs
: self.attrs
.clean(cx
),
2726 source
: self.span
.clean(cx
),
2727 visibility
: self.vis
.clean(cx
),
2728 stability
: get_stability(cx
, cx
.tcx
.hir
.local_def_id(self.id
)),
2729 deprecation
: get_deprecation(cx
, cx
.tcx
.hir
.local_def_id(self.id
)),
2730 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
2731 inner
: StructFieldItem(self.ty
.clean(cx
)),
2736 impl<'tcx
> Clean
<Item
> for ty
::FieldDef
{
2737 fn clean(&self, cx
: &DocContext
) -> Item
{
2739 name
: Some(self.name
).clean(cx
),
2740 attrs
: cx
.tcx
.get_attrs(self.did
).clean(cx
),
2741 source
: cx
.tcx
.def_span(self.did
).clean(cx
),
2742 visibility
: self.vis
.clean(cx
),
2743 stability
: get_stability(cx
, self.did
),
2744 deprecation
: get_deprecation(cx
, self.did
),
2746 inner
: StructFieldItem(cx
.tcx
.type_of(self.did
).clean(cx
)),
2751 #[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug)]
2752 pub enum Visibility
{
2757 impl Clean
<Option
<Visibility
>> for hir
::Visibility
{
2758 fn clean(&self, _
: &DocContext
) -> Option
<Visibility
> {
2759 Some(if *self == hir
::Visibility
::Public { Public }
else { Inherited }
)
2763 impl Clean
<Option
<Visibility
>> for ty
::Visibility
{
2764 fn clean(&self, _
: &DocContext
) -> Option
<Visibility
> {
2765 Some(if *self == ty
::Visibility
::Public { Public }
else { Inherited }
)
2769 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2771 pub struct_type
: doctree
::StructType
,
2772 pub generics
: Generics
,
2773 pub fields
: Vec
<Item
>,
2774 pub fields_stripped
: bool
,
2777 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2779 pub struct_type
: doctree
::StructType
,
2780 pub generics
: Generics
,
2781 pub fields
: Vec
<Item
>,
2782 pub fields_stripped
: bool
,
2785 impl Clean
<Item
> for doctree
::Struct
{
2786 fn clean(&self, cx
: &DocContext
) -> Item
{
2788 name
: Some(self.name
.clean(cx
)),
2789 attrs
: self.attrs
.clean(cx
),
2790 source
: self.whence
.clean(cx
),
2791 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
2792 visibility
: self.vis
.clean(cx
),
2793 stability
: self.stab
.clean(cx
),
2794 deprecation
: self.depr
.clean(cx
),
2795 inner
: StructItem(Struct
{
2796 struct_type
: self.struct_type
,
2797 generics
: self.generics
.clean(cx
),
2798 fields
: self.fields
.clean(cx
),
2799 fields_stripped
: false,
2805 impl Clean
<Item
> for doctree
::Union
{
2806 fn clean(&self, cx
: &DocContext
) -> Item
{
2808 name
: Some(self.name
.clean(cx
)),
2809 attrs
: self.attrs
.clean(cx
),
2810 source
: self.whence
.clean(cx
),
2811 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
2812 visibility
: self.vis
.clean(cx
),
2813 stability
: self.stab
.clean(cx
),
2814 deprecation
: self.depr
.clean(cx
),
2815 inner
: UnionItem(Union
{
2816 struct_type
: self.struct_type
,
2817 generics
: self.generics
.clean(cx
),
2818 fields
: self.fields
.clean(cx
),
2819 fields_stripped
: false,
2825 /// This is a more limited form of the standard Struct, different in that
2826 /// it lacks the things most items have (name, id, parameterization). Found
2827 /// only as a variant in an enum.
2828 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2829 pub struct VariantStruct
{
2830 pub struct_type
: doctree
::StructType
,
2831 pub fields
: Vec
<Item
>,
2832 pub fields_stripped
: bool
,
2835 impl Clean
<VariantStruct
> for ::rustc
::hir
::VariantData
{
2836 fn clean(&self, cx
: &DocContext
) -> VariantStruct
{
2838 struct_type
: doctree
::struct_type_from_def(self),
2839 fields
: self.fields().iter().map(|x
| x
.clean(cx
)).collect(),
2840 fields_stripped
: false,
2845 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2847 pub variants
: Vec
<Item
>,
2848 pub generics
: Generics
,
2849 pub variants_stripped
: bool
,
2852 impl Clean
<Item
> for doctree
::Enum
{
2853 fn clean(&self, cx
: &DocContext
) -> Item
{
2855 name
: Some(self.name
.clean(cx
)),
2856 attrs
: self.attrs
.clean(cx
),
2857 source
: self.whence
.clean(cx
),
2858 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
2859 visibility
: self.vis
.clean(cx
),
2860 stability
: self.stab
.clean(cx
),
2861 deprecation
: self.depr
.clean(cx
),
2862 inner
: EnumItem(Enum
{
2863 variants
: self.variants
.clean(cx
),
2864 generics
: self.generics
.clean(cx
),
2865 variants_stripped
: false,
2871 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2872 pub struct Variant
{
2873 pub kind
: VariantKind
,
2876 impl Clean
<Item
> for doctree
::Variant
{
2877 fn clean(&self, cx
: &DocContext
) -> Item
{
2879 name
: Some(self.name
.clean(cx
)),
2880 attrs
: self.attrs
.clean(cx
),
2881 source
: self.whence
.clean(cx
),
2883 stability
: self.stab
.clean(cx
),
2884 deprecation
: self.depr
.clean(cx
),
2885 def_id
: cx
.tcx
.hir
.local_def_id(self.def
.id()),
2886 inner
: VariantItem(Variant
{
2887 kind
: self.def
.clean(cx
),
2893 impl<'tcx
> Clean
<Item
> for ty
::VariantDef
{
2894 fn clean(&self, cx
: &DocContext
) -> Item
{
2895 let kind
= match self.ctor_kind
{
2896 CtorKind
::Const
=> VariantKind
::CLike
,
2899 self.fields
.iter().map(|f
| cx
.tcx
.type_of(f
.did
).clean(cx
)).collect()
2902 CtorKind
::Fictive
=> {
2903 VariantKind
::Struct(VariantStruct
{
2904 struct_type
: doctree
::Plain
,
2905 fields_stripped
: false,
2906 fields
: self.fields
.iter().map(|field
| {
2908 source
: cx
.tcx
.def_span(field
.did
).clean(cx
),
2909 name
: Some(field
.name
.clean(cx
)),
2910 attrs
: cx
.tcx
.get_attrs(field
.did
).clean(cx
),
2911 visibility
: field
.vis
.clean(cx
),
2913 stability
: get_stability(cx
, field
.did
),
2914 deprecation
: get_deprecation(cx
, field
.did
),
2915 inner
: StructFieldItem(cx
.tcx
.type_of(field
.did
).clean(cx
))
2922 name
: Some(self.name
.clean(cx
)),
2923 attrs
: inline
::load_attrs(cx
, self.did
),
2924 source
: cx
.tcx
.def_span(self.did
).clean(cx
),
2925 visibility
: Some(Inherited
),
2927 inner
: VariantItem(Variant { kind: kind }
),
2928 stability
: get_stability(cx
, self.did
),
2929 deprecation
: get_deprecation(cx
, self.did
),
2934 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2935 pub enum VariantKind
{
2938 Struct(VariantStruct
),
2941 impl Clean
<VariantKind
> for hir
::VariantData
{
2942 fn clean(&self, cx
: &DocContext
) -> VariantKind
{
2943 if self.is_struct() {
2944 VariantKind
::Struct(self.clean(cx
))
2945 } else if self.is_unit() {
2948 VariantKind
::Tuple(self.fields().iter().map(|x
| x
.ty
.clean(cx
)).collect())
2953 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2955 pub filename
: FileName
,
2963 pub fn empty() -> Span
{
2965 filename
: FileName
::Anon
,
2966 loline
: 0, locol
: 0,
2967 hiline
: 0, hicol
: 0,
2972 impl Clean
<Span
> for syntax_pos
::Span
{
2973 fn clean(&self, cx
: &DocContext
) -> Span
{
2974 if *self == DUMMY_SP
{
2975 return Span
::empty();
2978 let cm
= cx
.sess().codemap();
2979 let filename
= cm
.span_to_filename(*self);
2980 let lo
= cm
.lookup_char_pos(self.lo());
2981 let hi
= cm
.lookup_char_pos(self.hi());
2985 locol
: lo
.col
.to_usize(),
2987 hicol
: hi
.col
.to_usize(),
2992 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2996 pub segments
: Vec
<PathSegment
>,
3000 pub fn singleton(name
: String
) -> Path
{
3004 segments
: vec
![PathSegment
{
3006 params
: PathParameters
::AngleBracketed
{
3007 lifetimes
: Vec
::new(),
3009 bindings
: Vec
::new()
3015 pub fn last_name(&self) -> &str {
3016 self.segments
.last().unwrap().name
.as_str()
3020 impl Clean
<Path
> for hir
::Path
{
3021 fn clean(&self, cx
: &DocContext
) -> Path
{
3023 global
: self.is_global(),
3025 segments
: if self.is_global() { &self.segments[1..] }
else { &self.segments }
.clean(cx
),
3030 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
3031 pub enum PathParameters
{
3033 lifetimes
: Vec
<Lifetime
>,
3035 bindings
: Vec
<TypeBinding
>,
3039 output
: Option
<Type
>,
3043 impl Clean
<PathParameters
> for hir
::PathParameters
{
3044 fn clean(&self, cx
: &DocContext
) -> PathParameters
{
3045 if self.parenthesized
{
3046 let output
= self.bindings
[0].ty
.clean(cx
);
3047 PathParameters
::Parenthesized
{
3048 inputs
: self.inputs().clean(cx
),
3049 output
: if output
!= Type
::Tuple(Vec
::new()) { Some(output) }
else { None }
3052 PathParameters
::AngleBracketed
{
3053 lifetimes
: if self.lifetimes
.iter().all(|lt
| lt
.is_elided()) {
3056 self.lifetimes
.clean(cx
)
3058 types
: self.types
.clean(cx
),
3059 bindings
: self.bindings
.clean(cx
),
3065 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
3066 pub struct PathSegment
{
3068 pub params
: PathParameters
,
3071 impl Clean
<PathSegment
> for hir
::PathSegment
{
3072 fn clean(&self, cx
: &DocContext
) -> PathSegment
{
3074 name
: self.name
.clean(cx
),
3075 params
: self.with_parameters(|parameters
| parameters
.clean(cx
))
3080 fn qpath_to_string(p
: &hir
::QPath
) -> String
{
3081 let segments
= match *p
{
3082 hir
::QPath
::Resolved(_
, ref path
) => &path
.segments
,
3083 hir
::QPath
::TypeRelative(_
, ref segment
) => return segment
.name
.to_string(),
3086 let mut s
= String
::new();
3087 for (i
, seg
) in segments
.iter().enumerate() {
3091 if seg
.name
!= keywords
::CrateRoot
.name() {
3092 s
.push_str(&*seg
.name
.as_str());
3098 impl Clean
<String
> for ast
::Name
{
3099 fn clean(&self, _
: &DocContext
) -> String
{
3104 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3105 pub struct Typedef
{
3107 pub generics
: Generics
,
3110 impl Clean
<Item
> for doctree
::Typedef
{
3111 fn clean(&self, cx
: &DocContext
) -> Item
{
3113 name
: Some(self.name
.clean(cx
)),
3114 attrs
: self.attrs
.clean(cx
),
3115 source
: self.whence
.clean(cx
),
3116 def_id
: cx
.tcx
.hir
.local_def_id(self.id
.clone()),
3117 visibility
: self.vis
.clean(cx
),
3118 stability
: self.stab
.clean(cx
),
3119 deprecation
: self.depr
.clean(cx
),
3120 inner
: TypedefItem(Typedef
{
3121 type_
: self.ty
.clean(cx
),
3122 generics
: self.gen
.clean(cx
),
3128 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
3129 pub struct BareFunctionDecl
{
3130 pub unsafety
: hir
::Unsafety
,
3131 pub generic_params
: Vec
<GenericParam
>,
3136 impl Clean
<BareFunctionDecl
> for hir
::BareFnTy
{
3137 fn clean(&self, cx
: &DocContext
) -> BareFunctionDecl
{
3139 unsafety
: self.unsafety
,
3140 generic_params
: self.generic_params
.clean(cx
),
3141 decl
: (&*self.decl
, &self.arg_names
[..]).clean(cx
),
3147 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3150 pub mutability
: Mutability
,
3151 /// It's useful to have the value of a static documented, but I have no
3152 /// desire to represent expressions (that'd basically be all of the AST,
3153 /// which is huge!). So, have a string.
3157 impl Clean
<Item
> for doctree
::Static
{
3158 fn clean(&self, cx
: &DocContext
) -> Item
{
3159 debug
!("cleaning static {}: {:?}", self.name
.clean(cx
), self);
3161 name
: Some(self.name
.clean(cx
)),
3162 attrs
: self.attrs
.clean(cx
),
3163 source
: self.whence
.clean(cx
),
3164 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
3165 visibility
: self.vis
.clean(cx
),
3166 stability
: self.stab
.clean(cx
),
3167 deprecation
: self.depr
.clean(cx
),
3168 inner
: StaticItem(Static
{
3169 type_
: self.type_
.clean(cx
),
3170 mutability
: self.mutability
.clean(cx
),
3171 expr
: print_const_expr(cx
, self.expr
),
3177 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3178 pub struct Constant
{
3183 impl Clean
<Item
> for doctree
::Constant
{
3184 fn clean(&self, cx
: &DocContext
) -> Item
{
3186 name
: Some(self.name
.clean(cx
)),
3187 attrs
: self.attrs
.clean(cx
),
3188 source
: self.whence
.clean(cx
),
3189 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
3190 visibility
: self.vis
.clean(cx
),
3191 stability
: self.stab
.clean(cx
),
3192 deprecation
: self.depr
.clean(cx
),
3193 inner
: ConstantItem(Constant
{
3194 type_
: self.type_
.clean(cx
),
3195 expr
: print_const_expr(cx
, self.expr
),
3201 #[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Copy)]
3202 pub enum Mutability
{
3207 impl Clean
<Mutability
> for hir
::Mutability
{
3208 fn clean(&self, _
: &DocContext
) -> Mutability
{
3210 &hir
::MutMutable
=> Mutable
,
3211 &hir
::MutImmutable
=> Immutable
,
3216 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Copy, Debug)]
3217 pub enum ImplPolarity
{
3222 impl Clean
<ImplPolarity
> for hir
::ImplPolarity
{
3223 fn clean(&self, _
: &DocContext
) -> ImplPolarity
{
3225 &hir
::ImplPolarity
::Positive
=> ImplPolarity
::Positive
,
3226 &hir
::ImplPolarity
::Negative
=> ImplPolarity
::Negative
,
3231 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3233 pub unsafety
: hir
::Unsafety
,
3234 pub generics
: Generics
,
3235 pub provided_trait_methods
: FxHashSet
<String
>,
3236 pub trait_
: Option
<Type
>,
3238 pub items
: Vec
<Item
>,
3239 pub polarity
: Option
<ImplPolarity
>,
3242 impl Clean
<Vec
<Item
>> for doctree
::Impl
{
3243 fn clean(&self, cx
: &DocContext
) -> Vec
<Item
> {
3244 let mut ret
= Vec
::new();
3245 let trait_
= self.trait_
.clean(cx
);
3246 let items
= self.items
.clean(cx
);
3248 // If this impl block is an implementation of the Deref trait, then we
3249 // need to try inlining the target's inherent impl blocks as well.
3250 if trait_
.def_id() == cx
.tcx
.lang_items().deref_trait() {
3251 build_deref_target_impls(cx
, &items
, &mut ret
);
3254 let provided
= trait_
.def_id().map(|did
| {
3255 cx
.tcx
.provided_trait_methods(did
)
3257 .map(|meth
| meth
.name
.to_string())
3259 }).unwrap_or(FxHashSet());
3263 attrs
: self.attrs
.clean(cx
),
3264 source
: self.whence
.clean(cx
),
3265 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
3266 visibility
: self.vis
.clean(cx
),
3267 stability
: self.stab
.clean(cx
),
3268 deprecation
: self.depr
.clean(cx
),
3269 inner
: ImplItem(Impl
{
3270 unsafety
: self.unsafety
,
3271 generics
: self.generics
.clean(cx
),
3272 provided_trait_methods
: provided
,
3274 for_
: self.for_
.clean(cx
),
3276 polarity
: Some(self.polarity
.clean(cx
)),
3283 fn build_deref_target_impls(cx
: &DocContext
,
3285 ret
: &mut Vec
<Item
>) {
3286 use self::PrimitiveType
::*;
3290 let target
= match item
.inner
{
3291 TypedefItem(ref t
, true) => &t
.type_
,
3294 let primitive
= match *target
{
3295 ResolvedPath { did, .. }
if did
.is_local() => continue,
3296 ResolvedPath { did, .. }
=> {
3297 ret
.extend(inline
::build_impls(cx
, did
));
3300 _
=> match target
.primitive_type() {
3305 let did
= match primitive
{
3306 Isize
=> tcx
.lang_items().isize_impl(),
3307 I8
=> tcx
.lang_items().i8_impl(),
3308 I16
=> tcx
.lang_items().i16_impl(),
3309 I32
=> tcx
.lang_items().i32_impl(),
3310 I64
=> tcx
.lang_items().i64_impl(),
3311 I128
=> tcx
.lang_items().i128_impl(),
3312 Usize
=> tcx
.lang_items().usize_impl(),
3313 U8
=> tcx
.lang_items().u8_impl(),
3314 U16
=> tcx
.lang_items().u16_impl(),
3315 U32
=> tcx
.lang_items().u32_impl(),
3316 U64
=> tcx
.lang_items().u64_impl(),
3317 U128
=> tcx
.lang_items().u128_impl(),
3318 F32
=> tcx
.lang_items().f32_impl(),
3319 F64
=> tcx
.lang_items().f64_impl(),
3320 Char
=> tcx
.lang_items().char_impl(),
3322 Str
=> tcx
.lang_items().str_impl(),
3323 Slice
=> tcx
.lang_items().slice_impl(),
3324 Array
=> tcx
.lang_items().slice_impl(),
3327 RawPointer
=> tcx
.lang_items().const_ptr_impl(),
3332 if let Some(did
) = did
{
3333 if !did
.is_local() {
3334 inline
::build_impl(cx
, did
, ret
);
3340 impl Clean
<Item
> for doctree
::ExternCrate
{
3341 fn clean(&self, cx
: &DocContext
) -> Item
{
3344 attrs
: self.attrs
.clean(cx
),
3345 source
: self.whence
.clean(cx
),
3346 def_id
: DefId { krate: self.cnum, index: CRATE_DEF_INDEX }
,
3347 visibility
: self.vis
.clean(cx
),
3350 inner
: ExternCrateItem(self.name
.clean(cx
), self.path
.clone())
3355 impl Clean
<Vec
<Item
>> for doctree
::Import
{
3356 fn clean(&self, cx
: &DocContext
) -> Vec
<Item
> {
3357 // We consider inlining the documentation of `pub use` statements, but we
3358 // forcefully don't inline if this is not public or if the
3359 // #[doc(no_inline)] attribute is present.
3360 // Don't inline doc(hidden) imports so they can be stripped at a later stage.
3361 let denied
= self.vis
!= hir
::Public
|| self.attrs
.iter().any(|a
| {
3362 a
.name().unwrap() == "doc" && match a
.meta_item_list() {
3363 Some(l
) => attr
::list_contains_name(&l
, "no_inline") ||
3364 attr
::list_contains_name(&l
, "hidden"),
3368 let path
= self.path
.clean(cx
);
3369 let inner
= if self.glob
{
3370 Import
::Glob(resolve_use_source(cx
, path
))
3372 let name
= self.name
;
3374 if let Some(items
) = inline
::try_inline(cx
, path
.def
, name
) {
3378 Import
::Simple(name
.clean(cx
), resolve_use_source(cx
, path
))
3382 attrs
: self.attrs
.clean(cx
),
3383 source
: self.whence
.clean(cx
),
3384 def_id
: cx
.tcx
.hir
.local_def_id(ast
::CRATE_NODE_ID
),
3385 visibility
: self.vis
.clean(cx
),
3388 inner
: ImportItem(inner
)
3393 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3395 // use source as str;
3396 Simple(String
, ImportSource
),
3401 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3402 pub struct ImportSource
{
3404 pub did
: Option
<DefId
>,
3407 impl Clean
<Vec
<Item
>> for hir
::ForeignMod
{
3408 fn clean(&self, cx
: &DocContext
) -> Vec
<Item
> {
3409 let mut items
= self.items
.clean(cx
);
3410 for item
in &mut items
{
3411 if let ForeignFunctionItem(ref mut f
) = item
.inner
{
3419 impl Clean
<Item
> for hir
::ForeignItem
{
3420 fn clean(&self, cx
: &DocContext
) -> Item
{
3421 let inner
= match self.node
{
3422 hir
::ForeignItemFn(ref decl
, ref names
, ref generics
) => {
3423 ForeignFunctionItem(Function
{
3424 decl
: (&**decl
, &names
[..]).clean(cx
),
3425 generics
: generics
.clean(cx
),
3426 unsafety
: hir
::Unsafety
::Unsafe
,
3428 constness
: hir
::Constness
::NotConst
,
3431 hir
::ForeignItemStatic(ref ty
, mutbl
) => {
3432 ForeignStaticItem(Static
{
3433 type_
: ty
.clean(cx
),
3434 mutability
: if mutbl {Mutable}
else {Immutable}
,
3435 expr
: "".to_string(),
3438 hir
::ForeignItemType
=> {
3443 name
: Some(self.name
.clean(cx
)),
3444 attrs
: self.attrs
.clean(cx
),
3445 source
: self.span
.clean(cx
),
3446 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
3447 visibility
: self.vis
.clean(cx
),
3448 stability
: get_stability(cx
, cx
.tcx
.hir
.local_def_id(self.id
)),
3449 deprecation
: get_deprecation(cx
, cx
.tcx
.hir
.local_def_id(self.id
)),
3458 fn to_src(&self, cx
: &DocContext
) -> String
;
3461 impl ToSource
for syntax_pos
::Span
{
3462 fn to_src(&self, cx
: &DocContext
) -> String
{
3463 debug
!("converting span {:?} to snippet", self.clean(cx
));
3464 let sn
= match cx
.sess().codemap().span_to_snippet(*self) {
3465 Ok(x
) => x
.to_string(),
3466 Err(_
) => "".to_string()
3468 debug
!("got snippet {}", sn
);
3473 fn name_from_pat(p
: &hir
::Pat
) -> String
{
3475 debug
!("Trying to get a name from pattern: {:?}", p
);
3478 PatKind
::Wild
=> "_".to_string(),
3479 PatKind
::Binding(_
, _
, ref p
, _
) => p
.node
.to_string(),
3480 PatKind
::TupleStruct(ref p
, ..) | PatKind
::Path(ref p
) => qpath_to_string(p
),
3481 PatKind
::Struct(ref name
, ref fields
, etc
) => {
3482 format
!("{} {{ {}{} }}", qpath_to_string(name
),
3483 fields
.iter().map(|&Spanned { node: ref fp, .. }
|
3484 format
!("{}: {}", fp
.name
, name_from_pat(&*fp
.pat
)))
3485 .collect
::<Vec
<String
>>().join(", "),
3486 if etc { ", ..." }
else { "" }
3489 PatKind
::Tuple(ref elts
, _
) => format
!("({})", elts
.iter().map(|p
| name_from_pat(&**p
))
3490 .collect
::<Vec
<String
>>().join(", ")),
3491 PatKind
::Box(ref p
) => name_from_pat(&**p
),
3492 PatKind
::Ref(ref p
, _
) => name_from_pat(&**p
),
3493 PatKind
::Lit(..) => {
3494 warn
!("tried to get argument name from PatKind::Lit, \
3495 which is silly in function arguments");
3498 PatKind
::Range(..) => panic
!("tried to get argument name from PatKind::Range, \
3499 which is not allowed in function arguments"),
3500 PatKind
::Slice(ref begin
, ref mid
, ref end
) => {
3501 let begin
= begin
.iter().map(|p
| name_from_pat(&**p
));
3502 let mid
= mid
.as_ref().map(|p
| format
!("..{}", name_from_pat(&**p
))).into_iter();
3503 let end
= end
.iter().map(|p
| name_from_pat(&**p
));
3504 format
!("[{}]", begin
.chain(mid
).chain(end
).collect
::<Vec
<_
>>().join(", "))
3509 fn print_const_expr(cx
: &DocContext
, body
: hir
::BodyId
) -> String
{
3510 cx
.tcx
.hir
.node_to_pretty_string(body
.node_id
)
3513 /// Given a type Path, resolve it to a Type using the TyCtxt
3514 fn resolve_type(cx
: &DocContext
,
3516 id
: ast
::NodeId
) -> Type
{
3517 debug
!("resolve_type({:?},{:?})", path
, id
);
3519 let is_generic
= match path
.def
{
3520 Def
::PrimTy(p
) => match p
{
3521 hir
::TyStr
=> return Primitive(PrimitiveType
::Str
),
3522 hir
::TyBool
=> return Primitive(PrimitiveType
::Bool
),
3523 hir
::TyChar
=> return Primitive(PrimitiveType
::Char
),
3524 hir
::TyInt(int_ty
) => return Primitive(int_ty
.into()),
3525 hir
::TyUint(uint_ty
) => return Primitive(uint_ty
.into()),
3526 hir
::TyFloat(float_ty
) => return Primitive(float_ty
.into()),
3528 Def
::SelfTy(..) if path
.segments
.len() == 1 => {
3529 return Generic(keywords
::SelfType
.name().to_string());
3531 Def
::TyParam(..) if path
.segments
.len() == 1 => {
3532 return Generic(format
!("{:#}", path
));
3534 Def
::SelfTy(..) | Def
::TyParam(..) | Def
::AssociatedTy(..) => true,
3537 let did
= register_def(&*cx
, path
.def
);
3538 ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
3541 fn register_def(cx
: &DocContext
, def
: Def
) -> DefId
{
3542 debug
!("register_def({:?})", def
);
3544 let (did
, kind
) = match def
{
3545 Def
::Fn(i
) => (i
, TypeKind
::Function
),
3546 Def
::TyAlias(i
) => (i
, TypeKind
::Typedef
),
3547 Def
::Enum(i
) => (i
, TypeKind
::Enum
),
3548 Def
::Trait(i
) => (i
, TypeKind
::Trait
),
3549 Def
::Struct(i
) => (i
, TypeKind
::Struct
),
3550 Def
::Union(i
) => (i
, TypeKind
::Union
),
3551 Def
::Mod(i
) => (i
, TypeKind
::Module
),
3552 Def
::TyForeign(i
) => (i
, TypeKind
::Foreign
),
3553 Def
::Static(i
, _
) => (i
, TypeKind
::Static
),
3554 Def
::Variant(i
) => (cx
.tcx
.parent_def_id(i
).unwrap(), TypeKind
::Enum
),
3555 Def
::Macro(i
, _
) => (i
, TypeKind
::Macro
),
3556 Def
::SelfTy(Some(def_id
), _
) => (def_id
, TypeKind
::Trait
),
3557 Def
::SelfTy(_
, Some(impl_def_id
)) => {
3560 _
=> return def
.def_id()
3562 if did
.is_local() { return did }
3563 inline
::record_extern_fqn(cx
, did
, kind
);
3564 if let TypeKind
::Trait
= kind
{
3565 inline
::record_extern_trait(cx
, did
);
3570 fn resolve_use_source(cx
: &DocContext
, path
: Path
) -> ImportSource
{
3572 did
: if path
.def
== Def
::Err
{
3575 Some(register_def(cx
, path
.def
))
3581 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3584 pub imported_from
: Option
<String
>,
3587 impl Clean
<Item
> for doctree
::Macro
{
3588 fn clean(&self, cx
: &DocContext
) -> Item
{
3589 let name
= self.name
.clean(cx
);
3591 name
: Some(name
.clone()),
3592 attrs
: self.attrs
.clean(cx
),
3593 source
: self.whence
.clean(cx
),
3594 visibility
: Some(Public
),
3595 stability
: self.stab
.clean(cx
),
3596 deprecation
: self.depr
.clean(cx
),
3597 def_id
: self.def_id
,
3598 inner
: MacroItem(Macro
{
3599 source
: format
!("macro_rules! {} {{\n{}}}",
3601 self.matchers
.iter().map(|span
| {
3602 format
!(" {} => {{ ... }};\n", span
.to_src(cx
))
3603 }).collect
::<String
>()),
3604 imported_from
: self.imported_from
.clean(cx
),
3610 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3611 pub struct Stability
{
3612 pub level
: stability
::StabilityLevel
,
3613 pub feature
: String
,
3615 pub deprecated_since
: String
,
3616 pub deprecated_reason
: String
,
3617 pub unstable_reason
: String
,
3618 pub issue
: Option
<u32>
3621 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3622 pub struct Deprecation
{
3627 impl Clean
<Stability
> for attr
::Stability
{
3628 fn clean(&self, _
: &DocContext
) -> Stability
{
3630 level
: stability
::StabilityLevel
::from_attr_level(&self.level
),
3631 feature
: self.feature
.to_string(),
3632 since
: match self.level
{
3633 attr
::Stable {ref since}
=> since
.to_string(),
3634 _
=> "".to_string(),
3636 deprecated_since
: match self.rustc_depr
{
3637 Some(attr
::RustcDeprecation {ref since, ..}
) => since
.to_string(),
3640 deprecated_reason
: match self.rustc_depr
{
3641 Some(ref depr
) => depr
.reason
.to_string(),
3642 _
=> "".to_string(),
3644 unstable_reason
: match self.level
{
3645 attr
::Unstable { reason: Some(ref reason), .. }
=> reason
.to_string(),
3646 _
=> "".to_string(),
3648 issue
: match self.level
{
3649 attr
::Unstable {issue, ..}
=> Some(issue
),
3656 impl<'a
> Clean
<Stability
> for &'a attr
::Stability
{
3657 fn clean(&self, dc
: &DocContext
) -> Stability
{
3662 impl Clean
<Deprecation
> for attr
::Deprecation
{
3663 fn clean(&self, _
: &DocContext
) -> Deprecation
{
3665 since
: self.since
.as_ref().map_or("".to_string(), |s
| s
.to_string()),
3666 note
: self.note
.as_ref().map_or("".to_string(), |s
| s
.to_string()),
3671 /// An equality constraint on an associated type, e.g. `A=Bar` in `Foo<A=Bar>`
3672 #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Debug)]
3673 pub struct TypeBinding
{
3678 impl Clean
<TypeBinding
> for hir
::TypeBinding
{
3679 fn clean(&self, cx
: &DocContext
) -> TypeBinding
{
3681 name
: self.name
.clean(cx
),
3682 ty
: self.ty
.clean(cx
)