1 //! This module contains the "cleaned" pieces of the AST, and the functions
11 use rustc_data_structures
::indexed_vec
::{IndexVec, Idx}
;
12 use rustc_data_structures
::sync
::Lrc
;
13 use rustc_target
::spec
::abi
::Abi
;
14 use rustc_typeck
::hir_ty_to_ty
;
15 use rustc
::infer
::region_constraints
::{RegionConstraintData, Constraint}
;
16 use rustc
::middle
::resolve_lifetime
as rl
;
17 use rustc
::middle
::lang_items
;
18 use rustc
::middle
::stability
;
19 use rustc
::mir
::interpret
::{GlobalId, ConstValue}
;
20 use rustc
::hir
::{self, HirVec}
;
21 use rustc
::hir
::def
::{self, Def, CtorKind}
;
22 use rustc
::hir
::def_id
::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}
;
23 use rustc
::hir
::map
::DisambiguatedDefPathData
;
24 use rustc
::ty
::subst
::{Kind, InternalSubsts, SubstsRef, UnpackedKind}
;
25 use rustc
::ty
::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind}
;
26 use rustc
::ty
::fold
::TypeFolder
;
27 use rustc
::ty
::layout
::VariantIdx
;
28 use rustc
::util
::nodemap
::{FxHashMap, FxHashSet}
;
29 use syntax
::ast
::{self, AttrStyle, Ident}
;
31 use syntax
::ext
::base
::MacroKind
;
32 use syntax
::source_map
::{dummy_spanned, Spanned}
;
34 use syntax
::symbol
::keywords
::{self, Keyword}
;
35 use syntax
::symbol
::InternedString
;
36 use syntax_pos
::{self, DUMMY_SP, Pos, FileName}
;
38 use std
::collections
::hash_map
::Entry
;
40 use std
::hash
::{Hash, Hasher}
;
41 use std
::default::Default
;
42 use std
::{mem, slice, vec}
;
43 use std
::iter
::{FromIterator, once}
;
45 use std
::str::FromStr
;
46 use std
::cell
::RefCell
;
50 use parking_lot
::ReentrantMutex
;
52 use crate::core
::{self, DocContext}
;
55 use crate::html
::render
::{cache, ExternalLocation}
;
56 use crate::html
::item_type
::ItemType
;
60 use self::auto_trait
::AutoTraitFinder
;
61 use self::blanket_impl
::BlanketImplFinder
;
63 pub use self::Type
::*;
64 pub use self::Mutability
::*;
65 pub use self::ItemEnum
::*;
66 pub use self::SelfTy
::*;
67 pub use self::FunctionRetTy
::*;
68 pub use self::Visibility
::{Public, Inherited}
;
70 thread_local
!(pub static MAX_DEF_ID
: RefCell
<FxHashMap
<CrateNum
, DefId
>> = Default
::default());
72 const FN_OUTPUT_NAME
: &'
static str = "Output";
74 // extract the stability index for a node from tcx, if possible
75 fn get_stability(cx
: &DocContext
<'_
>, def_id
: DefId
) -> Option
<Stability
> {
76 cx
.tcx
.lookup_stability(def_id
).clean(cx
)
79 fn get_deprecation(cx
: &DocContext
<'_
>, def_id
: DefId
) -> Option
<Deprecation
> {
80 cx
.tcx
.lookup_deprecation(def_id
).clean(cx
)
84 fn clean(&self, cx
: &DocContext
<'_
>) -> T
;
87 impl<T
: Clean
<U
>, U
> Clean
<Vec
<U
>> for [T
] {
88 fn clean(&self, cx
: &DocContext
<'_
>) -> Vec
<U
> {
89 self.iter().map(|x
| x
.clean(cx
)).collect()
93 impl<T
: Clean
<U
>, U
, V
: Idx
> Clean
<IndexVec
<V
, U
>> for IndexVec
<V
, T
> {
94 fn clean(&self, cx
: &DocContext
<'_
>) -> IndexVec
<V
, U
> {
95 self.iter().map(|x
| x
.clean(cx
)).collect()
99 impl<T
: Clean
<U
>, U
> Clean
<U
> for P
<T
> {
100 fn clean(&self, cx
: &DocContext
<'_
>) -> U
{
105 impl<T
: Clean
<U
>, U
> Clean
<U
> for Rc
<T
> {
106 fn clean(&self, cx
: &DocContext
<'_
>) -> U
{
111 impl<T
: Clean
<U
>, U
> Clean
<Option
<U
>> for Option
<T
> {
112 fn clean(&self, cx
: &DocContext
<'_
>) -> Option
<U
> {
113 self.as_ref().map(|v
| v
.clean(cx
))
117 impl<T
, U
> Clean
<U
> for ty
::Binder
<T
> where T
: Clean
<U
> {
118 fn clean(&self, cx
: &DocContext
<'_
>) -> U
{
119 self.skip_binder().clean(cx
)
123 impl<T
: Clean
<U
>, U
> Clean
<Vec
<U
>> for P
<[T
]> {
124 fn clean(&self, cx
: &DocContext
<'_
>) -> Vec
<U
> {
125 self.iter().map(|x
| x
.clean(cx
)).collect()
129 #[derive(Clone, Debug)]
132 pub version
: Option
<String
>,
134 pub module
: Option
<Item
>,
135 pub externs
: Vec
<(CrateNum
, ExternalCrate
)>,
136 pub primitives
: Vec
<(DefId
, PrimitiveType
, Attributes
)>,
137 // These are later on moved into `CACHEKEY`, leaving the map empty.
138 // Only here so that they can be filtered through the rustdoc passes.
139 pub external_traits
: Arc
<ReentrantMutex
<RefCell
<FxHashMap
<DefId
, Trait
>>>>,
140 pub masked_crates
: FxHashSet
<CrateNum
>,
143 impl<'a
, 'tcx
> Clean
<Crate
> for visit_ast
::RustdocVisitor
<'a
, 'tcx
> {
144 fn clean(&self, cx
: &DocContext
<'_
>) -> Crate
{
145 use crate::visit_lib
::LibEmbargoVisitor
;
148 let mut r
= cx
.renderinfo
.borrow_mut();
149 r
.deref_trait_did
= cx
.tcx
.lang_items().deref_trait();
150 r
.deref_mut_trait_did
= cx
.tcx
.lang_items().deref_mut_trait();
151 r
.owned_box_did
= cx
.tcx
.lang_items().owned_box();
154 let mut externs
= Vec
::new();
155 for &cnum
in cx
.tcx
.crates().iter() {
156 externs
.push((cnum
, cnum
.clean(cx
)));
157 // Analyze doc-reachability for extern items
158 LibEmbargoVisitor
::new(cx
).visit_lib(cnum
);
160 externs
.sort_by(|&(a
, _
), &(b
, _
)| a
.cmp(&b
));
162 // Clean the crate, translating the entire libsyntax AST to one that is
163 // understood by rustdoc.
164 let mut module
= self.module
.clean(cx
);
165 let mut masked_crates
= FxHashSet
::default();
168 ModuleItem(ref module
) => {
169 for it
in &module
.items
{
170 // `compiler_builtins` should be masked too, but we can't apply
171 // `#[doc(masked)]` to the injected `extern crate` because it's unstable.
172 if it
.is_extern_crate()
173 && (it
.attrs
.has_doc_flag("masked")
174 || self.cx
.tcx
.is_compiler_builtins(it
.def_id
.krate
))
176 masked_crates
.insert(it
.def_id
.krate
);
183 let ExternalCrate { name, src, primitives, keywords, .. }
= 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
),
201 m
.items
.extend(keywords
.into_iter().map(|(def_id
, kw
, attrs
)| {
203 source
: Span
::empty(),
204 name
: Some(kw
.clone()),
206 visibility
: Some(Public
),
207 stability
: get_stability(cx
, def_id
),
208 deprecation
: get_deprecation(cx
, def_id
),
210 inner
: KeywordItem(kw
),
219 module
: Some(module
),
222 external_traits
: cx
.external_traits
.clone(),
228 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
229 pub struct ExternalCrate
{
232 pub attrs
: Attributes
,
233 pub primitives
: Vec
<(DefId
, PrimitiveType
, Attributes
)>,
234 pub keywords
: Vec
<(DefId
, String
, Attributes
)>,
237 impl Clean
<ExternalCrate
> for CrateNum
{
238 fn clean(&self, cx
: &DocContext
<'_
>) -> ExternalCrate
{
239 let root
= DefId { krate: *self, index: CRATE_DEF_INDEX }
;
240 let krate_span
= cx
.tcx
.def_span(root
);
241 let krate_src
= cx
.sess().source_map().span_to_filename(krate_span
);
243 // Collect all inner modules which are tagged as implementations of
246 // Note that this loop only searches the top-level items of the crate,
247 // and this is intentional. If we were to search the entire crate for an
248 // item tagged with `#[doc(primitive)]` then we would also have to
249 // search the entirety of external modules for items tagged
250 // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
251 // all that metadata unconditionally).
253 // In order to keep the metadata load under control, the
254 // `#[doc(primitive)]` feature is explicitly designed to only allow the
255 // primitive tags to show up as the top level items in a crate.
257 // Also note that this does not attempt to deal with modules tagged
258 // duplicately for the same primitive. This is handled later on when
259 // rendering by delegating everything to a hash map.
260 let as_primitive
= |def
: Def
| {
261 if let Def
::Mod(def_id
) = def
{
262 let attrs
= cx
.tcx
.get_attrs(def_id
).clean(cx
);
264 for attr
in attrs
.lists("doc") {
265 if let Some(v
) = attr
.value_str() {
266 if attr
.check_name("primitive") {
267 prim
= PrimitiveType
::from_str(&v
.as_str());
271 // FIXME: should warn on unknown primitives?
275 return prim
.map(|p
| (def_id
, p
, attrs
));
279 let primitives
= if root
.is_local() {
280 cx
.tcx
.hir().krate().module
.item_ids
.iter().filter_map(|&id
| {
281 let item
= cx
.tcx
.hir().expect_item_by_hir_id(id
.id
);
283 hir
::ItemKind
::Mod(_
) => {
284 as_primitive(Def
::Mod(cx
.tcx
.hir().local_def_id_from_hir_id(id
.id
)))
286 hir
::ItemKind
::Use(ref path
, hir
::UseKind
::Single
)
287 if item
.vis
.node
.is_pub() => {
288 as_primitive(path
.def
).map(|(_
, prim
, attrs
)| {
289 // Pretend the primitive is local.
290 (cx
.tcx
.hir().local_def_id_from_hir_id(id
.id
), prim
, attrs
)
297 cx
.tcx
.item_children(root
).iter().map(|item
| item
.def
)
298 .filter_map(as_primitive
).collect()
301 let as_keyword
= |def
: Def
| {
302 if let Def
::Mod(def_id
) = def
{
303 let attrs
= cx
.tcx
.get_attrs(def_id
).clean(cx
);
304 let mut keyword
= None
;
305 for attr
in attrs
.lists("doc") {
306 if let Some(v
) = attr
.value_str() {
307 if attr
.check_name("keyword") {
308 keyword
= Keyword
::from_str(&v
.as_str()).ok()
309 .map(|x
| x
.name().to_string());
310 if keyword
.is_some() {
313 // FIXME: should warn on unknown keywords?
317 return keyword
.map(|p
| (def_id
, p
, attrs
));
321 let keywords
= if root
.is_local() {
322 cx
.tcx
.hir().krate().module
.item_ids
.iter().filter_map(|&id
| {
323 let item
= cx
.tcx
.hir().expect_item_by_hir_id(id
.id
);
325 hir
::ItemKind
::Mod(_
) => {
326 as_keyword(Def
::Mod(cx
.tcx
.hir().local_def_id_from_hir_id(id
.id
)))
328 hir
::ItemKind
::Use(ref path
, hir
::UseKind
::Single
)
329 if item
.vis
.node
.is_pub() => {
330 as_keyword(path
.def
).map(|(_
, prim
, attrs
)| {
331 (cx
.tcx
.hir().local_def_id_from_hir_id(id
.id
), prim
, attrs
)
338 cx
.tcx
.item_children(root
).iter().map(|item
| item
.def
)
339 .filter_map(as_keyword
).collect()
343 name
: cx
.tcx
.crate_name(*self).to_string(),
345 attrs
: cx
.tcx
.get_attrs(root
).clean(cx
),
352 /// Anything with a source location and set of attributes and, optionally, a
353 /// name. That is, anything that can be documented. This doesn't correspond
354 /// directly to the AST's concept of an item; it's a strict superset.
355 #[derive(Clone, RustcEncodable, RustcDecodable)]
359 /// Not everything has a name. E.g., impls
360 pub name
: Option
<String
>,
361 pub attrs
: Attributes
,
363 pub visibility
: Option
<Visibility
>,
365 pub stability
: Option
<Stability
>,
366 pub deprecation
: Option
<Deprecation
>,
369 impl fmt
::Debug
for Item
{
370 fn fmt(&self, fmt
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
372 let fake
= MAX_DEF_ID
.with(|m
| m
.borrow().get(&self.def_id
.krate
)
373 .map(|id
| self.def_id
>= *id
).unwrap_or(false));
374 let def_id
: &dyn fmt
::Debug
= if fake { &"**FAKE**" }
else { &self.def_id }
;
376 fmt
.debug_struct("Item")
377 .field("source", &self.source
)
378 .field("name", &self.name
)
379 .field("attrs", &self.attrs
)
380 .field("inner", &self.inner
)
381 .field("visibility", &self.visibility
)
382 .field("def_id", def_id
)
383 .field("stability", &self.stability
)
384 .field("deprecation", &self.deprecation
)
390 /// Finds the `doc` attribute as a NameValue and returns the corresponding
392 pub fn doc_value
<'a
>(&'a
self) -> Option
<&'a
str> {
393 self.attrs
.doc_value()
395 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
397 pub fn collapsed_doc_value(&self) -> Option
<String
> {
398 self.attrs
.collapsed_doc_value()
401 pub fn links(&self) -> Vec
<(String
, String
)> {
402 self.attrs
.links(&self.def_id
.krate
)
405 pub fn is_crate(&self) -> bool
{
407 StrippedItem(box ModuleItem(Module { is_crate: true, ..}
)) |
408 ModuleItem(Module { is_crate: true, ..}
) => true,
412 pub fn is_mod(&self) -> bool
{
413 self.type_() == ItemType
::Module
415 pub fn is_trait(&self) -> bool
{
416 self.type_() == ItemType
::Trait
418 pub fn is_struct(&self) -> bool
{
419 self.type_() == ItemType
::Struct
421 pub fn is_enum(&self) -> bool
{
422 self.type_() == ItemType
::Enum
424 pub fn is_variant(&self) -> bool
{
425 self.type_() == ItemType
::Variant
427 pub fn is_associated_type(&self) -> bool
{
428 self.type_() == ItemType
::AssociatedType
430 pub fn is_associated_const(&self) -> bool
{
431 self.type_() == ItemType
::AssociatedConst
433 pub fn is_method(&self) -> bool
{
434 self.type_() == ItemType
::Method
436 pub fn is_ty_method(&self) -> bool
{
437 self.type_() == ItemType
::TyMethod
439 pub fn is_typedef(&self) -> bool
{
440 self.type_() == ItemType
::Typedef
442 pub fn is_primitive(&self) -> bool
{
443 self.type_() == ItemType
::Primitive
445 pub fn is_union(&self) -> bool
{
446 self.type_() == ItemType
::Union
448 pub fn is_import(&self) -> bool
{
449 self.type_() == ItemType
::Import
451 pub fn is_extern_crate(&self) -> bool
{
452 self.type_() == ItemType
::ExternCrate
454 pub fn is_keyword(&self) -> bool
{
455 self.type_() == ItemType
::Keyword
458 pub fn is_stripped(&self) -> bool
{
459 match self.inner { StrippedItem(..) => true, _ => false }
461 pub fn has_stripped_fields(&self) -> Option
<bool
> {
463 StructItem(ref _struct
) => Some(_struct
.fields_stripped
),
464 UnionItem(ref union) => Some(union.fields_stripped
),
465 VariantItem(Variant { kind: VariantKind::Struct(ref vstruct)}
) => {
466 Some(vstruct
.fields_stripped
)
472 pub fn stability_class(&self) -> Option
<String
> {
473 self.stability
.as_ref().and_then(|ref s
| {
474 let mut classes
= Vec
::with_capacity(2);
476 if s
.level
== stability
::Unstable
{
477 classes
.push("unstable");
480 if s
.deprecation
.is_some() {
481 classes
.push("deprecated");
484 if classes
.len() != 0 {
485 Some(classes
.join(" "))
492 pub fn stable_since(&self) -> Option
<&str> {
493 self.stability
.as_ref().map(|s
| &s
.since
[..])
496 pub fn is_non_exhaustive(&self) -> bool
{
497 self.attrs
.other_attrs
.iter()
498 .any(|a
| a
.check_name("non_exhaustive"))
501 /// Returns a documentation-level item type from the item.
502 pub fn type_(&self) -> ItemType
{
506 /// Returns the info in the item's `#[deprecated]` or `#[rustc_deprecated]` attributes.
508 /// If the item is not deprecated, returns `None`.
509 pub fn deprecation(&self) -> Option
<&Deprecation
> {
512 .or_else(|| self.stability
.as_ref().and_then(|s
| s
.deprecation
.as_ref()))
514 pub fn is_default(&self) -> bool
{
516 ItemEnum
::MethodItem(ref meth
) => {
517 if let Some(defaultness
) = meth
.defaultness
{
518 defaultness
.has_value() && !defaultness
.is_final()
528 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
530 ExternCrateItem(String
, Option
<String
>),
535 FunctionItem(Function
),
537 TypedefItem(Typedef
, bool
/* is associated type */),
538 ExistentialItem(Existential
, bool
/* is associated type */),
540 ConstantItem(Constant
),
542 TraitAliasItem(TraitAlias
),
544 /// A method signature only. Used for required methods in traits (ie,
545 /// non-default-methods).
546 TyMethodItem(TyMethod
),
547 /// A method with a body.
549 StructFieldItem(Type
),
550 VariantItem(Variant
),
551 /// `fn`s from an extern block
552 ForeignFunctionItem(Function
),
553 /// `static`s from an extern block
554 ForeignStaticItem(Static
),
555 /// `type`s from an extern block
558 ProcMacroItem(ProcMacro
),
559 PrimitiveItem(PrimitiveType
),
560 AssociatedConstItem(Type
, Option
<String
>),
561 AssociatedTypeItem(Vec
<GenericBound
>, Option
<Type
>),
562 /// An item that has been stripped by a rustdoc pass
563 StrippedItem(Box
<ItemEnum
>),
568 pub fn generics(&self) -> Option
<&Generics
> {
570 ItemEnum
::StructItem(ref s
) => &s
.generics
,
571 ItemEnum
::EnumItem(ref e
) => &e
.generics
,
572 ItemEnum
::FunctionItem(ref f
) => &f
.generics
,
573 ItemEnum
::TypedefItem(ref t
, _
) => &t
.generics
,
574 ItemEnum
::ExistentialItem(ref t
, _
) => &t
.generics
,
575 ItemEnum
::TraitItem(ref t
) => &t
.generics
,
576 ItemEnum
::ImplItem(ref i
) => &i
.generics
,
577 ItemEnum
::TyMethodItem(ref i
) => &i
.generics
,
578 ItemEnum
::MethodItem(ref i
) => &i
.generics
,
579 ItemEnum
::ForeignFunctionItem(ref f
) => &f
.generics
,
580 ItemEnum
::TraitAliasItem(ref ta
) => &ta
.generics
,
585 pub fn is_associated(&self) -> bool
{
587 ItemEnum
::TypedefItem(_
, _
) |
588 ItemEnum
::AssociatedTypeItem(_
, _
) => true,
594 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
596 pub items
: Vec
<Item
>,
600 impl Clean
<Item
> for doctree
::Module
{
601 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
602 let name
= if self.name
.is_some() {
603 self.name
.expect("No name provided").clean(cx
)
608 // maintain a stack of mod ids, for doc comment path resolution
609 // but we also need to resolve the module's own docs based on whether its docs were written
610 // inside or outside the module, so check for that
611 let attrs
= self.attrs
.clean(cx
);
613 let mut items
: Vec
<Item
> = vec
![];
614 items
.extend(self.extern_crates
.iter().flat_map(|x
| x
.clean(cx
)));
615 items
.extend(self.imports
.iter().flat_map(|x
| x
.clean(cx
)));
616 items
.extend(self.structs
.iter().map(|x
| x
.clean(cx
)));
617 items
.extend(self.unions
.iter().map(|x
| x
.clean(cx
)));
618 items
.extend(self.enums
.iter().map(|x
| x
.clean(cx
)));
619 items
.extend(self.fns
.iter().map(|x
| x
.clean(cx
)));
620 items
.extend(self.foreigns
.iter().flat_map(|x
| x
.clean(cx
)));
621 items
.extend(self.mods
.iter().map(|x
| x
.clean(cx
)));
622 items
.extend(self.typedefs
.iter().map(|x
| x
.clean(cx
)));
623 items
.extend(self.existentials
.iter().map(|x
| x
.clean(cx
)));
624 items
.extend(self.statics
.iter().map(|x
| x
.clean(cx
)));
625 items
.extend(self.constants
.iter().map(|x
| x
.clean(cx
)));
626 items
.extend(self.traits
.iter().map(|x
| x
.clean(cx
)));
627 items
.extend(self.impls
.iter().flat_map(|x
| x
.clean(cx
)));
628 items
.extend(self.macros
.iter().map(|x
| x
.clean(cx
)));
629 items
.extend(self.proc_macros
.iter().map(|x
| x
.clean(cx
)));
630 items
.extend(self.trait_aliases
.iter().map(|x
| x
.clean(cx
)));
632 // determine if we should display the inner contents or
633 // the outer `mod` item for the source code.
635 let cm
= cx
.sess().source_map();
636 let outer
= cm
.lookup_char_pos(self.where_outer
.lo());
637 let inner
= cm
.lookup_char_pos(self.where_inner
.lo());
638 if outer
.file
.start_pos
== inner
.file
.start_pos
{
642 // mod foo; (and a separate SourceFile for the contents)
650 source
: whence
.clean(cx
),
651 visibility
: self.vis
.clean(cx
),
652 stability
: self.stab
.clean(cx
),
653 deprecation
: self.depr
.clean(cx
),
654 def_id
: cx
.tcx
.hir().local_def_id(self.id
),
655 inner
: ModuleItem(Module
{
656 is_crate
: self.is_crate
,
663 pub struct ListAttributesIter
<'a
> {
664 attrs
: slice
::Iter
<'a
, ast
::Attribute
>,
665 current_list
: vec
::IntoIter
<ast
::NestedMetaItem
>,
669 impl<'a
> Iterator
for ListAttributesIter
<'a
> {
670 type Item
= ast
::NestedMetaItem
;
672 fn next(&mut self) -> Option
<Self::Item
> {
673 if let Some(nested
) = self.current_list
.next() {
677 for attr
in &mut self.attrs
{
678 if let Some(list
) = attr
.meta_item_list() {
679 if attr
.check_name(self.name
) {
680 self.current_list
= list
.into_iter();
681 if let Some(nested
) = self.current_list
.next() {
691 fn size_hint(&self) -> (usize, Option
<usize>) {
692 let lower
= self.current_list
.len();
697 pub trait AttributesExt
{
698 /// Finds an attribute as List and returns the list of attributes nested inside.
699 fn lists
<'a
>(&'a
self, name
: &'a
str) -> ListAttributesIter
<'a
>;
702 impl AttributesExt
for [ast
::Attribute
] {
703 fn lists
<'a
>(&'a
self, name
: &'a
str) -> ListAttributesIter
<'a
> {
706 current_list
: Vec
::new().into_iter(),
712 pub trait NestedAttributesExt
{
713 /// Returns `true` if the attribute list contains a specific `Word`
714 fn has_word(self, word
: &str) -> bool
;
717 impl<I
: IntoIterator
<Item
=ast
::NestedMetaItem
>> NestedAttributesExt
for I
{
718 fn has_word(self, word
: &str) -> bool
{
719 self.into_iter().any(|attr
| attr
.is_word() && attr
.check_name(word
))
723 /// A portion of documentation, extracted from a `#[doc]` attribute.
725 /// Each variant contains the line number within the complete doc-comment where the fragment
726 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
728 /// Included files are kept separate from inline doc comments so that proper line-number
729 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
730 /// kept separate because of issue #42760.
731 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
732 pub enum DocFragment
{
733 /// A doc fragment created from a `///` or `//!` doc comment.
734 SugaredDoc(usize, syntax_pos
::Span
, String
),
735 /// A doc fragment created from a "raw" `#[doc=""]` attribute.
736 RawDoc(usize, syntax_pos
::Span
, String
),
737 /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
738 /// given filename and the file contents.
739 Include(usize, syntax_pos
::Span
, String
, String
),
743 pub fn as_str(&self) -> &str {
745 DocFragment
::SugaredDoc(_
, _
, ref s
) => &s
[..],
746 DocFragment
::RawDoc(_
, _
, ref s
) => &s
[..],
747 DocFragment
::Include(_
, _
, _
, ref s
) => &s
[..],
751 pub fn span(&self) -> syntax_pos
::Span
{
753 DocFragment
::SugaredDoc(_
, span
, _
) |
754 DocFragment
::RawDoc(_
, span
, _
) |
755 DocFragment
::Include(_
, span
, _
, _
) => span
,
760 impl<'a
> FromIterator
<&'a DocFragment
> for String
{
761 fn from_iter
<T
>(iter
: T
) -> Self
763 T
: IntoIterator
<Item
= &'a DocFragment
>
765 iter
.into_iter().fold(String
::new(), |mut acc
, frag
| {
770 DocFragment
::SugaredDoc(_
, _
, ref docs
)
771 | DocFragment
::RawDoc(_
, _
, ref docs
)
772 | DocFragment
::Include(_
, _
, _
, ref docs
) =>
781 #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)]
782 pub struct Attributes
{
783 pub doc_strings
: Vec
<DocFragment
>,
784 pub other_attrs
: Vec
<ast
::Attribute
>,
785 pub cfg
: Option
<Arc
<Cfg
>>,
786 pub span
: Option
<syntax_pos
::Span
>,
787 /// map from Rust paths to resolved defs and potential URL fragments
788 pub links
: Vec
<(String
, Option
<DefId
>, Option
<String
>)>,
789 pub inner_docs
: bool
,
793 /// Extracts the content from an attribute `#[doc(cfg(content))]`.
794 fn extract_cfg(mi
: &ast
::MetaItem
) -> Option
<&ast
::MetaItem
> {
795 use syntax
::ast
::NestedMetaItem
::MetaItem
;
797 if let ast
::MetaItemKind
::List(ref nmis
) = mi
.node
{
799 if let MetaItem(ref cfg_mi
) = nmis
[0] {
800 if cfg_mi
.check_name("cfg") {
801 if let ast
::MetaItemKind
::List(ref cfg_nmis
) = cfg_mi
.node
{
802 if cfg_nmis
.len() == 1 {
803 if let MetaItem(ref content_mi
) = cfg_nmis
[0] {
804 return Some(content_mi
);
816 /// Reads a `MetaItem` from within an attribute, looks for whether it is a
817 /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
819 fn extract_include(mi
: &ast
::MetaItem
)
820 -> Option
<(String
, String
)>
822 mi
.meta_item_list().and_then(|list
| {
824 if meta
.check_name("include") {
825 // the actual compiled `#[doc(include="filename")]` gets expanded to
826 // `#[doc(include(file="filename", contents="file contents")]` so we need to
827 // look for that instead
828 return meta
.meta_item_list().and_then(|list
| {
829 let mut filename
: Option
<String
> = None
;
830 let mut contents
: Option
<String
> = None
;
833 if it
.check_name("file") {
834 if let Some(name
) = it
.value_str() {
835 filename
= Some(name
.to_string());
837 } else if it
.check_name("contents") {
838 if let Some(docs
) = it
.value_str() {
839 contents
= Some(docs
.to_string());
844 if let (Some(filename
), Some(contents
)) = (filename
, contents
) {
845 Some((filename
, contents
))
857 pub fn has_doc_flag(&self, flag
: &str) -> bool
{
858 for attr
in &self.other_attrs
{
859 if !attr
.check_name("doc") { continue; }
861 if let Some(items
) = attr
.meta_item_list() {
862 if items
.iter().filter_map(|i
| i
.meta_item()).any(|it
| it
.check_name(flag
)) {
871 pub fn from_ast(diagnostic
: &::errors
::Handler
,
872 attrs
: &[ast
::Attribute
]) -> Attributes
{
873 let mut doc_strings
= vec
![];
875 let mut cfg
= Cfg
::True
;
876 let mut doc_line
= 0;
878 let other_attrs
= attrs
.iter().filter_map(|attr
| {
879 attr
.with_desugared_doc(|attr
| {
880 if attr
.check_name("doc") {
881 if let Some(mi
) = attr
.meta() {
882 if let Some(value
) = mi
.value_str() {
883 // Extracted #[doc = "..."]
884 let value
= value
.to_string();
886 doc_line
+= value
.lines().count();
888 if attr
.is_sugared_doc
{
889 doc_strings
.push(DocFragment
::SugaredDoc(line
, attr
.span
, value
));
891 doc_strings
.push(DocFragment
::RawDoc(line
, attr
.span
, value
));
895 sp
= Some(attr
.span
);
898 } else if let Some(cfg_mi
) = Attributes
::extract_cfg(&mi
) {
899 // Extracted #[doc(cfg(...))]
900 match Cfg
::parse(cfg_mi
) {
901 Ok(new_cfg
) => cfg
&= new_cfg
,
902 Err(e
) => diagnostic
.span_err(e
.span
, e
.msg
),
905 } else if let Some((filename
, contents
)) = Attributes
::extract_include(&mi
)
908 doc_line
+= contents
.lines().count();
909 doc_strings
.push(DocFragment
::Include(line
,
920 // treat #[target_feature(enable = "feat")] attributes as if they were
921 // #[doc(cfg(target_feature = "feat"))] attributes as well
922 for attr
in attrs
.lists("target_feature") {
923 if attr
.check_name("enable") {
924 if let Some(feat
) = attr
.value_str() {
925 let meta
= attr
::mk_name_value_item_str(Ident
::from_str("target_feature"),
926 dummy_spanned(feat
));
927 if let Ok(feat_cfg
) = Cfg
::parse(&meta
) {
934 let inner_docs
= attrs
.iter()
935 .filter(|a
| a
.check_name("doc"))
937 .map_or(true, |a
| a
.style
== AttrStyle
::Inner
);
942 cfg
: if cfg
== Cfg
::True { None }
else { Some(Arc::new(cfg)) }
,
949 /// Finds the `doc` attribute as a NameValue and returns the corresponding
951 pub fn doc_value
<'a
>(&'a
self) -> Option
<&'a
str> {
952 self.doc_strings
.first().map(|s
| s
.as_str())
955 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
957 pub fn collapsed_doc_value(&self) -> Option
<String
> {
958 if !self.doc_strings
.is_empty() {
959 Some(self.doc_strings
.iter().collect())
965 /// Gets links as a vector
967 /// Cache must be populated before call
968 pub fn links(&self, krate
: &CrateNum
) -> Vec
<(String
, String
)> {
969 use crate::html
::format
::href
;
971 self.links
.iter().filter_map(|&(ref s
, did
, ref fragment
)| {
974 if let Some((mut href
, ..)) = href(did
) {
975 if let Some(ref fragment
) = *fragment
{
977 href
.push_str(fragment
);
979 Some((s
.clone(), href
))
985 if let Some(ref fragment
) = *fragment
{
987 let url
= match cache
.extern_locations
.get(krate
) {
988 Some(&(_
, ref src
, ExternalLocation
::Local
)) =>
989 src
.to_str().expect("invalid file path"),
990 Some(&(_
, _
, ExternalLocation
::Remote(ref s
))) => s
,
991 Some(&(_
, _
, ExternalLocation
::Unknown
)) | None
=>
992 "https://doc.rust-lang.org/nightly",
994 // This is a primitive so the url is done "by hand".
995 let tail
= fragment
.find('
#').unwrap_or_else(|| fragment.len());
997 format
!("{}{}std/primitive.{}.html{}",
999 if !url
.ends_with('
/'
) { "/" }
else { "" }
,
1001 &fragment
[tail
..])))
1003 panic
!("This isn't a primitive?!");
1011 impl PartialEq
for Attributes
{
1012 fn eq(&self, rhs
: &Self) -> bool
{
1013 self.doc_strings
== rhs
.doc_strings
&&
1014 self.cfg
== rhs
.cfg
&&
1015 self.span
== rhs
.span
&&
1016 self.links
== rhs
.links
&&
1017 self.other_attrs
.iter().map(|attr
| attr
.id
).eq(rhs
.other_attrs
.iter().map(|attr
| attr
.id
))
1021 impl Eq
for Attributes {}
1023 impl Hash
for Attributes
{
1024 fn hash
<H
: Hasher
>(&self, hasher
: &mut H
) {
1025 self.doc_strings
.hash(hasher
);
1026 self.cfg
.hash(hasher
);
1027 self.span
.hash(hasher
);
1028 self.links
.hash(hasher
);
1029 for attr
in &self.other_attrs
{
1030 attr
.id
.hash(hasher
);
1035 impl AttributesExt
for Attributes
{
1036 fn lists
<'a
>(&'a
self, name
: &'a
str) -> ListAttributesIter
<'a
> {
1037 self.other_attrs
.lists(name
)
1041 impl Clean
<Attributes
> for [ast
::Attribute
] {
1042 fn clean(&self, cx
: &DocContext
<'_
>) -> Attributes
{
1043 Attributes
::from_ast(cx
.sess().diagnostic(), self)
1047 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1048 pub enum GenericBound
{
1049 TraitBound(PolyTrait
, hir
::TraitBoundModifier
),
1054 fn maybe_sized(cx
: &DocContext
<'_
>) -> GenericBound
{
1055 let did
= cx
.tcx
.require_lang_item(lang_items
::SizedTraitLangItem
);
1056 let empty
= cx
.tcx
.intern_substs(&[]);
1057 let path
= external_path(cx
, &cx
.tcx
.item_name(did
).as_str(),
1058 Some(did
), false, vec
![], empty
);
1059 inline
::record_extern_fqn(cx
, did
, TypeKind
::Trait
);
1060 GenericBound
::TraitBound(PolyTrait
{
1061 trait_
: ResolvedPath
{
1067 generic_params
: Vec
::new(),
1068 }, hir
::TraitBoundModifier
::Maybe
)
1071 fn is_sized_bound(&self, cx
: &DocContext
<'_
>) -> bool
{
1072 use rustc
::hir
::TraitBoundModifier
as TBM
;
1073 if let GenericBound
::TraitBound(PolyTrait { ref trait_, .. }
, TBM
::None
) = *self {
1074 if trait_
.def_id() == cx
.tcx
.lang_items().sized_trait() {
1081 fn get_poly_trait(&self) -> Option
<PolyTrait
> {
1082 if let GenericBound
::TraitBound(ref p
, _
) = *self {
1083 return Some(p
.clone())
1088 fn get_trait_type(&self) -> Option
<Type
> {
1089 if let GenericBound
::TraitBound(PolyTrait { ref trait_, .. }
, _
) = *self {
1090 Some(trait_
.clone())
1097 impl Clean
<GenericBound
> for hir
::GenericBound
{
1098 fn clean(&self, cx
: &DocContext
<'_
>) -> GenericBound
{
1100 hir
::GenericBound
::Outlives(lt
) => GenericBound
::Outlives(lt
.clean(cx
)),
1101 hir
::GenericBound
::Trait(ref t
, modifier
) => {
1102 GenericBound
::TraitBound(t
.clean(cx
), modifier
)
1108 fn external_generic_args(
1109 cx
: &DocContext
<'_
>,
1110 trait_did
: Option
<DefId
>,
1112 bindings
: Vec
<TypeBinding
>,
1113 substs
: SubstsRef
<'_
>,
1115 let mut skip_self
= has_self
;
1116 let mut ty_sty
= None
;
1117 let args
: Vec
<_
> = substs
.iter().filter_map(|kind
| match kind
.unpack() {
1118 UnpackedKind
::Lifetime(lt
) => {
1119 lt
.clean(cx
).and_then(|lt
| Some(GenericArg
::Lifetime(lt
)))
1121 UnpackedKind
::Type(_
) if skip_self
=> {
1125 UnpackedKind
::Type(ty
) => {
1126 ty_sty
= Some(&ty
.sty
);
1127 Some(GenericArg
::Type(ty
.clean(cx
)))
1129 UnpackedKind
::Const(ct
) => Some(GenericArg
::Const(ct
.clean(cx
))),
1133 // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
1134 Some(did
) if cx
.tcx
.lang_items().fn_trait_kind(did
).is_some() => {
1135 assert
!(ty_sty
.is_some());
1136 let inputs
= match ty_sty
{
1137 Some(ty
::Tuple(ref tys
)) => tys
.iter().map(|t
| t
.clean(cx
)).collect(),
1138 _
=> return GenericArgs
::AngleBracketed { args, bindings }
,
1141 // FIXME(#20299) return type comes from a projection now
1142 // match types[1].sty {
1143 // ty::Tuple(ref v) if v.is_empty() => None, // -> ()
1144 // _ => Some(types[1].clean(cx))
1146 GenericArgs
::Parenthesized { inputs, output }
1149 GenericArgs
::AngleBracketed { args, bindings }
1154 // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
1155 // from Fn<(A, B,), C> to Fn(A, B) -> C
1156 fn external_path(cx
: &DocContext
<'_
>, name
: &str, trait_did
: Option
<DefId
>, has_self
: bool
,
1157 bindings
: Vec
<TypeBinding
>, substs
: SubstsRef
<'_
>) -> Path
{
1161 segments
: vec
![PathSegment
{
1162 name
: name
.to_string(),
1163 args
: external_generic_args(cx
, trait_did
, has_self
, bindings
, substs
)
1168 impl<'a
, 'tcx
> Clean
<GenericBound
> for (&'a ty
::TraitRef
<'tcx
>, Vec
<TypeBinding
>) {
1169 fn clean(&self, cx
: &DocContext
<'_
>) -> GenericBound
{
1170 let (trait_ref
, ref bounds
) = *self;
1171 inline
::record_extern_fqn(cx
, trait_ref
.def_id
, TypeKind
::Trait
);
1172 let path
= external_path(cx
, &cx
.tcx
.item_name(trait_ref
.def_id
).as_str(),
1173 Some(trait_ref
.def_id
), true, bounds
.clone(), trait_ref
.substs
);
1175 debug
!("ty::TraitRef\n subst: {:?}\n", trait_ref
.substs
);
1177 // collect any late bound regions
1178 let mut late_bounds
= vec
![];
1179 for ty_s
in trait_ref
.input_types().skip(1) {
1180 if let ty
::Tuple(ts
) = ty_s
.sty
{
1182 if let ty
::Ref(ref reg
, _
, _
) = ty_s
.sty
{
1183 if let &ty
::RegionKind
::ReLateBound(..) = *reg
{
1184 debug
!(" hit an ReLateBound {:?}", reg
);
1185 if let Some(Lifetime(name
)) = reg
.clean(cx
) {
1186 late_bounds
.push(GenericParamDef
{
1188 kind
: GenericParamDefKind
::Lifetime
,
1197 GenericBound
::TraitBound(
1199 trait_
: ResolvedPath
{
1202 did
: trait_ref
.def_id
,
1205 generic_params
: late_bounds
,
1207 hir
::TraitBoundModifier
::None
1212 impl<'tcx
> Clean
<GenericBound
> for ty
::TraitRef
<'tcx
> {
1213 fn clean(&self, cx
: &DocContext
<'_
>) -> GenericBound
{
1214 (self, vec
![]).clean(cx
)
1218 impl<'tcx
> Clean
<Option
<Vec
<GenericBound
>>> for InternalSubsts
<'tcx
> {
1219 fn clean(&self, cx
: &DocContext
<'_
>) -> Option
<Vec
<GenericBound
>> {
1220 let mut v
= Vec
::new();
1221 v
.extend(self.regions().filter_map(|r
| r
.clean(cx
)).map(GenericBound
::Outlives
));
1222 v
.extend(self.types().map(|t
| GenericBound
::TraitBound(PolyTrait
{
1223 trait_
: t
.clean(cx
),
1224 generic_params
: Vec
::new(),
1225 }, hir
::TraitBoundModifier
::None
)));
1226 if !v
.is_empty() {Some(v)}
else {None}
1230 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1231 pub struct Lifetime(String
);
1234 pub fn get_ref
<'a
>(&'a
self) -> &'a
str {
1235 let Lifetime(ref s
) = *self;
1240 pub fn statik() -> Lifetime
{
1241 Lifetime("'static".to_string())
1245 impl Clean
<Lifetime
> for hir
::Lifetime
{
1246 fn clean(&self, cx
: &DocContext
<'_
>) -> Lifetime
{
1247 if self.hir_id
!= hir
::DUMMY_HIR_ID
{
1248 let def
= cx
.tcx
.named_region(self.hir_id
);
1250 Some(rl
::Region
::EarlyBound(_
, node_id
, _
)) |
1251 Some(rl
::Region
::LateBound(_
, node_id
, _
)) |
1252 Some(rl
::Region
::Free(_
, node_id
)) => {
1253 if let Some(lt
) = cx
.lt_substs
.borrow().get(&node_id
).cloned() {
1260 Lifetime(self.name
.ident().to_string())
1264 impl Clean
<Lifetime
> for hir
::GenericParam
{
1265 fn clean(&self, _
: &DocContext
<'_
>) -> Lifetime
{
1267 hir
::GenericParamKind
::Lifetime { .. }
=> {
1268 if self.bounds
.len() > 0 {
1269 let mut bounds
= self.bounds
.iter().map(|bound
| match bound
{
1270 hir
::GenericBound
::Outlives(lt
) => lt
,
1273 let name
= bounds
.next().expect("no more bounds").name
.ident();
1274 let mut s
= format
!("{}: {}", self.name
.ident(), name
);
1275 for bound
in bounds
{
1276 s
.push_str(&format
!(" + {}", bound
.name
.ident()));
1280 Lifetime(self.name
.ident().to_string())
1288 impl Clean
<Constant
> for hir
::ConstArg
{
1289 fn clean(&self, cx
: &DocContext
<'_
>) -> Constant
{
1291 type_
: cx
.tcx
.type_of(cx
.tcx
.hir().body_owner_def_id(self.value
.body
)).clean(cx
),
1292 expr
: print_const_expr(cx
, self.value
.body
),
1297 impl<'tcx
> Clean
<Lifetime
> for ty
::GenericParamDef
{
1298 fn clean(&self, _cx
: &DocContext
<'_
>) -> Lifetime
{
1299 Lifetime(self.name
.to_string())
1303 impl Clean
<Option
<Lifetime
>> for ty
::RegionKind
{
1304 fn clean(&self, cx
: &DocContext
<'_
>) -> Option
<Lifetime
> {
1306 ty
::ReStatic
=> Some(Lifetime
::statik()),
1307 ty
::ReLateBound(_
, ty
::BrNamed(_
, name
)) => Some(Lifetime(name
.to_string())),
1308 ty
::ReEarlyBound(ref data
) => Some(Lifetime(data
.name
.clean(cx
))),
1310 ty
::ReLateBound(..) |
1314 ty
::RePlaceholder(..) |
1316 ty
::ReClosureBound(_
) |
1318 debug
!("Cannot clean region {:?}", self);
1325 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1326 pub enum WherePredicate
{
1327 BoundPredicate { ty: Type, bounds: Vec<GenericBound> }
,
1328 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> }
,
1329 EqPredicate { lhs: Type, rhs: Type }
,
1332 impl WherePredicate
{
1333 pub fn get_bounds(&self) -> Option
<&[GenericBound
]> {
1335 WherePredicate
::BoundPredicate { ref bounds, .. }
=> Some(bounds
),
1336 WherePredicate
::RegionPredicate { ref bounds, .. }
=> Some(bounds
),
1342 impl Clean
<WherePredicate
> for hir
::WherePredicate
{
1343 fn clean(&self, cx
: &DocContext
<'_
>) -> WherePredicate
{
1345 hir
::WherePredicate
::BoundPredicate(ref wbp
) => {
1346 WherePredicate
::BoundPredicate
{
1347 ty
: wbp
.bounded_ty
.clean(cx
),
1348 bounds
: wbp
.bounds
.clean(cx
)
1352 hir
::WherePredicate
::RegionPredicate(ref wrp
) => {
1353 WherePredicate
::RegionPredicate
{
1354 lifetime
: wrp
.lifetime
.clean(cx
),
1355 bounds
: wrp
.bounds
.clean(cx
)
1359 hir
::WherePredicate
::EqPredicate(ref wrp
) => {
1360 WherePredicate
::EqPredicate
{
1361 lhs
: wrp
.lhs_ty
.clean(cx
),
1362 rhs
: wrp
.rhs_ty
.clean(cx
)
1369 impl<'a
> Clean
<Option
<WherePredicate
>> for ty
::Predicate
<'a
> {
1370 fn clean(&self, cx
: &DocContext
<'_
>) -> Option
<WherePredicate
> {
1371 use rustc
::ty
::Predicate
;
1374 Predicate
::Trait(ref pred
) => Some(pred
.clean(cx
)),
1375 Predicate
::Subtype(ref pred
) => Some(pred
.clean(cx
)),
1376 Predicate
::RegionOutlives(ref pred
) => pred
.clean(cx
),
1377 Predicate
::TypeOutlives(ref pred
) => pred
.clean(cx
),
1378 Predicate
::Projection(ref pred
) => Some(pred
.clean(cx
)),
1380 Predicate
::WellFormed(..) |
1381 Predicate
::ObjectSafe(..) |
1382 Predicate
::ClosureKind(..) |
1383 Predicate
::ConstEvaluatable(..) => panic
!("not user writable"),
1388 impl<'a
> Clean
<WherePredicate
> for ty
::TraitPredicate
<'a
> {
1389 fn clean(&self, cx
: &DocContext
<'_
>) -> WherePredicate
{
1390 WherePredicate
::BoundPredicate
{
1391 ty
: self.trait_ref
.self_ty().clean(cx
),
1392 bounds
: vec
![self.trait_ref
.clean(cx
)]
1397 impl<'tcx
> Clean
<WherePredicate
> for ty
::SubtypePredicate
<'tcx
> {
1398 fn clean(&self, _cx
: &DocContext
<'_
>) -> WherePredicate
{
1399 panic
!("subtype predicates are an internal rustc artifact \
1400 and should not be seen by rustdoc")
1404 impl<'tcx
> Clean
<Option
<WherePredicate
>> for
1405 ty
::OutlivesPredicate
<ty
::Region
<'tcx
>,ty
::Region
<'tcx
>> {
1407 fn clean(&self, cx
: &DocContext
<'_
>) -> Option
<WherePredicate
> {
1408 let ty
::OutlivesPredicate(ref a
, ref b
) = *self;
1411 (ty
::ReEmpty
, ty
::ReEmpty
) => {
1417 Some(WherePredicate
::RegionPredicate
{
1418 lifetime
: a
.clean(cx
).expect("failed to clean lifetime"),
1419 bounds
: vec
![GenericBound
::Outlives(b
.clean(cx
).expect("failed to clean bounds"))]
1424 impl<'tcx
> Clean
<Option
<WherePredicate
>> for ty
::OutlivesPredicate
<Ty
<'tcx
>, ty
::Region
<'tcx
>> {
1425 fn clean(&self, cx
: &DocContext
<'_
>) -> Option
<WherePredicate
> {
1426 let ty
::OutlivesPredicate(ref ty
, ref lt
) = *self;
1429 ty
::ReEmpty
=> return None
,
1433 Some(WherePredicate
::BoundPredicate
{
1435 bounds
: vec
![GenericBound
::Outlives(lt
.clean(cx
).expect("failed to clean lifetimes"))]
1440 impl<'tcx
> Clean
<WherePredicate
> for ty
::ProjectionPredicate
<'tcx
> {
1441 fn clean(&self, cx
: &DocContext
<'_
>) -> WherePredicate
{
1442 WherePredicate
::EqPredicate
{
1443 lhs
: self.projection_ty
.clean(cx
),
1444 rhs
: self.ty
.clean(cx
)
1449 impl<'tcx
> Clean
<Type
> for ty
::ProjectionTy
<'tcx
> {
1450 fn clean(&self, cx
: &DocContext
<'_
>) -> Type
{
1451 let trait_
= match self.trait_ref(cx
.tcx
).clean(cx
) {
1452 GenericBound
::TraitBound(t
, _
) => t
.trait_
,
1453 GenericBound
::Outlives(_
) => panic
!("cleaning a trait got a lifetime"),
1456 name
: cx
.tcx
.associated_item(self.item_def_id
).ident
.name
.clean(cx
),
1457 self_type
: box self.self_ty().clean(cx
),
1463 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1464 pub enum GenericParamDefKind
{
1468 bounds
: Vec
<GenericBound
>,
1469 default: Option
<Type
>,
1470 synthetic
: Option
<hir
::SyntheticTyParamKind
>,
1478 impl GenericParamDefKind
{
1479 pub fn is_type(&self) -> bool
{
1481 GenericParamDefKind
::Type { .. }
=> true,
1486 pub fn get_type(&self, cx
: &DocContext
<'_
>) -> Option
<Type
> {
1488 GenericParamDefKind
::Type { did, .. }
=> {
1489 rustc_typeck
::checked_type_of(cx
.tcx
, did
, false).map(|t
| t
.clean(cx
))
1491 GenericParamDefKind
::Const { ref ty, .. }
=> Some(ty
.clone()),
1492 GenericParamDefKind
::Lifetime
=> None
,
1497 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1498 pub struct GenericParamDef
{
1501 pub kind
: GenericParamDefKind
,
1504 impl GenericParamDef
{
1505 pub fn is_synthetic_type_param(&self) -> bool
{
1507 GenericParamDefKind
::Lifetime
|
1508 GenericParamDefKind
::Const { .. }
=> false,
1509 GenericParamDefKind
::Type { ref synthetic, .. }
=> synthetic
.is_some(),
1513 pub fn is_type(&self) -> bool
{
1517 pub fn get_type(&self, cx
: &DocContext
<'_
>) -> Option
<Type
> {
1518 self.kind
.get_type(cx
)
1521 pub fn get_bounds(&self) -> Option
<&[GenericBound
]> {
1523 GenericParamDefKind
::Type { ref bounds, .. }
=> Some(bounds
),
1529 impl Clean
<GenericParamDef
> for ty
::GenericParamDef
{
1530 fn clean(&self, cx
: &DocContext
<'_
>) -> GenericParamDef
{
1531 let (name
, kind
) = match self.kind
{
1532 ty
::GenericParamDefKind
::Lifetime
=> {
1533 (self.name
.to_string(), GenericParamDefKind
::Lifetime
)
1535 ty
::GenericParamDefKind
::Type { has_default, .. }
=> {
1536 cx
.renderinfo
.borrow_mut().external_param_names
1537 .insert(self.def_id
, self.name
.clean(cx
));
1538 let default = if has_default
{
1539 Some(cx
.tcx
.type_of(self.def_id
).clean(cx
))
1543 (self.name
.clean(cx
), GenericParamDefKind
::Type
{
1545 bounds
: vec
![], // These are filled in from the where-clauses.
1550 ty
::GenericParamDefKind
::Const { .. }
=> {
1551 (self.name
.clean(cx
), GenericParamDefKind
::Const
{
1553 ty
: cx
.tcx
.type_of(self.def_id
).clean(cx
),
1565 impl Clean
<GenericParamDef
> for hir
::GenericParam
{
1566 fn clean(&self, cx
: &DocContext
<'_
>) -> GenericParamDef
{
1567 let (name
, kind
) = match self.kind
{
1568 hir
::GenericParamKind
::Lifetime { .. }
=> {
1569 let name
= if self.bounds
.len() > 0 {
1570 let mut bounds
= self.bounds
.iter().map(|bound
| match bound
{
1571 hir
::GenericBound
::Outlives(lt
) => lt
,
1574 let name
= bounds
.next().expect("no more bounds").name
.ident();
1575 let mut s
= format
!("{}: {}", self.name
.ident(), name
);
1576 for bound
in bounds
{
1577 s
.push_str(&format
!(" + {}", bound
.name
.ident()));
1581 self.name
.ident().to_string()
1583 (name
, GenericParamDefKind
::Lifetime
)
1585 hir
::GenericParamKind
::Type { ref default, synthetic }
=> {
1586 (self.name
.ident().name
.clean(cx
), GenericParamDefKind
::Type
{
1587 did
: cx
.tcx
.hir().local_def_id_from_hir_id(self.hir_id
),
1588 bounds
: self.bounds
.clean(cx
),
1589 default: default.clean(cx
),
1590 synthetic
: synthetic
,
1593 hir
::GenericParamKind
::Const { ref ty }
=> {
1594 (self.name
.ident().name
.clean(cx
), GenericParamDefKind
::Const
{
1595 did
: cx
.tcx
.hir().local_def_id_from_hir_id(self.hir_id
),
1608 // maybe use a Generic enum and use Vec<Generic>?
1609 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Default, Hash)]
1610 pub struct Generics
{
1611 pub params
: Vec
<GenericParamDef
>,
1612 pub where_predicates
: Vec
<WherePredicate
>,
1615 impl Clean
<Generics
> for hir
::Generics
{
1616 fn clean(&self, cx
: &DocContext
<'_
>) -> Generics
{
1617 // Synthetic type-parameters are inserted after normal ones.
1618 // In order for normal parameters to be able to refer to synthetic ones,
1619 // scans them first.
1620 fn is_impl_trait(param
: &hir
::GenericParam
) -> bool
{
1622 hir
::GenericParamKind
::Type { synthetic, .. }
=> {
1623 synthetic
== Some(hir
::SyntheticTyParamKind
::ImplTrait
)
1628 let impl_trait_params
= self.params
1630 .filter(|param
| is_impl_trait(param
))
1632 let param
: GenericParamDef
= param
.clean(cx
);
1634 GenericParamDefKind
::Lifetime
=> unreachable
!(),
1635 GenericParamDefKind
::Type { did, ref bounds, .. }
=> {
1636 cx
.impl_trait_bounds
.borrow_mut().insert(did
, bounds
.clone());
1638 GenericParamDefKind
::Const { .. }
=> unreachable
!(),
1642 .collect
::<Vec
<_
>>();
1644 let mut params
= Vec
::with_capacity(self.params
.len());
1645 for p
in self.params
.iter().filter(|p
| !is_impl_trait(p
)) {
1646 let p
= p
.clean(cx
);
1649 params
.extend(impl_trait_params
);
1651 let mut generics
= Generics
{
1653 where_predicates
: self.where_clause
.predicates
.clean(cx
),
1656 // Some duplicates are generated for ?Sized bounds between type params and where
1657 // predicates. The point in here is to move the bounds definitions from type params
1658 // to where predicates when such cases occur.
1659 for where_pred
in &mut generics
.where_predicates
{
1661 WherePredicate
::BoundPredicate { ty: Generic(ref name), ref mut bounds }
=> {
1662 if bounds
.is_empty() {
1663 for param
in &mut generics
.params
{
1665 GenericParamDefKind
::Lifetime
=> {}
1666 GenericParamDefKind
::Type { bounds: ref mut ty_bounds, .. }
=> {
1667 if ¶m
.name
== name
{
1668 mem
::swap(bounds
, ty_bounds
);
1672 GenericParamDefKind
::Const { .. }
=> {}
1684 impl<'a
, 'tcx
> Clean
<Generics
> for (&'a ty
::Generics
,
1685 &'a Lrc
<ty
::GenericPredicates
<'tcx
>>) {
1686 fn clean(&self, cx
: &DocContext
<'_
>) -> Generics
{
1687 use self::WherePredicate
as WP
;
1689 let (gens
, preds
) = *self;
1691 // Bounds in the type_params and lifetimes fields are repeated in the
1692 // predicates field (see rustc_typeck::collect::ty_generics), so remove
1694 let stripped_typarams
= gens
.params
.iter().filter_map(|param
| match param
.kind
{
1695 ty
::GenericParamDefKind
::Lifetime
=> None
,
1696 ty
::GenericParamDefKind
::Type { .. }
=> {
1697 if param
.name
== keywords
::SelfUpper
.name().as_str() {
1698 assert_eq
!(param
.index
, 0);
1701 Some(param
.clean(cx
))
1703 ty
::GenericParamDefKind
::Const { .. }
=> {
1704 unimplemented
!() // FIXME(const_generics)
1706 }).collect
::<Vec
<GenericParamDef
>>();
1708 let mut where_predicates
= preds
.predicates
.iter()
1709 .flat_map(|(p
, _
)| p
.clean(cx
))
1710 .collect
::<Vec
<_
>>();
1712 // Type parameters and have a Sized bound by default unless removed with
1713 // ?Sized. Scan through the predicates and mark any type parameter with
1714 // a Sized bound, removing the bounds as we find them.
1716 // Note that associated types also have a sized bound by default, but we
1717 // don't actually know the set of associated types right here so that's
1718 // handled in cleaning associated types
1719 let mut sized_params
= FxHashSet
::default();
1720 where_predicates
.retain(|pred
| {
1722 WP
::BoundPredicate { ty: Generic(ref g), ref bounds }
=> {
1723 if bounds
.iter().any(|b
| b
.is_sized_bound(cx
)) {
1724 sized_params
.insert(g
.clone());
1734 // Run through the type parameters again and insert a ?Sized
1735 // unbound for any we didn't find to be Sized.
1736 for tp
in &stripped_typarams
{
1737 if !sized_params
.contains(&tp
.name
) {
1738 where_predicates
.push(WP
::BoundPredicate
{
1739 ty
: Type
::Generic(tp
.name
.clone()),
1740 bounds
: vec
![GenericBound
::maybe_sized(cx
)],
1745 // It would be nice to collect all of the bounds on a type and recombine
1746 // them if possible, to avoid e.g., `where T: Foo, T: Bar, T: Sized, T: 'a`
1747 // and instead see `where T: Foo + Bar + Sized + 'a`
1752 .flat_map(|param
| match param
.kind
{
1753 ty
::GenericParamDefKind
::Lifetime
=> Some(param
.clean(cx
)),
1754 ty
::GenericParamDefKind
::Type { .. }
=> None
,
1755 ty
::GenericParamDefKind
::Const { .. }
=> Some(param
.clean(cx
)),
1756 }).chain(simplify
::ty_params(stripped_typarams
).into_iter())
1758 where_predicates
: simplify
::where_clauses(cx
, where_predicates
),
1763 /// The point of this function is to replace bounds with types.
1765 /// i.e. `[T, U]` when you have the following bounds: `T: Display, U: Option<T>` will return
1766 /// `[Display, Option]` (we just returns the list of the types, we don't care about the
1767 /// wrapped types in here).
1769 generics
: &Generics
,
1771 cx
: &DocContext
<'_
>,
1773 ) -> FxHashSet
<Type
> {
1774 let arg_s
= arg
.to_string();
1775 let mut res
= FxHashSet
::default();
1776 if recurse
>= 10 { // FIXME: remove this whole recurse thing when the recursion bug is fixed
1779 if arg
.is_full_generic() {
1780 if let Some(where_pred
) = generics
.where_predicates
.iter().find(|g
| {
1782 &WherePredicate
::BoundPredicate { ref ty, .. }
=> ty
.def_id() == arg
.def_id(),
1786 let bounds
= where_pred
.get_bounds().unwrap_or_else(|| &[]);
1787 for bound
in bounds
.iter() {
1789 GenericBound
::TraitBound(ref poly_trait
, _
) => {
1790 for x
in poly_trait
.generic_params
.iter() {
1794 if let Some(ty
) = x
.get_type(cx
) {
1795 let adds
= get_real_types(generics
, &ty
, cx
, recurse
+ 1);
1796 if !adds
.is_empty() {
1798 } else if !ty
.is_full_generic() {
1808 if let Some(bound
) = generics
.params
.iter().find(|g
| {
1809 g
.is_type() && g
.name
== arg_s
1811 for bound
in bound
.get_bounds().unwrap_or_else(|| &[]) {
1812 if let Some(ty
) = bound
.get_trait_type() {
1813 let adds
= get_real_types(generics
, &ty
, cx
, recurse
+ 1);
1814 if !adds
.is_empty() {
1816 } else if !ty
.is_full_generic() {
1817 res
.insert(ty
.clone());
1823 res
.insert(arg
.clone());
1824 if let Some(gens
) = arg
.generics() {
1825 for gen
in gens
.iter() {
1826 if gen
.is_full_generic() {
1827 let adds
= get_real_types(generics
, gen
, cx
, recurse
+ 1);
1828 if !adds
.is_empty() {
1832 res
.insert(gen
.clone());
1840 /// Return the full list of types when bounds have been resolved.
1842 /// i.e. `fn foo<A: Display, B: Option<A>>(x: u32, y: B)` will return
1843 /// `[u32, Display, Option]`.
1844 pub fn get_all_types(
1845 generics
: &Generics
,
1847 cx
: &DocContext
<'_
>,
1848 ) -> (Vec
<Type
>, Vec
<Type
>) {
1849 let mut all_types
= FxHashSet
::default();
1850 for arg
in decl
.inputs
.values
.iter() {
1851 if arg
.type_
.is_self_type() {
1854 let args
= get_real_types(generics
, &arg
.type_
, cx
, 0);
1855 if !args
.is_empty() {
1856 all_types
.extend(args
);
1858 all_types
.insert(arg
.type_
.clone());
1862 let ret_types
= match decl
.output
{
1863 FunctionRetTy
::Return(ref return_type
) => {
1864 let mut ret
= get_real_types(generics
, &return_type
, cx
, 0);
1866 ret
.insert(return_type
.clone());
1868 ret
.into_iter().collect()
1872 (all_types
.into_iter().collect(), ret_types
)
1875 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1877 pub generics
: Generics
,
1879 pub header
: hir
::FnHeader
,
1880 pub defaultness
: Option
<hir
::Defaultness
>,
1881 pub all_types
: Vec
<Type
>,
1882 pub ret_types
: Vec
<Type
>,
1885 impl<'a
> Clean
<Method
> for (&'a hir
::MethodSig
, &'a hir
::Generics
, hir
::BodyId
,
1886 Option
<hir
::Defaultness
>) {
1887 fn clean(&self, cx
: &DocContext
<'_
>) -> Method
{
1888 let (generics
, decl
) = enter_impl_trait(cx
, || {
1889 (self.1.clean(cx
), (&*self.0.decl
, self.2).clean(cx
))
1891 let (all_types
, ret_types
) = get_all_types(&generics
, &decl
, cx
);
1895 header
: self.0.header
,
1896 defaultness
: self.3,
1903 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1904 pub struct TyMethod
{
1905 pub header
: hir
::FnHeader
,
1907 pub generics
: Generics
,
1908 pub all_types
: Vec
<Type
>,
1909 pub ret_types
: Vec
<Type
>,
1912 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1913 pub struct Function
{
1915 pub generics
: Generics
,
1916 pub header
: hir
::FnHeader
,
1917 pub all_types
: Vec
<Type
>,
1918 pub ret_types
: Vec
<Type
>,
1921 impl Clean
<Item
> for doctree
::Function
{
1922 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
1923 let (generics
, decl
) = enter_impl_trait(cx
, || {
1924 (self.generics
.clean(cx
), (&self.decl
, self.body
).clean(cx
))
1927 let did
= cx
.tcx
.hir().local_def_id_from_hir_id(self.id
);
1928 let constness
= if cx
.tcx
.is_min_const_fn(did
) {
1929 hir
::Constness
::Const
1931 hir
::Constness
::NotConst
1933 let (all_types
, ret_types
) = get_all_types(&generics
, &decl
, cx
);
1935 name
: Some(self.name
.clean(cx
)),
1936 attrs
: self.attrs
.clean(cx
),
1937 source
: self.whence
.clean(cx
),
1938 visibility
: self.vis
.clean(cx
),
1939 stability
: self.stab
.clean(cx
),
1940 deprecation
: self.depr
.clean(cx
),
1942 inner
: FunctionItem(Function
{
1945 header
: hir
::FnHeader { constness, ..self.header }
,
1953 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1955 pub inputs
: Arguments
,
1956 pub output
: FunctionRetTy
,
1957 pub attrs
: Attributes
,
1961 pub fn self_type(&self) -> Option
<SelfTy
> {
1962 self.inputs
.values
.get(0).and_then(|v
| v
.to_self())
1965 /// Returns the sugared return type for an async function.
1967 /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
1968 /// will return `i32`.
1972 /// This function will panic if the return type does not match the expected sugaring for async
1974 pub fn sugared_async_return_type(&self) -> FunctionRetTy
{
1975 match &self.output
{
1976 FunctionRetTy
::Return(Type
::ImplTrait(bounds
)) => {
1978 GenericBound
::TraitBound(PolyTrait { trait_, .. }
, ..) => {
1979 let bindings
= trait_
.bindings().unwrap();
1980 FunctionRetTy
::Return(bindings
[0].ty
.clone())
1982 _
=> panic
!("unexpected desugaring of async function"),
1985 _
=> panic
!("unexpected desugaring of async function"),
1990 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1991 pub struct Arguments
{
1992 pub values
: Vec
<Argument
>,
1995 impl<'a
> Clean
<Arguments
> for (&'a
[hir
::Ty
], &'a
[ast
::Ident
]) {
1996 fn clean(&self, cx
: &DocContext
<'_
>) -> Arguments
{
1998 values
: self.0.iter
().enumerate().map(|(i
, ty
)| {
1999 let mut name
= self.1.get(i
).map(|ident
| ident
.to_string())
2000 .unwrap_or(String
::new());
2001 if name
.is_empty() {
2002 name
= "_".to_string();
2006 type_
: ty
.clean(cx
),
2013 impl<'a
> Clean
<Arguments
> for (&'a
[hir
::Ty
], hir
::BodyId
) {
2014 fn clean(&self, cx
: &DocContext
<'_
>) -> Arguments
{
2015 let body
= cx
.tcx
.hir().body(self.1);
2018 values
: self.0.iter
().enumerate().map(|(i
, ty
)| {
2020 name
: name_from_pat(&body
.arguments
[i
].pat
),
2021 type_
: ty
.clean(cx
),
2028 impl<'a
, A
: Copy
> Clean
<FnDecl
> for (&'a hir
::FnDecl
, A
)
2029 where (&'a
[hir
::Ty
], A
): Clean
<Arguments
>
2031 fn clean(&self, cx
: &DocContext
<'_
>) -> FnDecl
{
2033 inputs
: (&self.0.inputs
[..], self.1).clean(cx
),
2034 output
: self.0.output
.clean(cx
),
2035 attrs
: Attributes
::default(),
2040 impl<'a
, 'tcx
> Clean
<FnDecl
> for (DefId
, ty
::PolyFnSig
<'tcx
>) {
2041 fn clean(&self, cx
: &DocContext
<'_
>) -> FnDecl
{
2042 let (did
, sig
) = *self;
2043 let mut names
= if cx
.tcx
.hir().as_local_hir_id(did
).is_some() {
2046 cx
.tcx
.fn_arg_names(did
).into_iter()
2050 output
: Return(sig
.skip_binder().output().clean(cx
)),
2051 attrs
: Attributes
::default(),
2053 values
: sig
.skip_binder().inputs().iter().map(|t
| {
2056 name
: names
.next().map_or(String
::new(), |name
| name
.to_string()),
2064 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
2065 pub struct Argument
{
2070 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2073 SelfBorrowed(Option
<Lifetime
>, Mutability
),
2078 pub fn to_self(&self) -> Option
<SelfTy
> {
2079 if self.name
!= "self" {
2082 if self.type_
.is_self_type() {
2083 return Some(SelfValue
);
2086 BorrowedRef{ref lifetime, mutability, ref type_}
if type_
.is_self_type() => {
2087 Some(SelfBorrowed(lifetime
.clone(), mutability
))
2089 _
=> Some(SelfExplicit(self.type_
.clone()))
2094 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
2095 pub enum FunctionRetTy
{
2100 impl Clean
<FunctionRetTy
> for hir
::FunctionRetTy
{
2101 fn clean(&self, cx
: &DocContext
<'_
>) -> FunctionRetTy
{
2103 hir
::Return(ref typ
) => Return(typ
.clean(cx
)),
2104 hir
::DefaultReturn(..) => DefaultReturn
,
2109 impl GetDefId
for FunctionRetTy
{
2110 fn def_id(&self) -> Option
<DefId
> {
2112 Return(ref ty
) => ty
.def_id(),
2113 DefaultReturn
=> None
,
2118 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2121 pub unsafety
: hir
::Unsafety
,
2122 pub items
: Vec
<Item
>,
2123 pub generics
: Generics
,
2124 pub bounds
: Vec
<GenericBound
>,
2125 pub is_spotlight
: bool
,
2129 impl Clean
<Item
> for doctree
::Trait
{
2130 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
2131 let attrs
= self.attrs
.clean(cx
);
2132 let is_spotlight
= attrs
.has_doc_flag("spotlight");
2134 name
: Some(self.name
.clean(cx
)),
2136 source
: self.whence
.clean(cx
),
2137 def_id
: cx
.tcx
.hir().local_def_id_from_hir_id(self.id
),
2138 visibility
: self.vis
.clean(cx
),
2139 stability
: self.stab
.clean(cx
),
2140 deprecation
: self.depr
.clean(cx
),
2141 inner
: TraitItem(Trait
{
2142 auto: self.is_auto
.clean(cx
),
2143 unsafety
: self.unsafety
,
2144 items
: self.items
.clean(cx
),
2145 generics
: self.generics
.clean(cx
),
2146 bounds
: self.bounds
.clean(cx
),
2148 is_auto
: self.is_auto
.clean(cx
),
2154 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2155 pub struct TraitAlias
{
2156 pub generics
: Generics
,
2157 pub bounds
: Vec
<GenericBound
>,
2160 impl Clean
<Item
> for doctree
::TraitAlias
{
2161 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
2162 let attrs
= self.attrs
.clean(cx
);
2164 name
: Some(self.name
.clean(cx
)),
2166 source
: self.whence
.clean(cx
),
2167 def_id
: cx
.tcx
.hir().local_def_id_from_hir_id(self.id
),
2168 visibility
: self.vis
.clean(cx
),
2169 stability
: self.stab
.clean(cx
),
2170 deprecation
: self.depr
.clean(cx
),
2171 inner
: TraitAliasItem(TraitAlias
{
2172 generics
: self.generics
.clean(cx
),
2173 bounds
: self.bounds
.clean(cx
),
2179 impl Clean
<bool
> for hir
::IsAuto
{
2180 fn clean(&self, _
: &DocContext
<'_
>) -> bool
{
2182 hir
::IsAuto
::Yes
=> true,
2183 hir
::IsAuto
::No
=> false,
2188 impl Clean
<Type
> for hir
::TraitRef
{
2189 fn clean(&self, cx
: &DocContext
<'_
>) -> Type
{
2190 resolve_type(cx
, self.path
.clean(cx
), self.hir_ref_id
)
2194 impl Clean
<PolyTrait
> for hir
::PolyTraitRef
{
2195 fn clean(&self, cx
: &DocContext
<'_
>) -> PolyTrait
{
2197 trait_
: self.trait_ref
.clean(cx
),
2198 generic_params
: self.bound_generic_params
.clean(cx
)
2203 impl Clean
<Item
> for hir
::TraitItem
{
2204 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
2205 let inner
= match self.node
{
2206 hir
::TraitItemKind
::Const(ref ty
, default) => {
2207 AssociatedConstItem(ty
.clean(cx
),
2208 default.map(|e
| print_const_expr(cx
, e
)))
2210 hir
::TraitItemKind
::Method(ref sig
, hir
::TraitMethod
::Provided(body
)) => {
2211 MethodItem((sig
, &self.generics
, body
, None
).clean(cx
))
2213 hir
::TraitItemKind
::Method(ref sig
, hir
::TraitMethod
::Required(ref names
)) => {
2214 let (generics
, decl
) = enter_impl_trait(cx
, || {
2215 (self.generics
.clean(cx
), (&*sig
.decl
, &names
[..]).clean(cx
))
2217 let (all_types
, ret_types
) = get_all_types(&generics
, &decl
, cx
);
2218 TyMethodItem(TyMethod
{
2226 hir
::TraitItemKind
::Type(ref bounds
, ref default) => {
2227 AssociatedTypeItem(bounds
.clean(cx
), default.clean(cx
))
2230 let local_did
= cx
.tcx
.hir().local_def_id_from_hir_id(self.hir_id
);
2232 name
: Some(self.ident
.name
.clean(cx
)),
2233 attrs
: self.attrs
.clean(cx
),
2234 source
: self.span
.clean(cx
),
2237 stability
: get_stability(cx
, local_did
),
2238 deprecation
: get_deprecation(cx
, local_did
),
2244 impl Clean
<Item
> for hir
::ImplItem
{
2245 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
2246 let inner
= match self.node
{
2247 hir
::ImplItemKind
::Const(ref ty
, expr
) => {
2248 AssociatedConstItem(ty
.clean(cx
),
2249 Some(print_const_expr(cx
, expr
)))
2251 hir
::ImplItemKind
::Method(ref sig
, body
) => {
2252 MethodItem((sig
, &self.generics
, body
, Some(self.defaultness
)).clean(cx
))
2254 hir
::ImplItemKind
::Type(ref ty
) => TypedefItem(Typedef
{
2255 type_
: ty
.clean(cx
),
2256 generics
: Generics
::default(),
2258 hir
::ImplItemKind
::Existential(ref bounds
) => ExistentialItem(Existential
{
2259 bounds
: bounds
.clean(cx
),
2260 generics
: Generics
::default(),
2263 let local_did
= cx
.tcx
.hir().local_def_id_from_hir_id(self.hir_id
);
2265 name
: Some(self.ident
.name
.clean(cx
)),
2266 source
: self.span
.clean(cx
),
2267 attrs
: self.attrs
.clean(cx
),
2269 visibility
: self.vis
.clean(cx
),
2270 stability
: get_stability(cx
, local_did
),
2271 deprecation
: get_deprecation(cx
, local_did
),
2277 impl<'tcx
> Clean
<Item
> for ty
::AssociatedItem
{
2278 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
2279 let inner
= match self.kind
{
2280 ty
::AssociatedKind
::Const
=> {
2281 let ty
= cx
.tcx
.type_of(self.def_id
);
2282 let default = if self.defaultness
.has_value() {
2283 Some(inline
::print_inlined_const(cx
, self.def_id
))
2287 AssociatedConstItem(ty
.clean(cx
), default)
2289 ty
::AssociatedKind
::Method
=> {
2290 let generics
= (cx
.tcx
.generics_of(self.def_id
),
2291 &cx
.tcx
.explicit_predicates_of(self.def_id
)).clean(cx
);
2292 let sig
= cx
.tcx
.fn_sig(self.def_id
);
2293 let mut decl
= (self.def_id
, sig
).clean(cx
);
2295 if self.method_has_self_argument
{
2296 let self_ty
= match self.container
{
2297 ty
::ImplContainer(def_id
) => {
2298 cx
.tcx
.type_of(def_id
)
2300 ty
::TraitContainer(_
) => cx
.tcx
.mk_self_type()
2302 let self_arg_ty
= *sig
.input(0).skip_binder();
2303 if self_arg_ty
== self_ty
{
2304 decl
.inputs
.values
[0].type_
= Generic(String
::from("Self"));
2305 } else if let ty
::Ref(_
, ty
, _
) = self_arg_ty
.sty
{
2307 match decl
.inputs
.values
[0].type_
{
2308 BorrowedRef{ref mut type_, ..}
=> {
2309 **type_
= Generic(String
::from("Self"))
2311 _
=> unreachable
!(),
2317 let provided
= match self.container
{
2318 ty
::ImplContainer(_
) => true,
2319 ty
::TraitContainer(_
) => self.defaultness
.has_value()
2321 let (all_types
, ret_types
) = get_all_types(&generics
, &decl
, cx
);
2323 let constness
= if cx
.tcx
.is_min_const_fn(self.def_id
) {
2324 hir
::Constness
::Const
2326 hir
::Constness
::NotConst
2328 let defaultness
= match self.container
{
2329 ty
::ImplContainer(_
) => Some(self.defaultness
),
2330 ty
::TraitContainer(_
) => None
,
2335 header
: hir
::FnHeader
{
2336 unsafety
: sig
.unsafety(),
2339 asyncness
: hir
::IsAsync
::NotAsync
,
2346 TyMethodItem(TyMethod
{
2349 header
: hir
::FnHeader
{
2350 unsafety
: sig
.unsafety(),
2352 constness
: hir
::Constness
::NotConst
,
2353 asyncness
: hir
::IsAsync
::NotAsync
,
2360 ty
::AssociatedKind
::Type
=> {
2361 let my_name
= self.ident
.name
.clean(cx
);
2363 if let ty
::TraitContainer(did
) = self.container
{
2364 // When loading a cross-crate associated type, the bounds for this type
2365 // are actually located on the trait/impl itself, so we need to load
2366 // all of the generics from there and then look for bounds that are
2367 // applied to this associated type in question.
2368 let predicates
= cx
.tcx
.explicit_predicates_of(did
);
2369 let generics
= (cx
.tcx
.generics_of(did
), &predicates
).clean(cx
);
2370 let mut bounds
= generics
.where_predicates
.iter().filter_map(|pred
| {
2371 let (name
, self_type
, trait_
, bounds
) = match *pred
{
2372 WherePredicate
::BoundPredicate
{
2373 ty
: QPath { ref name, ref self_type, ref trait_ }
,
2375 } => (name
, self_type
, trait_
, bounds
),
2378 if *name
!= my_name { return None }
2380 ResolvedPath { did, .. }
if did
== self.container
.id() => {}
2384 Generic(ref s
) if *s
== "Self" => {}
2388 }).flat_map(|i
| i
.iter().cloned()).collect
::<Vec
<_
>>();
2389 // Our Sized/?Sized bound didn't get handled when creating the generics
2390 // because we didn't actually get our whole set of bounds until just now
2391 // (some of them may have come from the trait). If we do have a sized
2392 // bound, we remove it, and if we don't then we add the `?Sized` bound
2394 match bounds
.iter().position(|b
| b
.is_sized_bound(cx
)) {
2395 Some(i
) => { bounds.remove(i); }
2396 None
=> bounds
.push(GenericBound
::maybe_sized(cx
)),
2399 let ty
= if self.defaultness
.has_value() {
2400 Some(cx
.tcx
.type_of(self.def_id
))
2405 AssociatedTypeItem(bounds
, ty
.clean(cx
))
2407 TypedefItem(Typedef
{
2408 type_
: cx
.tcx
.type_of(self.def_id
).clean(cx
),
2409 generics
: Generics
{
2411 where_predicates
: Vec
::new(),
2416 ty
::AssociatedKind
::Existential
=> unimplemented
!(),
2419 let visibility
= match self.container
{
2420 ty
::ImplContainer(_
) => self.vis
.clean(cx
),
2421 ty
::TraitContainer(_
) => None
,
2425 name
: Some(self.ident
.name
.clean(cx
)),
2427 stability
: get_stability(cx
, self.def_id
),
2428 deprecation
: get_deprecation(cx
, self.def_id
),
2429 def_id
: self.def_id
,
2430 attrs
: inline
::load_attrs(cx
, self.def_id
),
2431 source
: cx
.tcx
.def_span(self.def_id
).clean(cx
),
2437 /// A trait reference, which may have higher ranked lifetimes.
2438 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
2439 pub struct PolyTrait
{
2441 pub generic_params
: Vec
<GenericParamDef
>,
2444 /// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
2445 /// type out of the AST/TyCtxt given one of these, if more information is needed. Most importantly
2446 /// it does not preserve mutability or boxes.
2447 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
2449 /// Structs/enums/traits (most that'd be an `hir::TyKind::Path`).
2452 param_names
: Option
<Vec
<GenericBound
>>,
2454 /// `true` if is a `T::Name` path for associated types.
2457 /// For parameterized types, so the consumer of the JSON don't go
2458 /// looking for types which don't exist anywhere.
2460 /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
2461 /// arrays, slices, and tuples.
2462 Primitive(PrimitiveType
),
2464 BareFunction(Box
<BareFunctionDecl
>),
2467 Array(Box
<Type
>, String
),
2471 RawPointer(Mutability
, Box
<Type
>),
2473 lifetime
: Option
<Lifetime
>,
2474 mutability
: Mutability
,
2478 // <Type as Trait>::Name
2481 self_type
: Box
<Type
>,
2488 // impl TraitA+TraitB
2489 ImplTrait(Vec
<GenericBound
>),
2492 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
2493 pub enum PrimitiveType
{
2494 Isize
, I8
, I16
, I32
, I64
, I128
,
2495 Usize
, U8
, U16
, U32
, U64
, U128
,
2511 #[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
2530 pub trait GetDefId
{
2531 fn def_id(&self) -> Option
<DefId
>;
2534 impl<T
: GetDefId
> GetDefId
for Option
<T
> {
2535 fn def_id(&self) -> Option
<DefId
> {
2536 self.as_ref().and_then(|d
| d
.def_id())
2541 pub fn primitive_type(&self) -> Option
<PrimitiveType
> {
2543 Primitive(p
) | BorrowedRef { type_: box Primitive(p), ..}
=> Some(p
),
2544 Slice(..) | BorrowedRef { type_: box Slice(..), .. }
=> Some(PrimitiveType
::Slice
),
2545 Array(..) | BorrowedRef { type_: box Array(..), .. }
=> Some(PrimitiveType
::Array
),
2546 Tuple(ref tys
) => if tys
.is_empty() {
2547 Some(PrimitiveType
::Unit
)
2549 Some(PrimitiveType
::Tuple
)
2551 RawPointer(..) => Some(PrimitiveType
::RawPointer
),
2552 BorrowedRef { type_: box Generic(..), .. }
=> Some(PrimitiveType
::Reference
),
2553 BareFunction(..) => Some(PrimitiveType
::Fn
),
2554 Never
=> Some(PrimitiveType
::Never
),
2559 pub fn is_generic(&self) -> bool
{
2561 ResolvedPath { is_generic, .. }
=> is_generic
,
2566 pub fn is_self_type(&self) -> bool
{
2568 Generic(ref name
) => name
== "Self",
2573 pub fn generics(&self) -> Option
<Vec
<Type
>> {
2575 ResolvedPath { ref path, .. }
=> {
2576 path
.segments
.last().and_then(|seg
| {
2577 if let GenericArgs
::AngleBracketed { ref args, .. }
= seg
.args
{
2578 Some(args
.iter().filter_map(|arg
| match arg
{
2579 GenericArg
::Type(ty
) => Some(ty
.clone()),
2591 pub fn bindings(&self) -> Option
<&[TypeBinding
]> {
2593 ResolvedPath { ref path, .. }
=> {
2594 path
.segments
.last().and_then(|seg
| {
2595 if let GenericArgs
::AngleBracketed { ref bindings, .. }
= seg
.args
{
2606 pub fn is_full_generic(&self) -> bool
{
2608 Type
::Generic(_
) => true,
2614 impl GetDefId
for Type
{
2615 fn def_id(&self) -> Option
<DefId
> {
2617 ResolvedPath { did, .. }
=> Some(did
),
2618 Primitive(p
) => crate::html
::render
::cache().primitive_locations
.get(&p
).cloned(),
2619 BorrowedRef { type_: box Generic(..), .. }
=>
2620 Primitive(PrimitiveType
::Reference
).def_id(),
2621 BorrowedRef { ref type_, .. }
=> type_
.def_id(),
2622 Tuple(ref tys
) => if tys
.is_empty() {
2623 Primitive(PrimitiveType
::Unit
).def_id()
2625 Primitive(PrimitiveType
::Tuple
).def_id()
2627 BareFunction(..) => Primitive(PrimitiveType
::Fn
).def_id(),
2628 Never
=> Primitive(PrimitiveType
::Never
).def_id(),
2629 Slice(..) => Primitive(PrimitiveType
::Slice
).def_id(),
2630 Array(..) => Primitive(PrimitiveType
::Array
).def_id(),
2631 RawPointer(..) => Primitive(PrimitiveType
::RawPointer
).def_id(),
2632 QPath { ref self_type, .. }
=> self_type
.def_id(),
2638 impl PrimitiveType
{
2639 fn from_str(s
: &str) -> Option
<PrimitiveType
> {
2641 "isize" => Some(PrimitiveType
::Isize
),
2642 "i8" => Some(PrimitiveType
::I8
),
2643 "i16" => Some(PrimitiveType
::I16
),
2644 "i32" => Some(PrimitiveType
::I32
),
2645 "i64" => Some(PrimitiveType
::I64
),
2646 "i128" => Some(PrimitiveType
::I128
),
2647 "usize" => Some(PrimitiveType
::Usize
),
2648 "u8" => Some(PrimitiveType
::U8
),
2649 "u16" => Some(PrimitiveType
::U16
),
2650 "u32" => Some(PrimitiveType
::U32
),
2651 "u64" => Some(PrimitiveType
::U64
),
2652 "u128" => Some(PrimitiveType
::U128
),
2653 "bool" => Some(PrimitiveType
::Bool
),
2654 "char" => Some(PrimitiveType
::Char
),
2655 "str" => Some(PrimitiveType
::Str
),
2656 "f32" => Some(PrimitiveType
::F32
),
2657 "f64" => Some(PrimitiveType
::F64
),
2658 "array" => Some(PrimitiveType
::Array
),
2659 "slice" => Some(PrimitiveType
::Slice
),
2660 "tuple" => Some(PrimitiveType
::Tuple
),
2661 "unit" => Some(PrimitiveType
::Unit
),
2662 "pointer" => Some(PrimitiveType
::RawPointer
),
2663 "reference" => Some(PrimitiveType
::Reference
),
2664 "fn" => Some(PrimitiveType
::Fn
),
2665 "never" => Some(PrimitiveType
::Never
),
2670 pub fn as_str(&self) -> &'
static str {
2671 use self::PrimitiveType
::*;
2694 RawPointer
=> "pointer",
2695 Reference
=> "reference",
2702 pub fn to_url_str(&self) -> &'
static str {
2707 impl From
<ast
::IntTy
> for PrimitiveType
{
2708 fn from(int_ty
: ast
::IntTy
) -> PrimitiveType
{
2710 ast
::IntTy
::Isize
=> PrimitiveType
::Isize
,
2711 ast
::IntTy
::I8
=> PrimitiveType
::I8
,
2712 ast
::IntTy
::I16
=> PrimitiveType
::I16
,
2713 ast
::IntTy
::I32
=> PrimitiveType
::I32
,
2714 ast
::IntTy
::I64
=> PrimitiveType
::I64
,
2715 ast
::IntTy
::I128
=> PrimitiveType
::I128
,
2720 impl From
<ast
::UintTy
> for PrimitiveType
{
2721 fn from(uint_ty
: ast
::UintTy
) -> PrimitiveType
{
2723 ast
::UintTy
::Usize
=> PrimitiveType
::Usize
,
2724 ast
::UintTy
::U8
=> PrimitiveType
::U8
,
2725 ast
::UintTy
::U16
=> PrimitiveType
::U16
,
2726 ast
::UintTy
::U32
=> PrimitiveType
::U32
,
2727 ast
::UintTy
::U64
=> PrimitiveType
::U64
,
2728 ast
::UintTy
::U128
=> PrimitiveType
::U128
,
2733 impl From
<ast
::FloatTy
> for PrimitiveType
{
2734 fn from(float_ty
: ast
::FloatTy
) -> PrimitiveType
{
2736 ast
::FloatTy
::F32
=> PrimitiveType
::F32
,
2737 ast
::FloatTy
::F64
=> PrimitiveType
::F64
,
2742 impl Clean
<Type
> for hir
::Ty
{
2743 fn clean(&self, cx
: &DocContext
<'_
>) -> Type
{
2747 TyKind
::Never
=> Never
,
2748 TyKind
::CVarArgs(_
) => CVarArgs
,
2749 TyKind
::Ptr(ref m
) => RawPointer(m
.mutbl
.clean(cx
), box m
.ty
.clean(cx
)),
2750 TyKind
::Rptr(ref l
, ref m
) => {
2751 let lifetime
= if l
.is_elided() {
2756 BorrowedRef
{lifetime
: lifetime
, mutability
: m
.mutbl
.clean(cx
),
2757 type_
: box m
.ty
.clean(cx
)}
2759 TyKind
::Slice(ref ty
) => Slice(box ty
.clean(cx
)),
2760 TyKind
::Array(ref ty
, ref length
) => {
2761 let def_id
= cx
.tcx
.hir().local_def_id_from_hir_id(length
.hir_id
);
2762 let param_env
= cx
.tcx
.param_env(def_id
);
2763 let substs
= InternalSubsts
::identity_for_item(cx
.tcx
, def_id
);
2764 let cid
= GlobalId
{
2765 instance
: ty
::Instance
::new(def_id
, substs
),
2768 let length
= match cx
.tcx
.const_eval(param_env
.and(cid
)) {
2769 Ok(length
) => print_const(cx
, length
),
2770 Err(_
) => "_".to_string(),
2772 Array(box ty
.clean(cx
), length
)
2774 TyKind
::Tup(ref tys
) => Tuple(tys
.clean(cx
)),
2775 TyKind
::Def(item_id
, _
) => {
2776 let item
= cx
.tcx
.hir().expect_item_by_hir_id(item_id
.id
);
2777 if let hir
::ItemKind
::Existential(ref ty
) = item
.node
{
2778 ImplTrait(ty
.bounds
.clean(cx
))
2783 TyKind
::Path(hir
::QPath
::Resolved(None
, ref path
)) => {
2784 if let Some(new_ty
) = cx
.ty_substs
.borrow().get(&path
.def
).cloned() {
2788 if let Def
::TyParam(did
) = path
.def
{
2789 if let Some(bounds
) = cx
.impl_trait_bounds
.borrow_mut().remove(&did
) {
2790 return ImplTrait(bounds
);
2794 let mut alias
= None
;
2795 if let Def
::TyAlias(def_id
) = path
.def
{
2796 // Substitute private type aliases
2797 if let Some(hir_id
) = cx
.tcx
.hir().as_local_hir_id(def_id
) {
2798 if !cx
.renderinfo
.borrow().access_levels
.is_exported(def_id
) {
2799 alias
= Some(&cx
.tcx
.hir().expect_item_by_hir_id(hir_id
).node
);
2804 if let Some(&hir
::ItemKind
::Ty(ref ty
, ref generics
)) = alias
{
2805 let provided_params
= &path
.segments
.last().expect("segments were empty");
2806 let mut ty_substs
= FxHashMap
::default();
2807 let mut lt_substs
= FxHashMap
::default();
2808 let mut const_substs
= FxHashMap
::default();
2809 provided_params
.with_generic_args(|generic_args
| {
2810 let mut indices
: GenericParamCount
= Default
::default();
2811 for param
in generics
.params
.iter() {
2813 hir
::GenericParamKind
::Lifetime { .. }
=> {
2815 let lifetime
= generic_args
.args
.iter().find_map(|arg
| {
2817 hir
::GenericArg
::Lifetime(lt
) => {
2818 if indices
.lifetimes
== j
{
2827 if let Some(lt
) = lifetime
.cloned() {
2828 if !lt
.is_elided() {
2830 cx
.tcx
.hir().local_def_id_from_hir_id(param
.hir_id
);
2831 lt_substs
.insert(lt_def_id
, lt
.clean(cx
));
2834 indices
.lifetimes
+= 1;
2836 hir
::GenericParamKind
::Type { ref default, .. }
=> {
2839 cx
.tcx
.hir().local_def_id_from_hir_id(param
.hir_id
));
2841 let type_
= generic_args
.args
.iter().find_map(|arg
| {
2843 hir
::GenericArg
::Type(ty
) => {
2844 if indices
.types
== j
{
2853 if let Some(ty
) = type_
.cloned() {
2854 ty_substs
.insert(ty_param_def
, ty
.clean(cx
));
2855 } else if let Some(default) = default.clone() {
2856 ty_substs
.insert(ty_param_def
,
2857 default.into_inner().clean(cx
));
2861 hir
::GenericParamKind
::Const { .. }
=> {
2862 let const_param_def
=
2864 cx
.tcx
.hir().local_def_id_from_hir_id(param
.hir_id
));
2866 let const_
= generic_args
.args
.iter().find_map(|arg
| {
2868 hir
::GenericArg
::Const(ct
) => {
2869 if indices
.consts
== j
{
2878 if let Some(ct
) = const_
.cloned() {
2879 const_substs
.insert(const_param_def
, ct
.clean(cx
));
2881 // FIXME(const_generics:defaults)
2882 indices
.consts
+= 1;
2887 return cx
.enter_alias(ty_substs
, lt_substs
, const_substs
, || ty
.clean(cx
));
2889 resolve_type(cx
, path
.clean(cx
), self.hir_id
)
2891 TyKind
::Path(hir
::QPath
::Resolved(Some(ref qself
), ref p
)) => {
2892 let mut segments
: Vec
<_
> = p
.segments
.clone().into();
2894 let trait_path
= hir
::Path
{
2896 def
: Def
::Trait(cx
.tcx
.associated_item(p
.def
.def_id()).container
.id()),
2897 segments
: segments
.into(),
2900 name
: p
.segments
.last().expect("segments were empty").ident
.name
.clean(cx
),
2901 self_type
: box qself
.clean(cx
),
2902 trait_
: box resolve_type(cx
, trait_path
.clean(cx
), self.hir_id
)
2905 TyKind
::Path(hir
::QPath
::TypeRelative(ref qself
, ref segment
)) => {
2906 let mut def
= Def
::Err
;
2907 let ty
= hir_ty_to_ty(cx
.tcx
, self);
2908 if let ty
::Projection(proj
) = ty
.sty
{
2909 def
= Def
::Trait(proj
.trait_ref(cx
.tcx
).def_id
);
2911 let trait_path
= hir
::Path
{
2914 segments
: vec
![].into(),
2917 name
: segment
.ident
.name
.clean(cx
),
2918 self_type
: box qself
.clean(cx
),
2919 trait_
: box resolve_type(cx
, trait_path
.clean(cx
), self.hir_id
)
2922 TyKind
::TraitObject(ref bounds
, ref lifetime
) => {
2923 match bounds
[0].clean(cx
).trait_
{
2924 ResolvedPath { path, param_names: None, did, is_generic }
=> {
2925 let mut bounds
: Vec
<self::GenericBound
> = bounds
[1..].iter().map(|bound
| {
2926 self::GenericBound
::TraitBound(bound
.clean(cx
),
2927 hir
::TraitBoundModifier
::None
)
2929 if !lifetime
.is_elided() {
2930 bounds
.push(self::GenericBound
::Outlives(lifetime
.clean(cx
)));
2932 ResolvedPath { path, param_names: Some(bounds), did, is_generic, }
2934 _
=> Infer
// shouldn't happen
2937 TyKind
::BareFn(ref barefn
) => BareFunction(box barefn
.clean(cx
)),
2938 TyKind
::Infer
| TyKind
::Err
=> Infer
,
2939 TyKind
::Typeof(..) => panic
!("Unimplemented type {:?}", self.node
),
2944 impl<'tcx
> Clean
<Type
> for Ty
<'tcx
> {
2945 fn clean(&self, cx
: &DocContext
<'_
>) -> Type
{
2948 ty
::Bool
=> Primitive(PrimitiveType
::Bool
),
2949 ty
::Char
=> Primitive(PrimitiveType
::Char
),
2950 ty
::Int(int_ty
) => Primitive(int_ty
.into()),
2951 ty
::Uint(uint_ty
) => Primitive(uint_ty
.into()),
2952 ty
::Float(float_ty
) => Primitive(float_ty
.into()),
2953 ty
::Str
=> Primitive(PrimitiveType
::Str
),
2954 ty
::Slice(ty
) => Slice(box ty
.clean(cx
)),
2955 ty
::Array(ty
, n
) => {
2956 let mut n
= *cx
.tcx
.lift(&n
).expect("array lift failed");
2957 if let ConstValue
::Unevaluated(def_id
, substs
) = n
.val
{
2958 let param_env
= cx
.tcx
.param_env(def_id
);
2959 let cid
= GlobalId
{
2960 instance
: ty
::Instance
::new(def_id
, substs
),
2963 if let Ok(new_n
) = cx
.tcx
.const_eval(param_env
.and(cid
)) {
2967 let n
= print_const(cx
, n
);
2968 Array(box ty
.clean(cx
), n
)
2970 ty
::RawPtr(mt
) => RawPointer(mt
.mutbl
.clean(cx
), box mt
.ty
.clean(cx
)),
2971 ty
::Ref(r
, ty
, mutbl
) => BorrowedRef
{
2972 lifetime
: r
.clean(cx
),
2973 mutability
: mutbl
.clean(cx
),
2974 type_
: box ty
.clean(cx
),
2978 let ty
= cx
.tcx
.lift(self).expect("FnPtr lift failed");
2979 let sig
= ty
.fn_sig(cx
.tcx
);
2980 BareFunction(box BareFunctionDecl
{
2981 unsafety
: sig
.unsafety(),
2982 generic_params
: Vec
::new(),
2983 decl
: (cx
.tcx
.hir().local_def_id(ast
::CRATE_NODE_ID
), sig
).clean(cx
),
2987 ty
::Adt(def
, substs
) => {
2989 let kind
= match def
.adt_kind() {
2990 AdtKind
::Struct
=> TypeKind
::Struct
,
2991 AdtKind
::Union
=> TypeKind
::Union
,
2992 AdtKind
::Enum
=> TypeKind
::Enum
,
2994 inline
::record_extern_fqn(cx
, did
, kind
);
2995 let path
= external_path(cx
, &cx
.tcx
.item_name(did
).as_str(),
2996 None
, false, vec
![], substs
);
3004 ty
::Foreign(did
) => {
3005 inline
::record_extern_fqn(cx
, did
, TypeKind
::Foreign
);
3006 let path
= external_path(cx
, &cx
.tcx
.item_name(did
).as_str(),
3007 None
, false, vec
![], InternalSubsts
::empty());
3015 ty
::Dynamic(ref obj
, ref reg
) => {
3016 // HACK: pick the first `did` as the `did` of the trait object. Someone
3017 // might want to implement "native" support for marker-trait-only
3019 let mut dids
= obj
.principal_def_id().into_iter().chain(obj
.auto_traits());
3020 let did
= dids
.next().unwrap_or_else(|| {
3021 panic
!("found trait object `{:?}` with no traits?", self)
3023 let substs
= match obj
.principal() {
3024 Some(principal
) => principal
.skip_binder().substs
,
3025 // marker traits have no substs.
3026 _
=> cx
.tcx
.intern_substs(&[])
3029 inline
::record_extern_fqn(cx
, did
, TypeKind
::Trait
);
3031 let mut param_names
= vec
![];
3032 reg
.clean(cx
).map(|b
| param_names
.push(GenericBound
::Outlives(b
)));
3034 let empty
= cx
.tcx
.intern_substs(&[]);
3035 let path
= external_path(cx
, &cx
.tcx
.item_name(did
).as_str(),
3036 Some(did
), false, vec
![], empty
);
3037 inline
::record_extern_fqn(cx
, did
, TypeKind
::Trait
);
3038 let bound
= GenericBound
::TraitBound(PolyTrait
{
3039 trait_
: ResolvedPath
{
3045 generic_params
: Vec
::new(),
3046 }, hir
::TraitBoundModifier
::None
);
3047 param_names
.push(bound
);
3050 let mut bindings
= vec
![];
3051 for pb
in obj
.projection_bounds() {
3052 bindings
.push(TypeBinding
{
3053 name
: cx
.tcx
.associated_item(pb
.item_def_id()).ident
.name
.clean(cx
),
3054 ty
: pb
.skip_binder().ty
.clean(cx
)
3058 let path
= external_path(cx
, &cx
.tcx
.item_name(did
).as_str(), Some(did
),
3059 false, bindings
, substs
);
3062 param_names
: Some(param_names
),
3067 ty
::Tuple(ref t
) => Tuple(t
.clean(cx
)),
3069 ty
::Projection(ref data
) => data
.clean(cx
),
3071 ty
::Param(ref p
) => Generic(p
.name
.to_string()),
3073 ty
::Opaque(def_id
, substs
) => {
3074 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
3075 // by looking up the projections associated with the def_id.
3076 let predicates_of
= cx
.tcx
.explicit_predicates_of(def_id
);
3077 let substs
= cx
.tcx
.lift(&substs
).expect("Opaque lift failed");
3078 let bounds
= predicates_of
.instantiate(cx
.tcx
, substs
);
3079 let mut regions
= vec
![];
3080 let mut has_sized
= false;
3081 let mut bounds
= bounds
.predicates
.iter().filter_map(|predicate
| {
3082 let trait_ref
= if let Some(tr
) = predicate
.to_opt_poly_trait_ref() {
3084 } else if let ty
::Predicate
::TypeOutlives(pred
) = *predicate
{
3085 // these should turn up at the end
3086 pred
.skip_binder().1.clean(cx
).map(|r
| {
3087 regions
.push(GenericBound
::Outlives(r
))
3094 if let Some(sized
) = cx
.tcx
.lang_items().sized_trait() {
3095 if trait_ref
.def_id() == sized
{
3101 let bounds
= bounds
.predicates
.iter().filter_map(|pred
|
3102 if let ty
::Predicate
::Projection(proj
) = *pred
{
3103 let proj
= proj
.skip_binder();
3104 if proj
.projection_ty
.trait_ref(cx
.tcx
) == *trait_ref
.skip_binder() {
3106 name
: cx
.tcx
.associated_item(proj
.projection_ty
.item_def_id
)
3107 .ident
.name
.clean(cx
),
3108 ty
: proj
.ty
.clean(cx
),
3118 Some((trait_ref
.skip_binder(), bounds
).clean(cx
))
3119 }).collect
::<Vec
<_
>>();
3120 bounds
.extend(regions
);
3121 if !has_sized
&& !bounds
.is_empty() {
3122 bounds
.insert(0, GenericBound
::maybe_sized(cx
));
3127 ty
::Closure(..) | ty
::Generator(..) => Tuple(vec
![]), // FIXME(pcwalton)
3129 ty
::Bound(..) => panic
!("Bound"),
3130 ty
::Placeholder(..) => panic
!("Placeholder"),
3131 ty
::UnnormalizedProjection(..) => panic
!("UnnormalizedProjection"),
3132 ty
::GeneratorWitness(..) => panic
!("GeneratorWitness"),
3133 ty
::Infer(..) => panic
!("Infer"),
3134 ty
::Error
=> panic
!("Error"),
3139 impl<'tcx
> Clean
<Constant
> for ty
::Const
<'tcx
> {
3140 fn clean(&self, cx
: &DocContext
<'_
>) -> Constant
{
3142 type_
: self.ty
.clean(cx
),
3143 expr
: format
!("{:?}", self.val
), // FIXME(const_generics)
3148 impl Clean
<Item
> for hir
::StructField
{
3149 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3150 let local_did
= cx
.tcx
.hir().local_def_id_from_hir_id(self.hir_id
);
3153 name
: Some(self.ident
.name
).clean(cx
),
3154 attrs
: self.attrs
.clean(cx
),
3155 source
: self.span
.clean(cx
),
3156 visibility
: self.vis
.clean(cx
),
3157 stability
: get_stability(cx
, local_did
),
3158 deprecation
: get_deprecation(cx
, local_did
),
3160 inner
: StructFieldItem(self.ty
.clean(cx
)),
3165 impl<'tcx
> Clean
<Item
> for ty
::FieldDef
{
3166 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3168 name
: Some(self.ident
.name
).clean(cx
),
3169 attrs
: cx
.tcx
.get_attrs(self.did
).clean(cx
),
3170 source
: cx
.tcx
.def_span(self.did
).clean(cx
),
3171 visibility
: self.vis
.clean(cx
),
3172 stability
: get_stability(cx
, self.did
),
3173 deprecation
: get_deprecation(cx
, self.did
),
3175 inner
: StructFieldItem(cx
.tcx
.type_of(self.did
).clean(cx
)),
3180 #[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug)]
3181 pub enum Visibility
{
3185 Restricted(DefId
, Path
),
3188 impl Clean
<Option
<Visibility
>> for hir
::Visibility
{
3189 fn clean(&self, cx
: &DocContext
<'_
>) -> Option
<Visibility
> {
3190 Some(match self.node
{
3191 hir
::VisibilityKind
::Public
=> Visibility
::Public
,
3192 hir
::VisibilityKind
::Inherited
=> Visibility
::Inherited
,
3193 hir
::VisibilityKind
::Crate(_
) => Visibility
::Crate
,
3194 hir
::VisibilityKind
::Restricted { ref path, .. }
=> {
3195 let path
= path
.clean(cx
);
3196 let did
= register_def(cx
, path
.def
);
3197 Visibility
::Restricted(did
, path
)
3203 impl Clean
<Option
<Visibility
>> for ty
::Visibility
{
3204 fn clean(&self, _
: &DocContext
<'_
>) -> Option
<Visibility
> {
3205 Some(if *self == ty
::Visibility
::Public { Public }
else { Inherited }
)
3209 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3211 pub struct_type
: doctree
::StructType
,
3212 pub generics
: Generics
,
3213 pub fields
: Vec
<Item
>,
3214 pub fields_stripped
: bool
,
3217 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3219 pub struct_type
: doctree
::StructType
,
3220 pub generics
: Generics
,
3221 pub fields
: Vec
<Item
>,
3222 pub fields_stripped
: bool
,
3225 impl Clean
<Item
> for doctree
::Struct
{
3226 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3228 name
: Some(self.name
.clean(cx
)),
3229 attrs
: self.attrs
.clean(cx
),
3230 source
: self.whence
.clean(cx
),
3231 def_id
: cx
.tcx
.hir().local_def_id_from_hir_id(self.id
),
3232 visibility
: self.vis
.clean(cx
),
3233 stability
: self.stab
.clean(cx
),
3234 deprecation
: self.depr
.clean(cx
),
3235 inner
: StructItem(Struct
{
3236 struct_type
: self.struct_type
,
3237 generics
: self.generics
.clean(cx
),
3238 fields
: self.fields
.clean(cx
),
3239 fields_stripped
: false,
3245 impl Clean
<Item
> for doctree
::Union
{
3246 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3248 name
: Some(self.name
.clean(cx
)),
3249 attrs
: self.attrs
.clean(cx
),
3250 source
: self.whence
.clean(cx
),
3251 def_id
: cx
.tcx
.hir().local_def_id_from_hir_id(self.id
),
3252 visibility
: self.vis
.clean(cx
),
3253 stability
: self.stab
.clean(cx
),
3254 deprecation
: self.depr
.clean(cx
),
3255 inner
: UnionItem(Union
{
3256 struct_type
: self.struct_type
,
3257 generics
: self.generics
.clean(cx
),
3258 fields
: self.fields
.clean(cx
),
3259 fields_stripped
: false,
3265 /// This is a more limited form of the standard Struct, different in that
3266 /// it lacks the things most items have (name, id, parameterization). Found
3267 /// only as a variant in an enum.
3268 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3269 pub struct VariantStruct
{
3270 pub struct_type
: doctree
::StructType
,
3271 pub fields
: Vec
<Item
>,
3272 pub fields_stripped
: bool
,
3275 impl Clean
<VariantStruct
> for ::rustc
::hir
::VariantData
{
3276 fn clean(&self, cx
: &DocContext
<'_
>) -> VariantStruct
{
3278 struct_type
: doctree
::struct_type_from_def(self),
3279 fields
: self.fields().iter().map(|x
| x
.clean(cx
)).collect(),
3280 fields_stripped
: false,
3285 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3287 pub variants
: IndexVec
<VariantIdx
, Item
>,
3288 pub generics
: Generics
,
3289 pub variants_stripped
: bool
,
3292 impl Clean
<Item
> for doctree
::Enum
{
3293 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3295 name
: Some(self.name
.clean(cx
)),
3296 attrs
: self.attrs
.clean(cx
),
3297 source
: self.whence
.clean(cx
),
3298 def_id
: cx
.tcx
.hir().local_def_id_from_hir_id(self.id
),
3299 visibility
: self.vis
.clean(cx
),
3300 stability
: self.stab
.clean(cx
),
3301 deprecation
: self.depr
.clean(cx
),
3302 inner
: EnumItem(Enum
{
3303 variants
: self.variants
.iter().map(|v
| v
.clean(cx
)).collect(),
3304 generics
: self.generics
.clean(cx
),
3305 variants_stripped
: false,
3311 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3312 pub struct Variant
{
3313 pub kind
: VariantKind
,
3316 impl Clean
<Item
> for doctree
::Variant
{
3317 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3319 name
: Some(self.name
.clean(cx
)),
3320 attrs
: self.attrs
.clean(cx
),
3321 source
: self.whence
.clean(cx
),
3323 stability
: self.stab
.clean(cx
),
3324 deprecation
: self.depr
.clean(cx
),
3325 def_id
: cx
.tcx
.hir().local_def_id_from_hir_id(self.id
),
3326 inner
: VariantItem(Variant
{
3327 kind
: self.def
.clean(cx
),
3333 impl<'tcx
> Clean
<Item
> for ty
::VariantDef
{
3334 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3335 let kind
= match self.ctor_kind
{
3336 CtorKind
::Const
=> VariantKind
::CLike
,
3339 self.fields
.iter().map(|f
| cx
.tcx
.type_of(f
.did
).clean(cx
)).collect()
3342 CtorKind
::Fictive
=> {
3343 VariantKind
::Struct(VariantStruct
{
3344 struct_type
: doctree
::Plain
,
3345 fields_stripped
: false,
3346 fields
: self.fields
.iter().map(|field
| {
3348 source
: cx
.tcx
.def_span(field
.did
).clean(cx
),
3349 name
: Some(field
.ident
.name
.clean(cx
)),
3350 attrs
: cx
.tcx
.get_attrs(field
.did
).clean(cx
),
3351 visibility
: field
.vis
.clean(cx
),
3353 stability
: get_stability(cx
, field
.did
),
3354 deprecation
: get_deprecation(cx
, field
.did
),
3355 inner
: StructFieldItem(cx
.tcx
.type_of(field
.did
).clean(cx
))
3362 name
: Some(self.ident
.clean(cx
)),
3363 attrs
: inline
::load_attrs(cx
, self.def_id
),
3364 source
: cx
.tcx
.def_span(self.def_id
).clean(cx
),
3365 visibility
: Some(Inherited
),
3366 def_id
: self.def_id
,
3367 inner
: VariantItem(Variant { kind }
),
3368 stability
: get_stability(cx
, self.def_id
),
3369 deprecation
: get_deprecation(cx
, self.def_id
),
3374 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3375 pub enum VariantKind
{
3378 Struct(VariantStruct
),
3381 impl Clean
<VariantKind
> for hir
::VariantData
{
3382 fn clean(&self, cx
: &DocContext
<'_
>) -> VariantKind
{
3384 hir
::VariantData
::Struct(..) => VariantKind
::Struct(self.clean(cx
)),
3385 hir
::VariantData
::Tuple(..) =>
3386 VariantKind
::Tuple(self.fields().iter().map(|x
| x
.ty
.clean(cx
)).collect()),
3387 hir
::VariantData
::Unit(..) => VariantKind
::CLike
,
3392 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3394 pub filename
: FileName
,
3402 pub fn empty() -> Span
{
3404 filename
: FileName
::Anon(0),
3405 loline
: 0, locol
: 0,
3406 hiline
: 0, hicol
: 0,
3411 impl Clean
<Span
> for syntax_pos
::Span
{
3412 fn clean(&self, cx
: &DocContext
<'_
>) -> Span
{
3413 if self.is_dummy() {
3414 return Span
::empty();
3417 let cm
= cx
.sess().source_map();
3418 let filename
= cm
.span_to_filename(*self);
3419 let lo
= cm
.lookup_char_pos(self.lo());
3420 let hi
= cm
.lookup_char_pos(self.hi());
3424 locol
: lo
.col
.to_usize(),
3426 hicol
: hi
.col
.to_usize(),
3431 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3435 pub segments
: Vec
<PathSegment
>,
3439 pub fn last_name(&self) -> &str {
3440 self.segments
.last().expect("segments were empty").name
.as_str()
3444 impl Clean
<Path
> for hir
::Path
{
3445 fn clean(&self, cx
: &DocContext
<'_
>) -> Path
{
3447 global
: self.is_global(),
3449 segments
: if self.is_global() { &self.segments[1..] }
else { &self.segments }
.clean(cx
),
3454 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3455 pub enum GenericArg
{
3461 impl fmt
::Display
for GenericArg
{
3462 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
3464 GenericArg
::Lifetime(lt
) => lt
.fmt(f
),
3465 GenericArg
::Type(ty
) => ty
.fmt(f
),
3466 GenericArg
::Const(ct
) => ct
.fmt(f
),
3471 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3472 pub enum GenericArgs
{
3474 args
: Vec
<GenericArg
>,
3475 bindings
: Vec
<TypeBinding
>,
3479 output
: Option
<Type
>,
3483 impl Clean
<GenericArgs
> for hir
::GenericArgs
{
3484 fn clean(&self, cx
: &DocContext
<'_
>) -> GenericArgs
{
3485 if self.parenthesized
{
3486 let output
= self.bindings
[0].ty
.clean(cx
);
3487 GenericArgs
::Parenthesized
{
3488 inputs
: self.inputs().clean(cx
),
3489 output
: if output
!= Type
::Tuple(Vec
::new()) { Some(output) }
else { None }
3492 let elide_lifetimes
= self.args
.iter().all(|arg
| match arg
{
3493 hir
::GenericArg
::Lifetime(lt
) => lt
.is_elided(),
3496 GenericArgs
::AngleBracketed
{
3497 args
: self.args
.iter().filter_map(|arg
| match arg
{
3498 hir
::GenericArg
::Lifetime(lt
) if !elide_lifetimes
=> {
3499 Some(GenericArg
::Lifetime(lt
.clean(cx
)))
3501 hir
::GenericArg
::Lifetime(_
) => None
,
3502 hir
::GenericArg
::Type(ty
) => Some(GenericArg
::Type(ty
.clean(cx
))),
3503 hir
::GenericArg
::Const(ct
) => Some(GenericArg
::Const(ct
.clean(cx
))),
3505 bindings
: self.bindings
.clean(cx
),
3511 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3512 pub struct PathSegment
{
3514 pub args
: GenericArgs
,
3517 impl Clean
<PathSegment
> for hir
::PathSegment
{
3518 fn clean(&self, cx
: &DocContext
<'_
>) -> PathSegment
{
3520 name
: self.ident
.name
.clean(cx
),
3521 args
: self.with_generic_args(|generic_args
| generic_args
.clean(cx
))
3526 fn strip_type(ty
: Type
) -> Type
{
3528 Type
::ResolvedPath { path, param_names, did, is_generic }
=> {
3529 Type
::ResolvedPath { path: strip_path(&path), param_names, did, is_generic }
3531 Type
::Tuple(inner_tys
) => {
3532 Type
::Tuple(inner_tys
.iter().map(|t
| strip_type(t
.clone())).collect())
3534 Type
::Slice(inner_ty
) => Type
::Slice(Box
::new(strip_type(*inner_ty
))),
3535 Type
::Array(inner_ty
, s
) => Type
::Array(Box
::new(strip_type(*inner_ty
)), s
),
3536 Type
::Unique(inner_ty
) => Type
::Unique(Box
::new(strip_type(*inner_ty
))),
3537 Type
::RawPointer(m
, inner_ty
) => Type
::RawPointer(m
, Box
::new(strip_type(*inner_ty
))),
3538 Type
::BorrowedRef { lifetime, mutability, type_ }
=> {
3539 Type
::BorrowedRef { lifetime, mutability, type_: Box::new(strip_type(*type_)) }
3541 Type
::QPath { name, self_type, trait_ }
=> {
3544 self_type
: Box
::new(strip_type(*self_type
)), trait_
: Box
::new(strip_type(*trait_
))
3551 fn strip_path(path
: &Path
) -> Path
{
3552 let segments
= path
.segments
.iter().map(|s
| {
3554 name
: s
.name
.clone(),
3555 args
: GenericArgs
::AngleBracketed
{
3563 global
: path
.global
,
3564 def
: path
.def
.clone(),
3569 fn qpath_to_string(p
: &hir
::QPath
) -> String
{
3570 let segments
= match *p
{
3571 hir
::QPath
::Resolved(_
, ref path
) => &path
.segments
,
3572 hir
::QPath
::TypeRelative(_
, ref segment
) => return segment
.ident
.to_string(),
3575 let mut s
= String
::new();
3576 for (i
, seg
) in segments
.iter().enumerate() {
3580 if seg
.ident
.name
!= keywords
::PathRoot
.name() {
3581 s
.push_str(&*seg
.ident
.as_str());
3587 impl Clean
<String
> for Ident
{
3589 fn clean(&self, cx
: &DocContext
<'_
>) -> String
{
3594 impl Clean
<String
> for ast
::Name
{
3596 fn clean(&self, _
: &DocContext
<'_
>) -> String
{
3601 impl Clean
<String
> for InternedString
{
3603 fn clean(&self, _
: &DocContext
<'_
>) -> String
{
3608 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3609 pub struct Typedef
{
3611 pub generics
: Generics
,
3614 impl Clean
<Item
> for doctree
::Typedef
{
3615 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3617 name
: Some(self.name
.clean(cx
)),
3618 attrs
: self.attrs
.clean(cx
),
3619 source
: self.whence
.clean(cx
),
3620 def_id
: cx
.tcx
.hir().local_def_id_from_hir_id(self.id
),
3621 visibility
: self.vis
.clean(cx
),
3622 stability
: self.stab
.clean(cx
),
3623 deprecation
: self.depr
.clean(cx
),
3624 inner
: TypedefItem(Typedef
{
3625 type_
: self.ty
.clean(cx
),
3626 generics
: self.gen
.clean(cx
),
3632 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3633 pub struct Existential
{
3634 pub bounds
: Vec
<GenericBound
>,
3635 pub generics
: Generics
,
3638 impl Clean
<Item
> for doctree
::Existential
{
3639 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3641 name
: Some(self.name
.clean(cx
)),
3642 attrs
: self.attrs
.clean(cx
),
3643 source
: self.whence
.clean(cx
),
3644 def_id
: cx
.tcx
.hir().local_def_id_from_hir_id(self.id
),
3645 visibility
: self.vis
.clean(cx
),
3646 stability
: self.stab
.clean(cx
),
3647 deprecation
: self.depr
.clean(cx
),
3648 inner
: ExistentialItem(Existential
{
3649 bounds
: self.exist_ty
.bounds
.clean(cx
),
3650 generics
: self.exist_ty
.generics
.clean(cx
),
3656 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3657 pub struct BareFunctionDecl
{
3658 pub unsafety
: hir
::Unsafety
,
3659 pub generic_params
: Vec
<GenericParamDef
>,
3664 impl Clean
<BareFunctionDecl
> for hir
::BareFnTy
{
3665 fn clean(&self, cx
: &DocContext
<'_
>) -> BareFunctionDecl
{
3666 let (generic_params
, decl
) = enter_impl_trait(cx
, || {
3667 (self.generic_params
.clean(cx
), (&*self.decl
, &self.arg_names
[..]).clean(cx
))
3670 unsafety
: self.unsafety
,
3678 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3681 pub mutability
: Mutability
,
3682 /// It's useful to have the value of a static documented, but I have no
3683 /// desire to represent expressions (that'd basically be all of the AST,
3684 /// which is huge!). So, have a string.
3688 impl Clean
<Item
> for doctree
::Static
{
3689 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3690 debug
!("cleaning static {}: {:?}", self.name
.clean(cx
), self);
3692 name
: Some(self.name
.clean(cx
)),
3693 attrs
: self.attrs
.clean(cx
),
3694 source
: self.whence
.clean(cx
),
3695 def_id
: cx
.tcx
.hir().local_def_id_from_hir_id(self.id
),
3696 visibility
: self.vis
.clean(cx
),
3697 stability
: self.stab
.clean(cx
),
3698 deprecation
: self.depr
.clean(cx
),
3699 inner
: StaticItem(Static
{
3700 type_
: self.type_
.clean(cx
),
3701 mutability
: self.mutability
.clean(cx
),
3702 expr
: print_const_expr(cx
, self.expr
),
3708 #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
3709 pub struct Constant
{
3714 impl Clean
<Item
> for doctree
::Constant
{
3715 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3717 name
: Some(self.name
.clean(cx
)),
3718 attrs
: self.attrs
.clean(cx
),
3719 source
: self.whence
.clean(cx
),
3720 def_id
: cx
.tcx
.hir().local_def_id_from_hir_id(self.id
),
3721 visibility
: self.vis
.clean(cx
),
3722 stability
: self.stab
.clean(cx
),
3723 deprecation
: self.depr
.clean(cx
),
3724 inner
: ConstantItem(Constant
{
3725 type_
: self.type_
.clean(cx
),
3726 expr
: print_const_expr(cx
, self.expr
),
3732 #[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Copy, Hash)]
3733 pub enum Mutability
{
3738 impl Clean
<Mutability
> for hir
::Mutability
{
3739 fn clean(&self, _
: &DocContext
<'_
>) -> Mutability
{
3741 &hir
::MutMutable
=> Mutable
,
3742 &hir
::MutImmutable
=> Immutable
,
3747 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Copy, Debug, Hash)]
3748 pub enum ImplPolarity
{
3753 impl Clean
<ImplPolarity
> for hir
::ImplPolarity
{
3754 fn clean(&self, _
: &DocContext
<'_
>) -> ImplPolarity
{
3756 &hir
::ImplPolarity
::Positive
=> ImplPolarity
::Positive
,
3757 &hir
::ImplPolarity
::Negative
=> ImplPolarity
::Negative
,
3762 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3764 pub unsafety
: hir
::Unsafety
,
3765 pub generics
: Generics
,
3766 pub provided_trait_methods
: FxHashSet
<String
>,
3767 pub trait_
: Option
<Type
>,
3769 pub items
: Vec
<Item
>,
3770 pub polarity
: Option
<ImplPolarity
>,
3771 pub synthetic
: bool
,
3772 pub blanket_impl
: Option
<Type
>,
3775 pub fn get_auto_traits_with_hir_id(
3776 cx
: &DocContext
<'_
>,
3780 let finder
= AutoTraitFinder
::new(cx
);
3781 finder
.get_with_hir_id(id
, name
)
3784 pub fn get_auto_traits_with_def_id(
3785 cx
: &DocContext
<'_
>,
3788 let finder
= AutoTraitFinder
::new(cx
);
3790 finder
.get_with_def_id(id
)
3793 pub fn get_blanket_impls_with_hir_id(
3794 cx
: &DocContext
<'_
>,
3798 let finder
= BlanketImplFinder
::new(cx
);
3799 finder
.get_with_hir_id(id
, name
)
3802 pub fn get_blanket_impls_with_def_id(
3803 cx
: &DocContext
<'_
>,
3806 let finder
= BlanketImplFinder
::new(cx
);
3808 finder
.get_with_def_id(id
)
3811 impl Clean
<Vec
<Item
>> for doctree
::Impl
{
3812 fn clean(&self, cx
: &DocContext
<'_
>) -> Vec
<Item
> {
3813 let mut ret
= Vec
::new();
3814 let trait_
= self.trait_
.clean(cx
);
3815 let items
= self.items
.clean(cx
);
3817 // If this impl block is an implementation of the Deref trait, then we
3818 // need to try inlining the target's inherent impl blocks as well.
3819 if trait_
.def_id() == cx
.tcx
.lang_items().deref_trait() {
3820 build_deref_target_impls(cx
, &items
, &mut ret
);
3823 let provided
= trait_
.def_id().map(|did
| {
3824 cx
.tcx
.provided_trait_methods(did
)
3826 .map(|meth
| meth
.ident
.to_string())
3828 }).unwrap_or_default();
3832 attrs
: self.attrs
.clean(cx
),
3833 source
: self.whence
.clean(cx
),
3834 def_id
: cx
.tcx
.hir().local_def_id_from_hir_id(self.id
),
3835 visibility
: self.vis
.clean(cx
),
3836 stability
: self.stab
.clean(cx
),
3837 deprecation
: self.depr
.clean(cx
),
3838 inner
: ImplItem(Impl
{
3839 unsafety
: self.unsafety
,
3840 generics
: self.generics
.clean(cx
),
3841 provided_trait_methods
: provided
,
3843 for_
: self.for_
.clean(cx
),
3845 polarity
: Some(self.polarity
.clean(cx
)),
3854 fn build_deref_target_impls(cx
: &DocContext
<'_
>,
3856 ret
: &mut Vec
<Item
>) {
3857 use self::PrimitiveType
::*;
3861 let target
= match item
.inner
{
3862 TypedefItem(ref t
, true) => &t
.type_
,
3865 let primitive
= match *target
{
3866 ResolvedPath { did, .. }
if did
.is_local() => continue,
3867 ResolvedPath { did, .. }
=> {
3868 ret
.extend(inline
::build_impls(cx
, did
));
3871 _
=> match target
.primitive_type() {
3876 let did
= match primitive
{
3877 Isize
=> tcx
.lang_items().isize_impl(),
3878 I8
=> tcx
.lang_items().i8_impl(),
3879 I16
=> tcx
.lang_items().i16_impl(),
3880 I32
=> tcx
.lang_items().i32_impl(),
3881 I64
=> tcx
.lang_items().i64_impl(),
3882 I128
=> tcx
.lang_items().i128_impl(),
3883 Usize
=> tcx
.lang_items().usize_impl(),
3884 U8
=> tcx
.lang_items().u8_impl(),
3885 U16
=> tcx
.lang_items().u16_impl(),
3886 U32
=> tcx
.lang_items().u32_impl(),
3887 U64
=> tcx
.lang_items().u64_impl(),
3888 U128
=> tcx
.lang_items().u128_impl(),
3889 F32
=> tcx
.lang_items().f32_impl(),
3890 F64
=> tcx
.lang_items().f64_impl(),
3891 Char
=> tcx
.lang_items().char_impl(),
3893 Str
=> tcx
.lang_items().str_impl(),
3894 Slice
=> tcx
.lang_items().slice_impl(),
3895 Array
=> tcx
.lang_items().slice_impl(),
3898 RawPointer
=> tcx
.lang_items().const_ptr_impl(),
3902 CVarArgs
=> tcx
.lang_items().va_list(),
3904 if let Some(did
) = did
{
3905 if !did
.is_local() {
3906 inline
::build_impl(cx
, did
, ret
);
3912 impl Clean
<Vec
<Item
>> for doctree
::ExternCrate
{
3913 fn clean(&self, cx
: &DocContext
<'_
>) -> Vec
<Item
> {
3915 let please_inline
= self.vis
.node
.is_pub() && self.attrs
.iter().any(|a
| {
3916 a
.check_name("doc") && match a
.meta_item_list() {
3917 Some(l
) => attr
::list_contains_name(&l
, "inline"),
3923 let mut visited
= FxHashSet
::default();
3925 let def
= Def
::Mod(DefId
{
3927 index
: CRATE_DEF_INDEX
,
3930 if let Some(items
) = inline
::try_inline(cx
, def
, self.name
, &mut visited
) {
3937 attrs
: self.attrs
.clean(cx
),
3938 source
: self.whence
.clean(cx
),
3939 def_id
: DefId { krate: self.cnum, index: CRATE_DEF_INDEX }
,
3940 visibility
: self.vis
.clean(cx
),
3943 inner
: ExternCrateItem(self.name
.clean(cx
), self.path
.clone())
3948 impl Clean
<Vec
<Item
>> for doctree
::Import
{
3949 fn clean(&self, cx
: &DocContext
<'_
>) -> Vec
<Item
> {
3950 // We consider inlining the documentation of `pub use` statements, but we
3951 // forcefully don't inline if this is not public or if the
3952 // #[doc(no_inline)] attribute is present.
3953 // Don't inline doc(hidden) imports so they can be stripped at a later stage.
3954 let mut denied
= !self.vis
.node
.is_pub() || self.attrs
.iter().any(|a
| {
3955 a
.check_name("doc") && match a
.meta_item_list() {
3956 Some(l
) => attr
::list_contains_name(&l
, "no_inline") ||
3957 attr
::list_contains_name(&l
, "hidden"),
3961 // Also check whether imports were asked to be inlined, in case we're trying to re-export a
3962 // crate in Rust 2018+
3963 let please_inline
= self.attrs
.lists("doc").has_word("inline");
3964 let path
= self.path
.clean(cx
);
3965 let inner
= if self.glob
{
3967 let mut visited
= FxHashSet
::default();
3968 if let Some(items
) = inline
::try_inline_glob(cx
, path
.def
, &mut visited
) {
3973 Import
::Glob(resolve_use_source(cx
, path
))
3975 let name
= self.name
;
3978 Def
::Mod(did
) => if !did
.is_local() && did
.index
== CRATE_DEF_INDEX
{
3979 // if we're `pub use`ing an extern crate root, don't inline it unless we
3980 // were specifically asked for it
3987 let mut visited
= FxHashSet
::default();
3988 if let Some(items
) = inline
::try_inline(cx
, path
.def
, name
, &mut visited
) {
3992 Import
::Simple(name
.clean(cx
), resolve_use_source(cx
, path
))
3997 attrs
: self.attrs
.clean(cx
),
3998 source
: self.whence
.clean(cx
),
3999 def_id
: cx
.tcx
.hir().local_def_id(ast
::CRATE_NODE_ID
),
4000 visibility
: self.vis
.clean(cx
),
4003 inner
: ImportItem(inner
)
4008 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
4010 // use source as str;
4011 Simple(String
, ImportSource
),
4016 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
4017 pub struct ImportSource
{
4019 pub did
: Option
<DefId
>,
4022 impl Clean
<Vec
<Item
>> for hir
::ForeignMod
{
4023 fn clean(&self, cx
: &DocContext
<'_
>) -> Vec
<Item
> {
4024 let mut items
= self.items
.clean(cx
);
4025 for item
in &mut items
{
4026 if let ForeignFunctionItem(ref mut f
) = item
.inner
{
4027 f
.header
.abi
= self.abi
;
4034 impl Clean
<Item
> for hir
::ForeignItem
{
4035 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
4036 let inner
= match self.node
{
4037 hir
::ForeignItemKind
::Fn(ref decl
, ref names
, ref generics
) => {
4038 let (generics
, decl
) = enter_impl_trait(cx
, || {
4039 (generics
.clean(cx
), (&**decl
, &names
[..]).clean(cx
))
4041 let (all_types
, ret_types
) = get_all_types(&generics
, &decl
, cx
);
4042 ForeignFunctionItem(Function
{
4045 header
: hir
::FnHeader
{
4046 unsafety
: hir
::Unsafety
::Unsafe
,
4048 constness
: hir
::Constness
::NotConst
,
4049 asyncness
: hir
::IsAsync
::NotAsync
,
4055 hir
::ForeignItemKind
::Static(ref ty
, mutbl
) => {
4056 ForeignStaticItem(Static
{
4057 type_
: ty
.clean(cx
),
4058 mutability
: if mutbl {Mutable}
else {Immutable}
,
4059 expr
: String
::new(),
4062 hir
::ForeignItemKind
::Type
=> {
4067 let local_did
= cx
.tcx
.hir().local_def_id_from_hir_id(self.hir_id
);
4070 name
: Some(self.ident
.clean(cx
)),
4071 attrs
: self.attrs
.clean(cx
),
4072 source
: self.span
.clean(cx
),
4074 visibility
: self.vis
.clean(cx
),
4075 stability
: get_stability(cx
, local_did
),
4076 deprecation
: get_deprecation(cx
, local_did
),
4084 pub trait ToSource
{
4085 fn to_src(&self, cx
: &DocContext
<'_
>) -> String
;
4088 impl ToSource
for syntax_pos
::Span
{
4089 fn to_src(&self, cx
: &DocContext
<'_
>) -> String
{
4090 debug
!("converting span {:?} to snippet", self.clean(cx
));
4091 let sn
= match cx
.sess().source_map().span_to_snippet(*self) {
4093 Err(_
) => String
::new()
4095 debug
!("got snippet {}", sn
);
4100 fn name_from_pat(p
: &hir
::Pat
) -> String
{
4102 debug
!("Trying to get a name from pattern: {:?}", p
);
4105 PatKind
::Wild
=> "_".to_string(),
4106 PatKind
::Binding(_
, _
, ident
, _
) => ident
.to_string(),
4107 PatKind
::TupleStruct(ref p
, ..) | PatKind
::Path(ref p
) => qpath_to_string(p
),
4108 PatKind
::Struct(ref name
, ref fields
, etc
) => {
4109 format
!("{} {{ {}{} }}", qpath_to_string(name
),
4110 fields
.iter().map(|&Spanned { node: ref fp, .. }
|
4111 format
!("{}: {}", fp
.ident
, name_from_pat(&*fp
.pat
)))
4112 .collect
::<Vec
<String
>>().join(", "),
4113 if etc { ", .." }
else { "" }
4116 PatKind
::Tuple(ref elts
, _
) => format
!("({})", elts
.iter().map(|p
| name_from_pat(&**p
))
4117 .collect
::<Vec
<String
>>().join(", ")),
4118 PatKind
::Box(ref p
) => name_from_pat(&**p
),
4119 PatKind
::Ref(ref p
, _
) => name_from_pat(&**p
),
4120 PatKind
::Lit(..) => {
4121 warn
!("tried to get argument name from PatKind::Lit, \
4122 which is silly in function arguments");
4125 PatKind
::Range(..) => panic
!("tried to get argument name from PatKind::Range, \
4126 which is not allowed in function arguments"),
4127 PatKind
::Slice(ref begin
, ref mid
, ref end
) => {
4128 let begin
= begin
.iter().map(|p
| name_from_pat(&**p
));
4129 let mid
= mid
.as_ref().map(|p
| format
!("..{}", name_from_pat(&**p
))).into_iter();
4130 let end
= end
.iter().map(|p
| name_from_pat(&**p
));
4131 format
!("[{}]", begin
.chain(mid
).chain(end
).collect
::<Vec
<_
>>().join(", "))
4136 fn print_const(cx
: &DocContext
<'_
>, n
: ty
::Const
<'_
>) -> String
{
4138 ConstValue
::Unevaluated(def_id
, _
) => {
4139 if let Some(hir_id
) = cx
.tcx
.hir().as_local_hir_id(def_id
) {
4140 print_const_expr(cx
, cx
.tcx
.hir().body_owned_by(hir_id
))
4142 inline
::print_inlined_const(cx
, def_id
)
4146 let mut s
= String
::new();
4147 ::rustc
::mir
::fmt_const_val(&mut s
, n
).expect("fmt_const_val failed");
4148 // array lengths are obviously usize
4149 if s
.ends_with("usize") {
4150 let n
= s
.len() - "usize".len();
4158 fn print_const_expr(cx
: &DocContext
<'_
>, body
: hir
::BodyId
) -> String
{
4159 cx
.tcx
.hir().hir_to_pretty_string(body
.hir_id
)
4162 /// Given a type Path, resolve it to a Type using the TyCtxt
4163 fn resolve_type(cx
: &DocContext
<'_
>,
4165 id
: hir
::HirId
) -> Type
{
4166 if id
== hir
::DUMMY_HIR_ID
{
4167 debug
!("resolve_type({:?})", path
);
4169 debug
!("resolve_type({:?},{:?})", path
, id
);
4172 let is_generic
= match path
.def
{
4173 Def
::PrimTy(p
) => match p
{
4174 hir
::Str
=> return Primitive(PrimitiveType
::Str
),
4175 hir
::Bool
=> return Primitive(PrimitiveType
::Bool
),
4176 hir
::Char
=> return Primitive(PrimitiveType
::Char
),
4177 hir
::Int(int_ty
) => return Primitive(int_ty
.into()),
4178 hir
::Uint(uint_ty
) => return Primitive(uint_ty
.into()),
4179 hir
::Float(float_ty
) => return Primitive(float_ty
.into()),
4181 Def
::SelfTy(..) if path
.segments
.len() == 1 => {
4182 return Generic(keywords
::SelfUpper
.name().to_string());
4184 Def
::TyParam(..) if path
.segments
.len() == 1 => {
4185 return Generic(format
!("{:#}", path
));
4187 Def
::SelfTy(..) | Def
::TyParam(..) | Def
::AssociatedTy(..) => true,
4190 let did
= register_def(&*cx
, path
.def
);
4191 ResolvedPath { path: path, param_names: None, did: did, is_generic: is_generic }
4194 pub fn register_def(cx
: &DocContext
<'_
>, def
: Def
) -> DefId
{
4195 debug
!("register_def({:?})", def
);
4197 let (did
, kind
) = match def
{
4198 Def
::Fn(i
) => (i
, TypeKind
::Function
),
4199 Def
::TyAlias(i
) => (i
, TypeKind
::Typedef
),
4200 Def
::Enum(i
) => (i
, TypeKind
::Enum
),
4201 Def
::Trait(i
) => (i
, TypeKind
::Trait
),
4202 Def
::Struct(i
) => (i
, TypeKind
::Struct
),
4203 Def
::Union(i
) => (i
, TypeKind
::Union
),
4204 Def
::Mod(i
) => (i
, TypeKind
::Module
),
4205 Def
::ForeignTy(i
) => (i
, TypeKind
::Foreign
),
4206 Def
::Const(i
) => (i
, TypeKind
::Const
),
4207 Def
::Static(i
, _
) => (i
, TypeKind
::Static
),
4208 Def
::Variant(i
) => (cx
.tcx
.parent(i
).expect("cannot get parent def id"),
4210 Def
::Macro(i
, mac_kind
) => match mac_kind
{
4211 MacroKind
::Bang
=> (i
, TypeKind
::Macro
),
4212 MacroKind
::Attr
=> (i
, TypeKind
::Attr
),
4213 MacroKind
::Derive
=> (i
, TypeKind
::Derive
),
4214 MacroKind
::ProcMacroStub
=> unreachable
!(),
4216 Def
::TraitAlias(i
) => (i
, TypeKind
::TraitAlias
),
4217 Def
::SelfTy(Some(def_id
), _
) => (def_id
, TypeKind
::Trait
),
4218 Def
::SelfTy(_
, Some(impl_def_id
)) => return impl_def_id
,
4219 _
=> return def
.def_id()
4221 if did
.is_local() { return did }
4222 inline
::record_extern_fqn(cx
, did
, kind
);
4223 if let TypeKind
::Trait
= kind
{
4224 inline
::record_extern_trait(cx
, did
);
4229 fn resolve_use_source(cx
: &DocContext
<'_
>, path
: Path
) -> ImportSource
{
4231 did
: if path
.def
.opt_def_id().is_none() {
4234 Some(register_def(cx
, path
.def
))
4240 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
4243 pub imported_from
: Option
<String
>,
4246 impl Clean
<Item
> for doctree
::Macro
{
4247 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
4248 let name
= self.name
.clean(cx
);
4250 name
: Some(name
.clone()),
4251 attrs
: self.attrs
.clean(cx
),
4252 source
: self.whence
.clean(cx
),
4253 visibility
: Some(Public
),
4254 stability
: self.stab
.clean(cx
),
4255 deprecation
: self.depr
.clean(cx
),
4256 def_id
: self.def_id
,
4257 inner
: MacroItem(Macro
{
4258 source
: format
!("macro_rules! {} {{\n{}}}",
4260 self.matchers
.iter().map(|span
| {
4261 format
!(" {} => {{ ... }};\n", span
.to_src(cx
))
4262 }).collect
::<String
>()),
4263 imported_from
: self.imported_from
.clean(cx
),
4269 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
4270 pub struct ProcMacro
{
4271 pub kind
: MacroKind
,
4272 pub helpers
: Vec
<String
>,
4275 impl Clean
<Item
> for doctree
::ProcMacro
{
4276 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
4278 name
: Some(self.name
.clean(cx
)),
4279 attrs
: self.attrs
.clean(cx
),
4280 source
: self.whence
.clean(cx
),
4281 visibility
: Some(Public
),
4282 stability
: self.stab
.clean(cx
),
4283 deprecation
: self.depr
.clean(cx
),
4284 def_id
: cx
.tcx
.hir().local_def_id_from_hir_id(self.id
),
4285 inner
: ProcMacroItem(ProcMacro
{
4287 helpers
: self.helpers
.clean(cx
),
4293 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
4294 pub struct Stability
{
4295 pub level
: stability
::StabilityLevel
,
4296 pub feature
: Option
<String
>,
4298 pub deprecation
: Option
<Deprecation
>,
4299 pub unstable_reason
: Option
<String
>,
4300 pub issue
: Option
<u32>,
4303 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
4304 pub struct Deprecation
{
4305 pub since
: Option
<String
>,
4306 pub note
: Option
<String
>,
4309 impl Clean
<Stability
> for attr
::Stability
{
4310 fn clean(&self, _
: &DocContext
<'_
>) -> Stability
{
4312 level
: stability
::StabilityLevel
::from_attr_level(&self.level
),
4313 feature
: Some(self.feature
.to_string()).filter(|f
| !f
.is_empty()),
4314 since
: match self.level
{
4315 attr
::Stable {ref since}
=> since
.to_string(),
4318 deprecation
: self.rustc_depr
.as_ref().map(|d
| {
4320 note
: Some(d
.reason
.to_string()).filter(|r
| !r
.is_empty()),
4321 since
: Some(d
.since
.to_string()).filter(|d
| !d
.is_empty()),
4324 unstable_reason
: match self.level
{
4325 attr
::Unstable { reason: Some(ref reason), .. }
=> Some(reason
.to_string()),
4328 issue
: match self.level
{
4329 attr
::Unstable {issue, ..}
=> Some(issue
),
4336 impl<'a
> Clean
<Stability
> for &'a attr
::Stability
{
4337 fn clean(&self, dc
: &DocContext
<'_
>) -> Stability
{
4342 impl Clean
<Deprecation
> for attr
::Deprecation
{
4343 fn clean(&self, _
: &DocContext
<'_
>) -> Deprecation
{
4345 since
: self.since
.map(|s
| s
.to_string()).filter(|s
| !s
.is_empty()),
4346 note
: self.note
.map(|n
| n
.to_string()).filter(|n
| !n
.is_empty()),
4351 /// An equality constraint on an associated type, e.g., `A = Bar` in `Foo<A = Bar>`
4352 #[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug, Hash)]
4353 pub struct TypeBinding
{
4358 impl Clean
<TypeBinding
> for hir
::TypeBinding
{
4359 fn clean(&self, cx
: &DocContext
<'_
>) -> TypeBinding
{
4361 name
: self.ident
.name
.clean(cx
),
4362 ty
: self.ty
.clean(cx
)
4367 pub fn def_id_to_path(
4368 cx
: &DocContext
<'_
>,
4370 name
: Option
<String
>
4372 let crate_name
= name
.unwrap_or_else(|| cx
.tcx
.crate_name(did
.krate
).to_string());
4373 let relative
= cx
.tcx
.def_path(did
).data
.into_iter().filter_map(|elem
| {
4374 // extern blocks have an empty name
4375 let s
= elem
.data
.to_string();
4382 once(crate_name
).chain(relative
).collect()
4385 pub fn enter_impl_trait
<F
, R
>(cx
: &DocContext
<'_
>, f
: F
) -> R
4389 let old_bounds
= mem
::replace(&mut *cx
.impl_trait_bounds
.borrow_mut(), Default
::default());
4391 assert
!(cx
.impl_trait_bounds
.borrow().is_empty());
4392 *cx
.impl_trait_bounds
.borrow_mut() = old_bounds
;
4396 // Start of code copied from rust-clippy
4398 pub fn path_to_def_local(tcx
: &TyCtxt
<'_
, '_
, '_
>, path
: &[&str]) -> Option
<DefId
> {
4399 let krate
= tcx
.hir().krate();
4400 let mut items
= krate
.module
.item_ids
.clone();
4401 let mut path_it
= path
.iter().peekable();
4404 let segment
= path_it
.next()?
;
4406 for item_id
in mem
::replace(&mut items
, HirVec
::new()).iter() {
4407 let item
= tcx
.hir().expect_item_by_hir_id(item_id
.id
);
4408 if item
.ident
.name
== *segment
{
4409 if path_it
.peek().is_none() {
4410 return Some(tcx
.hir().local_def_id_from_hir_id(item_id
.id
))
4413 items
= match &item
.node
{
4414 &hir
::ItemKind
::Mod(ref m
) => m
.item_ids
.clone(),
4415 _
=> panic
!("Unexpected item {:?} in path {:?} path")
4423 pub fn path_to_def(tcx
: &TyCtxt
<'_
, '_
, '_
>, path
: &[&str]) -> Option
<DefId
> {
4424 let crates
= tcx
.crates();
4428 .find(|&&krate
| tcx
.crate_name(krate
) == path
[0]);
4430 if let Some(krate
) = krate
{
4433 index
: CRATE_DEF_INDEX
,
4435 let mut items
= tcx
.item_children(krate
);
4436 let mut path_it
= path
.iter().skip(1).peekable();
4439 let segment
= path_it
.next()?
;
4441 for item
in mem
::replace(&mut items
, Lrc
::new(vec
![])).iter() {
4442 if item
.ident
.name
== *segment
{
4443 if path_it
.peek().is_none() {
4444 return match item
.def
{
4445 def
::Def
::Trait(did
) => Some(did
),
4450 items
= tcx
.item_children(item
.def
.def_id());
4460 pub fn get_path_for_type(
4461 tcx
: TyCtxt
<'_
, '_
, '_
>,
4463 def_ctor
: impl Fn(DefId
) -> Def
,
4465 use rustc
::ty
::print
::Printer
;
4467 struct AbsolutePathPrinter
<'a
, 'tcx
> {
4468 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
4471 impl Printer
<'tcx
, 'tcx
> for AbsolutePathPrinter
<'_
, 'tcx
> {
4474 type Path
= Vec
<String
>;
4477 type DynExistential
= ();
4479 fn tcx(&'a
self) -> TyCtxt
<'a
, 'tcx
, 'tcx
> {
4485 _region
: ty
::Region
<'_
>,
4486 ) -> Result
<Self::Region
, Self::Error
> {
4493 ) -> Result
<Self::Type
, Self::Error
> {
4497 fn print_dyn_existential(
4499 _predicates
: &'tcx ty
::List
<ty
::ExistentialPredicate
<'tcx
>>,
4500 ) -> Result
<Self::DynExistential
, Self::Error
> {
4507 ) -> Result
<Self::Path
, Self::Error
> {
4508 Ok(vec
![self.tcx
.original_crate_name(cnum
).to_string()])
4513 trait_ref
: Option
<ty
::TraitRef
<'tcx
>>,
4514 ) -> Result
<Self::Path
, Self::Error
> {
4515 // This shouldn't ever be needed, but just in case:
4516 Ok(vec
![match trait_ref
{
4517 Some(trait_ref
) => format
!("{:?}", trait_ref
),
4518 None
=> format
!("<{}>", self_ty
),
4522 fn path_append_impl(
4524 print_prefix
: impl FnOnce(Self) -> Result
<Self::Path
, Self::Error
>,
4525 _disambiguated_data
: &DisambiguatedDefPathData
,
4527 trait_ref
: Option
<ty
::TraitRef
<'tcx
>>,
4528 ) -> Result
<Self::Path
, Self::Error
> {
4529 let mut path
= print_prefix(self)?
;
4531 // This shouldn't ever be needed, but just in case:
4532 path
.push(match trait_ref
{
4533 Some(trait_ref
) => {
4534 format
!("<impl {} for {}>", trait_ref
, self_ty
)
4536 None
=> format
!("<impl {}>", self_ty
),
4543 print_prefix
: impl FnOnce(Self) -> Result
<Self::Path
, Self::Error
>,
4544 disambiguated_data
: &DisambiguatedDefPathData
,
4545 ) -> Result
<Self::Path
, Self::Error
> {
4546 let mut path
= print_prefix(self)?
;
4547 path
.push(disambiguated_data
.data
.as_interned_str().to_string());
4550 fn path_generic_args(
4552 print_prefix
: impl FnOnce(Self) -> Result
<Self::Path
, Self::Error
>,
4553 _args
: &[Kind
<'tcx
>],
4554 ) -> Result
<Self::Path
, Self::Error
> {
4559 let names
= AbsolutePathPrinter { tcx: tcx.global_tcx() }
4560 .print_def_path(def_id
, &[])
4565 def
: def_ctor(def_id
),
4566 segments
: hir
::HirVec
::from_vec(names
.iter().map(|s
| hir
::PathSegment
{
4567 ident
: ast
::Ident
::from_str(&s
),
4576 // End of code copied from rust-clippy
4579 #[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
4580 enum RegionTarget
<'tcx
> {
4581 Region(Region
<'tcx
>),
4582 RegionVid(RegionVid
)
4585 #[derive(Default, Debug, Clone)]
4586 struct RegionDeps
<'tcx
> {
4587 larger
: FxHashSet
<RegionTarget
<'tcx
>>,
4588 smaller
: FxHashSet
<RegionTarget
<'tcx
>>
4591 #[derive(Eq, PartialEq, Hash, Debug)]
4593 TraitBound(Vec
<PathSegment
>, Vec
<SimpleBound
>, Vec
<GenericParamDef
>, hir
::TraitBoundModifier
),
4597 enum AutoTraitResult
{
4599 PositiveImpl(Generics
),
4603 impl AutoTraitResult
{
4604 fn is_auto(&self) -> bool
{
4606 AutoTraitResult
::PositiveImpl(_
) | AutoTraitResult
::NegativeImpl
=> true,
4612 impl From
<GenericBound
> for SimpleBound
{
4613 fn from(bound
: GenericBound
) -> Self {
4614 match bound
.clone() {
4615 GenericBound
::Outlives(l
) => SimpleBound
::Outlives(l
),
4616 GenericBound
::TraitBound(t
, mod_
) => match t
.trait_
{
4617 Type
::ResolvedPath { path, param_names, .. }
=> {
4618 SimpleBound
::TraitBound(path
.segments
,
4620 .map_or_else(|| Vec
::new(), |v
| v
.iter()
4621 .map(|p
| SimpleBound
::from(p
.clone()))
4626 _
=> panic
!("Unexpected bound {:?}", bound
),