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 rustc_target
::spec
::abi
::Abi
;
24 use syntax
::ast
::{self, AttrStyle, Ident}
;
26 use syntax
::codemap
::{dummy_spanned, Spanned}
;
27 use syntax
::feature_gate
::UnstableFeatures
;
29 use syntax
::symbol
::keywords
;
30 use syntax
::symbol
::{Symbol, InternedString}
;
31 use syntax_pos
::{self, DUMMY_SP, Pos, FileName}
;
33 use rustc
::middle
::const_val
::ConstVal
;
34 use rustc
::middle
::privacy
::AccessLevels
;
35 use rustc
::middle
::resolve_lifetime
as rl
;
36 use rustc
::ty
::fold
::TypeFolder
;
37 use rustc
::middle
::lang_items
;
38 use rustc
::mir
::interpret
::GlobalId
;
39 use rustc
::hir
::{self, HirVec}
;
40 use rustc
::hir
::def
::{self, Def, CtorKind}
;
41 use rustc
::hir
::def_id
::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}
;
42 use rustc
::hir
::def_id
::DefIndexAddressSpace
;
44 use rustc
::ty
::subst
::Substs
;
45 use rustc
::ty
::{self, TyCtxt, Region, RegionVid, Ty, AdtKind}
;
46 use rustc
::middle
::stability
;
47 use rustc
::util
::nodemap
::{FxHashMap, FxHashSet}
;
48 use rustc_typeck
::hir_ty_to_ty
;
49 use rustc
::infer
::{InferCtxt, RegionObligation}
;
50 use rustc
::infer
::region_constraints
::{RegionConstraintData, Constraint}
;
52 use std
::collections
::hash_map
::Entry
;
53 use std
::collections
::VecDeque
;
56 use std
::default::Default
;
57 use std
::{mem, slice, vec}
;
58 use std
::iter
::{FromIterator, once}
;
59 use rustc_data_structures
::sync
::Lrc
;
61 use std
::cell
::RefCell
;
65 use core
::{self, DocContext}
;
68 use html
::render
::{cache, ExternalLocation}
;
69 use html
::item_type
::ItemType
;
70 use html
::markdown
::markdown_links
;
78 use self::auto_trait
::AutoTraitFinder
;
80 thread_local
!(static MAX_DEF_ID
: RefCell
<FxHashMap
<CrateNum
, DefId
>> = RefCell
::new(FxHashMap()));
82 const FN_OUTPUT_NAME
: &'
static str = "Output";
84 // extract the stability index for a node from tcx, if possible
85 fn get_stability(cx
: &DocContext
, def_id
: DefId
) -> Option
<Stability
> {
86 cx
.tcx
.lookup_stability(def_id
).clean(cx
)
89 fn get_deprecation(cx
: &DocContext
, def_id
: DefId
) -> Option
<Deprecation
> {
90 cx
.tcx
.lookup_deprecation(def_id
).clean(cx
)
94 fn clean(&self, cx
: &DocContext
) -> T
;
97 impl<T
: Clean
<U
>, U
> Clean
<Vec
<U
>> for [T
] {
98 fn clean(&self, cx
: &DocContext
) -> Vec
<U
> {
99 self.iter().map(|x
| x
.clean(cx
)).collect()
103 impl<T
: Clean
<U
>, U
> Clean
<U
> for P
<T
> {
104 fn clean(&self, cx
: &DocContext
) -> U
{
109 impl<T
: Clean
<U
>, U
> Clean
<U
> for Rc
<T
> {
110 fn clean(&self, cx
: &DocContext
) -> U
{
115 impl<T
: Clean
<U
>, U
> Clean
<Option
<U
>> for Option
<T
> {
116 fn clean(&self, cx
: &DocContext
) -> Option
<U
> {
117 self.as_ref().map(|v
| v
.clean(cx
))
121 impl<T
, U
> Clean
<U
> for ty
::Binder
<T
> where T
: Clean
<U
> {
122 fn clean(&self, cx
: &DocContext
) -> U
{
123 self.skip_binder().clean(cx
)
127 impl<T
: Clean
<U
>, U
> Clean
<Vec
<U
>> for P
<[T
]> {
128 fn clean(&self, cx
: &DocContext
) -> Vec
<U
> {
129 self.iter().map(|x
| x
.clean(cx
)).collect()
133 #[derive(Clone, Debug)]
136 pub version
: Option
<String
>,
138 pub module
: Option
<Item
>,
139 pub externs
: Vec
<(CrateNum
, ExternalCrate
)>,
140 pub primitives
: Vec
<(DefId
, PrimitiveType
, Attributes
)>,
141 pub access_levels
: Arc
<AccessLevels
<DefId
>>,
142 // These are later on moved into `CACHEKEY`, leaving the map empty.
143 // Only here so that they can be filtered through the rustdoc passes.
144 pub external_traits
: FxHashMap
<DefId
, Trait
>,
145 pub masked_crates
: FxHashSet
<CrateNum
>,
148 impl<'a
, 'tcx
, 'rcx
> Clean
<Crate
> for visit_ast
::RustdocVisitor
<'a
, 'tcx
, 'rcx
> {
149 fn clean(&self, cx
: &DocContext
) -> Crate
{
150 use ::visit_lib
::LibEmbargoVisitor
;
153 let mut r
= cx
.renderinfo
.borrow_mut();
154 r
.deref_trait_did
= cx
.tcx
.lang_items().deref_trait();
155 r
.deref_mut_trait_did
= cx
.tcx
.lang_items().deref_mut_trait();
156 r
.owned_box_did
= cx
.tcx
.lang_items().owned_box();
159 let mut externs
= Vec
::new();
160 for &cnum
in cx
.tcx
.crates().iter() {
161 externs
.push((cnum
, cnum
.clean(cx
)));
162 // Analyze doc-reachability for extern items
163 LibEmbargoVisitor
::new(cx
).visit_lib(cnum
);
165 externs
.sort_by(|&(a
, _
), &(b
, _
)| a
.cmp(&b
));
167 // Clean the crate, translating the entire libsyntax AST to one that is
168 // understood by rustdoc.
169 let mut module
= self.module
.clean(cx
);
170 let mut masked_crates
= FxHashSet();
173 ModuleItem(ref module
) => {
174 for it
in &module
.items
{
175 if it
.is_extern_crate() && it
.attrs
.has_doc_flag("masked") {
176 masked_crates
.insert(it
.def_id
.krate
);
183 let ExternalCrate { name, src, primitives, .. }
= LOCAL_CRATE
.clean(cx
);
185 let m
= match module
.inner
{
186 ModuleItem(ref mut m
) => m
,
189 m
.items
.extend(primitives
.iter().map(|&(def_id
, prim
, ref attrs
)| {
191 source
: Span
::empty(),
192 name
: Some(prim
.to_url_str().to_string()),
193 attrs
: attrs
.clone(),
194 visibility
: Some(Public
),
195 stability
: get_stability(cx
, def_id
),
196 deprecation
: get_deprecation(cx
, def_id
),
198 inner
: PrimitiveItem(prim
),
203 let mut access_levels
= cx
.access_levels
.borrow_mut();
204 let mut external_traits
= cx
.external_traits
.borrow_mut();
210 module
: Some(module
),
213 access_levels
: Arc
::new(mem
::replace(&mut access_levels
, Default
::default())),
214 external_traits
: mem
::replace(&mut external_traits
, Default
::default()),
220 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
221 pub struct ExternalCrate
{
224 pub attrs
: Attributes
,
225 pub primitives
: Vec
<(DefId
, PrimitiveType
, Attributes
)>,
228 impl Clean
<ExternalCrate
> for CrateNum
{
229 fn clean(&self, cx
: &DocContext
) -> ExternalCrate
{
230 let root
= DefId { krate: *self, index: CRATE_DEF_INDEX }
;
231 let krate_span
= cx
.tcx
.def_span(root
);
232 let krate_src
= cx
.sess().codemap().span_to_filename(krate_span
);
234 // Collect all inner modules which are tagged as implementations of
237 // Note that this loop only searches the top-level items of the crate,
238 // and this is intentional. If we were to search the entire crate for an
239 // item tagged with `#[doc(primitive)]` then we would also have to
240 // search the entirety of external modules for items tagged
241 // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
242 // all that metadata unconditionally).
244 // In order to keep the metadata load under control, the
245 // `#[doc(primitive)]` feature is explicitly designed to only allow the
246 // primitive tags to show up as the top level items in a crate.
248 // Also note that this does not attempt to deal with modules tagged
249 // duplicately for the same primitive. This is handled later on when
250 // rendering by delegating everything to a hash map.
251 let as_primitive
= |def
: Def
| {
252 if let Def
::Mod(def_id
) = def
{
253 let attrs
= cx
.tcx
.get_attrs(def_id
).clean(cx
);
255 for attr
in attrs
.lists("doc") {
256 if let Some(v
) = attr
.value_str() {
257 if attr
.check_name("primitive") {
258 prim
= PrimitiveType
::from_str(&v
.as_str());
262 // FIXME: should warn on unknown primitives?
266 return prim
.map(|p
| (def_id
, p
, attrs
));
270 let primitives
= if root
.is_local() {
271 cx
.tcx
.hir
.krate().module
.item_ids
.iter().filter_map(|&id
| {
272 let item
= cx
.tcx
.hir
.expect_item(id
.id
);
275 as_primitive(Def
::Mod(cx
.tcx
.hir
.local_def_id(id
.id
)))
277 hir
::ItemUse(ref path
, hir
::UseKind
::Single
)
278 if item
.vis
== hir
::Visibility
::Public
=> {
279 as_primitive(path
.def
).map(|(_
, prim
, attrs
)| {
280 // Pretend the primitive is local.
281 (cx
.tcx
.hir
.local_def_id(id
.id
), prim
, attrs
)
288 cx
.tcx
.item_children(root
).iter().map(|item
| item
.def
)
289 .filter_map(as_primitive
).collect()
293 name
: cx
.tcx
.crate_name(*self).to_string(),
295 attrs
: cx
.tcx
.get_attrs(root
).clean(cx
),
301 /// Anything with a source location and set of attributes and, optionally, a
302 /// name. That is, anything that can be documented. This doesn't correspond
303 /// directly to the AST's concept of an item; it's a strict superset.
304 #[derive(Clone, RustcEncodable, RustcDecodable)]
308 /// Not everything has a name. E.g., impls
309 pub name
: Option
<String
>,
310 pub attrs
: Attributes
,
312 pub visibility
: Option
<Visibility
>,
314 pub stability
: Option
<Stability
>,
315 pub deprecation
: Option
<Deprecation
>,
318 impl fmt
::Debug
for Item
{
319 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
321 let fake
= MAX_DEF_ID
.with(|m
| m
.borrow().get(&self.def_id
.krate
)
322 .map(|id
| self.def_id
>= *id
).unwrap_or(false));
323 let def_id
: &fmt
::Debug
= if fake { &"**FAKE**" }
else { &self.def_id }
;
325 fmt
.debug_struct("Item")
326 .field("source", &self.source
)
327 .field("name", &self.name
)
328 .field("attrs", &self.attrs
)
329 .field("inner", &self.inner
)
330 .field("visibility", &self.visibility
)
331 .field("def_id", def_id
)
332 .field("stability", &self.stability
)
333 .field("deprecation", &self.deprecation
)
339 /// Finds the `doc` attribute as a NameValue and returns the corresponding
341 pub fn doc_value
<'a
>(&'a
self) -> Option
<&'a
str> {
342 self.attrs
.doc_value()
344 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
346 pub fn collapsed_doc_value(&self) -> Option
<String
> {
347 self.attrs
.collapsed_doc_value()
350 pub fn links(&self) -> Vec
<(String
, String
)> {
351 self.attrs
.links(&self.def_id
.krate
)
354 pub fn is_crate(&self) -> bool
{
356 StrippedItem(box ModuleItem(Module { is_crate: true, ..}
)) |
357 ModuleItem(Module { is_crate: true, ..}
) => true,
361 pub fn is_mod(&self) -> bool
{
362 self.type_() == ItemType
::Module
364 pub fn is_trait(&self) -> bool
{
365 self.type_() == ItemType
::Trait
367 pub fn is_struct(&self) -> bool
{
368 self.type_() == ItemType
::Struct
370 pub fn is_enum(&self) -> bool
{
371 self.type_() == ItemType
::Enum
373 pub fn is_fn(&self) -> bool
{
374 self.type_() == ItemType
::Function
376 pub fn is_associated_type(&self) -> bool
{
377 self.type_() == ItemType
::AssociatedType
379 pub fn is_associated_const(&self) -> bool
{
380 self.type_() == ItemType
::AssociatedConst
382 pub fn is_method(&self) -> bool
{
383 self.type_() == ItemType
::Method
385 pub fn is_ty_method(&self) -> bool
{
386 self.type_() == ItemType
::TyMethod
388 pub fn is_typedef(&self) -> bool
{
389 self.type_() == ItemType
::Typedef
391 pub fn is_primitive(&self) -> bool
{
392 self.type_() == ItemType
::Primitive
394 pub fn is_union(&self) -> bool
{
395 self.type_() == ItemType
::Union
397 pub fn is_import(&self) -> bool
{
398 self.type_() == ItemType
::Import
400 pub fn is_extern_crate(&self) -> bool
{
401 self.type_() == ItemType
::ExternCrate
404 pub fn is_stripped(&self) -> bool
{
405 match self.inner { StrippedItem(..) => true, _ => false }
407 pub fn has_stripped_fields(&self) -> Option
<bool
> {
409 StructItem(ref _struct
) => Some(_struct
.fields_stripped
),
410 UnionItem(ref union) => Some(union.fields_stripped
),
411 VariantItem(Variant { kind: VariantKind::Struct(ref vstruct)}
) => {
412 Some(vstruct
.fields_stripped
)
418 pub fn stability_class(&self) -> Option
<String
> {
419 self.stability
.as_ref().and_then(|ref s
| {
420 let mut classes
= Vec
::with_capacity(2);
422 if s
.level
== stability
::Unstable
{
423 classes
.push("unstable");
426 if !s
.deprecated_since
.is_empty() {
427 classes
.push("deprecated");
430 if classes
.len() != 0 {
431 Some(classes
.join(" "))
438 pub fn stable_since(&self) -> Option
<&str> {
439 self.stability
.as_ref().map(|s
| &s
.since
[..])
442 /// Returns a documentation-level item type from the item.
443 pub fn type_(&self) -> ItemType
{
448 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
450 ExternCrateItem(String
, Option
<String
>),
455 FunctionItem(Function
),
457 TypedefItem(Typedef
, bool
/* is associated type */),
459 ConstantItem(Constant
),
462 /// A method signature only. Used for required methods in traits (ie,
463 /// non-default-methods).
464 TyMethodItem(TyMethod
),
465 /// A method with a body.
467 StructFieldItem(Type
),
468 VariantItem(Variant
),
469 /// `fn`s from an extern block
470 ForeignFunctionItem(Function
),
471 /// `static`s from an extern block
472 ForeignStaticItem(Static
),
473 /// `type`s from an extern block
476 PrimitiveItem(PrimitiveType
),
477 AssociatedConstItem(Type
, Option
<String
>),
478 AssociatedTypeItem(Vec
<TyParamBound
>, Option
<Type
>),
479 /// An item that has been stripped by a rustdoc pass
480 StrippedItem(Box
<ItemEnum
>),
484 pub fn generics(&self) -> Option
<&Generics
> {
486 ItemEnum
::StructItem(ref s
) => &s
.generics
,
487 ItemEnum
::EnumItem(ref e
) => &e
.generics
,
488 ItemEnum
::FunctionItem(ref f
) => &f
.generics
,
489 ItemEnum
::TypedefItem(ref t
, _
) => &t
.generics
,
490 ItemEnum
::TraitItem(ref t
) => &t
.generics
,
491 ItemEnum
::ImplItem(ref i
) => &i
.generics
,
492 ItemEnum
::TyMethodItem(ref i
) => &i
.generics
,
493 ItemEnum
::MethodItem(ref i
) => &i
.generics
,
494 ItemEnum
::ForeignFunctionItem(ref f
) => &f
.generics
,
500 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
502 pub items
: Vec
<Item
>,
506 impl Clean
<Item
> for doctree
::Module
{
507 fn clean(&self, cx
: &DocContext
) -> Item
{
508 let name
= if self.name
.is_some() {
509 self.name
.unwrap().clean(cx
)
514 // maintain a stack of mod ids, for doc comment path resolution
515 // but we also need to resolve the module's own docs based on whether its docs were written
516 // inside or outside the module, so check for that
517 let attrs
= if self.attrs
.iter()
518 .filter(|a
| a
.check_name("doc"))
520 .map_or(true, |a
| a
.style
== AttrStyle
::Inner
) {
521 // inner doc comment, use the module's own scope for resolution
522 cx
.mod_ids
.borrow_mut().push(self.id
);
525 // outer doc comment, use its parent's scope
526 let attrs
= self.attrs
.clean(cx
);
527 cx
.mod_ids
.borrow_mut().push(self.id
);
531 let mut items
: Vec
<Item
> = vec
![];
532 items
.extend(self.extern_crates
.iter().map(|x
| x
.clean(cx
)));
533 items
.extend(self.imports
.iter().flat_map(|x
| x
.clean(cx
)));
534 items
.extend(self.structs
.iter().flat_map(|x
| x
.clean(cx
)));
535 items
.extend(self.unions
.iter().flat_map(|x
| x
.clean(cx
)));
536 items
.extend(self.enums
.iter().flat_map(|x
| x
.clean(cx
)));
537 items
.extend(self.fns
.iter().map(|x
| x
.clean(cx
)));
538 items
.extend(self.foreigns
.iter().flat_map(|x
| x
.clean(cx
)));
539 items
.extend(self.mods
.iter().map(|x
| x
.clean(cx
)));
540 items
.extend(self.typedefs
.iter().map(|x
| x
.clean(cx
)));
541 items
.extend(self.statics
.iter().map(|x
| x
.clean(cx
)));
542 items
.extend(self.constants
.iter().map(|x
| x
.clean(cx
)));
543 items
.extend(self.traits
.iter().map(|x
| x
.clean(cx
)));
544 items
.extend(self.impls
.iter().flat_map(|x
| x
.clean(cx
)));
545 items
.extend(self.macros
.iter().map(|x
| x
.clean(cx
)));
547 cx
.mod_ids
.borrow_mut().pop();
549 // determine if we should display the inner contents or
550 // the outer `mod` item for the source code.
552 let cm
= cx
.sess().codemap();
553 let outer
= cm
.lookup_char_pos(self.where_outer
.lo());
554 let inner
= cm
.lookup_char_pos(self.where_inner
.lo());
555 if outer
.file
.start_pos
== inner
.file
.start_pos
{
559 // mod foo; (and a separate FileMap for the contents)
567 source
: whence
.clean(cx
),
568 visibility
: self.vis
.clean(cx
),
569 stability
: self.stab
.clean(cx
),
570 deprecation
: self.depr
.clean(cx
),
571 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
572 inner
: ModuleItem(Module
{
573 is_crate
: self.is_crate
,
580 pub struct ListAttributesIter
<'a
> {
581 attrs
: slice
::Iter
<'a
, ast
::Attribute
>,
582 current_list
: vec
::IntoIter
<ast
::NestedMetaItem
>,
586 impl<'a
> Iterator
for ListAttributesIter
<'a
> {
587 type Item
= ast
::NestedMetaItem
;
589 fn next(&mut self) -> Option
<Self::Item
> {
590 if let Some(nested
) = self.current_list
.next() {
594 for attr
in &mut self.attrs
{
595 if let Some(list
) = attr
.meta_item_list() {
596 if attr
.check_name(self.name
) {
597 self.current_list
= list
.into_iter();
598 if let Some(nested
) = self.current_list
.next() {
608 fn size_hint(&self) -> (usize, Option
<usize>) {
609 let lower
= self.current_list
.len();
614 pub trait AttributesExt
{
615 /// Finds an attribute as List and returns the list of attributes nested inside.
616 fn lists
<'a
>(&'a
self, name
: &'a
str) -> ListAttributesIter
<'a
>;
619 impl AttributesExt
for [ast
::Attribute
] {
620 fn lists
<'a
>(&'a
self, name
: &'a
str) -> ListAttributesIter
<'a
> {
623 current_list
: Vec
::new().into_iter(),
629 pub trait NestedAttributesExt
{
630 /// Returns whether the attribute list contains a specific `Word`
631 fn has_word(self, word
: &str) -> bool
;
634 impl<I
: IntoIterator
<Item
=ast
::NestedMetaItem
>> NestedAttributesExt
for I
{
635 fn has_word(self, word
: &str) -> bool
{
636 self.into_iter().any(|attr
| attr
.is_word() && attr
.check_name(word
))
640 /// A portion of documentation, extracted from a `#[doc]` attribute.
642 /// Each variant contains the line number within the complete doc-comment where the fragment
643 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
645 /// Included files are kept separate from inline doc comments so that proper line-number
646 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
647 /// kept separate because of issue #42760.
648 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
649 pub enum DocFragment
{
650 // FIXME #44229 (misdreavus): sugared and raw doc comments can be brought back together once
651 // hoedown is completely removed from rustdoc.
652 /// A doc fragment created from a `///` or `//!` doc comment.
653 SugaredDoc(usize, syntax_pos
::Span
, String
),
654 /// A doc fragment created from a "raw" `#[doc=""]` attribute.
655 RawDoc(usize, syntax_pos
::Span
, String
),
656 /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
657 /// given filename and the file contents.
658 Include(usize, syntax_pos
::Span
, String
, String
),
662 pub fn as_str(&self) -> &str {
664 DocFragment
::SugaredDoc(_
, _
, ref s
) => &s
[..],
665 DocFragment
::RawDoc(_
, _
, ref s
) => &s
[..],
666 DocFragment
::Include(_
, _
, _
, ref s
) => &s
[..],
670 pub fn span(&self) -> syntax_pos
::Span
{
672 DocFragment
::SugaredDoc(_
, span
, _
) |
673 DocFragment
::RawDoc(_
, span
, _
) |
674 DocFragment
::Include(_
, span
, _
, _
) => span
,
679 impl<'a
> FromIterator
<&'a DocFragment
> for String
{
680 fn from_iter
<T
>(iter
: T
) -> Self
682 T
: IntoIterator
<Item
= &'a DocFragment
>
684 iter
.into_iter().fold(String
::new(), |mut acc
, frag
| {
689 DocFragment
::SugaredDoc(_
, _
, ref docs
)
690 | DocFragment
::RawDoc(_
, _
, ref docs
)
691 | DocFragment
::Include(_
, _
, _
, ref docs
) =>
700 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Default, Hash)]
701 pub struct Attributes
{
702 pub doc_strings
: Vec
<DocFragment
>,
703 pub other_attrs
: Vec
<ast
::Attribute
>,
704 pub cfg
: Option
<Rc
<Cfg
>>,
705 pub span
: Option
<syntax_pos
::Span
>,
706 /// map from Rust paths to resolved defs and potential URL fragments
707 pub links
: Vec
<(String
, Option
<DefId
>, Option
<String
>)>,
711 /// Extracts the content from an attribute `#[doc(cfg(content))]`.
712 fn extract_cfg(mi
: &ast
::MetaItem
) -> Option
<&ast
::MetaItem
> {
713 use syntax
::ast
::NestedMetaItemKind
::MetaItem
;
715 if let ast
::MetaItemKind
::List(ref nmis
) = mi
.node
{
717 if let MetaItem(ref cfg_mi
) = nmis
[0].node
{
718 if cfg_mi
.check_name("cfg") {
719 if let ast
::MetaItemKind
::List(ref cfg_nmis
) = cfg_mi
.node
{
720 if cfg_nmis
.len() == 1 {
721 if let MetaItem(ref content_mi
) = cfg_nmis
[0].node
{
722 return Some(content_mi
);
734 /// Reads a `MetaItem` from within an attribute, looks for whether it is a
735 /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
737 fn extract_include(mi
: &ast
::MetaItem
)
738 -> Option
<(String
, String
)>
740 mi
.meta_item_list().and_then(|list
| {
742 if meta
.check_name("include") {
743 // the actual compiled `#[doc(include="filename")]` gets expanded to
744 // `#[doc(include(file="filename", contents="file contents")]` so we need to
745 // look for that instead
746 return meta
.meta_item_list().and_then(|list
| {
747 let mut filename
: Option
<String
> = None
;
748 let mut contents
: Option
<String
> = None
;
751 if it
.check_name("file") {
752 if let Some(name
) = it
.value_str() {
753 filename
= Some(name
.to_string());
755 } else if it
.check_name("contents") {
756 if let Some(docs
) = it
.value_str() {
757 contents
= Some(docs
.to_string());
762 if let (Some(filename
), Some(contents
)) = (filename
, contents
) {
763 Some((filename
, contents
))
775 pub fn has_doc_flag(&self, flag
: &str) -> bool
{
776 for attr
in &self.other_attrs
{
777 if !attr
.check_name("doc") { continue; }
779 if let Some(items
) = attr
.meta_item_list() {
780 if items
.iter().filter_map(|i
| i
.meta_item()).any(|it
| it
.check_name(flag
)) {
789 pub fn from_ast(diagnostic
: &::errors
::Handler
,
790 attrs
: &[ast
::Attribute
]) -> Attributes
{
791 let mut doc_strings
= vec
![];
793 let mut cfg
= Cfg
::True
;
794 let mut doc_line
= 0;
796 let other_attrs
= attrs
.iter().filter_map(|attr
| {
797 attr
.with_desugared_doc(|attr
| {
798 if attr
.check_name("doc") {
799 if let Some(mi
) = attr
.meta() {
800 if let Some(value
) = mi
.value_str() {
801 // Extracted #[doc = "..."]
802 let value
= value
.to_string();
804 doc_line
+= value
.lines().count();
806 if attr
.is_sugared_doc
{
807 doc_strings
.push(DocFragment
::SugaredDoc(line
, attr
.span
, value
));
809 doc_strings
.push(DocFragment
::RawDoc(line
, attr
.span
, value
));
813 sp
= Some(attr
.span
);
816 } else if let Some(cfg_mi
) = Attributes
::extract_cfg(&mi
) {
817 // Extracted #[doc(cfg(...))]
818 match Cfg
::parse(cfg_mi
) {
819 Ok(new_cfg
) => cfg
&= new_cfg
,
820 Err(e
) => diagnostic
.span_err(e
.span
, e
.msg
),
823 } else if let Some((filename
, contents
)) = Attributes
::extract_include(&mi
)
826 doc_line
+= contents
.lines().count();
827 doc_strings
.push(DocFragment
::Include(line
,
838 // treat #[target_feature(enable = "feat")] attributes as if they were
839 // #[doc(cfg(target_feature = "feat"))] attributes as well
840 for attr
in attrs
.lists("target_feature") {
841 if attr
.check_name("enable") {
842 if let Some(feat
) = attr
.value_str() {
843 let meta
= attr
::mk_name_value_item_str(Ident
::from_str("target_feature"),
844 dummy_spanned(feat
));
845 if let Ok(feat_cfg
) = Cfg
::parse(&meta
) {
855 cfg
: if cfg
== Cfg
::True { None }
else { Some(Rc::new(cfg)) }
,
861 /// Finds the `doc` attribute as a NameValue and returns the corresponding
863 pub fn doc_value
<'a
>(&'a
self) -> Option
<&'a
str> {
864 self.doc_strings
.first().map(|s
| s
.as_str())
867 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
869 pub fn collapsed_doc_value(&self) -> Option
<String
> {
870 if !self.doc_strings
.is_empty() {
871 Some(self.doc_strings
.iter().collect())
877 /// Get links as a vector
879 /// Cache must be populated before call
880 pub fn links(&self, krate
: &CrateNum
) -> Vec
<(String
, String
)> {
881 use html
::format
::href
;
882 self.links
.iter().filter_map(|&(ref s
, did
, ref fragment
)| {
885 if let Some((mut href
, ..)) = href(did
) {
886 if let Some(ref fragment
) = *fragment
{
888 href
.push_str(fragment
);
890 Some((s
.clone(), href
))
896 if let Some(ref fragment
) = *fragment
{
898 let url
= match cache
.extern_locations
.get(krate
) {
899 Some(&(_
, ref src
, ExternalLocation
::Local
)) =>
900 src
.to_str().expect("invalid file path"),
901 Some(&(_
, _
, ExternalLocation
::Remote(ref s
))) => s
,
902 Some(&(_
, _
, ExternalLocation
::Unknown
)) | None
=>
903 "https://doc.rust-lang.org/nightly",
905 // This is a primitive so the url is done "by hand".
907 format
!("{}{}std/primitive.{}.html",
909 if !url
.ends_with('
/'
) { "/" }
else { "" }
,
912 panic
!("This isn't a primitive?!");
920 impl AttributesExt
for Attributes
{
921 fn lists
<'a
>(&'a
self, name
: &'a
str) -> ListAttributesIter
<'a
> {
922 self.other_attrs
.lists(name
)
926 /// Given a def, returns its name and disambiguator
927 /// for a value namespace
929 /// Returns None for things which cannot be ambiguous since
930 /// they exist in both namespaces (structs and modules)
931 fn value_ns_kind(def
: Def
, path_str
: &str) -> Option
<(&'
static str, String
)> {
933 // structs, variants, and mods exist in both namespaces. skip them
934 Def
::StructCtor(..) | Def
::Mod(..) | Def
::Variant(..) | Def
::VariantCtor(..) => None
,
936 => Some(("function", format
!("{}()", path_str
))),
938 => Some(("method", format
!("{}()", path_str
))),
940 => Some(("const", format
!("const@{}", path_str
))),
942 => Some(("static", format
!("static@{}", path_str
))),
943 _
=> Some(("value", format
!("value@{}", path_str
))),
947 /// Given a def, returns its name, the article to be used, and a disambiguator
948 /// for the type namespace
949 fn type_ns_kind(def
: Def
, path_str
: &str) -> (&'
static str, &'
static str, String
) {
950 let (kind
, article
) = match def
{
951 // we can still have non-tuple structs
952 Def
::Struct(..) => ("struct", "a"),
953 Def
::Enum(..) => ("enum", "an"),
954 Def
::Trait(..) => ("trait", "a"),
955 Def
::Union(..) => ("union", "a"),
958 (kind
, article
, format
!("{}@{}", kind
, path_str
))
961 fn ambiguity_error(cx
: &DocContext
, attrs
: &Attributes
,
963 article1
: &str, kind1
: &str, disambig1
: &str,
964 article2
: &str, kind2
: &str, disambig2
: &str) {
965 let sp
= attrs
.doc_strings
.first()
966 .map_or(DUMMY_SP
, |a
| a
.span());
968 .struct_span_warn(sp
,
969 &format
!("`{}` is both {} {} and {} {}",
970 path_str
, article1
, kind1
,
972 .help(&format
!("try `{}` if you want to select the {}, \
973 or `{}` if you want to \
975 disambig1
, kind1
, disambig2
,
980 /// Given an enum variant's def, return the def of its enum and the associated fragment
981 fn handle_variant(cx
: &DocContext
, def
: Def
) -> Result
<(Def
, Option
<String
>), ()> {
982 use rustc
::ty
::DefIdTree
;
984 let parent
= if let Some(parent
) = cx
.tcx
.parent(def
.def_id()) {
989 let parent_def
= Def
::Enum(parent
);
990 let variant
= cx
.tcx
.expect_variant_def(def
);
991 Ok((parent_def
, Some(format
!("{}.v", variant
.name
))))
994 const PRIMITIVES
: &[(&str, Def
)] = &[
995 ("u8", Def
::PrimTy(hir
::PrimTy
::TyUint(syntax
::ast
::UintTy
::U8
))),
996 ("u16", Def
::PrimTy(hir
::PrimTy
::TyUint(syntax
::ast
::UintTy
::U16
))),
997 ("u32", Def
::PrimTy(hir
::PrimTy
::TyUint(syntax
::ast
::UintTy
::U32
))),
998 ("u64", Def
::PrimTy(hir
::PrimTy
::TyUint(syntax
::ast
::UintTy
::U64
))),
999 ("u128", Def
::PrimTy(hir
::PrimTy
::TyUint(syntax
::ast
::UintTy
::U128
))),
1000 ("usize", Def
::PrimTy(hir
::PrimTy
::TyUint(syntax
::ast
::UintTy
::Usize
))),
1001 ("i8", Def
::PrimTy(hir
::PrimTy
::TyInt(syntax
::ast
::IntTy
::I8
))),
1002 ("i16", Def
::PrimTy(hir
::PrimTy
::TyInt(syntax
::ast
::IntTy
::I16
))),
1003 ("i32", Def
::PrimTy(hir
::PrimTy
::TyInt(syntax
::ast
::IntTy
::I32
))),
1004 ("i64", Def
::PrimTy(hir
::PrimTy
::TyInt(syntax
::ast
::IntTy
::I64
))),
1005 ("i128", Def
::PrimTy(hir
::PrimTy
::TyInt(syntax
::ast
::IntTy
::I128
))),
1006 ("isize", Def
::PrimTy(hir
::PrimTy
::TyInt(syntax
::ast
::IntTy
::Isize
))),
1007 ("f32", Def
::PrimTy(hir
::PrimTy
::TyFloat(syntax
::ast
::FloatTy
::F32
))),
1008 ("f64", Def
::PrimTy(hir
::PrimTy
::TyFloat(syntax
::ast
::FloatTy
::F64
))),
1009 ("str", Def
::PrimTy(hir
::PrimTy
::TyStr
)),
1010 ("bool", Def
::PrimTy(hir
::PrimTy
::TyBool
)),
1011 ("char", Def
::PrimTy(hir
::PrimTy
::TyChar
)),
1014 fn is_primitive(path_str
: &str, is_val
: bool
) -> Option
<Def
> {
1018 PRIMITIVES
.iter().find(|x
| x
.0 == path_str
).map(|x
| x
.1)
1022 /// Resolve a given string as a path, along with whether or not it is
1023 /// in the value namespace. Also returns an optional URL fragment in the case
1024 /// of variants and methods
1025 fn resolve(cx
: &DocContext
, path_str
: &str, is_val
: bool
) -> Result
<(Def
, Option
<String
>), ()> {
1026 // In case we're in a module, try to resolve the relative
1028 if let Some(id
) = cx
.mod_ids
.borrow().last() {
1029 let result
= cx
.resolver
.borrow_mut()
1032 resolver
.resolve_str_path_error(DUMMY_SP
,
1036 if let Ok(result
) = result
{
1037 // In case this is a trait item, skip the
1038 // early return and try looking for the trait
1039 let value
= match result
.def
{
1040 Def
::Method(_
) | Def
::AssociatedConst(_
) => true,
1041 Def
::AssociatedTy(_
) => false,
1042 Def
::Variant(_
) => return handle_variant(cx
, result
.def
),
1043 // not a trait item, just return what we found
1044 _
=> return Ok((result
.def
, None
))
1047 if value
!= is_val
{
1050 } else if let Some(prim
) = is_primitive(path_str
, is_val
) {
1051 return Ok((prim
, Some(path_str
.to_owned())))
1053 // If resolution failed, it may still be a method
1054 // because methods are not handled by the resolver
1055 // If so, bail when we're not looking for a value
1061 // Try looking for methods and associated items
1062 let mut split
= path_str
.rsplitn(2, "::");
1063 let mut item_name
= if let Some(first
) = split
.next() {
1069 let mut path
= if let Some(second
) = split
.next() {
1075 let ty
= cx
.resolver
.borrow_mut()
1078 resolver
.resolve_str_path_error(DUMMY_SP
, &path
, false)
1081 Def
::Struct(did
) | Def
::Union(did
) | Def
::Enum(did
) | Def
::TyAlias(did
) => {
1082 let item
= cx
.tcx
.inherent_impls(did
).iter()
1083 .flat_map(|imp
| cx
.tcx
.associated_items(*imp
))
1084 .find(|item
| item
.name
== item_name
);
1085 if let Some(item
) = item
{
1086 let out
= match item
.kind
{
1087 ty
::AssociatedKind
::Method
if is_val
=> "method",
1088 ty
::AssociatedKind
::Const
if is_val
=> "associatedconstant",
1091 Ok((ty
.def
, Some(format
!("{}.{}", out
, item_name
))))
1093 let is_enum
= match ty
.def
{
1094 Def
::Enum(_
) => true,
1097 let elem
= if is_enum
{
1098 cx
.tcx
.adt_def(did
).all_fields().find(|item
| item
.name
== item_name
)
1104 .find(|item
| item
.name
== item_name
)
1106 if let Some(item
) = elem
{
1108 Some(format
!("{}.{}",
1109 if is_enum { "variant" }
else { "structfield" }
,
1116 Def
::Trait(did
) => {
1117 let item
= cx
.tcx
.associated_item_def_ids(did
).iter()
1118 .map(|item
| cx
.tcx
.associated_item(*item
))
1119 .find(|item
| item
.name
== item_name
);
1120 if let Some(item
) = item
{
1121 let kind
= match item
.kind
{
1122 ty
::AssociatedKind
::Const
if is_val
=> "associatedconstant",
1123 ty
::AssociatedKind
::Type
if !is_val
=> "associatedtype",
1124 ty
::AssociatedKind
::Method
if is_val
=> {
1125 if item
.defaultness
.has_value() {
1134 Ok((ty
.def
, Some(format
!("{}.{}", kind
, item_name
))))
1146 /// Resolve a string as a macro
1147 fn macro_resolve(cx
: &DocContext
, path_str
: &str) -> Option
<Def
> {
1148 use syntax
::ext
::base
::{MacroKind, SyntaxExtension}
;
1149 use syntax
::ext
::hygiene
::Mark
;
1150 let segment
= ast
::PathSegment
::from_ident(Ident
::from_str(path_str
));
1151 let path
= ast
::Path { segments: vec![segment], span: DUMMY_SP }
;
1152 let mut resolver
= cx
.resolver
.borrow_mut();
1153 let mark
= Mark
::root();
1155 .resolve_macro_to_def_inner(mark
, &path
, MacroKind
::Bang
, false);
1156 if let Ok(def
) = res
{
1157 if let SyntaxExtension
::DeclMacro(..) = *resolver
.get_macro(def
) {
1162 } else if let Some(def
) = resolver
.all_macros
.get(&Symbol
::intern(path_str
)) {
1171 /// can be either value or type, not a macro
1175 /// values, functions, consts, statics, everything in the value namespace
1177 /// types, traits, everything in the type namespace
1181 fn resolution_failure(cx
: &DocContext
, path_str
: &str) {
1182 cx
.sess().warn(&format
!("[{}] cannot be resolved, ignoring it...", path_str
));
1185 impl Clean
<Attributes
> for [ast
::Attribute
] {
1186 fn clean(&self, cx
: &DocContext
) -> Attributes
{
1187 let mut attrs
= Attributes
::from_ast(cx
.sess().diagnostic(), self);
1189 if UnstableFeatures
::from_environment().is_nightly_build() {
1190 let dox
= attrs
.collapsed_doc_value().unwrap_or_else(String
::new
);
1191 for ori_link
in markdown_links(&dox
) {
1192 // bail early for real links
1193 if ori_link
.contains('
/'
) {
1196 let link
= ori_link
.replace("`", "");
1197 let (def
, fragment
) = {
1198 let mut kind
= PathKind
::Unknown
;
1199 let path_str
= if let Some(prefix
) =
1200 ["struct@", "enum@", "type@",
1201 "trait@", "union@"].iter()
1202 .find(|p
| link
.starts_with(**p
)) {
1203 kind
= PathKind
::Type
;
1204 link
.trim_left_matches(prefix
)
1205 } else if let Some(prefix
) =
1206 ["const@", "static@",
1207 "value@", "function@", "mod@",
1208 "fn@", "module@", "method@"]
1209 .iter().find(|p
| link
.starts_with(**p
)) {
1210 kind
= PathKind
::Value
;
1211 link
.trim_left_matches(prefix
)
1212 } else if link
.ends_with("()") {
1213 kind
= PathKind
::Value
;
1214 link
.trim_right_matches("()")
1215 } else if link
.starts_with("macro@") {
1216 kind
= PathKind
::Macro
;
1217 link
.trim_left_matches("macro@")
1218 } else if link
.ends_with('
!'
) {
1219 kind
= PathKind
::Macro
;
1220 link
.trim_right_matches('
!'
)
1225 if path_str
.contains(|ch
: char| !(ch
.is_alphanumeric() ||
1226 ch
== '
:'
|| ch
== '_'
)) {
1231 PathKind
::Value
=> {
1232 if let Ok(def
) = resolve(cx
, path_str
, true) {
1235 resolution_failure(cx
, path_str
);
1236 // this could just be a normal link or a broken link
1237 // we could potentially check if something is
1238 // "intra-doc-link-like" and warn in that case
1243 if let Ok(def
) = resolve(cx
, path_str
, false) {
1246 resolution_failure(cx
, path_str
);
1247 // this could just be a normal link
1251 PathKind
::Unknown
=> {
1253 if let Some(macro_def
) = macro_resolve(cx
, path_str
) {
1254 if let Ok(type_def
) = resolve(cx
, path_str
, false) {
1255 let (type_kind
, article
, type_disambig
)
1256 = type_ns_kind(type_def
.0, path_str
);
1257 ambiguity_error(cx
, &attrs
, path_str
,
1258 article
, type_kind
, &type_disambig
,
1259 "a", "macro", &format
!("macro@{}", path_str
));
1261 } else if let Ok(value_def
) = resolve(cx
, path_str
, true) {
1262 let (value_kind
, value_disambig
)
1263 = value_ns_kind(value_def
.0, path_str
)
1264 .expect("struct and mod cases should have been \
1265 caught in previous branch");
1266 ambiguity_error(cx
, &attrs
, path_str
,
1267 "a", value_kind
, &value_disambig
,
1268 "a", "macro", &format
!("macro@{}", path_str
));
1271 } else if let Ok(type_def
) = resolve(cx
, path_str
, false) {
1272 // It is imperative we search for not-a-value first
1273 // Otherwise we will find struct ctors for when we are looking
1274 // for structs, and the link won't work.
1275 // if there is something in both namespaces
1276 if let Ok(value_def
) = resolve(cx
, path_str
, true) {
1277 let kind
= value_ns_kind(value_def
.0, path_str
);
1278 if let Some((value_kind
, value_disambig
)) = kind
{
1279 let (type_kind
, article
, type_disambig
)
1280 = type_ns_kind(type_def
.0, path_str
);
1281 ambiguity_error(cx
, &attrs
, path_str
,
1282 article
, type_kind
, &type_disambig
,
1283 "a", value_kind
, &value_disambig
);
1288 } else if let Ok(value_def
) = resolve(cx
, path_str
, true) {
1291 resolution_failure(cx
, path_str
);
1292 // this could just be a normal link
1296 PathKind
::Macro
=> {
1297 if let Some(def
) = macro_resolve(cx
, path_str
) {
1300 resolution_failure(cx
, path_str
);
1307 if let Def
::PrimTy(_
) = def
{
1308 attrs
.links
.push((ori_link
, None
, fragment
));
1310 let id
= register_def(cx
, def
);
1311 attrs
.links
.push((ori_link
, Some(id
), fragment
));
1315 cx
.sess().abort_if_errors();
1322 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1323 pub struct TyParam
{
1326 pub bounds
: Vec
<TyParamBound
>,
1327 pub default: Option
<Type
>,
1328 pub synthetic
: Option
<hir
::SyntheticTyParamKind
>,
1331 impl Clean
<TyParam
> for hir
::TyParam
{
1332 fn clean(&self, cx
: &DocContext
) -> TyParam
{
1334 name
: self.name
.clean(cx
),
1335 did
: cx
.tcx
.hir
.local_def_id(self.id
),
1336 bounds
: self.bounds
.clean(cx
),
1337 default: self.default.clean(cx
),
1338 synthetic
: self.synthetic
,
1343 impl<'tcx
> Clean
<TyParam
> for ty
::TypeParameterDef
{
1344 fn clean(&self, cx
: &DocContext
) -> TyParam
{
1345 cx
.renderinfo
.borrow_mut().external_typarams
.insert(self.def_id
, self.name
.clean(cx
));
1347 name
: self.name
.clean(cx
),
1349 bounds
: vec
![], // these are filled in from the where-clauses
1350 default: if self.has_default
{
1351 Some(cx
.tcx
.type_of(self.def_id
).clean(cx
))
1360 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1361 pub enum TyParamBound
{
1362 RegionBound(Lifetime
),
1363 TraitBound(PolyTrait
, hir
::TraitBoundModifier
)
1367 fn maybe_sized(cx
: &DocContext
) -> TyParamBound
{
1368 let did
= cx
.tcx
.require_lang_item(lang_items
::SizedTraitLangItem
);
1369 let empty
= cx
.tcx
.intern_substs(&[]);
1370 let path
= external_path(cx
, &cx
.tcx
.item_name(did
).as_str(),
1371 Some(did
), false, vec
![], empty
);
1372 inline
::record_extern_fqn(cx
, did
, TypeKind
::Trait
);
1373 TraitBound(PolyTrait
{
1374 trait_
: ResolvedPath
{
1380 generic_params
: Vec
::new(),
1381 }, hir
::TraitBoundModifier
::Maybe
)
1384 fn is_sized_bound(&self, cx
: &DocContext
) -> bool
{
1385 use rustc
::hir
::TraitBoundModifier
as TBM
;
1386 if let TyParamBound
::TraitBound(PolyTrait { ref trait_, .. }
, TBM
::None
) = *self {
1387 if trait_
.def_id() == cx
.tcx
.lang_items().sized_trait() {
1394 fn get_poly_trait(&self) -> Option
<PolyTrait
> {
1395 if let TyParamBound
::TraitBound(ref p
, _
) = *self {
1396 return Some(p
.clone())
1401 fn get_trait_type(&self) -> Option
<Type
> {
1403 if let TyParamBound
::TraitBound(PolyTrait { ref trait_, .. }
, _
) = *self {
1404 return Some(trait_
.clone());
1410 impl Clean
<TyParamBound
> for hir
::TyParamBound
{
1411 fn clean(&self, cx
: &DocContext
) -> TyParamBound
{
1413 hir
::RegionTyParamBound(lt
) => RegionBound(lt
.clean(cx
)),
1414 hir
::TraitTyParamBound(ref t
, modifier
) => TraitBound(t
.clean(cx
), modifier
),
1419 fn external_path_params(cx
: &DocContext
, trait_did
: Option
<DefId
>, has_self
: bool
,
1420 bindings
: Vec
<TypeBinding
>, substs
: &Substs
) -> PathParameters
{
1421 let lifetimes
= substs
.regions().filter_map(|v
| v
.clean(cx
)).collect();
1422 let types
= substs
.types().skip(has_self
as usize).collect
::<Vec
<_
>>();
1425 // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
1426 Some(did
) if cx
.tcx
.lang_items().fn_trait_kind(did
).is_some() => {
1427 assert_eq
!(types
.len(), 1);
1428 let inputs
= match types
[0].sty
{
1429 ty
::TyTuple(ref tys
) => tys
.iter().map(|t
| t
.clean(cx
)).collect(),
1431 return PathParameters
::AngleBracketed
{
1433 types
: types
.clean(cx
),
1439 // FIXME(#20299) return type comes from a projection now
1440 // match types[1].sty {
1441 // ty::TyTuple(ref v) if v.is_empty() => None, // -> ()
1442 // _ => Some(types[1].clean(cx))
1444 PathParameters
::Parenthesized
{
1450 PathParameters
::AngleBracketed
{
1452 types
: types
.clean(cx
),
1459 // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
1460 // from Fn<(A, B,), C> to Fn(A, B) -> C
1461 fn external_path(cx
: &DocContext
, name
: &str, trait_did
: Option
<DefId
>, has_self
: bool
,
1462 bindings
: Vec
<TypeBinding
>, substs
: &Substs
) -> Path
{
1466 segments
: vec
![PathSegment
{
1467 name
: name
.to_string(),
1468 params
: external_path_params(cx
, trait_did
, has_self
, bindings
, substs
)
1473 impl<'a
, 'tcx
> Clean
<TyParamBound
> for (&'a ty
::TraitRef
<'tcx
>, Vec
<TypeBinding
>) {
1474 fn clean(&self, cx
: &DocContext
) -> TyParamBound
{
1475 let (trait_ref
, ref bounds
) = *self;
1476 inline
::record_extern_fqn(cx
, trait_ref
.def_id
, TypeKind
::Trait
);
1477 let path
= external_path(cx
, &cx
.tcx
.item_name(trait_ref
.def_id
).as_str(),
1478 Some(trait_ref
.def_id
), true, bounds
.clone(), trait_ref
.substs
);
1480 debug
!("ty::TraitRef\n subst: {:?}\n", trait_ref
.substs
);
1482 // collect any late bound regions
1483 let mut late_bounds
= vec
![];
1484 for ty_s
in trait_ref
.input_types().skip(1) {
1485 if let ty
::TyTuple(ts
) = ty_s
.sty
{
1487 if let ty
::TyRef(ref reg
, _
) = ty_s
.sty
{
1488 if let &ty
::RegionKind
::ReLateBound(..) = *reg
{
1489 debug
!(" hit an ReLateBound {:?}", reg
);
1490 if let Some(lt
) = reg
.clean(cx
) {
1491 late_bounds
.push(GenericParam
::Lifetime(lt
));
1501 trait_
: ResolvedPath
{
1504 did
: trait_ref
.def_id
,
1507 generic_params
: late_bounds
,
1509 hir
::TraitBoundModifier
::None
1514 impl<'tcx
> Clean
<TyParamBound
> for ty
::TraitRef
<'tcx
> {
1515 fn clean(&self, cx
: &DocContext
) -> TyParamBound
{
1516 (self, vec
![]).clean(cx
)
1520 impl<'tcx
> Clean
<Option
<Vec
<TyParamBound
>>> for Substs
<'tcx
> {
1521 fn clean(&self, cx
: &DocContext
) -> Option
<Vec
<TyParamBound
>> {
1522 let mut v
= Vec
::new();
1523 v
.extend(self.regions().filter_map(|r
| r
.clean(cx
))
1525 v
.extend(self.types().map(|t
| TraitBound(PolyTrait
{
1526 trait_
: t
.clean(cx
),
1527 generic_params
: Vec
::new(),
1528 }, hir
::TraitBoundModifier
::None
)));
1529 if !v
.is_empty() {Some(v)}
else {None}
1533 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1534 pub struct Lifetime(String
);
1537 pub fn get_ref
<'a
>(&'a
self) -> &'a
str {
1538 let Lifetime(ref s
) = *self;
1543 pub fn statik() -> Lifetime
{
1544 Lifetime("'static".to_string())
1548 impl Clean
<Lifetime
> for hir
::Lifetime
{
1549 fn clean(&self, cx
: &DocContext
) -> Lifetime
{
1550 if self.id
!= ast
::DUMMY_NODE_ID
{
1551 let hir_id
= cx
.tcx
.hir
.node_to_hir_id(self.id
);
1552 let def
= cx
.tcx
.named_region(hir_id
);
1554 Some(rl
::Region
::EarlyBound(_
, node_id
, _
)) |
1555 Some(rl
::Region
::LateBound(_
, node_id
, _
)) |
1556 Some(rl
::Region
::Free(_
, node_id
)) => {
1557 if let Some(lt
) = cx
.lt_substs
.borrow().get(&node_id
).cloned() {
1564 Lifetime(self.name
.name().to_string())
1568 impl Clean
<Lifetime
> for hir
::LifetimeDef
{
1569 fn clean(&self, _
: &DocContext
) -> Lifetime
{
1570 if self.bounds
.len() > 0 {
1571 let mut s
= format
!("{}: {}",
1572 self.lifetime
.name
.name(),
1573 self.bounds
[0].name
.name());
1574 for bound
in self.bounds
.iter().skip(1) {
1575 s
.push_str(&format
!(" + {}", bound
.name
.name()));
1579 Lifetime(self.lifetime
.name
.name().to_string())
1584 impl Clean
<Lifetime
> for ty
::RegionParameterDef
{
1585 fn clean(&self, _
: &DocContext
) -> Lifetime
{
1586 Lifetime(self.name
.to_string())
1590 impl Clean
<Option
<Lifetime
>> for ty
::RegionKind
{
1591 fn clean(&self, cx
: &DocContext
) -> Option
<Lifetime
> {
1593 ty
::ReStatic
=> Some(Lifetime
::statik()),
1594 ty
::ReLateBound(_
, ty
::BrNamed(_
, name
)) => Some(Lifetime(name
.to_string())),
1595 ty
::ReEarlyBound(ref data
) => Some(Lifetime(data
.name
.clean(cx
))),
1597 ty
::ReLateBound(..) |
1601 ty
::ReSkolemized(..) |
1603 ty
::ReClosureBound(_
) |
1604 ty
::ReCanonical(_
) |
1605 ty
::ReErased
=> None
1610 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1611 pub enum WherePredicate
{
1612 BoundPredicate { ty: Type, bounds: Vec<TyParamBound> }
,
1613 RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>}
,
1614 EqPredicate { lhs: Type, rhs: Type }
,
1617 impl Clean
<WherePredicate
> for hir
::WherePredicate
{
1618 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
1620 hir
::WherePredicate
::BoundPredicate(ref wbp
) => {
1621 WherePredicate
::BoundPredicate
{
1622 ty
: wbp
.bounded_ty
.clean(cx
),
1623 bounds
: wbp
.bounds
.clean(cx
)
1627 hir
::WherePredicate
::RegionPredicate(ref wrp
) => {
1628 WherePredicate
::RegionPredicate
{
1629 lifetime
: wrp
.lifetime
.clean(cx
),
1630 bounds
: wrp
.bounds
.clean(cx
)
1634 hir
::WherePredicate
::EqPredicate(ref wrp
) => {
1635 WherePredicate
::EqPredicate
{
1636 lhs
: wrp
.lhs_ty
.clean(cx
),
1637 rhs
: wrp
.rhs_ty
.clean(cx
)
1644 impl<'a
> Clean
<WherePredicate
> for ty
::Predicate
<'a
> {
1645 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
1646 use rustc
::ty
::Predicate
;
1649 Predicate
::Trait(ref pred
) => pred
.clean(cx
),
1650 Predicate
::Subtype(ref pred
) => pred
.clean(cx
),
1651 Predicate
::RegionOutlives(ref pred
) => pred
.clean(cx
),
1652 Predicate
::TypeOutlives(ref pred
) => pred
.clean(cx
),
1653 Predicate
::Projection(ref pred
) => pred
.clean(cx
),
1654 Predicate
::WellFormed(_
) => panic
!("not user writable"),
1655 Predicate
::ObjectSafe(_
) => panic
!("not user writable"),
1656 Predicate
::ClosureKind(..) => panic
!("not user writable"),
1657 Predicate
::ConstEvaluatable(..) => panic
!("not user writable"),
1662 impl<'a
> Clean
<WherePredicate
> for ty
::TraitPredicate
<'a
> {
1663 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
1664 WherePredicate
::BoundPredicate
{
1665 ty
: self.trait_ref
.self_ty().clean(cx
),
1666 bounds
: vec
![self.trait_ref
.clean(cx
)]
1671 impl<'tcx
> Clean
<WherePredicate
> for ty
::SubtypePredicate
<'tcx
> {
1672 fn clean(&self, _cx
: &DocContext
) -> WherePredicate
{
1673 panic
!("subtype predicates are an internal rustc artifact \
1674 and should not be seen by rustdoc")
1678 impl<'tcx
> Clean
<WherePredicate
> for ty
::OutlivesPredicate
<ty
::Region
<'tcx
>, ty
::Region
<'tcx
>> {
1679 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
1680 let ty
::OutlivesPredicate(ref a
, ref b
) = *self;
1681 WherePredicate
::RegionPredicate
{
1682 lifetime
: a
.clean(cx
).unwrap(),
1683 bounds
: vec
![b
.clean(cx
).unwrap()]
1688 impl<'tcx
> Clean
<WherePredicate
> for ty
::OutlivesPredicate
<Ty
<'tcx
>, ty
::Region
<'tcx
>> {
1689 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
1690 let ty
::OutlivesPredicate(ref ty
, ref lt
) = *self;
1692 WherePredicate
::BoundPredicate
{
1694 bounds
: vec
![TyParamBound
::RegionBound(lt
.clean(cx
).unwrap())]
1699 impl<'tcx
> Clean
<WherePredicate
> for ty
::ProjectionPredicate
<'tcx
> {
1700 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
1701 WherePredicate
::EqPredicate
{
1702 lhs
: self.projection_ty
.clean(cx
),
1703 rhs
: self.ty
.clean(cx
)
1708 impl<'tcx
> Clean
<Type
> for ty
::ProjectionTy
<'tcx
> {
1709 fn clean(&self, cx
: &DocContext
) -> Type
{
1710 let trait_
= match self.trait_ref(cx
.tcx
).clean(cx
) {
1711 TyParamBound
::TraitBound(t
, _
) => t
.trait_
,
1712 TyParamBound
::RegionBound(_
) => {
1713 panic
!("cleaning a trait got a region")
1717 name
: cx
.tcx
.associated_item(self.item_def_id
).name
.clean(cx
),
1718 self_type
: box self.self_ty().clean(cx
),
1724 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1725 pub enum GenericParam
{
1731 pub fn is_synthetic_type_param(&self) -> bool
{
1732 if let GenericParam
::Type(ref t
) = *self {
1733 t
.synthetic
.is_some()
1740 impl Clean
<GenericParam
> for hir
::GenericParam
{
1741 fn clean(&self, cx
: &DocContext
) -> GenericParam
{
1743 hir
::GenericParam
::Lifetime(ref l
) => GenericParam
::Lifetime(l
.clean(cx
)),
1744 hir
::GenericParam
::Type(ref t
) => GenericParam
::Type(t
.clean(cx
)),
1749 // maybe use a Generic enum and use Vec<Generic>?
1750 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Default, Hash)]
1751 pub struct Generics
{
1752 pub params
: Vec
<GenericParam
>,
1753 pub where_predicates
: Vec
<WherePredicate
>,
1756 impl Clean
<Generics
> for hir
::Generics
{
1757 fn clean(&self, cx
: &DocContext
) -> Generics
{
1758 let mut params
= Vec
::with_capacity(self.params
.len());
1759 for p
in &self.params
{
1760 let p
= p
.clean(cx
);
1761 if let GenericParam
::Type(ref tp
) = p
{
1762 if tp
.synthetic
== Some(hir
::SyntheticTyParamKind
::ImplTrait
) {
1763 cx
.impl_trait_bounds
.borrow_mut().insert(tp
.did
, tp
.bounds
.clone());
1768 let mut g
= Generics
{
1770 where_predicates
: self.where_clause
.predicates
.clean(cx
)
1773 // Some duplicates are generated for ?Sized bounds between type params and where
1774 // predicates. The point in here is to move the bounds definitions from type params
1775 // to where predicates when such cases occur.
1776 for where_pred
in &mut g
.where_predicates
{
1778 WherePredicate
::BoundPredicate { ty: Generic(ref name), ref mut bounds }
=> {
1779 if bounds
.is_empty() {
1780 for param
in &mut g
.params
{
1781 if let GenericParam
::Type(ref mut type_param
) = *param
{
1782 if &type_param
.name
== name
{
1783 mem
::swap(bounds
, &mut type_param
.bounds
);
1797 impl<'a
, 'tcx
> Clean
<Generics
> for (&'a ty
::Generics
,
1798 &'a ty
::GenericPredicates
<'tcx
>) {
1799 fn clean(&self, cx
: &DocContext
) -> Generics
{
1800 use self::WherePredicate
as WP
;
1802 let (gens
, preds
) = *self;
1804 // Bounds in the type_params and lifetimes fields are repeated in the
1805 // predicates field (see rustc_typeck::collect::ty_generics), so remove
1807 let stripped_typarams
= gens
.types
.iter().filter_map(|tp
| {
1808 if tp
.name
== keywords
::SelfType
.name().as_str() {
1809 assert_eq
!(tp
.index
, 0);
1814 }).collect
::<Vec
<_
>>();
1816 let mut where_predicates
= preds
.predicates
.to_vec().clean(cx
);
1818 // Type parameters and have a Sized bound by default unless removed with
1819 // ?Sized. Scan through the predicates and mark any type parameter with
1820 // a Sized bound, removing the bounds as we find them.
1822 // Note that associated types also have a sized bound by default, but we
1823 // don't actually know the set of associated types right here so that's
1824 // handled in cleaning associated types
1825 let mut sized_params
= FxHashSet();
1826 where_predicates
.retain(|pred
| {
1828 WP
::BoundPredicate { ty: Generic(ref g), ref bounds }
=> {
1829 if bounds
.iter().any(|b
| b
.is_sized_bound(cx
)) {
1830 sized_params
.insert(g
.clone());
1840 // Run through the type parameters again and insert a ?Sized
1841 // unbound for any we didn't find to be Sized.
1842 for tp
in &stripped_typarams
{
1843 if !sized_params
.contains(&tp
.name
) {
1844 where_predicates
.push(WP
::BoundPredicate
{
1845 ty
: Type
::Generic(tp
.name
.clone()),
1846 bounds
: vec
![TyParamBound
::maybe_sized(cx
)],
1851 // It would be nice to collect all of the bounds on a type and recombine
1852 // them if possible, to avoid e.g. `where T: Foo, T: Bar, T: Sized, T: 'a`
1853 // and instead see `where T: Foo + Bar + Sized + 'a`
1856 params
: gens
.regions
1859 .map(|lp
| GenericParam
::Lifetime(lp
))
1861 simplify
::ty_params(stripped_typarams
)
1863 .map(|tp
| GenericParam
::Type(tp
))
1866 where_predicates
: simplify
::where_clauses(cx
, where_predicates
),
1871 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1873 pub generics
: Generics
,
1874 pub unsafety
: hir
::Unsafety
,
1875 pub constness
: hir
::Constness
,
1880 impl<'a
> Clean
<Method
> for (&'a hir
::MethodSig
, &'a hir
::Generics
, hir
::BodyId
) {
1881 fn clean(&self, cx
: &DocContext
) -> Method
{
1882 let (generics
, decl
) = enter_impl_trait(cx
, || {
1883 (self.1.clean(cx
), (&*self.0.decl
, self.2).clean(cx
))
1888 unsafety
: self.0.unsafety
,
1889 constness
: self.0.constness
,
1895 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1896 pub struct TyMethod
{
1897 pub unsafety
: hir
::Unsafety
,
1899 pub generics
: Generics
,
1903 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1904 pub struct Function
{
1906 pub generics
: Generics
,
1907 pub unsafety
: hir
::Unsafety
,
1908 pub constness
: hir
::Constness
,
1912 impl Clean
<Item
> for doctree
::Function
{
1913 fn clean(&self, cx
: &DocContext
) -> Item
{
1914 let (generics
, decl
) = enter_impl_trait(cx
, || {
1915 (self.generics
.clean(cx
), (&self.decl
, self.body
).clean(cx
))
1918 name
: Some(self.name
.clean(cx
)),
1919 attrs
: self.attrs
.clean(cx
),
1920 source
: self.whence
.clean(cx
),
1921 visibility
: self.vis
.clean(cx
),
1922 stability
: self.stab
.clean(cx
),
1923 deprecation
: self.depr
.clean(cx
),
1924 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
1925 inner
: FunctionItem(Function
{
1928 unsafety
: self.unsafety
,
1929 constness
: self.constness
,
1936 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1938 pub inputs
: Arguments
,
1939 pub output
: FunctionRetTy
,
1941 pub attrs
: Attributes
,
1945 pub fn has_self(&self) -> bool
{
1946 self.inputs
.values
.len() > 0 && self.inputs
.values
[0].name
== "self"
1949 pub fn self_type(&self) -> Option
<SelfTy
> {
1950 self.inputs
.values
.get(0).and_then(|v
| v
.to_self())
1954 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1955 pub struct Arguments
{
1956 pub values
: Vec
<Argument
>,
1959 impl<'a
> Clean
<Arguments
> for (&'a
[P
<hir
::Ty
>], &'a
[Spanned
<ast
::Name
>]) {
1960 fn clean(&self, cx
: &DocContext
) -> Arguments
{
1962 values
: self.0.iter
().enumerate().map(|(i
, ty
)| {
1963 let mut name
= self.1.get(i
).map(|n
| n
.node
.to_string())
1964 .unwrap_or(String
::new());
1965 if name
.is_empty() {
1966 name
= "_".to_string();
1970 type_
: ty
.clean(cx
),
1977 impl<'a
> Clean
<Arguments
> for (&'a
[P
<hir
::Ty
>], hir
::BodyId
) {
1978 fn clean(&self, cx
: &DocContext
) -> Arguments
{
1979 let body
= cx
.tcx
.hir
.body(self.1);
1982 values
: self.0.iter
().enumerate().map(|(i
, ty
)| {
1984 name
: name_from_pat(&body
.arguments
[i
].pat
),
1985 type_
: ty
.clean(cx
),
1992 impl<'a
, A
: Copy
> Clean
<FnDecl
> for (&'a hir
::FnDecl
, A
)
1993 where (&'a
[P
<hir
::Ty
>], A
): Clean
<Arguments
>
1995 fn clean(&self, cx
: &DocContext
) -> FnDecl
{
1997 inputs
: (&self.0.inputs
[..], self.1).clean(cx
),
1998 output
: self.0.output
.clean(cx
),
1999 variadic
: self.0.variadic
,
2000 attrs
: Attributes
::default()
2005 impl<'a
, 'tcx
> Clean
<FnDecl
> for (DefId
, ty
::PolyFnSig
<'tcx
>) {
2006 fn clean(&self, cx
: &DocContext
) -> FnDecl
{
2007 let (did
, sig
) = *self;
2008 let mut names
= if cx
.tcx
.hir
.as_local_node_id(did
).is_some() {
2011 cx
.tcx
.fn_arg_names(did
).into_iter()
2015 output
: Return(sig
.skip_binder().output().clean(cx
)),
2016 attrs
: Attributes
::default(),
2017 variadic
: sig
.skip_binder().variadic
,
2019 values
: sig
.skip_binder().inputs().iter().map(|t
| {
2022 name
: names
.next().map_or("".to_string(), |name
| name
.to_string()),
2030 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
2031 pub struct Argument
{
2036 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2039 SelfBorrowed(Option
<Lifetime
>, Mutability
),
2044 pub fn to_self(&self) -> Option
<SelfTy
> {
2045 if self.name
!= "self" {
2048 if self.type_
.is_self_type() {
2049 return Some(SelfValue
);
2052 BorrowedRef{ref lifetime, mutability, ref type_}
if type_
.is_self_type() => {
2053 Some(SelfBorrowed(lifetime
.clone(), mutability
))
2055 _
=> Some(SelfExplicit(self.type_
.clone()))
2060 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
2061 pub enum FunctionRetTy
{
2066 impl Clean
<FunctionRetTy
> for hir
::FunctionRetTy
{
2067 fn clean(&self, cx
: &DocContext
) -> FunctionRetTy
{
2069 hir
::Return(ref typ
) => Return(typ
.clean(cx
)),
2070 hir
::DefaultReturn(..) => DefaultReturn
,
2075 impl GetDefId
for FunctionRetTy
{
2076 fn def_id(&self) -> Option
<DefId
> {
2078 Return(ref ty
) => ty
.def_id(),
2079 DefaultReturn
=> None
,
2084 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2087 pub unsafety
: hir
::Unsafety
,
2088 pub items
: Vec
<Item
>,
2089 pub generics
: Generics
,
2090 pub bounds
: Vec
<TyParamBound
>,
2091 pub is_spotlight
: bool
,
2095 impl Clean
<Item
> for doctree
::Trait
{
2096 fn clean(&self, cx
: &DocContext
) -> Item
{
2097 let attrs
= self.attrs
.clean(cx
);
2098 let is_spotlight
= attrs
.has_doc_flag("spotlight");
2100 name
: Some(self.name
.clean(cx
)),
2102 source
: self.whence
.clean(cx
),
2103 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
2104 visibility
: self.vis
.clean(cx
),
2105 stability
: self.stab
.clean(cx
),
2106 deprecation
: self.depr
.clean(cx
),
2107 inner
: TraitItem(Trait
{
2108 auto: self.is_auto
.clean(cx
),
2109 unsafety
: self.unsafety
,
2110 items
: self.items
.clean(cx
),
2111 generics
: self.generics
.clean(cx
),
2112 bounds
: self.bounds
.clean(cx
),
2113 is_spotlight
: is_spotlight
,
2114 is_auto
: self.is_auto
.clean(cx
),
2120 impl Clean
<bool
> for hir
::IsAuto
{
2121 fn clean(&self, _
: &DocContext
) -> bool
{
2123 hir
::IsAuto
::Yes
=> true,
2124 hir
::IsAuto
::No
=> false,
2129 impl Clean
<Type
> for hir
::TraitRef
{
2130 fn clean(&self, cx
: &DocContext
) -> Type
{
2131 resolve_type(cx
, self.path
.clean(cx
), self.ref_id
)
2135 impl Clean
<PolyTrait
> for hir
::PolyTraitRef
{
2136 fn clean(&self, cx
: &DocContext
) -> PolyTrait
{
2138 trait_
: self.trait_ref
.clean(cx
),
2139 generic_params
: self.bound_generic_params
.clean(cx
)
2144 impl Clean
<Item
> for hir
::TraitItem
{
2145 fn clean(&self, cx
: &DocContext
) -> Item
{
2146 let inner
= match self.node
{
2147 hir
::TraitItemKind
::Const(ref ty
, default) => {
2148 AssociatedConstItem(ty
.clean(cx
),
2149 default.map(|e
| print_const_expr(cx
, e
)))
2151 hir
::TraitItemKind
::Method(ref sig
, hir
::TraitMethod
::Provided(body
)) => {
2152 MethodItem((sig
, &self.generics
, body
).clean(cx
))
2154 hir
::TraitItemKind
::Method(ref sig
, hir
::TraitMethod
::Required(ref names
)) => {
2155 let (generics
, decl
) = enter_impl_trait(cx
, || {
2156 (self.generics
.clean(cx
), (&*sig
.decl
, &names
[..]).clean(cx
))
2158 TyMethodItem(TyMethod
{
2159 unsafety
: sig
.unsafety
.clone(),
2165 hir
::TraitItemKind
::Type(ref bounds
, ref default) => {
2166 AssociatedTypeItem(bounds
.clean(cx
), default.clean(cx
))
2170 name
: Some(self.name
.clean(cx
)),
2171 attrs
: self.attrs
.clean(cx
),
2172 source
: self.span
.clean(cx
),
2173 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
2175 stability
: get_stability(cx
, cx
.tcx
.hir
.local_def_id(self.id
)),
2176 deprecation
: get_deprecation(cx
, cx
.tcx
.hir
.local_def_id(self.id
)),
2182 impl Clean
<Item
> for hir
::ImplItem
{
2183 fn clean(&self, cx
: &DocContext
) -> Item
{
2184 let inner
= match self.node
{
2185 hir
::ImplItemKind
::Const(ref ty
, expr
) => {
2186 AssociatedConstItem(ty
.clean(cx
),
2187 Some(print_const_expr(cx
, expr
)))
2189 hir
::ImplItemKind
::Method(ref sig
, body
) => {
2190 MethodItem((sig
, &self.generics
, body
).clean(cx
))
2192 hir
::ImplItemKind
::Type(ref ty
) => TypedefItem(Typedef
{
2193 type_
: ty
.clean(cx
),
2194 generics
: Generics
::default(),
2198 name
: Some(self.name
.clean(cx
)),
2199 source
: self.span
.clean(cx
),
2200 attrs
: self.attrs
.clean(cx
),
2201 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
2202 visibility
: self.vis
.clean(cx
),
2203 stability
: get_stability(cx
, cx
.tcx
.hir
.local_def_id(self.id
)),
2204 deprecation
: get_deprecation(cx
, cx
.tcx
.hir
.local_def_id(self.id
)),
2210 impl<'tcx
> Clean
<Item
> for ty
::AssociatedItem
{
2211 fn clean(&self, cx
: &DocContext
) -> Item
{
2212 let inner
= match self.kind
{
2213 ty
::AssociatedKind
::Const
=> {
2214 let ty
= cx
.tcx
.type_of(self.def_id
);
2215 let default = if self.defaultness
.has_value() {
2216 Some(inline
::print_inlined_const(cx
, self.def_id
))
2220 AssociatedConstItem(ty
.clean(cx
), default)
2222 ty
::AssociatedKind
::Method
=> {
2223 let generics
= (cx
.tcx
.generics_of(self.def_id
),
2224 &cx
.tcx
.predicates_of(self.def_id
)).clean(cx
);
2225 let sig
= cx
.tcx
.fn_sig(self.def_id
);
2226 let mut decl
= (self.def_id
, sig
).clean(cx
);
2228 if self.method_has_self_argument
{
2229 let self_ty
= match self.container
{
2230 ty
::ImplContainer(def_id
) => {
2231 cx
.tcx
.type_of(def_id
)
2233 ty
::TraitContainer(_
) => cx
.tcx
.mk_self_type()
2235 let self_arg_ty
= *sig
.input(0).skip_binder();
2236 if self_arg_ty
== self_ty
{
2237 decl
.inputs
.values
[0].type_
= Generic(String
::from("Self"));
2238 } else if let ty
::TyRef(_
, mt
) = self_arg_ty
.sty
{
2239 if mt
.ty
== self_ty
{
2240 match decl
.inputs
.values
[0].type_
{
2241 BorrowedRef{ref mut type_, ..}
=> {
2242 **type_
= Generic(String
::from("Self"))
2244 _
=> unreachable
!(),
2250 let provided
= match self.container
{
2251 ty
::ImplContainer(_
) => true,
2252 ty
::TraitContainer(_
) => self.defaultness
.has_value()
2255 let constness
= if cx
.tcx
.is_const_fn(self.def_id
) {
2256 hir
::Constness
::Const
2258 hir
::Constness
::NotConst
2261 unsafety
: sig
.unsafety(),
2268 TyMethodItem(TyMethod
{
2269 unsafety
: sig
.unsafety(),
2276 ty
::AssociatedKind
::Type
=> {
2277 let my_name
= self.name
.clean(cx
);
2279 if let ty
::TraitContainer(did
) = self.container
{
2280 // When loading a cross-crate associated type, the bounds for this type
2281 // are actually located on the trait/impl itself, so we need to load
2282 // all of the generics from there and then look for bounds that are
2283 // applied to this associated type in question.
2284 let predicates
= cx
.tcx
.predicates_of(did
);
2285 let generics
= (cx
.tcx
.generics_of(did
), &predicates
).clean(cx
);
2286 let mut bounds
= generics
.where_predicates
.iter().filter_map(|pred
| {
2287 let (name
, self_type
, trait_
, bounds
) = match *pred
{
2288 WherePredicate
::BoundPredicate
{
2289 ty
: QPath { ref name, ref self_type, ref trait_ }
,
2291 } => (name
, self_type
, trait_
, bounds
),
2294 if *name
!= my_name { return None }
2296 ResolvedPath { did, .. }
if did
== self.container
.id() => {}
2300 Generic(ref s
) if *s
== "Self" => {}
2304 }).flat_map(|i
| i
.iter().cloned()).collect
::<Vec
<_
>>();
2305 // Our Sized/?Sized bound didn't get handled when creating the generics
2306 // because we didn't actually get our whole set of bounds until just now
2307 // (some of them may have come from the trait). If we do have a sized
2308 // bound, we remove it, and if we don't then we add the `?Sized` bound
2310 match bounds
.iter().position(|b
| b
.is_sized_bound(cx
)) {
2311 Some(i
) => { bounds.remove(i); }
2312 None
=> bounds
.push(TyParamBound
::maybe_sized(cx
)),
2315 let ty
= if self.defaultness
.has_value() {
2316 Some(cx
.tcx
.type_of(self.def_id
))
2321 AssociatedTypeItem(bounds
, ty
.clean(cx
))
2323 TypedefItem(Typedef
{
2324 type_
: cx
.tcx
.type_of(self.def_id
).clean(cx
),
2325 generics
: Generics
{
2327 where_predicates
: Vec
::new(),
2334 let visibility
= match self.container
{
2335 ty
::ImplContainer(_
) => self.vis
.clean(cx
),
2336 ty
::TraitContainer(_
) => None
,
2340 name
: Some(self.name
.clean(cx
)),
2342 stability
: get_stability(cx
, self.def_id
),
2343 deprecation
: get_deprecation(cx
, self.def_id
),
2344 def_id
: self.def_id
,
2345 attrs
: inline
::load_attrs(cx
, self.def_id
),
2346 source
: cx
.tcx
.def_span(self.def_id
).clean(cx
),
2352 /// A trait reference, which may have higher ranked lifetimes.
2353 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
2354 pub struct PolyTrait
{
2356 pub generic_params
: Vec
<GenericParam
>,
2359 /// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
2360 /// type out of the AST/TyCtxt given one of these, if more information is needed. Most importantly
2361 /// it does not preserve mutability or boxes.
2362 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
2364 /// structs/enums/traits (most that'd be an hir::TyPath)
2367 typarams
: Option
<Vec
<TyParamBound
>>,
2369 /// true if is a `T::Name` path for associated types
2372 /// For parameterized types, so the consumer of the JSON don't go
2373 /// looking for types which don't exist anywhere.
2375 /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
2376 /// arrays, slices, and tuples.
2377 Primitive(PrimitiveType
),
2379 BareFunction(Box
<BareFunctionDecl
>),
2382 Array(Box
<Type
>, String
),
2385 RawPointer(Mutability
, Box
<Type
>),
2387 lifetime
: Option
<Lifetime
>,
2388 mutability
: Mutability
,
2392 // <Type as Trait>::Name
2395 self_type
: Box
<Type
>,
2402 // impl TraitA+TraitB
2403 ImplTrait(Vec
<TyParamBound
>),
2406 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
2407 pub enum PrimitiveType
{
2408 Isize
, I8
, I16
, I32
, I64
, I128
,
2409 Usize
, U8
, U16
, U32
, U64
, U128
,
2424 #[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
2440 pub trait GetDefId
{
2441 fn def_id(&self) -> Option
<DefId
>;
2444 impl<T
: GetDefId
> GetDefId
for Option
<T
> {
2445 fn def_id(&self) -> Option
<DefId
> {
2446 self.as_ref().and_then(|d
| d
.def_id())
2451 pub fn primitive_type(&self) -> Option
<PrimitiveType
> {
2453 Primitive(p
) | BorrowedRef { type_: box Primitive(p), ..}
=> Some(p
),
2454 Slice(..) | BorrowedRef { type_: box Slice(..), .. }
=> Some(PrimitiveType
::Slice
),
2455 Array(..) | BorrowedRef { type_: box Array(..), .. }
=> Some(PrimitiveType
::Array
),
2456 Tuple(ref tys
) => if tys
.is_empty() {
2457 Some(PrimitiveType
::Unit
)
2459 Some(PrimitiveType
::Tuple
)
2461 RawPointer(..) => Some(PrimitiveType
::RawPointer
),
2462 BorrowedRef { type_: box Generic(..), .. }
=> Some(PrimitiveType
::Reference
),
2463 BareFunction(..) => Some(PrimitiveType
::Fn
),
2464 Never
=> Some(PrimitiveType
::Never
),
2469 pub fn is_generic(&self) -> bool
{
2471 ResolvedPath { is_generic, .. }
=> is_generic
,
2476 pub fn is_self_type(&self) -> bool
{
2478 Generic(ref name
) => name
== "Self",
2483 pub fn generics(&self) -> Option
<&[Type
]> {
2485 ResolvedPath { ref path, .. }
=> {
2486 path
.segments
.last().and_then(|seg
| {
2487 if let PathParameters
::AngleBracketed { ref types, .. }
= seg
.params
{
2499 impl GetDefId
for Type
{
2500 fn def_id(&self) -> Option
<DefId
> {
2502 ResolvedPath { did, .. }
=> Some(did
),
2503 Primitive(p
) => ::html
::render
::cache().primitive_locations
.get(&p
).cloned(),
2504 BorrowedRef { type_: box Generic(..), .. }
=>
2505 Primitive(PrimitiveType
::Reference
).def_id(),
2506 BorrowedRef { ref type_, .. }
=> type_
.def_id(),
2507 Tuple(ref tys
) => if tys
.is_empty() {
2508 Primitive(PrimitiveType
::Unit
).def_id()
2510 Primitive(PrimitiveType
::Tuple
).def_id()
2512 BareFunction(..) => Primitive(PrimitiveType
::Fn
).def_id(),
2513 Never
=> Primitive(PrimitiveType
::Never
).def_id(),
2514 Slice(..) => Primitive(PrimitiveType
::Slice
).def_id(),
2515 Array(..) => Primitive(PrimitiveType
::Array
).def_id(),
2516 RawPointer(..) => Primitive(PrimitiveType
::RawPointer
).def_id(),
2517 QPath { ref self_type, .. }
=> self_type
.def_id(),
2523 impl PrimitiveType
{
2524 fn from_str(s
: &str) -> Option
<PrimitiveType
> {
2526 "isize" => Some(PrimitiveType
::Isize
),
2527 "i8" => Some(PrimitiveType
::I8
),
2528 "i16" => Some(PrimitiveType
::I16
),
2529 "i32" => Some(PrimitiveType
::I32
),
2530 "i64" => Some(PrimitiveType
::I64
),
2531 "i128" => Some(PrimitiveType
::I128
),
2532 "usize" => Some(PrimitiveType
::Usize
),
2533 "u8" => Some(PrimitiveType
::U8
),
2534 "u16" => Some(PrimitiveType
::U16
),
2535 "u32" => Some(PrimitiveType
::U32
),
2536 "u64" => Some(PrimitiveType
::U64
),
2537 "u128" => Some(PrimitiveType
::U128
),
2538 "bool" => Some(PrimitiveType
::Bool
),
2539 "char" => Some(PrimitiveType
::Char
),
2540 "str" => Some(PrimitiveType
::Str
),
2541 "f32" => Some(PrimitiveType
::F32
),
2542 "f64" => Some(PrimitiveType
::F64
),
2543 "array" => Some(PrimitiveType
::Array
),
2544 "slice" => Some(PrimitiveType
::Slice
),
2545 "tuple" => Some(PrimitiveType
::Tuple
),
2546 "unit" => Some(PrimitiveType
::Unit
),
2547 "pointer" => Some(PrimitiveType
::RawPointer
),
2548 "reference" => Some(PrimitiveType
::Reference
),
2549 "fn" => Some(PrimitiveType
::Fn
),
2550 "never" => Some(PrimitiveType
::Never
),
2555 pub fn as_str(&self) -> &'
static str {
2556 use self::PrimitiveType
::*;
2579 RawPointer
=> "pointer",
2580 Reference
=> "reference",
2586 pub fn to_url_str(&self) -> &'
static str {
2591 impl From
<ast
::IntTy
> for PrimitiveType
{
2592 fn from(int_ty
: ast
::IntTy
) -> PrimitiveType
{
2594 ast
::IntTy
::Isize
=> PrimitiveType
::Isize
,
2595 ast
::IntTy
::I8
=> PrimitiveType
::I8
,
2596 ast
::IntTy
::I16
=> PrimitiveType
::I16
,
2597 ast
::IntTy
::I32
=> PrimitiveType
::I32
,
2598 ast
::IntTy
::I64
=> PrimitiveType
::I64
,
2599 ast
::IntTy
::I128
=> PrimitiveType
::I128
,
2604 impl From
<ast
::UintTy
> for PrimitiveType
{
2605 fn from(uint_ty
: ast
::UintTy
) -> PrimitiveType
{
2607 ast
::UintTy
::Usize
=> PrimitiveType
::Usize
,
2608 ast
::UintTy
::U8
=> PrimitiveType
::U8
,
2609 ast
::UintTy
::U16
=> PrimitiveType
::U16
,
2610 ast
::UintTy
::U32
=> PrimitiveType
::U32
,
2611 ast
::UintTy
::U64
=> PrimitiveType
::U64
,
2612 ast
::UintTy
::U128
=> PrimitiveType
::U128
,
2617 impl From
<ast
::FloatTy
> for PrimitiveType
{
2618 fn from(float_ty
: ast
::FloatTy
) -> PrimitiveType
{
2620 ast
::FloatTy
::F32
=> PrimitiveType
::F32
,
2621 ast
::FloatTy
::F64
=> PrimitiveType
::F64
,
2626 impl Clean
<Type
> for hir
::Ty
{
2627 fn clean(&self, cx
: &DocContext
) -> Type
{
2631 TyPtr(ref m
) => RawPointer(m
.mutbl
.clean(cx
), box m
.ty
.clean(cx
)),
2632 TyRptr(ref l
, ref m
) => {
2633 let lifetime
= if l
.is_elided() {
2638 BorrowedRef
{lifetime
: lifetime
, mutability
: m
.mutbl
.clean(cx
),
2639 type_
: box m
.ty
.clean(cx
)}
2641 TySlice(ref ty
) => Slice(box ty
.clean(cx
)),
2642 TyArray(ref ty
, n
) => {
2643 let def_id
= cx
.tcx
.hir
.body_owner_def_id(n
);
2644 let param_env
= cx
.tcx
.param_env(def_id
);
2645 let substs
= Substs
::identity_for_item(cx
.tcx
, def_id
);
2646 let cid
= GlobalId
{
2647 instance
: ty
::Instance
::new(def_id
, substs
),
2650 let n
= cx
.tcx
.const_eval(param_env
.and(cid
)).unwrap_or_else(|_
| {
2651 cx
.tcx
.mk_const(ty
::Const
{
2652 val
: ConstVal
::Unevaluated(def_id
, substs
),
2653 ty
: cx
.tcx
.types
.usize
2656 let n
= print_const(cx
, n
);
2657 Array(box ty
.clean(cx
), n
)
2659 TyTup(ref tys
) => Tuple(tys
.clean(cx
)),
2660 TyPath(hir
::QPath
::Resolved(None
, ref path
)) => {
2661 if let Some(new_ty
) = cx
.ty_substs
.borrow().get(&path
.def
).cloned() {
2665 if let Def
::TyParam(did
) = path
.def
{
2666 if let Some(bounds
) = cx
.impl_trait_bounds
.borrow_mut().remove(&did
) {
2667 return ImplTrait(bounds
);
2671 let mut alias
= None
;
2672 if let Def
::TyAlias(def_id
) = path
.def
{
2673 // Substitute private type aliases
2674 if let Some(node_id
) = cx
.tcx
.hir
.as_local_node_id(def_id
) {
2675 if !cx
.access_levels
.borrow().is_exported(def_id
) {
2676 alias
= Some(&cx
.tcx
.hir
.expect_item(node_id
).node
);
2681 if let Some(&hir
::ItemTy(ref ty
, ref generics
)) = alias
{
2682 let provided_params
= &path
.segments
.last().unwrap();
2683 let mut ty_substs
= FxHashMap();
2684 let mut lt_substs
= FxHashMap();
2685 provided_params
.with_parameters(|provided_params
| {
2686 for (i
, ty_param
) in generics
.ty_params().enumerate() {
2687 let ty_param_def
= Def
::TyParam(cx
.tcx
.hir
.local_def_id(ty_param
.id
));
2688 if let Some(ty
) = provided_params
.types
.get(i
).cloned() {
2689 ty_substs
.insert(ty_param_def
, ty
.into_inner().clean(cx
));
2690 } else if let Some(default) = ty_param
.default.clone() {
2691 ty_substs
.insert(ty_param_def
, default.into_inner().clean(cx
));
2695 for (i
, lt_param
) in generics
.lifetimes().enumerate() {
2696 if let Some(lt
) = provided_params
.lifetimes
.get(i
).cloned() {
2697 if !lt
.is_elided() {
2698 let lt_def_id
= cx
.tcx
.hir
.local_def_id(lt_param
.lifetime
.id
);
2699 lt_substs
.insert(lt_def_id
, lt
.clean(cx
));
2704 return cx
.enter_alias(ty_substs
, lt_substs
, || ty
.clean(cx
));
2706 resolve_type(cx
, path
.clean(cx
), self.id
)
2708 TyPath(hir
::QPath
::Resolved(Some(ref qself
), ref p
)) => {
2709 let mut segments
: Vec
<_
> = p
.segments
.clone().into();
2711 let trait_path
= hir
::Path
{
2713 def
: Def
::Trait(cx
.tcx
.associated_item(p
.def
.def_id()).container
.id()),
2714 segments
: segments
.into(),
2717 name
: p
.segments
.last().unwrap().name
.clean(cx
),
2718 self_type
: box qself
.clean(cx
),
2719 trait_
: box resolve_type(cx
, trait_path
.clean(cx
), self.id
)
2722 TyPath(hir
::QPath
::TypeRelative(ref qself
, ref segment
)) => {
2723 let mut def
= Def
::Err
;
2724 let ty
= hir_ty_to_ty(cx
.tcx
, self);
2725 if let ty
::TyProjection(proj
) = ty
.sty
{
2726 def
= Def
::Trait(proj
.trait_ref(cx
.tcx
).def_id
);
2728 let trait_path
= hir
::Path
{
2731 segments
: vec
![].into(),
2734 name
: segment
.name
.clean(cx
),
2735 self_type
: box qself
.clean(cx
),
2736 trait_
: box resolve_type(cx
, trait_path
.clean(cx
), self.id
)
2739 TyTraitObject(ref bounds
, ref lifetime
) => {
2740 match bounds
[0].clean(cx
).trait_
{
2741 ResolvedPath { path, typarams: None, did, is_generic }
=> {
2742 let mut bounds
: Vec
<_
> = bounds
[1..].iter().map(|bound
| {
2743 TraitBound(bound
.clean(cx
), hir
::TraitBoundModifier
::None
)
2745 if !lifetime
.is_elided() {
2746 bounds
.push(RegionBound(lifetime
.clean(cx
)));
2750 typarams
: Some(bounds
),
2755 _
=> Infer
// shouldn't happen
2758 TyBareFn(ref barefn
) => BareFunction(box barefn
.clean(cx
)),
2759 TyImplTraitExistential(ref exist_ty
, ref _lts
) => ImplTrait(exist_ty
.bounds
.clean(cx
)),
2760 TyInfer
| TyErr
=> Infer
,
2761 TyTypeof(..) => panic
!("Unimplemented type {:?}", self.node
),
2766 impl<'tcx
> Clean
<Type
> for Ty
<'tcx
> {
2767 fn clean(&self, cx
: &DocContext
) -> Type
{
2769 ty
::TyNever
=> Never
,
2770 ty
::TyBool
=> Primitive(PrimitiveType
::Bool
),
2771 ty
::TyChar
=> Primitive(PrimitiveType
::Char
),
2772 ty
::TyInt(int_ty
) => Primitive(int_ty
.into()),
2773 ty
::TyUint(uint_ty
) => Primitive(uint_ty
.into()),
2774 ty
::TyFloat(float_ty
) => Primitive(float_ty
.into()),
2775 ty
::TyStr
=> Primitive(PrimitiveType
::Str
),
2776 ty
::TySlice(ty
) => Slice(box ty
.clean(cx
)),
2777 ty
::TyArray(ty
, n
) => {
2778 let mut n
= cx
.tcx
.lift(&n
).unwrap();
2779 if let ConstVal
::Unevaluated(def_id
, substs
) = n
.val
{
2780 let param_env
= cx
.tcx
.param_env(def_id
);
2781 let cid
= GlobalId
{
2782 instance
: ty
::Instance
::new(def_id
, substs
),
2785 if let Ok(new_n
) = cx
.tcx
.const_eval(param_env
.and(cid
)) {
2789 let n
= print_const(cx
, n
);
2790 Array(box ty
.clean(cx
), n
)
2792 ty
::TyRawPtr(mt
) => RawPointer(mt
.mutbl
.clean(cx
), box mt
.ty
.clean(cx
)),
2793 ty
::TyRef(r
, mt
) => BorrowedRef
{
2794 lifetime
: r
.clean(cx
),
2795 mutability
: mt
.mutbl
.clean(cx
),
2796 type_
: box mt
.ty
.clean(cx
),
2800 let ty
= cx
.tcx
.lift(self).unwrap();
2801 let sig
= ty
.fn_sig(cx
.tcx
);
2802 BareFunction(box BareFunctionDecl
{
2803 unsafety
: sig
.unsafety(),
2804 generic_params
: Vec
::new(),
2805 decl
: (cx
.tcx
.hir
.local_def_id(ast
::CRATE_NODE_ID
), sig
).clean(cx
),
2809 ty
::TyAdt(def
, substs
) => {
2811 let kind
= match def
.adt_kind() {
2812 AdtKind
::Struct
=> TypeKind
::Struct
,
2813 AdtKind
::Union
=> TypeKind
::Union
,
2814 AdtKind
::Enum
=> TypeKind
::Enum
,
2816 inline
::record_extern_fqn(cx
, did
, kind
);
2817 let path
= external_path(cx
, &cx
.tcx
.item_name(did
).as_str(),
2818 None
, false, vec
![], substs
);
2826 ty
::TyForeign(did
) => {
2827 inline
::record_extern_fqn(cx
, did
, TypeKind
::Foreign
);
2828 let path
= external_path(cx
, &cx
.tcx
.item_name(did
).as_str(),
2829 None
, false, vec
![], Substs
::empty());
2837 ty
::TyDynamic(ref obj
, ref reg
) => {
2838 if let Some(principal
) = obj
.principal() {
2839 let did
= principal
.def_id();
2840 inline
::record_extern_fqn(cx
, did
, TypeKind
::Trait
);
2842 let mut typarams
= vec
![];
2843 reg
.clean(cx
).map(|b
| typarams
.push(RegionBound(b
)));
2844 for did
in obj
.auto_traits() {
2845 let empty
= cx
.tcx
.intern_substs(&[]);
2846 let path
= external_path(cx
, &cx
.tcx
.item_name(did
).as_str(),
2847 Some(did
), false, vec
![], empty
);
2848 inline
::record_extern_fqn(cx
, did
, TypeKind
::Trait
);
2849 let bound
= TraitBound(PolyTrait
{
2850 trait_
: ResolvedPath
{
2856 generic_params
: Vec
::new(),
2857 }, hir
::TraitBoundModifier
::None
);
2858 typarams
.push(bound
);
2861 let mut bindings
= vec
![];
2862 for pb
in obj
.projection_bounds() {
2863 bindings
.push(TypeBinding
{
2864 name
: cx
.tcx
.associated_item(pb
.item_def_id()).name
.clean(cx
),
2865 ty
: pb
.skip_binder().ty
.clean(cx
)
2869 let path
= external_path(cx
, &cx
.tcx
.item_name(did
).as_str(), Some(did
),
2870 false, bindings
, principal
.skip_binder().substs
);
2873 typarams
: Some(typarams
),
2881 ty
::TyTuple(ref t
) => Tuple(t
.clean(cx
)),
2883 ty
::TyProjection(ref data
) => data
.clean(cx
),
2885 ty
::TyParam(ref p
) => Generic(p
.name
.to_string()),
2887 ty
::TyAnon(def_id
, substs
) => {
2888 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
2889 // by looking up the projections associated with the def_id.
2890 let predicates_of
= cx
.tcx
.predicates_of(def_id
);
2891 let substs
= cx
.tcx
.lift(&substs
).unwrap();
2892 let bounds
= predicates_of
.instantiate(cx
.tcx
, substs
);
2893 let mut regions
= vec
![];
2894 let mut has_sized
= false;
2895 let mut bounds
= bounds
.predicates
.iter().filter_map(|predicate
| {
2896 let trait_ref
= if let Some(tr
) = predicate
.to_opt_poly_trait_ref() {
2898 } else if let ty
::Predicate
::TypeOutlives(pred
) = *predicate
{
2899 // these should turn up at the end
2900 pred
.skip_binder().1.clean(cx
).map(|r
| regions
.push(RegionBound(r
)));
2906 if let Some(sized
) = cx
.tcx
.lang_items().sized_trait() {
2907 if trait_ref
.def_id() == sized
{
2914 let bounds
= bounds
.predicates
.iter().filter_map(|pred
|
2915 if let ty
::Predicate
::Projection(proj
) = *pred
{
2916 let proj
= proj
.skip_binder();
2917 if proj
.projection_ty
.trait_ref(cx
.tcx
) == *trait_ref
.skip_binder() {
2919 name
: cx
.tcx
.associated_item(proj
.projection_ty
.item_def_id
)
2921 ty
: proj
.ty
.clean(cx
),
2931 Some((trait_ref
.skip_binder(), bounds
).clean(cx
))
2932 }).collect
::<Vec
<_
>>();
2933 bounds
.extend(regions
);
2934 if !has_sized
&& !bounds
.is_empty() {
2935 bounds
.insert(0, TyParamBound
::maybe_sized(cx
));
2940 ty
::TyClosure(..) | ty
::TyGenerator(..) => Tuple(vec
![]), // FIXME(pcwalton)
2942 ty
::TyGeneratorWitness(..) => panic
!("TyGeneratorWitness"),
2943 ty
::TyInfer(..) => panic
!("TyInfer"),
2944 ty
::TyError
=> panic
!("TyError"),
2949 impl Clean
<Item
> for hir
::StructField
{
2950 fn clean(&self, cx
: &DocContext
) -> Item
{
2952 name
: Some(self.name
).clean(cx
),
2953 attrs
: self.attrs
.clean(cx
),
2954 source
: self.span
.clean(cx
),
2955 visibility
: self.vis
.clean(cx
),
2956 stability
: get_stability(cx
, cx
.tcx
.hir
.local_def_id(self.id
)),
2957 deprecation
: get_deprecation(cx
, cx
.tcx
.hir
.local_def_id(self.id
)),
2958 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
2959 inner
: StructFieldItem(self.ty
.clean(cx
)),
2964 impl<'tcx
> Clean
<Item
> for ty
::FieldDef
{
2965 fn clean(&self, cx
: &DocContext
) -> Item
{
2967 name
: Some(self.name
).clean(cx
),
2968 attrs
: cx
.tcx
.get_attrs(self.did
).clean(cx
),
2969 source
: cx
.tcx
.def_span(self.did
).clean(cx
),
2970 visibility
: self.vis
.clean(cx
),
2971 stability
: get_stability(cx
, self.did
),
2972 deprecation
: get_deprecation(cx
, self.did
),
2974 inner
: StructFieldItem(cx
.tcx
.type_of(self.did
).clean(cx
)),
2979 #[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug)]
2980 pub enum Visibility
{
2985 impl Clean
<Option
<Visibility
>> for hir
::Visibility
{
2986 fn clean(&self, _
: &DocContext
) -> Option
<Visibility
> {
2987 Some(if *self == hir
::Visibility
::Public { Public }
else { Inherited }
)
2991 impl Clean
<Option
<Visibility
>> for ty
::Visibility
{
2992 fn clean(&self, _
: &DocContext
) -> Option
<Visibility
> {
2993 Some(if *self == ty
::Visibility
::Public { Public }
else { Inherited }
)
2997 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2999 pub struct_type
: doctree
::StructType
,
3000 pub generics
: Generics
,
3001 pub fields
: Vec
<Item
>,
3002 pub fields_stripped
: bool
,
3005 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3007 pub struct_type
: doctree
::StructType
,
3008 pub generics
: Generics
,
3009 pub fields
: Vec
<Item
>,
3010 pub fields_stripped
: bool
,
3013 impl Clean
<Vec
<Item
>> for doctree
::Struct
{
3014 fn clean(&self, cx
: &DocContext
) -> Vec
<Item
> {
3015 let name
= self.name
.clean(cx
);
3016 let mut ret
= get_auto_traits_with_node_id(cx
, self.id
, name
.clone());
3020 attrs
: self.attrs
.clean(cx
),
3021 source
: self.whence
.clean(cx
),
3022 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
3023 visibility
: self.vis
.clean(cx
),
3024 stability
: self.stab
.clean(cx
),
3025 deprecation
: self.depr
.clean(cx
),
3026 inner
: StructItem(Struct
{
3027 struct_type
: self.struct_type
,
3028 generics
: self.generics
.clean(cx
),
3029 fields
: self.fields
.clean(cx
),
3030 fields_stripped
: false,
3038 impl Clean
<Vec
<Item
>> for doctree
::Union
{
3039 fn clean(&self, cx
: &DocContext
) -> Vec
<Item
> {
3040 let name
= self.name
.clean(cx
);
3041 let mut ret
= get_auto_traits_with_node_id(cx
, self.id
, name
.clone());
3045 attrs
: self.attrs
.clean(cx
),
3046 source
: self.whence
.clean(cx
),
3047 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
3048 visibility
: self.vis
.clean(cx
),
3049 stability
: self.stab
.clean(cx
),
3050 deprecation
: self.depr
.clean(cx
),
3051 inner
: UnionItem(Union
{
3052 struct_type
: self.struct_type
,
3053 generics
: self.generics
.clean(cx
),
3054 fields
: self.fields
.clean(cx
),
3055 fields_stripped
: false,
3063 /// This is a more limited form of the standard Struct, different in that
3064 /// it lacks the things most items have (name, id, parameterization). Found
3065 /// only as a variant in an enum.
3066 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3067 pub struct VariantStruct
{
3068 pub struct_type
: doctree
::StructType
,
3069 pub fields
: Vec
<Item
>,
3070 pub fields_stripped
: bool
,
3073 impl Clean
<VariantStruct
> for ::rustc
::hir
::VariantData
{
3074 fn clean(&self, cx
: &DocContext
) -> VariantStruct
{
3076 struct_type
: doctree
::struct_type_from_def(self),
3077 fields
: self.fields().iter().map(|x
| x
.clean(cx
)).collect(),
3078 fields_stripped
: false,
3083 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3085 pub variants
: Vec
<Item
>,
3086 pub generics
: Generics
,
3087 pub variants_stripped
: bool
,
3090 impl Clean
<Vec
<Item
>> for doctree
::Enum
{
3091 fn clean(&self, cx
: &DocContext
) -> Vec
<Item
> {
3092 let name
= self.name
.clean(cx
);
3093 let mut ret
= get_auto_traits_with_node_id(cx
, self.id
, name
.clone());
3097 attrs
: self.attrs
.clean(cx
),
3098 source
: self.whence
.clean(cx
),
3099 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
3100 visibility
: self.vis
.clean(cx
),
3101 stability
: self.stab
.clean(cx
),
3102 deprecation
: self.depr
.clean(cx
),
3103 inner
: EnumItem(Enum
{
3104 variants
: self.variants
.clean(cx
),
3105 generics
: self.generics
.clean(cx
),
3106 variants_stripped
: false,
3114 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3115 pub struct Variant
{
3116 pub kind
: VariantKind
,
3119 impl Clean
<Item
> for doctree
::Variant
{
3120 fn clean(&self, cx
: &DocContext
) -> Item
{
3122 name
: Some(self.name
.clean(cx
)),
3123 attrs
: self.attrs
.clean(cx
),
3124 source
: self.whence
.clean(cx
),
3126 stability
: self.stab
.clean(cx
),
3127 deprecation
: self.depr
.clean(cx
),
3128 def_id
: cx
.tcx
.hir
.local_def_id(self.def
.id()),
3129 inner
: VariantItem(Variant
{
3130 kind
: self.def
.clean(cx
),
3136 impl<'tcx
> Clean
<Item
> for ty
::VariantDef
{
3137 fn clean(&self, cx
: &DocContext
) -> Item
{
3138 let kind
= match self.ctor_kind
{
3139 CtorKind
::Const
=> VariantKind
::CLike
,
3142 self.fields
.iter().map(|f
| cx
.tcx
.type_of(f
.did
).clean(cx
)).collect()
3145 CtorKind
::Fictive
=> {
3146 VariantKind
::Struct(VariantStruct
{
3147 struct_type
: doctree
::Plain
,
3148 fields_stripped
: false,
3149 fields
: self.fields
.iter().map(|field
| {
3151 source
: cx
.tcx
.def_span(field
.did
).clean(cx
),
3152 name
: Some(field
.name
.clean(cx
)),
3153 attrs
: cx
.tcx
.get_attrs(field
.did
).clean(cx
),
3154 visibility
: field
.vis
.clean(cx
),
3156 stability
: get_stability(cx
, field
.did
),
3157 deprecation
: get_deprecation(cx
, field
.did
),
3158 inner
: StructFieldItem(cx
.tcx
.type_of(field
.did
).clean(cx
))
3165 name
: Some(self.name
.clean(cx
)),
3166 attrs
: inline
::load_attrs(cx
, self.did
),
3167 source
: cx
.tcx
.def_span(self.did
).clean(cx
),
3168 visibility
: Some(Inherited
),
3170 inner
: VariantItem(Variant { kind: kind }
),
3171 stability
: get_stability(cx
, self.did
),
3172 deprecation
: get_deprecation(cx
, self.did
),
3177 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3178 pub enum VariantKind
{
3181 Struct(VariantStruct
),
3184 impl Clean
<VariantKind
> for hir
::VariantData
{
3185 fn clean(&self, cx
: &DocContext
) -> VariantKind
{
3186 if self.is_struct() {
3187 VariantKind
::Struct(self.clean(cx
))
3188 } else if self.is_unit() {
3191 VariantKind
::Tuple(self.fields().iter().map(|x
| x
.ty
.clean(cx
)).collect())
3196 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3198 pub filename
: FileName
,
3206 pub fn empty() -> Span
{
3208 filename
: FileName
::Anon
,
3209 loline
: 0, locol
: 0,
3210 hiline
: 0, hicol
: 0,
3215 impl Clean
<Span
> for syntax_pos
::Span
{
3216 fn clean(&self, cx
: &DocContext
) -> Span
{
3217 if *self == DUMMY_SP
{
3218 return Span
::empty();
3221 let cm
= cx
.sess().codemap();
3222 let filename
= cm
.span_to_filename(*self);
3223 let lo
= cm
.lookup_char_pos(self.lo());
3224 let hi
= cm
.lookup_char_pos(self.hi());
3228 locol
: lo
.col
.to_usize(),
3230 hicol
: hi
.col
.to_usize(),
3235 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3239 pub segments
: Vec
<PathSegment
>,
3243 pub fn singleton(name
: String
) -> Path
{
3247 segments
: vec
![PathSegment
{
3249 params
: PathParameters
::AngleBracketed
{
3250 lifetimes
: Vec
::new(),
3252 bindings
: Vec
::new(),
3258 pub fn last_name(&self) -> &str {
3259 self.segments
.last().unwrap().name
.as_str()
3263 impl Clean
<Path
> for hir
::Path
{
3264 fn clean(&self, cx
: &DocContext
) -> Path
{
3266 global
: self.is_global(),
3268 segments
: if self.is_global() { &self.segments[1..] }
else { &self.segments }
.clean(cx
),
3273 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3274 pub enum PathParameters
{
3276 lifetimes
: Vec
<Lifetime
>,
3278 bindings
: Vec
<TypeBinding
>,
3282 output
: Option
<Type
>,
3286 impl Clean
<PathParameters
> for hir
::PathParameters
{
3287 fn clean(&self, cx
: &DocContext
) -> PathParameters
{
3288 if self.parenthesized
{
3289 let output
= self.bindings
[0].ty
.clean(cx
);
3290 PathParameters
::Parenthesized
{
3291 inputs
: self.inputs().clean(cx
),
3292 output
: if output
!= Type
::Tuple(Vec
::new()) { Some(output) }
else { None }
3295 PathParameters
::AngleBracketed
{
3296 lifetimes
: if self.lifetimes
.iter().all(|lt
| lt
.is_elided()) {
3299 self.lifetimes
.clean(cx
)
3301 types
: self.types
.clean(cx
),
3302 bindings
: self.bindings
.clean(cx
),
3308 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3309 pub struct PathSegment
{
3311 pub params
: PathParameters
,
3314 impl Clean
<PathSegment
> for hir
::PathSegment
{
3315 fn clean(&self, cx
: &DocContext
) -> PathSegment
{
3317 name
: self.name
.clean(cx
),
3318 params
: self.with_parameters(|parameters
| parameters
.clean(cx
))
3323 fn strip_type(ty
: Type
) -> Type
{
3325 Type
::ResolvedPath { path, typarams, did, is_generic }
=> {
3326 Type
::ResolvedPath { path: strip_path(&path), typarams, did, is_generic }
3328 Type
::Tuple(inner_tys
) => {
3329 Type
::Tuple(inner_tys
.iter().map(|t
| strip_type(t
.clone())).collect())
3331 Type
::Slice(inner_ty
) => Type
::Slice(Box
::new(strip_type(*inner_ty
))),
3332 Type
::Array(inner_ty
, s
) => Type
::Array(Box
::new(strip_type(*inner_ty
)), s
),
3333 Type
::Unique(inner_ty
) => Type
::Unique(Box
::new(strip_type(*inner_ty
))),
3334 Type
::RawPointer(m
, inner_ty
) => Type
::RawPointer(m
, Box
::new(strip_type(*inner_ty
))),
3335 Type
::BorrowedRef { lifetime, mutability, type_ }
=> {
3336 Type
::BorrowedRef { lifetime, mutability, type_: Box::new(strip_type(*type_)) }
3338 Type
::QPath { name, self_type, trait_ }
=> {
3341 self_type
: Box
::new(strip_type(*self_type
)), trait_
: Box
::new(strip_type(*trait_
))
3348 fn strip_path(path
: &Path
) -> Path
{
3349 let segments
= path
.segments
.iter().map(|s
| {
3351 name
: s
.name
.clone(),
3352 params
: PathParameters
::AngleBracketed
{
3353 lifetimes
: Vec
::new(),
3355 bindings
: Vec
::new(),
3361 global
: path
.global
,
3362 def
: path
.def
.clone(),
3367 fn qpath_to_string(p
: &hir
::QPath
) -> String
{
3368 let segments
= match *p
{
3369 hir
::QPath
::Resolved(_
, ref path
) => &path
.segments
,
3370 hir
::QPath
::TypeRelative(_
, ref segment
) => return segment
.name
.to_string(),
3373 let mut s
= String
::new();
3374 for (i
, seg
) in segments
.iter().enumerate() {
3378 if seg
.name
!= keywords
::CrateRoot
.name() {
3379 s
.push_str(&*seg
.name
.as_str());
3385 impl Clean
<String
> for ast
::Name
{
3386 fn clean(&self, _
: &DocContext
) -> String
{
3391 impl Clean
<String
> for InternedString
{
3392 fn clean(&self, _
: &DocContext
) -> String
{
3397 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3398 pub struct Typedef
{
3400 pub generics
: Generics
,
3403 impl Clean
<Item
> for doctree
::Typedef
{
3404 fn clean(&self, cx
: &DocContext
) -> Item
{
3406 name
: Some(self.name
.clean(cx
)),
3407 attrs
: self.attrs
.clean(cx
),
3408 source
: self.whence
.clean(cx
),
3409 def_id
: cx
.tcx
.hir
.local_def_id(self.id
.clone()),
3410 visibility
: self.vis
.clean(cx
),
3411 stability
: self.stab
.clean(cx
),
3412 deprecation
: self.depr
.clean(cx
),
3413 inner
: TypedefItem(Typedef
{
3414 type_
: self.ty
.clean(cx
),
3415 generics
: self.gen
.clean(cx
),
3421 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3422 pub struct BareFunctionDecl
{
3423 pub unsafety
: hir
::Unsafety
,
3424 pub generic_params
: Vec
<GenericParam
>,
3429 impl Clean
<BareFunctionDecl
> for hir
::BareFnTy
{
3430 fn clean(&self, cx
: &DocContext
) -> BareFunctionDecl
{
3431 let (generic_params
, decl
) = enter_impl_trait(cx
, || {
3432 (self.generic_params
.clean(cx
), (&*self.decl
, &self.arg_names
[..]).clean(cx
))
3435 unsafety
: self.unsafety
,
3443 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3446 pub mutability
: Mutability
,
3447 /// It's useful to have the value of a static documented, but I have no
3448 /// desire to represent expressions (that'd basically be all of the AST,
3449 /// which is huge!). So, have a string.
3453 impl Clean
<Item
> for doctree
::Static
{
3454 fn clean(&self, cx
: &DocContext
) -> Item
{
3455 debug
!("cleaning static {}: {:?}", self.name
.clean(cx
), self);
3457 name
: Some(self.name
.clean(cx
)),
3458 attrs
: self.attrs
.clean(cx
),
3459 source
: self.whence
.clean(cx
),
3460 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
3461 visibility
: self.vis
.clean(cx
),
3462 stability
: self.stab
.clean(cx
),
3463 deprecation
: self.depr
.clean(cx
),
3464 inner
: StaticItem(Static
{
3465 type_
: self.type_
.clean(cx
),
3466 mutability
: self.mutability
.clean(cx
),
3467 expr
: print_const_expr(cx
, self.expr
),
3473 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3474 pub struct Constant
{
3479 impl Clean
<Item
> for doctree
::Constant
{
3480 fn clean(&self, cx
: &DocContext
) -> Item
{
3482 name
: Some(self.name
.clean(cx
)),
3483 attrs
: self.attrs
.clean(cx
),
3484 source
: self.whence
.clean(cx
),
3485 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
3486 visibility
: self.vis
.clean(cx
),
3487 stability
: self.stab
.clean(cx
),
3488 deprecation
: self.depr
.clean(cx
),
3489 inner
: ConstantItem(Constant
{
3490 type_
: self.type_
.clean(cx
),
3491 expr
: print_const_expr(cx
, self.expr
),
3497 #[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Copy, Hash)]
3498 pub enum Mutability
{
3503 impl Clean
<Mutability
> for hir
::Mutability
{
3504 fn clean(&self, _
: &DocContext
) -> Mutability
{
3506 &hir
::MutMutable
=> Mutable
,
3507 &hir
::MutImmutable
=> Immutable
,
3512 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Copy, Debug, Hash)]
3513 pub enum ImplPolarity
{
3518 impl Clean
<ImplPolarity
> for hir
::ImplPolarity
{
3519 fn clean(&self, _
: &DocContext
) -> ImplPolarity
{
3521 &hir
::ImplPolarity
::Positive
=> ImplPolarity
::Positive
,
3522 &hir
::ImplPolarity
::Negative
=> ImplPolarity
::Negative
,
3527 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3529 pub unsafety
: hir
::Unsafety
,
3530 pub generics
: Generics
,
3531 pub provided_trait_methods
: FxHashSet
<String
>,
3532 pub trait_
: Option
<Type
>,
3534 pub items
: Vec
<Item
>,
3535 pub polarity
: Option
<ImplPolarity
>,
3536 pub synthetic
: bool
,
3539 pub fn get_auto_traits_with_node_id(cx
: &DocContext
, id
: ast
::NodeId
, name
: String
) -> Vec
<Item
> {
3540 let finder
= AutoTraitFinder { cx }
;
3541 finder
.get_with_node_id(id
, name
)
3544 pub fn get_auto_traits_with_def_id(cx
: &DocContext
, id
: DefId
) -> Vec
<Item
> {
3545 let finder
= AutoTraitFinder
{
3549 finder
.get_with_def_id(id
)
3552 impl Clean
<Vec
<Item
>> for doctree
::Impl
{
3553 fn clean(&self, cx
: &DocContext
) -> Vec
<Item
> {
3554 let mut ret
= Vec
::new();
3555 let trait_
= self.trait_
.clean(cx
);
3556 let items
= self.items
.clean(cx
);
3558 // If this impl block is an implementation of the Deref trait, then we
3559 // need to try inlining the target's inherent impl blocks as well.
3560 if trait_
.def_id() == cx
.tcx
.lang_items().deref_trait() {
3561 build_deref_target_impls(cx
, &items
, &mut ret
);
3564 let provided
= trait_
.def_id().map(|did
| {
3565 cx
.tcx
.provided_trait_methods(did
)
3567 .map(|meth
| meth
.name
.to_string())
3569 }).unwrap_or(FxHashSet());
3573 attrs
: self.attrs
.clean(cx
),
3574 source
: self.whence
.clean(cx
),
3575 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
3576 visibility
: self.vis
.clean(cx
),
3577 stability
: self.stab
.clean(cx
),
3578 deprecation
: self.depr
.clean(cx
),
3579 inner
: ImplItem(Impl
{
3580 unsafety
: self.unsafety
,
3581 generics
: self.generics
.clean(cx
),
3582 provided_trait_methods
: provided
,
3584 for_
: self.for_
.clean(cx
),
3586 polarity
: Some(self.polarity
.clean(cx
)),
3594 fn build_deref_target_impls(cx
: &DocContext
,
3596 ret
: &mut Vec
<Item
>) {
3597 use self::PrimitiveType
::*;
3601 let target
= match item
.inner
{
3602 TypedefItem(ref t
, true) => &t
.type_
,
3605 let primitive
= match *target
{
3606 ResolvedPath { did, .. }
if did
.is_local() => continue,
3607 ResolvedPath { did, .. }
=> {
3608 // We set the last parameter to false to avoid looking for auto-impls for traits
3609 // and therefore avoid an ICE.
3610 // The reason behind this is that auto-traits don't propagate through Deref so
3611 // we're not supposed to synthesise impls for them.
3612 ret
.extend(inline
::build_impls(cx
, did
, false));
3615 _
=> match target
.primitive_type() {
3620 let did
= match primitive
{
3621 Isize
=> tcx
.lang_items().isize_impl(),
3622 I8
=> tcx
.lang_items().i8_impl(),
3623 I16
=> tcx
.lang_items().i16_impl(),
3624 I32
=> tcx
.lang_items().i32_impl(),
3625 I64
=> tcx
.lang_items().i64_impl(),
3626 I128
=> tcx
.lang_items().i128_impl(),
3627 Usize
=> tcx
.lang_items().usize_impl(),
3628 U8
=> tcx
.lang_items().u8_impl(),
3629 U16
=> tcx
.lang_items().u16_impl(),
3630 U32
=> tcx
.lang_items().u32_impl(),
3631 U64
=> tcx
.lang_items().u64_impl(),
3632 U128
=> tcx
.lang_items().u128_impl(),
3633 F32
=> tcx
.lang_items().f32_impl(),
3634 F64
=> tcx
.lang_items().f64_impl(),
3635 Char
=> tcx
.lang_items().char_impl(),
3637 Str
=> tcx
.lang_items().str_impl(),
3638 Slice
=> tcx
.lang_items().slice_impl(),
3639 Array
=> tcx
.lang_items().slice_impl(),
3642 RawPointer
=> tcx
.lang_items().const_ptr_impl(),
3647 if let Some(did
) = did
{
3648 if !did
.is_local() {
3649 inline
::build_impl(cx
, did
, ret
);
3655 impl Clean
<Item
> for doctree
::ExternCrate
{
3656 fn clean(&self, cx
: &DocContext
) -> Item
{
3659 attrs
: self.attrs
.clean(cx
),
3660 source
: self.whence
.clean(cx
),
3661 def_id
: DefId { krate: self.cnum, index: CRATE_DEF_INDEX }
,
3662 visibility
: self.vis
.clean(cx
),
3665 inner
: ExternCrateItem(self.name
.clean(cx
), self.path
.clone())
3670 impl Clean
<Vec
<Item
>> for doctree
::Import
{
3671 fn clean(&self, cx
: &DocContext
) -> Vec
<Item
> {
3672 // We consider inlining the documentation of `pub use` statements, but we
3673 // forcefully don't inline if this is not public or if the
3674 // #[doc(no_inline)] attribute is present.
3675 // Don't inline doc(hidden) imports so they can be stripped at a later stage.
3676 let denied
= self.vis
!= hir
::Public
|| self.attrs
.iter().any(|a
| {
3677 a
.name() == "doc" && match a
.meta_item_list() {
3678 Some(l
) => attr
::list_contains_name(&l
, "no_inline") ||
3679 attr
::list_contains_name(&l
, "hidden"),
3683 let path
= self.path
.clean(cx
);
3684 let inner
= if self.glob
{
3685 Import
::Glob(resolve_use_source(cx
, path
))
3687 let name
= self.name
;
3689 let mut visited
= FxHashSet();
3690 if let Some(items
) = inline
::try_inline(cx
, path
.def
, name
, &mut visited
) {
3694 Import
::Simple(name
.clean(cx
), resolve_use_source(cx
, path
))
3698 attrs
: self.attrs
.clean(cx
),
3699 source
: self.whence
.clean(cx
),
3700 def_id
: cx
.tcx
.hir
.local_def_id(ast
::CRATE_NODE_ID
),
3701 visibility
: self.vis
.clean(cx
),
3704 inner
: ImportItem(inner
)
3709 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3711 // use source as str;
3712 Simple(String
, ImportSource
),
3717 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3718 pub struct ImportSource
{
3720 pub did
: Option
<DefId
>,
3723 impl Clean
<Vec
<Item
>> for hir
::ForeignMod
{
3724 fn clean(&self, cx
: &DocContext
) -> Vec
<Item
> {
3725 let mut items
= self.items
.clean(cx
);
3726 for item
in &mut items
{
3727 if let ForeignFunctionItem(ref mut f
) = item
.inner
{
3735 impl Clean
<Item
> for hir
::ForeignItem
{
3736 fn clean(&self, cx
: &DocContext
) -> Item
{
3737 let inner
= match self.node
{
3738 hir
::ForeignItemFn(ref decl
, ref names
, ref generics
) => {
3739 let (generics
, decl
) = enter_impl_trait(cx
, || {
3740 (generics
.clean(cx
), (&**decl
, &names
[..]).clean(cx
))
3742 ForeignFunctionItem(Function
{
3745 unsafety
: hir
::Unsafety
::Unsafe
,
3747 constness
: hir
::Constness
::NotConst
,
3750 hir
::ForeignItemStatic(ref ty
, mutbl
) => {
3751 ForeignStaticItem(Static
{
3752 type_
: ty
.clean(cx
),
3753 mutability
: if mutbl {Mutable}
else {Immutable}
,
3754 expr
: "".to_string(),
3757 hir
::ForeignItemType
=> {
3762 name
: Some(self.name
.clean(cx
)),
3763 attrs
: self.attrs
.clean(cx
),
3764 source
: self.span
.clean(cx
),
3765 def_id
: cx
.tcx
.hir
.local_def_id(self.id
),
3766 visibility
: self.vis
.clean(cx
),
3767 stability
: get_stability(cx
, cx
.tcx
.hir
.local_def_id(self.id
)),
3768 deprecation
: get_deprecation(cx
, cx
.tcx
.hir
.local_def_id(self.id
)),
3777 fn to_src(&self, cx
: &DocContext
) -> String
;
3780 impl ToSource
for syntax_pos
::Span
{
3781 fn to_src(&self, cx
: &DocContext
) -> String
{
3782 debug
!("converting span {:?} to snippet", self.clean(cx
));
3783 let sn
= match cx
.sess().codemap().span_to_snippet(*self) {
3784 Ok(x
) => x
.to_string(),
3785 Err(_
) => "".to_string()
3787 debug
!("got snippet {}", sn
);
3792 fn name_from_pat(p
: &hir
::Pat
) -> String
{
3794 debug
!("Trying to get a name from pattern: {:?}", p
);
3797 PatKind
::Wild
=> "_".to_string(),
3798 PatKind
::Binding(_
, _
, ref p
, _
) => p
.node
.to_string(),
3799 PatKind
::TupleStruct(ref p
, ..) | PatKind
::Path(ref p
) => qpath_to_string(p
),
3800 PatKind
::Struct(ref name
, ref fields
, etc
) => {
3801 format
!("{} {{ {}{} }}", qpath_to_string(name
),
3802 fields
.iter().map(|&Spanned { node: ref fp, .. }
|
3803 format
!("{}: {}", fp
.name
, name_from_pat(&*fp
.pat
)))
3804 .collect
::<Vec
<String
>>().join(", "),
3805 if etc { ", ..." }
else { "" }
3808 PatKind
::Tuple(ref elts
, _
) => format
!("({})", elts
.iter().map(|p
| name_from_pat(&**p
))
3809 .collect
::<Vec
<String
>>().join(", ")),
3810 PatKind
::Box(ref p
) => name_from_pat(&**p
),
3811 PatKind
::Ref(ref p
, _
) => name_from_pat(&**p
),
3812 PatKind
::Lit(..) => {
3813 warn
!("tried to get argument name from PatKind::Lit, \
3814 which is silly in function arguments");
3817 PatKind
::Range(..) => panic
!("tried to get argument name from PatKind::Range, \
3818 which is not allowed in function arguments"),
3819 PatKind
::Slice(ref begin
, ref mid
, ref end
) => {
3820 let begin
= begin
.iter().map(|p
| name_from_pat(&**p
));
3821 let mid
= mid
.as_ref().map(|p
| format
!("..{}", name_from_pat(&**p
))).into_iter();
3822 let end
= end
.iter().map(|p
| name_from_pat(&**p
));
3823 format
!("[{}]", begin
.chain(mid
).chain(end
).collect
::<Vec
<_
>>().join(", "))
3828 fn print_const(cx
: &DocContext
, n
: &ty
::Const
) -> String
{
3830 ConstVal
::Unevaluated(def_id
, _
) => {
3831 if let Some(node_id
) = cx
.tcx
.hir
.as_local_node_id(def_id
) {
3832 print_const_expr(cx
, cx
.tcx
.hir
.body_owned_by(node_id
))
3834 inline
::print_inlined_const(cx
, def_id
)
3837 ConstVal
::Value(val
) => {
3838 let mut s
= String
::new();
3839 ::rustc
::mir
::print_miri_value(val
, n
.ty
, &mut s
).unwrap();
3840 // array lengths are obviously usize
3841 if s
.ends_with("usize") {
3842 let n
= s
.len() - "usize".len();
3850 fn print_const_expr(cx
: &DocContext
, body
: hir
::BodyId
) -> String
{
3851 cx
.tcx
.hir
.node_to_pretty_string(body
.node_id
)
3854 /// Given a type Path, resolve it to a Type using the TyCtxt
3855 fn resolve_type(cx
: &DocContext
,
3857 id
: ast
::NodeId
) -> Type
{
3858 if id
== ast
::DUMMY_NODE_ID
{
3859 debug
!("resolve_type({:?})", path
);
3861 debug
!("resolve_type({:?},{:?})", path
, id
);
3864 let is_generic
= match path
.def
{
3865 Def
::PrimTy(p
) => match p
{
3866 hir
::TyStr
=> return Primitive(PrimitiveType
::Str
),
3867 hir
::TyBool
=> return Primitive(PrimitiveType
::Bool
),
3868 hir
::TyChar
=> return Primitive(PrimitiveType
::Char
),
3869 hir
::TyInt(int_ty
) => return Primitive(int_ty
.into()),
3870 hir
::TyUint(uint_ty
) => return Primitive(uint_ty
.into()),
3871 hir
::TyFloat(float_ty
) => return Primitive(float_ty
.into()),
3873 Def
::SelfTy(..) if path
.segments
.len() == 1 => {
3874 return Generic(keywords
::SelfType
.name().to_string());
3876 Def
::TyParam(..) if path
.segments
.len() == 1 => {
3877 return Generic(format
!("{:#}", path
));
3879 Def
::SelfTy(..) | Def
::TyParam(..) | Def
::AssociatedTy(..) => true,
3882 let did
= register_def(&*cx
, path
.def
);
3883 ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
3886 fn register_def(cx
: &DocContext
, def
: Def
) -> DefId
{
3887 debug
!("register_def({:?})", def
);
3889 let (did
, kind
) = match def
{
3890 Def
::Fn(i
) => (i
, TypeKind
::Function
),
3891 Def
::TyAlias(i
) => (i
, TypeKind
::Typedef
),
3892 Def
::Enum(i
) => (i
, TypeKind
::Enum
),
3893 Def
::Trait(i
) => (i
, TypeKind
::Trait
),
3894 Def
::Struct(i
) => (i
, TypeKind
::Struct
),
3895 Def
::Union(i
) => (i
, TypeKind
::Union
),
3896 Def
::Mod(i
) => (i
, TypeKind
::Module
),
3897 Def
::TyForeign(i
) => (i
, TypeKind
::Foreign
),
3898 Def
::Const(i
) => (i
, TypeKind
::Const
),
3899 Def
::Static(i
, _
) => (i
, TypeKind
::Static
),
3900 Def
::Variant(i
) => (cx
.tcx
.parent_def_id(i
).unwrap(), TypeKind
::Enum
),
3901 Def
::Macro(i
, _
) => (i
, TypeKind
::Macro
),
3902 Def
::SelfTy(Some(def_id
), _
) => (def_id
, TypeKind
::Trait
),
3903 Def
::SelfTy(_
, Some(impl_def_id
)) => {
3906 _
=> return def
.def_id()
3908 if did
.is_local() { return did }
3909 inline
::record_extern_fqn(cx
, did
, kind
);
3910 if let TypeKind
::Trait
= kind
{
3911 inline
::record_extern_trait(cx
, did
);
3916 fn resolve_use_source(cx
: &DocContext
, path
: Path
) -> ImportSource
{
3918 did
: if path
.def
== Def
::Err
{
3921 Some(register_def(cx
, path
.def
))
3927 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3930 pub imported_from
: Option
<String
>,
3933 impl Clean
<Item
> for doctree
::Macro
{
3934 fn clean(&self, cx
: &DocContext
) -> Item
{
3935 let name
= self.name
.clean(cx
);
3937 name
: Some(name
.clone()),
3938 attrs
: self.attrs
.clean(cx
),
3939 source
: self.whence
.clean(cx
),
3940 visibility
: Some(Public
),
3941 stability
: self.stab
.clean(cx
),
3942 deprecation
: self.depr
.clean(cx
),
3943 def_id
: self.def_id
,
3944 inner
: MacroItem(Macro
{
3945 source
: format
!("macro_rules! {} {{\n{}}}",
3947 self.matchers
.iter().map(|span
| {
3948 format
!(" {} => {{ ... }};\n", span
.to_src(cx
))
3949 }).collect
::<String
>()),
3950 imported_from
: self.imported_from
.clean(cx
),
3956 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3957 pub struct Stability
{
3958 pub level
: stability
::StabilityLevel
,
3959 pub feature
: String
,
3961 pub deprecated_since
: String
,
3962 pub deprecated_reason
: String
,
3963 pub unstable_reason
: String
,
3964 pub issue
: Option
<u32>
3967 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3968 pub struct Deprecation
{
3973 impl Clean
<Stability
> for attr
::Stability
{
3974 fn clean(&self, _
: &DocContext
) -> Stability
{
3976 level
: stability
::StabilityLevel
::from_attr_level(&self.level
),
3977 feature
: self.feature
.to_string(),
3978 since
: match self.level
{
3979 attr
::Stable {ref since}
=> since
.to_string(),
3980 _
=> "".to_string(),
3982 deprecated_since
: match self.rustc_depr
{
3983 Some(attr
::RustcDeprecation {ref since, ..}
) => since
.to_string(),
3986 deprecated_reason
: match self.rustc_depr
{
3987 Some(ref depr
) => depr
.reason
.to_string(),
3988 _
=> "".to_string(),
3990 unstable_reason
: match self.level
{
3991 attr
::Unstable { reason: Some(ref reason), .. }
=> reason
.to_string(),
3992 _
=> "".to_string(),
3994 issue
: match self.level
{
3995 attr
::Unstable {issue, ..}
=> Some(issue
),
4002 impl<'a
> Clean
<Stability
> for &'a attr
::Stability
{
4003 fn clean(&self, dc
: &DocContext
) -> Stability
{
4008 impl Clean
<Deprecation
> for attr
::Deprecation
{
4009 fn clean(&self, _
: &DocContext
) -> Deprecation
{
4011 since
: self.since
.as_ref().map_or("".to_string(), |s
| s
.to_string()),
4012 note
: self.note
.as_ref().map_or("".to_string(), |s
| s
.to_string()),
4017 /// An equality constraint on an associated type, e.g. `A=Bar` in `Foo<A=Bar>`
4018 #[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug, Hash)]
4019 pub struct TypeBinding
{
4024 impl Clean
<TypeBinding
> for hir
::TypeBinding
{
4025 fn clean(&self, cx
: &DocContext
) -> TypeBinding
{
4027 name
: self.name
.clean(cx
),
4028 ty
: self.ty
.clean(cx
)
4033 pub fn def_id_to_path(cx
: &DocContext
, did
: DefId
, name
: Option
<String
>) -> Vec
<String
> {
4034 let crate_name
= name
.unwrap_or_else(|| cx
.tcx
.crate_name(did
.krate
).to_string());
4035 let relative
= cx
.tcx
.def_path(did
).data
.into_iter().filter_map(|elem
| {
4036 // extern blocks have an empty name
4037 let s
= elem
.data
.to_string();
4044 once(crate_name
).chain(relative
).collect()
4047 pub fn enter_impl_trait
<F
, R
>(cx
: &DocContext
, f
: F
) -> R
4051 let old_bounds
= mem
::replace(&mut *cx
.impl_trait_bounds
.borrow_mut(), Default
::default());
4053 assert
!(cx
.impl_trait_bounds
.borrow().is_empty());
4054 *cx
.impl_trait_bounds
.borrow_mut() = old_bounds
;
4058 // Start of code copied from rust-clippy
4060 pub fn get_trait_def_id(tcx
: &TyCtxt
, path
: &[&str], use_local
: bool
) -> Option
<DefId
> {
4062 path_to_def_local(tcx
, path
)
4064 path_to_def(tcx
, path
)
4068 pub fn path_to_def_local(tcx
: &TyCtxt
, path
: &[&str]) -> Option
<DefId
> {
4069 let krate
= tcx
.hir
.krate();
4070 let mut items
= krate
.module
.item_ids
.clone();
4071 let mut path_it
= path
.iter().peekable();
4074 let segment
= match path_it
.next() {
4075 Some(segment
) => segment
,
4076 None
=> return None
,
4079 for item_id
in mem
::replace(&mut items
, HirVec
::new()).iter() {
4080 let item
= tcx
.hir
.expect_item(item_id
.id
);
4081 if item
.name
== *segment
{
4082 if path_it
.peek().is_none() {
4083 return Some(tcx
.hir
.local_def_id(item_id
.id
))
4086 items
= match &item
.node
{
4087 &hir
::ItemMod(ref m
) => m
.item_ids
.clone(),
4088 _
=> panic
!("Unexpected item {:?} in path {:?} path")
4096 pub fn path_to_def(tcx
: &TyCtxt
, path
: &[&str]) -> Option
<DefId
> {
4097 let crates
= tcx
.crates();
4101 .find(|&&krate
| tcx
.crate_name(krate
) == path
[0]);
4103 if let Some(krate
) = krate
{
4106 index
: CRATE_DEF_INDEX
,
4108 let mut items
= tcx
.item_children(krate
);
4109 let mut path_it
= path
.iter().skip(1).peekable();
4112 let segment
= match path_it
.next() {
4113 Some(segment
) => segment
,
4114 None
=> return None
,
4117 for item
in mem
::replace(&mut items
, Lrc
::new(vec
![])).iter() {
4118 if item
.ident
.name
== *segment
{
4119 if path_it
.peek().is_none() {
4120 return match item
.def
{
4121 def
::Def
::Trait(did
) => Some(did
),
4126 items
= tcx
.item_children(item
.def
.def_id());
4136 fn get_path_for_type(tcx
: TyCtxt
, def_id
: DefId
, def_ctor
: fn(DefId
) -> Def
) -> hir
::Path
{
4137 struct AbsolutePathBuffer
{
4141 impl ty
::item_path
::ItemPathBuffer
for AbsolutePathBuffer
{
4142 fn root_mode(&self) -> &ty
::item_path
::RootMode
{
4143 const ABSOLUTE
: &'
static ty
::item_path
::RootMode
= &ty
::item_path
::RootMode
::Absolute
;
4147 fn push(&mut self, text
: &str) {
4148 self.names
.push(text
.to_owned());
4152 let mut apb
= AbsolutePathBuffer { names: vec![] }
;
4154 tcx
.push_item_path(&mut apb
, def_id
);
4158 def
: def_ctor(def_id
),
4159 segments
: hir
::HirVec
::from_vec(apb
.names
.iter().map(|s
| hir
::PathSegment
{
4160 name
: ast
::Name
::intern(&s
),
4167 // End of code copied from rust-clippy
4170 #[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
4171 enum RegionTarget
<'tcx
> {
4172 Region(Region
<'tcx
>),
4173 RegionVid(RegionVid
)
4176 #[derive(Default, Debug, Clone)]
4177 struct RegionDeps
<'tcx
> {
4178 larger
: FxHashSet
<RegionTarget
<'tcx
>>,
4179 smaller
: FxHashSet
<RegionTarget
<'tcx
>>
4182 #[derive(Eq, PartialEq, Hash, Debug)]
4184 RegionBound(Lifetime
),
4185 TraitBound(Vec
<PathSegment
>, Vec
<SimpleBound
>, Vec
<GenericParam
>, hir
::TraitBoundModifier
)
4188 enum AutoTraitResult
{
4190 PositiveImpl(Generics
),
4194 impl AutoTraitResult
{
4195 fn is_auto(&self) -> bool
{
4197 AutoTraitResult
::PositiveImpl(_
) | AutoTraitResult
::NegativeImpl
=> true,
4203 impl From
<TyParamBound
> for SimpleBound
{
4204 fn from(bound
: TyParamBound
) -> Self {
4205 match bound
.clone() {
4206 TyParamBound
::RegionBound(l
) => SimpleBound
::RegionBound(l
),
4207 TyParamBound
::TraitBound(t
, mod_
) => match t
.trait_
{
4208 Type
::ResolvedPath { path, typarams, .. }
=> {
4209 SimpleBound
::TraitBound(path
.segments
,
4211 .map_or_else(|| Vec
::new(), |v
| v
.iter()
4212 .map(|p
| SimpleBound
::from(p
.clone()))
4217 _
=> panic
!("Unexpected bound {:?}", bound
),