1 // ignore-tidy-filelength
3 //! This module contains the "cleaned" pieces of the AST, and the functions
12 use rustc_index
::vec
::{IndexVec, Idx}
;
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}
;
21 use rustc
::hir
::def
::{CtorKind, DefKind, Res}
;
22 use rustc
::hir
::def_id
::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}
;
23 use rustc
::hir
::ptr
::P
;
24 use rustc
::ty
::subst
::{InternalSubsts, SubstsRef, GenericArgKind}
;
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, Attribute, AttrStyle, AttrItem, Ident}
;
31 use syntax
::parse
::lexer
::comments
;
32 use syntax
::source_map
::DUMMY_SP
;
33 use syntax_pos
::symbol
::{Symbol, kw, sym}
;
34 use syntax_pos
::hygiene
::MacroKind
;
35 use syntax_pos
::{self, Pos, FileName}
;
37 use std
::collections
::hash_map
::Entry
;
39 use std
::hash
::{Hash, Hasher}
;
40 use std
::default::Default
;
41 use std
::{mem, slice, vec}
;
42 use std
::iter
::FromIterator
;
44 use std
::cell
::RefCell
;
48 use crate::core
::{self, DocContext, ImplTraitParam}
;
50 use crate::html
::render
::{cache, ExternalLocation}
;
51 use crate::html
::item_type
::ItemType
;
55 use self::auto_trait
::AutoTraitFinder
;
56 use self::blanket_impl
::BlanketImplFinder
;
58 pub use self::Type
::*;
59 pub use self::Mutability
::*;
60 pub use self::ItemEnum
::*;
61 pub use self::SelfTy
::*;
62 pub use self::FunctionRetTy
::*;
63 pub use self::Visibility
::{Public, Inherited}
;
65 thread_local
!(pub static MAX_DEF_ID
: RefCell
<FxHashMap
<CrateNum
, DefId
>> = Default
::default());
67 const FN_OUTPUT_NAME
: &'
static str = "Output";
69 // extract the stability index for a node from tcx, if possible
70 fn get_stability(cx
: &DocContext
<'_
>, def_id
: DefId
) -> Option
<Stability
> {
71 cx
.tcx
.lookup_stability(def_id
).clean(cx
)
74 fn get_deprecation(cx
: &DocContext
<'_
>, def_id
: DefId
) -> Option
<Deprecation
> {
75 cx
.tcx
.lookup_deprecation(def_id
).clean(cx
)
79 fn clean(&self, cx
: &DocContext
<'_
>) -> T
;
82 impl<T
: Clean
<U
>, U
> Clean
<Vec
<U
>> for [T
] {
83 fn clean(&self, cx
: &DocContext
<'_
>) -> Vec
<U
> {
84 self.iter().map(|x
| x
.clean(cx
)).collect()
88 impl<T
: Clean
<U
>, U
, V
: Idx
> Clean
<IndexVec
<V
, U
>> for IndexVec
<V
, T
> {
89 fn clean(&self, cx
: &DocContext
<'_
>) -> IndexVec
<V
, U
> {
90 self.iter().map(|x
| x
.clean(cx
)).collect()
94 impl<T
: Clean
<U
>, U
> Clean
<U
> for P
<T
> {
95 fn clean(&self, cx
: &DocContext
<'_
>) -> U
{
100 impl<T
: Clean
<U
>, U
> Clean
<U
> for Rc
<T
> {
101 fn clean(&self, cx
: &DocContext
<'_
>) -> U
{
106 impl<T
: Clean
<U
>, U
> Clean
<Option
<U
>> for Option
<T
> {
107 fn clean(&self, cx
: &DocContext
<'_
>) -> Option
<U
> {
108 self.as_ref().map(|v
| v
.clean(cx
))
112 impl<T
, U
> Clean
<U
> for ty
::Binder
<T
> where T
: Clean
<U
> {
113 fn clean(&self, cx
: &DocContext
<'_
>) -> U
{
114 self.skip_binder().clean(cx
)
118 impl<T
: Clean
<U
>, U
> Clean
<Vec
<U
>> for P
<[T
]> {
119 fn clean(&self, cx
: &DocContext
<'_
>) -> Vec
<U
> {
120 self.iter().map(|x
| x
.clean(cx
)).collect()
124 #[derive(Clone, Debug)]
127 pub version
: Option
<String
>,
129 pub module
: Option
<Item
>,
130 pub externs
: Vec
<(CrateNum
, ExternalCrate
)>,
131 pub primitives
: Vec
<(DefId
, PrimitiveType
, Attributes
)>,
132 // These are later on moved into `CACHEKEY`, leaving the map empty.
133 // Only here so that they can be filtered through the rustdoc passes.
134 pub external_traits
: Rc
<RefCell
<FxHashMap
<DefId
, Trait
>>>,
135 pub masked_crates
: FxHashSet
<CrateNum
>,
139 pub fn krate(mut cx
: &mut DocContext
<'_
>) -> Crate
{
140 use crate::visit_lib
::LibEmbargoVisitor
;
142 let krate
= cx
.tcx
.hir().krate();
143 let module
= crate::visit_ast
::RustdocVisitor
::new(&mut cx
).visit(krate
);
145 let mut r
= cx
.renderinfo
.get_mut();
146 r
.deref_trait_did
= cx
.tcx
.lang_items().deref_trait();
147 r
.deref_mut_trait_did
= cx
.tcx
.lang_items().deref_mut_trait();
148 r
.owned_box_did
= cx
.tcx
.lang_items().owned_box();
150 let mut externs
= Vec
::new();
151 for &cnum
in cx
.tcx
.crates().iter() {
152 externs
.push((cnum
, cnum
.clean(cx
)));
153 // Analyze doc-reachability for extern items
154 LibEmbargoVisitor
::new(&mut cx
).visit_lib(cnum
);
156 externs
.sort_by(|&(a
, _
), &(b
, _
)| a
.cmp(&b
));
158 // Clean the crate, translating the entire libsyntax AST to one that is
159 // understood by rustdoc.
160 let mut module
= module
.clean(cx
);
161 let mut masked_crates
= FxHashSet
::default();
164 ModuleItem(ref module
) => {
165 for it
in &module
.items
{
166 // `compiler_builtins` should be masked too, but we can't apply
167 // `#[doc(masked)]` to the injected `extern crate` because it's unstable.
168 if it
.is_extern_crate()
169 && (it
.attrs
.has_doc_flag(sym
::masked
)
170 || cx
.tcx
.is_compiler_builtins(it
.def_id
.krate
))
172 masked_crates
.insert(it
.def_id
.krate
);
179 let ExternalCrate { name, src, primitives, keywords, .. }
= LOCAL_CRATE
.clean(cx
);
181 let m
= match module
.inner
{
182 ModuleItem(ref mut m
) => m
,
185 m
.items
.extend(primitives
.iter().map(|&(def_id
, prim
, ref attrs
)| {
187 source
: Span
::empty(),
188 name
: Some(prim
.to_url_str().to_string()),
189 attrs
: attrs
.clone(),
191 stability
: get_stability(cx
, def_id
),
192 deprecation
: get_deprecation(cx
, def_id
),
194 inner
: PrimitiveItem(prim
),
197 m
.items
.extend(keywords
.into_iter().map(|(def_id
, kw
, attrs
)| {
199 source
: Span
::empty(),
200 name
: Some(kw
.clone()),
203 stability
: get_stability(cx
, def_id
),
204 deprecation
: get_deprecation(cx
, def_id
),
206 inner
: KeywordItem(kw
),
215 module
: Some(module
),
218 external_traits
: cx
.external_traits
.clone(),
224 #[derive(Clone, Debug)]
225 pub struct ExternalCrate
{
228 pub attrs
: Attributes
,
229 pub primitives
: Vec
<(DefId
, PrimitiveType
, Attributes
)>,
230 pub keywords
: Vec
<(DefId
, String
, Attributes
)>,
233 impl Clean
<ExternalCrate
> for CrateNum
{
234 fn clean(&self, cx
: &DocContext
<'_
>) -> ExternalCrate
{
235 let root
= DefId { krate: *self, index: CRATE_DEF_INDEX }
;
236 let krate_span
= cx
.tcx
.def_span(root
);
237 let krate_src
= cx
.sess().source_map().span_to_filename(krate_span
);
239 // Collect all inner modules which are tagged as implementations of
242 // Note that this loop only searches the top-level items of the crate,
243 // and this is intentional. If we were to search the entire crate for an
244 // item tagged with `#[doc(primitive)]` then we would also have to
245 // search the entirety of external modules for items tagged
246 // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
247 // all that metadata unconditionally).
249 // In order to keep the metadata load under control, the
250 // `#[doc(primitive)]` feature is explicitly designed to only allow the
251 // primitive tags to show up as the top level items in a crate.
253 // Also note that this does not attempt to deal with modules tagged
254 // duplicately for the same primitive. This is handled later on when
255 // rendering by delegating everything to a hash map.
256 let as_primitive
= |res
: Res
| {
257 if let Res
::Def(DefKind
::Mod
, def_id
) = res
{
258 let attrs
= cx
.tcx
.get_attrs(def_id
).clean(cx
);
260 for attr
in attrs
.lists(sym
::doc
) {
261 if let Some(v
) = attr
.value_str() {
262 if attr
.check_name(sym
::primitive
) {
263 prim
= PrimitiveType
::from_str(&v
.as_str());
267 // FIXME: should warn on unknown primitives?
271 return prim
.map(|p
| (def_id
, p
, attrs
));
275 let primitives
= if root
.is_local() {
276 cx
.tcx
.hir().krate().module
.item_ids
.iter().filter_map(|&id
| {
277 let item
= cx
.tcx
.hir().expect_item(id
.id
);
279 hir
::ItemKind
::Mod(_
) => {
280 as_primitive(Res
::Def(
282 cx
.tcx
.hir().local_def_id(id
.id
),
285 hir
::ItemKind
::Use(ref path
, hir
::UseKind
::Single
)
286 if item
.vis
.node
.is_pub() => {
287 as_primitive(path
.res
).map(|(_
, prim
, attrs
)| {
288 // Pretend the primitive is local.
289 (cx
.tcx
.hir().local_def_id(id
.id
), prim
, attrs
)
296 cx
.tcx
.item_children(root
).iter().map(|item
| item
.res
)
297 .filter_map(as_primitive
).collect()
300 let as_keyword
= |res
: Res
| {
301 if let Res
::Def(DefKind
::Mod
, def_id
) = res
{
302 let attrs
= cx
.tcx
.get_attrs(def_id
).clean(cx
);
303 let mut keyword
= None
;
304 for attr
in attrs
.lists(sym
::doc
) {
305 if let Some(v
) = attr
.value_str() {
306 if attr
.check_name(sym
::keyword
) {
307 if v
.is_doc_keyword() {
308 keyword
= Some(v
.to_string());
311 // FIXME: should warn on unknown keywords?
315 return keyword
.map(|p
| (def_id
, p
, attrs
));
319 let keywords
= if root
.is_local() {
320 cx
.tcx
.hir().krate().module
.item_ids
.iter().filter_map(|&id
| {
321 let item
= cx
.tcx
.hir().expect_item(id
.id
);
323 hir
::ItemKind
::Mod(_
) => {
326 cx
.tcx
.hir().local_def_id(id
.id
),
329 hir
::ItemKind
::Use(ref path
, hir
::UseKind
::Single
)
330 if item
.vis
.node
.is_pub() => {
331 as_keyword(path
.res
).map(|(_
, prim
, attrs
)| {
332 (cx
.tcx
.hir().local_def_id(id
.id
), prim
, attrs
)
339 cx
.tcx
.item_children(root
).iter().map(|item
| item
.res
)
340 .filter_map(as_keyword
).collect()
344 name
: cx
.tcx
.crate_name(*self).to_string(),
346 attrs
: cx
.tcx
.get_attrs(root
).clean(cx
),
353 /// Anything with a source location and set of attributes and, optionally, a
354 /// name. That is, anything that can be documented. This doesn't correspond
355 /// directly to the AST's concept of an item; it's a strict superset.
360 /// Not everything has a name. E.g., impls
361 pub name
: Option
<String
>,
362 pub attrs
: Attributes
,
364 pub visibility
: Visibility
,
366 pub stability
: Option
<Stability
>,
367 pub deprecation
: Option
<Deprecation
>,
370 impl fmt
::Debug
for Item
{
371 fn fmt(&self, fmt
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
373 let fake
= MAX_DEF_ID
.with(|m
| m
.borrow().get(&self.def_id
.krate
)
374 .map(|id
| self.def_id
>= *id
).unwrap_or(false));
375 let def_id
: &dyn fmt
::Debug
= if fake { &"**FAKE**" }
else { &self.def_id }
;
377 fmt
.debug_struct("Item")
378 .field("source", &self.source
)
379 .field("name", &self.name
)
380 .field("attrs", &self.attrs
)
381 .field("inner", &self.inner
)
382 .field("visibility", &self.visibility
)
383 .field("def_id", def_id
)
384 .field("stability", &self.stability
)
385 .field("deprecation", &self.deprecation
)
391 /// Finds the `doc` attribute as a NameValue and returns the corresponding
393 pub fn doc_value(&self) -> Option
<&str> {
394 self.attrs
.doc_value()
396 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
398 pub fn collapsed_doc_value(&self) -> Option
<String
> {
399 self.attrs
.collapsed_doc_value()
402 pub fn links(&self) -> Vec
<(String
, String
)> {
403 self.attrs
.links(&self.def_id
.krate
)
406 pub fn is_crate(&self) -> bool
{
408 StrippedItem(box ModuleItem(Module { is_crate: true, ..}
)) |
409 ModuleItem(Module { is_crate: true, ..}
) => true,
413 pub fn is_mod(&self) -> bool
{
414 self.type_() == ItemType
::Module
416 pub fn is_trait(&self) -> bool
{
417 self.type_() == ItemType
::Trait
419 pub fn is_struct(&self) -> bool
{
420 self.type_() == ItemType
::Struct
422 pub fn is_enum(&self) -> bool
{
423 self.type_() == ItemType
::Enum
425 pub fn is_variant(&self) -> bool
{
426 self.type_() == ItemType
::Variant
428 pub fn is_associated_type(&self) -> bool
{
429 self.type_() == ItemType
::AssocType
431 pub fn is_associated_const(&self) -> bool
{
432 self.type_() == ItemType
::AssocConst
434 pub fn is_method(&self) -> bool
{
435 self.type_() == ItemType
::Method
437 pub fn is_ty_method(&self) -> bool
{
438 self.type_() == ItemType
::TyMethod
440 pub fn is_typedef(&self) -> bool
{
441 self.type_() == ItemType
::Typedef
443 pub fn is_primitive(&self) -> bool
{
444 self.type_() == ItemType
::Primitive
446 pub fn is_union(&self) -> bool
{
447 self.type_() == ItemType
::Union
449 pub fn is_import(&self) -> bool
{
450 self.type_() == ItemType
::Import
452 pub fn is_extern_crate(&self) -> bool
{
453 self.type_() == ItemType
::ExternCrate
455 pub fn is_keyword(&self) -> bool
{
456 self.type_() == ItemType
::Keyword
459 pub fn is_stripped(&self) -> bool
{
460 match self.inner { StrippedItem(..) => true, _ => false }
462 pub fn has_stripped_fields(&self) -> Option
<bool
> {
464 StructItem(ref _struct
) => Some(_struct
.fields_stripped
),
465 UnionItem(ref union) => Some(union.fields_stripped
),
466 VariantItem(Variant { kind: VariantKind::Struct(ref vstruct)}
) => {
467 Some(vstruct
.fields_stripped
)
473 pub fn stability_class(&self) -> Option
<String
> {
474 self.stability
.as_ref().and_then(|ref s
| {
475 let mut classes
= Vec
::with_capacity(2);
477 if s
.level
== stability
::Unstable
{
478 classes
.push("unstable");
481 if s
.deprecation
.is_some() {
482 classes
.push("deprecated");
485 if classes
.len() != 0 {
486 Some(classes
.join(" "))
493 pub fn stable_since(&self) -> Option
<&str> {
494 self.stability
.as_ref().map(|s
| &s
.since
[..])
497 pub fn is_non_exhaustive(&self) -> bool
{
498 self.attrs
.other_attrs
.iter()
499 .any(|a
| a
.check_name(sym
::non_exhaustive
))
502 /// Returns a documentation-level item type from the item.
503 pub fn type_(&self) -> ItemType
{
507 /// Returns the info in the item's `#[deprecated]` or `#[rustc_deprecated]` attributes.
509 /// If the item is not deprecated, returns `None`.
510 pub fn deprecation(&self) -> Option
<&Deprecation
> {
513 .or_else(|| self.stability
.as_ref().and_then(|s
| s
.deprecation
.as_ref()))
515 pub fn is_default(&self) -> bool
{
517 ItemEnum
::MethodItem(ref meth
) => {
518 if let Some(defaultness
) = meth
.defaultness
{
519 defaultness
.has_value() && !defaultness
.is_final()
529 #[derive(Clone, Debug)]
531 ExternCrateItem(String
, Option
<String
>),
536 FunctionItem(Function
),
538 TypedefItem(Typedef
, bool
/* is associated type */),
539 OpaqueTyItem(OpaqueTy
, bool
/* is associated type */),
541 ConstantItem(Constant
),
543 TraitAliasItem(TraitAlias
),
545 /// A method signature only. Used for required methods in traits (ie,
546 /// non-default-methods).
547 TyMethodItem(TyMethod
),
548 /// A method with a body.
550 StructFieldItem(Type
),
551 VariantItem(Variant
),
552 /// `fn`s from an extern block
553 ForeignFunctionItem(Function
),
554 /// `static`s from an extern block
555 ForeignStaticItem(Static
),
556 /// `type`s from an extern block
559 ProcMacroItem(ProcMacro
),
560 PrimitiveItem(PrimitiveType
),
561 AssocConstItem(Type
, Option
<String
>),
562 AssocTypeItem(Vec
<GenericBound
>, Option
<Type
>),
563 /// An item that has been stripped by a rustdoc pass
564 StrippedItem(Box
<ItemEnum
>),
569 pub fn is_associated(&self) -> bool
{
571 ItemEnum
::TypedefItem(_
, _
) |
572 ItemEnum
::AssocTypeItem(_
, _
) => true,
578 #[derive(Clone, Debug)]
580 pub items
: Vec
<Item
>,
584 impl Clean
<Item
> for doctree
::Module
<'_
> {
585 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
586 let name
= if self.name
.is_some() {
587 self.name
.expect("No name provided").clean(cx
)
592 // maintain a stack of mod ids, for doc comment path resolution
593 // but we also need to resolve the module's own docs based on whether its docs were written
594 // inside or outside the module, so check for that
595 let attrs
= self.attrs
.clean(cx
);
597 let mut items
: Vec
<Item
> = vec
![];
598 items
.extend(self.extern_crates
.iter().flat_map(|x
| x
.clean(cx
)));
599 items
.extend(self.imports
.iter().flat_map(|x
| x
.clean(cx
)));
600 items
.extend(self.structs
.iter().map(|x
| x
.clean(cx
)));
601 items
.extend(self.unions
.iter().map(|x
| x
.clean(cx
)));
602 items
.extend(self.enums
.iter().map(|x
| x
.clean(cx
)));
603 items
.extend(self.fns
.iter().map(|x
| x
.clean(cx
)));
604 items
.extend(self.foreigns
.iter().map(|x
| x
.clean(cx
)));
605 items
.extend(self.mods
.iter().map(|x
| x
.clean(cx
)));
606 items
.extend(self.typedefs
.iter().map(|x
| x
.clean(cx
)));
607 items
.extend(self.opaque_tys
.iter().map(|x
| x
.clean(cx
)));
608 items
.extend(self.statics
.iter().map(|x
| x
.clean(cx
)));
609 items
.extend(self.constants
.iter().map(|x
| x
.clean(cx
)));
610 items
.extend(self.traits
.iter().map(|x
| x
.clean(cx
)));
611 items
.extend(self.impls
.iter().flat_map(|x
| x
.clean(cx
)));
612 items
.extend(self.macros
.iter().map(|x
| x
.clean(cx
)));
613 items
.extend(self.proc_macros
.iter().map(|x
| x
.clean(cx
)));
614 items
.extend(self.trait_aliases
.iter().map(|x
| x
.clean(cx
)));
616 // determine if we should display the inner contents or
617 // the outer `mod` item for the source code.
619 let cm
= cx
.sess().source_map();
620 let outer
= cm
.lookup_char_pos(self.where_outer
.lo());
621 let inner
= cm
.lookup_char_pos(self.where_inner
.lo());
622 if outer
.file
.start_pos
== inner
.file
.start_pos
{
626 // mod foo; (and a separate SourceFile for the contents)
634 source
: whence
.clean(cx
),
635 visibility
: self.vis
.clean(cx
),
636 stability
: cx
.stability(self.id
).clean(cx
),
637 deprecation
: cx
.deprecation(self.id
).clean(cx
),
638 def_id
: cx
.tcx
.hir().local_def_id(self.id
),
639 inner
: ModuleItem(Module
{
640 is_crate
: self.is_crate
,
647 pub struct ListAttributesIter
<'a
> {
648 attrs
: slice
::Iter
<'a
, ast
::Attribute
>,
649 current_list
: vec
::IntoIter
<ast
::NestedMetaItem
>,
653 impl<'a
> Iterator
for ListAttributesIter
<'a
> {
654 type Item
= ast
::NestedMetaItem
;
656 fn next(&mut self) -> Option
<Self::Item
> {
657 if let Some(nested
) = self.current_list
.next() {
661 for attr
in &mut self.attrs
{
662 if let Some(list
) = attr
.meta_item_list() {
663 if attr
.check_name(self.name
) {
664 self.current_list
= list
.into_iter();
665 if let Some(nested
) = self.current_list
.next() {
675 fn size_hint(&self) -> (usize, Option
<usize>) {
676 let lower
= self.current_list
.len();
681 pub trait AttributesExt
{
682 /// Finds an attribute as List and returns the list of attributes nested inside.
683 fn lists(&self, name
: Symbol
) -> ListAttributesIter
<'_
>;
686 impl AttributesExt
for [ast
::Attribute
] {
687 fn lists(&self, name
: Symbol
) -> ListAttributesIter
<'_
> {
690 current_list
: Vec
::new().into_iter(),
696 pub trait NestedAttributesExt
{
697 /// Returns `true` if the attribute list contains a specific `Word`
698 fn has_word(self, word
: Symbol
) -> bool
;
701 impl<I
: IntoIterator
<Item
=ast
::NestedMetaItem
>> NestedAttributesExt
for I
{
702 fn has_word(self, word
: Symbol
) -> bool
{
703 self.into_iter().any(|attr
| attr
.is_word() && attr
.check_name(word
))
707 /// A portion of documentation, extracted from a `#[doc]` attribute.
709 /// Each variant contains the line number within the complete doc-comment where the fragment
710 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
712 /// Included files are kept separate from inline doc comments so that proper line-number
713 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
714 /// kept separate because of issue #42760.
715 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
716 pub enum DocFragment
{
717 /// A doc fragment created from a `///` or `//!` doc comment.
718 SugaredDoc(usize, syntax_pos
::Span
, String
),
719 /// A doc fragment created from a "raw" `#[doc=""]` attribute.
720 RawDoc(usize, syntax_pos
::Span
, String
),
721 /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
722 /// given filename and the file contents.
723 Include(usize, syntax_pos
::Span
, String
, String
),
727 pub fn as_str(&self) -> &str {
729 DocFragment
::SugaredDoc(_
, _
, ref s
) => &s
[..],
730 DocFragment
::RawDoc(_
, _
, ref s
) => &s
[..],
731 DocFragment
::Include(_
, _
, _
, ref s
) => &s
[..],
735 pub fn span(&self) -> syntax_pos
::Span
{
737 DocFragment
::SugaredDoc(_
, span
, _
) |
738 DocFragment
::RawDoc(_
, span
, _
) |
739 DocFragment
::Include(_
, span
, _
, _
) => span
,
744 impl<'a
> FromIterator
<&'a DocFragment
> for String
{
745 fn from_iter
<T
>(iter
: T
) -> Self
747 T
: IntoIterator
<Item
= &'a DocFragment
>
749 iter
.into_iter().fold(String
::new(), |mut acc
, frag
| {
754 DocFragment
::SugaredDoc(_
, _
, ref docs
)
755 | DocFragment
::RawDoc(_
, _
, ref docs
)
756 | DocFragment
::Include(_
, _
, _
, ref docs
) =>
765 #[derive(Clone, Debug, Default)]
766 pub struct Attributes
{
767 pub doc_strings
: Vec
<DocFragment
>,
768 pub other_attrs
: Vec
<ast
::Attribute
>,
769 pub cfg
: Option
<Arc
<Cfg
>>,
770 pub span
: Option
<syntax_pos
::Span
>,
771 /// map from Rust paths to resolved defs and potential URL fragments
772 pub links
: Vec
<(String
, Option
<DefId
>, Option
<String
>)>,
773 pub inner_docs
: bool
,
777 /// Extracts the content from an attribute `#[doc(cfg(content))]`.
778 fn extract_cfg(mi
: &ast
::MetaItem
) -> Option
<&ast
::MetaItem
> {
779 use syntax
::ast
::NestedMetaItem
::MetaItem
;
781 if let ast
::MetaItemKind
::List(ref nmis
) = mi
.kind
{
783 if let MetaItem(ref cfg_mi
) = nmis
[0] {
784 if cfg_mi
.check_name(sym
::cfg
) {
785 if let ast
::MetaItemKind
::List(ref cfg_nmis
) = cfg_mi
.kind
{
786 if cfg_nmis
.len() == 1 {
787 if let MetaItem(ref content_mi
) = cfg_nmis
[0] {
788 return Some(content_mi
);
800 /// Reads a `MetaItem` from within an attribute, looks for whether it is a
801 /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
803 fn extract_include(mi
: &ast
::MetaItem
)
804 -> Option
<(String
, String
)>
806 mi
.meta_item_list().and_then(|list
| {
808 if meta
.check_name(sym
::include
) {
809 // the actual compiled `#[doc(include="filename")]` gets expanded to
810 // `#[doc(include(file="filename", contents="file contents")]` so we need to
811 // look for that instead
812 return meta
.meta_item_list().and_then(|list
| {
813 let mut filename
: Option
<String
> = None
;
814 let mut contents
: Option
<String
> = None
;
817 if it
.check_name(sym
::file
) {
818 if let Some(name
) = it
.value_str() {
819 filename
= Some(name
.to_string());
821 } else if it
.check_name(sym
::contents
) {
822 if let Some(docs
) = it
.value_str() {
823 contents
= Some(docs
.to_string());
828 if let (Some(filename
), Some(contents
)) = (filename
, contents
) {
829 Some((filename
, contents
))
841 pub fn has_doc_flag(&self, flag
: Symbol
) -> bool
{
842 for attr
in &self.other_attrs
{
843 if !attr
.check_name(sym
::doc
) { continue; }
845 if let Some(items
) = attr
.meta_item_list() {
846 if items
.iter().filter_map(|i
| i
.meta_item()).any(|it
| it
.check_name(flag
)) {
855 pub fn from_ast(diagnostic
: &::errors
::Handler
,
856 attrs
: &[ast
::Attribute
]) -> Attributes
{
857 let mut doc_strings
= vec
![];
859 let mut cfg
= Cfg
::True
;
860 let mut doc_line
= 0;
862 /// Converts `attr` to a normal `#[doc="foo"]` comment, if it is a
863 /// comment like `///` or `/** */`. (Returns `attr` unchanged for
864 /// non-sugared doc attributes.)
865 pub fn with_desugared_doc
<T
>(attr
: &Attribute
, f
: impl FnOnce(&Attribute
) -> T
) -> T
{
866 if attr
.is_sugared_doc
{
867 let comment
= attr
.value_str().unwrap();
868 let meta
= attr
::mk_name_value_item_str(
869 Ident
::with_dummy_span(sym
::doc
),
870 Symbol
::intern(&comments
::strip_doc_comment_decoration(&comment
.as_str())),
874 item
: AttrItem { path: meta.path, tokens: meta.kind.tokens(meta.span) }
,
877 is_sugared_doc
: true,
885 let other_attrs
= attrs
.iter().filter_map(|attr
| {
886 with_desugared_doc(attr
, |attr
| {
887 if attr
.check_name(sym
::doc
) {
888 if let Some(mi
) = attr
.meta() {
889 if let Some(value
) = mi
.value_str() {
890 // Extracted #[doc = "..."]
891 let value
= value
.to_string();
893 doc_line
+= value
.lines().count();
895 if attr
.is_sugared_doc
{
896 doc_strings
.push(DocFragment
::SugaredDoc(line
, attr
.span
, value
));
898 doc_strings
.push(DocFragment
::RawDoc(line
, attr
.span
, value
));
902 sp
= Some(attr
.span
);
905 } else if let Some(cfg_mi
) = Attributes
::extract_cfg(&mi
) {
906 // Extracted #[doc(cfg(...))]
907 match Cfg
::parse(cfg_mi
) {
908 Ok(new_cfg
) => cfg
&= new_cfg
,
909 Err(e
) => diagnostic
.span_err(e
.span
, e
.msg
),
912 } else if let Some((filename
, contents
)) = Attributes
::extract_include(&mi
)
915 doc_line
+= contents
.lines().count();
916 doc_strings
.push(DocFragment
::Include(line
,
927 // treat #[target_feature(enable = "feat")] attributes as if they were
928 // #[doc(cfg(target_feature = "feat"))] attributes as well
929 for attr
in attrs
.lists(sym
::target_feature
) {
930 if attr
.check_name(sym
::enable
) {
931 if let Some(feat
) = attr
.value_str() {
932 let meta
= attr
::mk_name_value_item_str(
933 Ident
::with_dummy_span(sym
::target_feature
), feat
, DUMMY_SP
935 if let Ok(feat_cfg
) = Cfg
::parse(&meta
) {
942 let inner_docs
= attrs
.iter()
943 .filter(|a
| a
.check_name(sym
::doc
))
945 .map_or(true, |a
| a
.style
== AttrStyle
::Inner
);
950 cfg
: if cfg
== Cfg
::True { None }
else { Some(Arc::new(cfg)) }
,
957 /// Finds the `doc` attribute as a NameValue and returns the corresponding
959 pub fn doc_value(&self) -> Option
<&str> {
960 self.doc_strings
.first().map(|s
| s
.as_str())
963 /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
965 pub fn collapsed_doc_value(&self) -> Option
<String
> {
966 if !self.doc_strings
.is_empty() {
967 Some(self.doc_strings
.iter().collect())
973 /// Gets links as a vector
975 /// Cache must be populated before call
976 pub fn links(&self, krate
: &CrateNum
) -> Vec
<(String
, String
)> {
977 use crate::html
::format
::href
;
979 self.links
.iter().filter_map(|&(ref s
, did
, ref fragment
)| {
982 if let Some((mut href
, ..)) = href(did
) {
983 if let Some(ref fragment
) = *fragment
{
985 href
.push_str(fragment
);
987 Some((s
.clone(), href
))
993 if let Some(ref fragment
) = *fragment
{
995 let url
= match cache
.extern_locations
.get(krate
) {
996 Some(&(_
, ref src
, ExternalLocation
::Local
)) =>
997 src
.to_str().expect("invalid file path"),
998 Some(&(_
, _
, ExternalLocation
::Remote(ref s
))) => s
,
999 Some(&(_
, _
, ExternalLocation
::Unknown
)) | None
=>
1000 "https://doc.rust-lang.org/nightly",
1002 // This is a primitive so the url is done "by hand".
1003 let tail
= fragment
.find('
#').unwrap_or_else(|| fragment.len());
1005 format
!("{}{}std/primitive.{}.html{}",
1007 if !url
.ends_with('
/'
) { "/" }
else { "" }
,
1009 &fragment
[tail
..])))
1011 panic
!("This isn't a primitive?!");
1019 impl PartialEq
for Attributes
{
1020 fn eq(&self, rhs
: &Self) -> bool
{
1021 self.doc_strings
== rhs
.doc_strings
&&
1022 self.cfg
== rhs
.cfg
&&
1023 self.span
== rhs
.span
&&
1024 self.links
== rhs
.links
&&
1025 self.other_attrs
.iter().map(|attr
| attr
.id
).eq(rhs
.other_attrs
.iter().map(|attr
| attr
.id
))
1029 impl Eq
for Attributes {}
1031 impl Hash
for Attributes
{
1032 fn hash
<H
: Hasher
>(&self, hasher
: &mut H
) {
1033 self.doc_strings
.hash(hasher
);
1034 self.cfg
.hash(hasher
);
1035 self.span
.hash(hasher
);
1036 self.links
.hash(hasher
);
1037 for attr
in &self.other_attrs
{
1038 attr
.id
.hash(hasher
);
1043 impl AttributesExt
for Attributes
{
1044 fn lists(&self, name
: Symbol
) -> ListAttributesIter
<'_
> {
1045 self.other_attrs
.lists(name
)
1049 impl Clean
<Attributes
> for [ast
::Attribute
] {
1050 fn clean(&self, cx
: &DocContext
<'_
>) -> Attributes
{
1051 Attributes
::from_ast(cx
.sess().diagnostic(), self)
1055 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1056 pub enum GenericBound
{
1057 TraitBound(PolyTrait
, hir
::TraitBoundModifier
),
1062 fn maybe_sized(cx
: &DocContext
<'_
>) -> GenericBound
{
1063 let did
= cx
.tcx
.require_lang_item(lang_items
::SizedTraitLangItem
, None
);
1064 let empty
= cx
.tcx
.intern_substs(&[]);
1065 let path
= external_path(cx
, cx
.tcx
.item_name(did
),
1066 Some(did
), false, vec
![], empty
);
1067 inline
::record_extern_fqn(cx
, did
, TypeKind
::Trait
);
1068 GenericBound
::TraitBound(PolyTrait
{
1069 trait_
: ResolvedPath
{
1075 generic_params
: Vec
::new(),
1076 }, hir
::TraitBoundModifier
::Maybe
)
1079 fn is_sized_bound(&self, cx
: &DocContext
<'_
>) -> bool
{
1080 use rustc
::hir
::TraitBoundModifier
as TBM
;
1081 if let GenericBound
::TraitBound(PolyTrait { ref trait_, .. }
, TBM
::None
) = *self {
1082 if trait_
.def_id() == cx
.tcx
.lang_items().sized_trait() {
1089 fn get_poly_trait(&self) -> Option
<PolyTrait
> {
1090 if let GenericBound
::TraitBound(ref p
, _
) = *self {
1091 return Some(p
.clone())
1096 fn get_trait_type(&self) -> Option
<Type
> {
1097 if let GenericBound
::TraitBound(PolyTrait { ref trait_, .. }
, _
) = *self {
1098 Some(trait_
.clone())
1105 impl Clean
<GenericBound
> for hir
::GenericBound
{
1106 fn clean(&self, cx
: &DocContext
<'_
>) -> GenericBound
{
1108 hir
::GenericBound
::Outlives(lt
) => GenericBound
::Outlives(lt
.clean(cx
)),
1109 hir
::GenericBound
::Trait(ref t
, modifier
) => {
1110 GenericBound
::TraitBound(t
.clean(cx
), modifier
)
1116 fn external_generic_args(
1117 cx
: &DocContext
<'_
>,
1118 trait_did
: Option
<DefId
>,
1120 bindings
: Vec
<TypeBinding
>,
1121 substs
: SubstsRef
<'_
>,
1123 let mut skip_self
= has_self
;
1124 let mut ty_kind
= None
;
1125 let args
: Vec
<_
> = substs
.iter().filter_map(|kind
| match kind
.unpack() {
1126 GenericArgKind
::Lifetime(lt
) => {
1127 lt
.clean(cx
).and_then(|lt
| Some(GenericArg
::Lifetime(lt
)))
1129 GenericArgKind
::Type(_
) if skip_self
=> {
1133 GenericArgKind
::Type(ty
) => {
1134 ty_kind
= Some(&ty
.kind
);
1135 Some(GenericArg
::Type(ty
.clean(cx
)))
1137 GenericArgKind
::Const(ct
) => Some(GenericArg
::Const(ct
.clean(cx
))),
1141 // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
1142 Some(did
) if cx
.tcx
.lang_items().fn_trait_kind(did
).is_some() => {
1143 assert
!(ty_kind
.is_some());
1144 let inputs
= match ty_kind
{
1145 Some(ty
::Tuple(ref tys
)) => tys
.iter().map(|t
| t
.expect_ty().clean(cx
)).collect(),
1146 _
=> return GenericArgs
::AngleBracketed { args, bindings }
,
1149 // FIXME(#20299) return type comes from a projection now
1150 // match types[1].kind {
1151 // ty::Tuple(ref v) if v.is_empty() => None, // -> ()
1152 // _ => Some(types[1].clean(cx))
1154 GenericArgs
::Parenthesized { inputs, output }
1157 GenericArgs
::AngleBracketed { args, bindings }
1162 // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
1163 // from Fn<(A, B,), C> to Fn(A, B) -> C
1164 fn external_path(cx
: &DocContext
<'_
>, name
: Symbol
, trait_did
: Option
<DefId
>, has_self
: bool
,
1165 bindings
: Vec
<TypeBinding
>, substs
: SubstsRef
<'_
>) -> Path
{
1169 segments
: vec
![PathSegment
{
1170 name
: name
.as_str().to_string(),
1171 args
: external_generic_args(cx
, trait_did
, has_self
, bindings
, substs
)
1176 impl<'a
, 'tcx
> Clean
<GenericBound
> for (&'a ty
::TraitRef
<'tcx
>, Vec
<TypeBinding
>) {
1177 fn clean(&self, cx
: &DocContext
<'_
>) -> GenericBound
{
1178 let (trait_ref
, ref bounds
) = *self;
1179 inline
::record_extern_fqn(cx
, trait_ref
.def_id
, TypeKind
::Trait
);
1180 let path
= external_path(cx
, cx
.tcx
.item_name(trait_ref
.def_id
),
1181 Some(trait_ref
.def_id
), true, bounds
.clone(), trait_ref
.substs
);
1183 debug
!("ty::TraitRef\n subst: {:?}\n", trait_ref
.substs
);
1185 // collect any late bound regions
1186 let mut late_bounds
= vec
![];
1187 for ty_s
in trait_ref
.input_types().skip(1) {
1188 if let ty
::Tuple(ts
) = ty_s
.kind
{
1190 if let ty
::Ref(ref reg
, _
, _
) = ty_s
.expect_ty().kind
{
1191 if let &ty
::RegionKind
::ReLateBound(..) = *reg
{
1192 debug
!(" hit an ReLateBound {:?}", reg
);
1193 if let Some(Lifetime(name
)) = reg
.clean(cx
) {
1194 late_bounds
.push(GenericParamDef
{
1196 kind
: GenericParamDefKind
::Lifetime
,
1205 GenericBound
::TraitBound(
1207 trait_
: ResolvedPath
{
1210 did
: trait_ref
.def_id
,
1213 generic_params
: late_bounds
,
1215 hir
::TraitBoundModifier
::None
1220 impl<'tcx
> Clean
<GenericBound
> for ty
::TraitRef
<'tcx
> {
1221 fn clean(&self, cx
: &DocContext
<'_
>) -> GenericBound
{
1222 (self, vec
![]).clean(cx
)
1226 impl<'tcx
> Clean
<Option
<Vec
<GenericBound
>>> for InternalSubsts
<'tcx
> {
1227 fn clean(&self, cx
: &DocContext
<'_
>) -> Option
<Vec
<GenericBound
>> {
1228 let mut v
= Vec
::new();
1229 v
.extend(self.regions().filter_map(|r
| r
.clean(cx
)).map(GenericBound
::Outlives
));
1230 v
.extend(self.types().map(|t
| GenericBound
::TraitBound(PolyTrait
{
1231 trait_
: t
.clean(cx
),
1232 generic_params
: Vec
::new(),
1233 }, hir
::TraitBoundModifier
::None
)));
1234 if !v
.is_empty() {Some(v)}
else {None}
1238 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1239 pub struct Lifetime(String
);
1242 pub fn get_ref
<'a
>(&'a
self) -> &'a
str {
1243 let Lifetime(ref s
) = *self;
1248 pub fn statik() -> Lifetime
{
1249 Lifetime("'static".to_string())
1253 impl Clean
<Lifetime
> for hir
::Lifetime
{
1254 fn clean(&self, cx
: &DocContext
<'_
>) -> Lifetime
{
1255 if self.hir_id
!= hir
::DUMMY_HIR_ID
{
1256 let def
= cx
.tcx
.named_region(self.hir_id
);
1258 Some(rl
::Region
::EarlyBound(_
, node_id
, _
)) |
1259 Some(rl
::Region
::LateBound(_
, node_id
, _
)) |
1260 Some(rl
::Region
::Free(_
, node_id
)) => {
1261 if let Some(lt
) = cx
.lt_substs
.borrow().get(&node_id
).cloned() {
1268 Lifetime(self.name
.ident().to_string())
1272 impl Clean
<Lifetime
> for hir
::GenericParam
{
1273 fn clean(&self, _
: &DocContext
<'_
>) -> Lifetime
{
1275 hir
::GenericParamKind
::Lifetime { .. }
=> {
1276 if self.bounds
.len() > 0 {
1277 let mut bounds
= self.bounds
.iter().map(|bound
| match bound
{
1278 hir
::GenericBound
::Outlives(lt
) => lt
,
1281 let name
= bounds
.next().expect("no more bounds").name
.ident();
1282 let mut s
= format
!("{}: {}", self.name
.ident(), name
);
1283 for bound
in bounds
{
1284 s
.push_str(&format
!(" + {}", bound
.name
.ident()));
1288 Lifetime(self.name
.ident().to_string())
1296 impl Clean
<Constant
> for hir
::ConstArg
{
1297 fn clean(&self, cx
: &DocContext
<'_
>) -> Constant
{
1299 type_
: cx
.tcx
.type_of(cx
.tcx
.hir().body_owner_def_id(self.value
.body
)).clean(cx
),
1300 expr
: print_const_expr(cx
, self.value
.body
),
1305 impl Clean
<Lifetime
> for ty
::GenericParamDef
{
1306 fn clean(&self, _cx
: &DocContext
<'_
>) -> Lifetime
{
1307 Lifetime(self.name
.to_string())
1311 impl Clean
<Option
<Lifetime
>> for ty
::RegionKind
{
1312 fn clean(&self, cx
: &DocContext
<'_
>) -> Option
<Lifetime
> {
1314 ty
::ReStatic
=> Some(Lifetime
::statik()),
1315 ty
::ReLateBound(_
, ty
::BrNamed(_
, name
)) => Some(Lifetime(name
.to_string())),
1316 ty
::ReEarlyBound(ref data
) => Some(Lifetime(data
.name
.clean(cx
))),
1318 ty
::ReLateBound(..) |
1322 ty
::RePlaceholder(..) |
1324 ty
::ReClosureBound(_
) |
1326 debug
!("cannot clean region {:?}", self);
1333 #[derive(Clone, Debug)]
1334 pub enum WherePredicate
{
1335 BoundPredicate { ty: Type, bounds: Vec<GenericBound> }
,
1336 RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> }
,
1337 EqPredicate { lhs: Type, rhs: Type }
,
1340 impl WherePredicate
{
1341 pub fn get_bounds(&self) -> Option
<&[GenericBound
]> {
1343 WherePredicate
::BoundPredicate { ref bounds, .. }
=> Some(bounds
),
1344 WherePredicate
::RegionPredicate { ref bounds, .. }
=> Some(bounds
),
1350 impl Clean
<WherePredicate
> for hir
::WherePredicate
{
1351 fn clean(&self, cx
: &DocContext
<'_
>) -> WherePredicate
{
1353 hir
::WherePredicate
::BoundPredicate(ref wbp
) => {
1354 WherePredicate
::BoundPredicate
{
1355 ty
: wbp
.bounded_ty
.clean(cx
),
1356 bounds
: wbp
.bounds
.clean(cx
)
1360 hir
::WherePredicate
::RegionPredicate(ref wrp
) => {
1361 WherePredicate
::RegionPredicate
{
1362 lifetime
: wrp
.lifetime
.clean(cx
),
1363 bounds
: wrp
.bounds
.clean(cx
)
1367 hir
::WherePredicate
::EqPredicate(ref wrp
) => {
1368 WherePredicate
::EqPredicate
{
1369 lhs
: wrp
.lhs_ty
.clean(cx
),
1370 rhs
: wrp
.rhs_ty
.clean(cx
)
1377 impl<'a
> Clean
<Option
<WherePredicate
>> for ty
::Predicate
<'a
> {
1378 fn clean(&self, cx
: &DocContext
<'_
>) -> Option
<WherePredicate
> {
1379 use rustc
::ty
::Predicate
;
1382 Predicate
::Trait(ref pred
) => Some(pred
.clean(cx
)),
1383 Predicate
::Subtype(ref pred
) => Some(pred
.clean(cx
)),
1384 Predicate
::RegionOutlives(ref pred
) => pred
.clean(cx
),
1385 Predicate
::TypeOutlives(ref pred
) => pred
.clean(cx
),
1386 Predicate
::Projection(ref pred
) => Some(pred
.clean(cx
)),
1388 Predicate
::WellFormed(..) |
1389 Predicate
::ObjectSafe(..) |
1390 Predicate
::ClosureKind(..) |
1391 Predicate
::ConstEvaluatable(..) => panic
!("not user writable"),
1396 impl<'a
> Clean
<WherePredicate
> for ty
::TraitPredicate
<'a
> {
1397 fn clean(&self, cx
: &DocContext
<'_
>) -> WherePredicate
{
1398 WherePredicate
::BoundPredicate
{
1399 ty
: self.trait_ref
.self_ty().clean(cx
),
1400 bounds
: vec
![self.trait_ref
.clean(cx
)]
1405 impl<'tcx
> Clean
<WherePredicate
> for ty
::SubtypePredicate
<'tcx
> {
1406 fn clean(&self, _cx
: &DocContext
<'_
>) -> WherePredicate
{
1407 panic
!("subtype predicates are an internal rustc artifact \
1408 and should not be seen by rustdoc")
1412 impl<'tcx
> Clean
<Option
<WherePredicate
>> for
1413 ty
::OutlivesPredicate
<ty
::Region
<'tcx
>,ty
::Region
<'tcx
>> {
1415 fn clean(&self, cx
: &DocContext
<'_
>) -> Option
<WherePredicate
> {
1416 let ty
::OutlivesPredicate(ref a
, ref b
) = *self;
1419 (ty
::ReEmpty
, ty
::ReEmpty
) => {
1425 Some(WherePredicate
::RegionPredicate
{
1426 lifetime
: a
.clean(cx
).expect("failed to clean lifetime"),
1427 bounds
: vec
![GenericBound
::Outlives(b
.clean(cx
).expect("failed to clean bounds"))]
1432 impl<'tcx
> Clean
<Option
<WherePredicate
>> for ty
::OutlivesPredicate
<Ty
<'tcx
>, ty
::Region
<'tcx
>> {
1433 fn clean(&self, cx
: &DocContext
<'_
>) -> Option
<WherePredicate
> {
1434 let ty
::OutlivesPredicate(ref ty
, ref lt
) = *self;
1437 ty
::ReEmpty
=> return None
,
1441 Some(WherePredicate
::BoundPredicate
{
1443 bounds
: vec
![GenericBound
::Outlives(lt
.clean(cx
).expect("failed to clean lifetimes"))]
1448 impl<'tcx
> Clean
<WherePredicate
> for ty
::ProjectionPredicate
<'tcx
> {
1449 fn clean(&self, cx
: &DocContext
<'_
>) -> WherePredicate
{
1450 WherePredicate
::EqPredicate
{
1451 lhs
: self.projection_ty
.clean(cx
),
1452 rhs
: self.ty
.clean(cx
)
1457 impl<'tcx
> Clean
<Type
> for ty
::ProjectionTy
<'tcx
> {
1458 fn clean(&self, cx
: &DocContext
<'_
>) -> Type
{
1459 let trait_
= match self.trait_ref(cx
.tcx
).clean(cx
) {
1460 GenericBound
::TraitBound(t
, _
) => t
.trait_
,
1461 GenericBound
::Outlives(_
) => panic
!("cleaning a trait got a lifetime"),
1464 name
: cx
.tcx
.associated_item(self.item_def_id
).ident
.name
.clean(cx
),
1465 self_type
: box self.self_ty().clean(cx
),
1471 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1472 pub enum GenericParamDefKind
{
1476 bounds
: Vec
<GenericBound
>,
1477 default: Option
<Type
>,
1478 synthetic
: Option
<hir
::SyntheticTyParamKind
>,
1486 impl GenericParamDefKind
{
1487 pub fn is_type(&self) -> bool
{
1489 GenericParamDefKind
::Type { .. }
=> true,
1494 pub fn get_type(&self, cx
: &DocContext
<'_
>) -> Option
<Type
> {
1496 GenericParamDefKind
::Type { did, .. }
=> {
1497 rustc_typeck
::checked_type_of(cx
.tcx
, did
, false).map(|t
| t
.clean(cx
))
1499 GenericParamDefKind
::Const { ref ty, .. }
=> Some(ty
.clone()),
1500 GenericParamDefKind
::Lifetime
=> None
,
1505 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1506 pub struct GenericParamDef
{
1509 pub kind
: GenericParamDefKind
,
1512 impl GenericParamDef
{
1513 pub fn is_synthetic_type_param(&self) -> bool
{
1515 GenericParamDefKind
::Lifetime
|
1516 GenericParamDefKind
::Const { .. }
=> false,
1517 GenericParamDefKind
::Type { ref synthetic, .. }
=> synthetic
.is_some(),
1521 pub fn is_type(&self) -> bool
{
1525 pub fn get_type(&self, cx
: &DocContext
<'_
>) -> Option
<Type
> {
1526 self.kind
.get_type(cx
)
1529 pub fn get_bounds(&self) -> Option
<&[GenericBound
]> {
1531 GenericParamDefKind
::Type { ref bounds, .. }
=> Some(bounds
),
1537 impl Clean
<GenericParamDef
> for ty
::GenericParamDef
{
1538 fn clean(&self, cx
: &DocContext
<'_
>) -> GenericParamDef
{
1539 let (name
, kind
) = match self.kind
{
1540 ty
::GenericParamDefKind
::Lifetime
=> {
1541 (self.name
.to_string(), GenericParamDefKind
::Lifetime
)
1543 ty
::GenericParamDefKind
::Type { has_default, synthetic, .. }
=> {
1544 let default = if has_default
{
1545 Some(cx
.tcx
.type_of(self.def_id
).clean(cx
))
1549 (self.name
.clean(cx
), GenericParamDefKind
::Type
{
1551 bounds
: vec
![], // These are filled in from the where-clauses.
1556 ty
::GenericParamDefKind
::Const { .. }
=> {
1557 (self.name
.clean(cx
), GenericParamDefKind
::Const
{
1559 ty
: cx
.tcx
.type_of(self.def_id
).clean(cx
),
1571 impl Clean
<GenericParamDef
> for hir
::GenericParam
{
1572 fn clean(&self, cx
: &DocContext
<'_
>) -> GenericParamDef
{
1573 let (name
, kind
) = match self.kind
{
1574 hir
::GenericParamKind
::Lifetime { .. }
=> {
1575 let name
= if self.bounds
.len() > 0 {
1576 let mut bounds
= self.bounds
.iter().map(|bound
| match bound
{
1577 hir
::GenericBound
::Outlives(lt
) => lt
,
1580 let name
= bounds
.next().expect("no more bounds").name
.ident();
1581 let mut s
= format
!("{}: {}", self.name
.ident(), name
);
1582 for bound
in bounds
{
1583 s
.push_str(&format
!(" + {}", bound
.name
.ident()));
1587 self.name
.ident().to_string()
1589 (name
, GenericParamDefKind
::Lifetime
)
1591 hir
::GenericParamKind
::Type { ref default, synthetic }
=> {
1592 (self.name
.ident().name
.clean(cx
), GenericParamDefKind
::Type
{
1593 did
: cx
.tcx
.hir().local_def_id(self.hir_id
),
1594 bounds
: self.bounds
.clean(cx
),
1595 default: default.clean(cx
),
1599 hir
::GenericParamKind
::Const { ref ty }
=> {
1600 (self.name
.ident().name
.clean(cx
), GenericParamDefKind
::Const
{
1601 did
: cx
.tcx
.hir().local_def_id(self.hir_id
),
1614 // maybe use a Generic enum and use Vec<Generic>?
1615 #[derive(Clone, Debug, Default)]
1616 pub struct Generics
{
1617 pub params
: Vec
<GenericParamDef
>,
1618 pub where_predicates
: Vec
<WherePredicate
>,
1621 impl Clean
<Generics
> for hir
::Generics
{
1622 fn clean(&self, cx
: &DocContext
<'_
>) -> Generics
{
1623 // Synthetic type-parameters are inserted after normal ones.
1624 // In order for normal parameters to be able to refer to synthetic ones,
1625 // scans them first.
1626 fn is_impl_trait(param
: &hir
::GenericParam
) -> bool
{
1628 hir
::GenericParamKind
::Type { synthetic, .. }
=> {
1629 synthetic
== Some(hir
::SyntheticTyParamKind
::ImplTrait
)
1634 let impl_trait_params
= self.params
1636 .filter(|param
| is_impl_trait(param
))
1638 let param
: GenericParamDef
= param
.clean(cx
);
1640 GenericParamDefKind
::Lifetime
=> unreachable
!(),
1641 GenericParamDefKind
::Type { did, ref bounds, .. }
=> {
1642 cx
.impl_trait_bounds
.borrow_mut().insert(did
.into(), bounds
.clone());
1644 GenericParamDefKind
::Const { .. }
=> unreachable
!(),
1648 .collect
::<Vec
<_
>>();
1650 let mut params
= Vec
::with_capacity(self.params
.len());
1651 for p
in self.params
.iter().filter(|p
| !is_impl_trait(p
)) {
1652 let p
= p
.clean(cx
);
1655 params
.extend(impl_trait_params
);
1657 let mut generics
= Generics
{
1659 where_predicates
: self.where_clause
.predicates
.clean(cx
),
1662 // Some duplicates are generated for ?Sized bounds between type params and where
1663 // predicates. The point in here is to move the bounds definitions from type params
1664 // to where predicates when such cases occur.
1665 for where_pred
in &mut generics
.where_predicates
{
1667 WherePredicate
::BoundPredicate { ty: Generic(ref name), ref mut bounds }
=> {
1668 if bounds
.is_empty() {
1669 for param
in &mut generics
.params
{
1671 GenericParamDefKind
::Lifetime
=> {}
1672 GenericParamDefKind
::Type { bounds: ref mut ty_bounds, .. }
=> {
1673 if ¶m
.name
== name
{
1674 mem
::swap(bounds
, ty_bounds
);
1678 GenericParamDefKind
::Const { .. }
=> {}
1690 impl<'a
, 'tcx
> Clean
<Generics
> for (&'a ty
::Generics
, ty
::GenericPredicates
<'tcx
>) {
1691 fn clean(&self, cx
: &DocContext
<'_
>) -> Generics
{
1692 use self::WherePredicate
as WP
;
1693 use std
::collections
::BTreeMap
;
1695 let (gens
, preds
) = *self;
1697 // Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
1698 // since `Clean for ty::Predicate` would consume them.
1699 let mut impl_trait
= BTreeMap
::<ImplTraitParam
, Vec
<GenericBound
>>::default();
1701 // Bounds in the type_params and lifetimes fields are repeated in the
1702 // predicates field (see rustc_typeck::collect::ty_generics), so remove
1704 let stripped_typarams
= gens
.params
.iter()
1705 .filter_map(|param
| match param
.kind
{
1706 ty
::GenericParamDefKind
::Lifetime
=> None
,
1707 ty
::GenericParamDefKind
::Type { synthetic, .. }
=> {
1708 if param
.name
== kw
::SelfUpper
{
1709 assert_eq
!(param
.index
, 0);
1712 if synthetic
== Some(hir
::SyntheticTyParamKind
::ImplTrait
) {
1713 impl_trait
.insert(param
.index
.into(), vec
![]);
1716 Some(param
.clean(cx
))
1718 ty
::GenericParamDefKind
::Const { .. }
=> None
,
1719 }).collect
::<Vec
<GenericParamDef
>>();
1721 // param index -> [(DefId of trait, associated type name, type)]
1722 let mut impl_trait_proj
=
1723 FxHashMap
::<u32, Vec
<(DefId
, String
, Ty
<'tcx
>)>>::default();
1725 let where_predicates
= preds
.predicates
.iter()
1726 .flat_map(|(p
, _
)| {
1727 let mut projection
= None
;
1728 let param_idx
= (|| {
1729 if let Some(trait_ref
) = p
.to_opt_poly_trait_ref() {
1730 if let ty
::Param(param
) = trait_ref
.self_ty().kind
{
1731 return Some(param
.index
);
1733 } else if let Some(outlives
) = p
.to_opt_type_outlives() {
1734 if let ty
::Param(param
) = outlives
.skip_binder().0.kind
{
1735 return Some(param
.index
);
1737 } else if let ty
::Predicate
::Projection(p
) = p
{
1738 if let ty
::Param(param
) = p
.skip_binder().projection_ty
.self_ty().kind
{
1739 projection
= Some(p
);
1740 return Some(param
.index
);
1747 if let Some(param_idx
) = param_idx
{
1748 if let Some(b
) = impl_trait
.get_mut(¶m_idx
.into()) {
1749 let p
= p
.clean(cx
)?
;
1756 .filter(|b
| !b
.is_sized_bound(cx
))
1759 let proj
= projection
1760 .map(|p
| (p
.skip_binder().projection_ty
.clean(cx
), p
.skip_binder().ty
));
1761 if let Some(((_
, trait_did
, name
), rhs
)) =
1762 proj
.as_ref().and_then(|(lhs
, rhs
)| Some((lhs
.projection()?
, rhs
)))
1767 .push((trait_did
, name
.to_string(), rhs
));
1776 .collect
::<Vec
<_
>>();
1778 for (param
, mut bounds
) in impl_trait
{
1779 // Move trait bounds to the front.
1780 bounds
.sort_by_key(|b
| if let GenericBound
::TraitBound(..) = b
{
1786 if let crate::core
::ImplTraitParam
::ParamIndex(idx
) = param
{
1787 if let Some(proj
) = impl_trait_proj
.remove(&idx
) {
1788 for (trait_did
, name
, rhs
) in proj
{
1789 simplify
::merge_bounds(
1802 cx
.impl_trait_bounds
.borrow_mut().insert(param
, bounds
);
1805 // Now that `cx.impl_trait_bounds` is populated, we can process
1806 // remaining predicates which could contain `impl Trait`.
1807 let mut where_predicates
= where_predicates
1809 .flat_map(|p
| p
.clean(cx
))
1810 .collect
::<Vec
<_
>>();
1812 // Type parameters and have a Sized bound by default unless removed with
1813 // ?Sized. Scan through the predicates and mark any type parameter with
1814 // a Sized bound, removing the bounds as we find them.
1816 // Note that associated types also have a sized bound by default, but we
1817 // don't actually know the set of associated types right here so that's
1818 // handled in cleaning associated types
1819 let mut sized_params
= FxHashSet
::default();
1820 where_predicates
.retain(|pred
| {
1822 WP
::BoundPredicate { ty: Generic(ref g), ref bounds }
=> {
1823 if bounds
.iter().any(|b
| b
.is_sized_bound(cx
)) {
1824 sized_params
.insert(g
.clone());
1834 // Run through the type parameters again and insert a ?Sized
1835 // unbound for any we didn't find to be Sized.
1836 for tp
in &stripped_typarams
{
1837 if !sized_params
.contains(&tp
.name
) {
1838 where_predicates
.push(WP
::BoundPredicate
{
1839 ty
: Type
::Generic(tp
.name
.clone()),
1840 bounds
: vec
![GenericBound
::maybe_sized(cx
)],
1845 // It would be nice to collect all of the bounds on a type and recombine
1846 // them if possible, to avoid e.g., `where T: Foo, T: Bar, T: Sized, T: 'a`
1847 // and instead see `where T: Foo + Bar + Sized + 'a`
1852 .flat_map(|param
| match param
.kind
{
1853 ty
::GenericParamDefKind
::Lifetime
=> Some(param
.clean(cx
)),
1854 ty
::GenericParamDefKind
::Type { .. }
=> None
,
1855 ty
::GenericParamDefKind
::Const { .. }
=> Some(param
.clean(cx
)),
1856 }).chain(simplify
::ty_params(stripped_typarams
).into_iter())
1858 where_predicates
: simplify
::where_clauses(cx
, where_predicates
),
1863 /// The point of this function is to replace bounds with types.
1865 /// i.e. `[T, U]` when you have the following bounds: `T: Display, U: Option<T>` will return
1866 /// `[Display, Option]` (we just returns the list of the types, we don't care about the
1867 /// wrapped types in here).
1869 generics
: &Generics
,
1871 cx
: &DocContext
<'_
>,
1873 ) -> FxHashSet
<Type
> {
1874 let arg_s
= arg
.print().to_string();
1875 let mut res
= FxHashSet
::default();
1876 if recurse
>= 10 { // FIXME: remove this whole recurse thing when the recursion bug is fixed
1879 if arg
.is_full_generic() {
1880 if let Some(where_pred
) = generics
.where_predicates
.iter().find(|g
| {
1882 &WherePredicate
::BoundPredicate { ref ty, .. }
=> ty
.def_id() == arg
.def_id(),
1886 let bounds
= where_pred
.get_bounds().unwrap_or_else(|| &[]);
1887 for bound
in bounds
.iter() {
1889 GenericBound
::TraitBound(ref poly_trait
, _
) => {
1890 for x
in poly_trait
.generic_params
.iter() {
1894 if let Some(ty
) = x
.get_type(cx
) {
1895 let adds
= get_real_types(generics
, &ty
, cx
, recurse
+ 1);
1896 if !adds
.is_empty() {
1898 } else if !ty
.is_full_generic() {
1908 if let Some(bound
) = generics
.params
.iter().find(|g
| {
1909 g
.is_type() && g
.name
== arg_s
1911 for bound
in bound
.get_bounds().unwrap_or_else(|| &[]) {
1912 if let Some(ty
) = bound
.get_trait_type() {
1913 let adds
= get_real_types(generics
, &ty
, cx
, recurse
+ 1);
1914 if !adds
.is_empty() {
1916 } else if !ty
.is_full_generic() {
1917 res
.insert(ty
.clone());
1923 res
.insert(arg
.clone());
1924 if let Some(gens
) = arg
.generics() {
1925 for gen
in gens
.iter() {
1926 if gen
.is_full_generic() {
1927 let adds
= get_real_types(generics
, gen
, cx
, recurse
+ 1);
1928 if !adds
.is_empty() {
1932 res
.insert(gen
.clone());
1940 /// Return the full list of types when bounds have been resolved.
1942 /// i.e. `fn foo<A: Display, B: Option<A>>(x: u32, y: B)` will return
1943 /// `[u32, Display, Option]`.
1944 pub fn get_all_types(
1945 generics
: &Generics
,
1947 cx
: &DocContext
<'_
>,
1948 ) -> (Vec
<Type
>, Vec
<Type
>) {
1949 let mut all_types
= FxHashSet
::default();
1950 for arg
in decl
.inputs
.values
.iter() {
1951 if arg
.type_
.is_self_type() {
1954 let args
= get_real_types(generics
, &arg
.type_
, cx
, 0);
1955 if !args
.is_empty() {
1956 all_types
.extend(args
);
1958 all_types
.insert(arg
.type_
.clone());
1962 let ret_types
= match decl
.output
{
1963 FunctionRetTy
::Return(ref return_type
) => {
1964 let mut ret
= get_real_types(generics
, &return_type
, cx
, 0);
1966 ret
.insert(return_type
.clone());
1968 ret
.into_iter().collect()
1972 (all_types
.into_iter().collect(), ret_types
)
1975 #[derive(Clone, Debug)]
1977 pub generics
: Generics
,
1979 pub header
: hir
::FnHeader
,
1980 pub defaultness
: Option
<hir
::Defaultness
>,
1981 pub all_types
: Vec
<Type
>,
1982 pub ret_types
: Vec
<Type
>,
1985 impl<'a
> Clean
<Method
> for (&'a hir
::MethodSig
, &'a hir
::Generics
, hir
::BodyId
,
1986 Option
<hir
::Defaultness
>) {
1987 fn clean(&self, cx
: &DocContext
<'_
>) -> Method
{
1988 let (generics
, decl
) = enter_impl_trait(cx
, || {
1989 (self.1.clean(cx
), (&*self.0.decl
, self.2).clean(cx
))
1991 let (all_types
, ret_types
) = get_all_types(&generics
, &decl
, cx
);
1995 header
: self.0.header
,
1996 defaultness
: self.3,
2003 #[derive(Clone, Debug)]
2004 pub struct TyMethod
{
2005 pub header
: hir
::FnHeader
,
2007 pub generics
: Generics
,
2008 pub all_types
: Vec
<Type
>,
2009 pub ret_types
: Vec
<Type
>,
2012 #[derive(Clone, Debug)]
2013 pub struct Function
{
2015 pub generics
: Generics
,
2016 pub header
: hir
::FnHeader
,
2017 pub all_types
: Vec
<Type
>,
2018 pub ret_types
: Vec
<Type
>,
2021 impl Clean
<Item
> for doctree
::Function
<'_
> {
2022 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
2023 let (generics
, decl
) = enter_impl_trait(cx
, || {
2024 (self.generics
.clean(cx
), (self.decl
, self.body
).clean(cx
))
2027 let did
= cx
.tcx
.hir().local_def_id(self.id
);
2028 let constness
= if cx
.tcx
.is_min_const_fn(did
) {
2029 hir
::Constness
::Const
2031 hir
::Constness
::NotConst
2033 let (all_types
, ret_types
) = get_all_types(&generics
, &decl
, cx
);
2035 name
: Some(self.name
.clean(cx
)),
2036 attrs
: self.attrs
.clean(cx
),
2037 source
: self.whence
.clean(cx
),
2038 visibility
: self.vis
.clean(cx
),
2039 stability
: cx
.stability(self.id
).clean(cx
),
2040 deprecation
: cx
.deprecation(self.id
).clean(cx
),
2042 inner
: FunctionItem(Function
{
2045 header
: hir
::FnHeader { constness, ..self.header }
,
2053 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2055 pub inputs
: Arguments
,
2056 pub output
: FunctionRetTy
,
2057 pub c_variadic
: bool
,
2058 pub attrs
: Attributes
,
2062 pub fn self_type(&self) -> Option
<SelfTy
> {
2063 self.inputs
.values
.get(0).and_then(|v
| v
.to_self())
2066 /// Returns the sugared return type for an async function.
2068 /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
2069 /// will return `i32`.
2073 /// This function will panic if the return type does not match the expected sugaring for async
2075 pub fn sugared_async_return_type(&self) -> FunctionRetTy
{
2076 match &self.output
{
2077 FunctionRetTy
::Return(Type
::ImplTrait(bounds
)) => {
2079 GenericBound
::TraitBound(PolyTrait { trait_, .. }
, ..) => {
2080 let bindings
= trait_
.bindings().unwrap();
2081 FunctionRetTy
::Return(bindings
[0].ty().clone())
2083 _
=> panic
!("unexpected desugaring of async function"),
2086 _
=> panic
!("unexpected desugaring of async function"),
2091 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2092 pub struct Arguments
{
2093 pub values
: Vec
<Argument
>,
2096 impl<'a
> Clean
<Arguments
> for (&'a
[hir
::Ty
], &'a
[ast
::Ident
]) {
2097 fn clean(&self, cx
: &DocContext
<'_
>) -> Arguments
{
2099 values
: self.0.iter
().enumerate().map(|(i
, ty
)| {
2100 let mut name
= self.1.get(i
).map(|ident
| ident
.to_string())
2101 .unwrap_or(String
::new());
2102 if name
.is_empty() {
2103 name
= "_".to_string();
2107 type_
: ty
.clean(cx
),
2114 impl<'a
> Clean
<Arguments
> for (&'a
[hir
::Ty
], hir
::BodyId
) {
2115 fn clean(&self, cx
: &DocContext
<'_
>) -> Arguments
{
2116 let body
= cx
.tcx
.hir().body(self.1);
2119 values
: self.0.iter
().enumerate().map(|(i
, ty
)| {
2121 name
: name_from_pat(&body
.params
[i
].pat
),
2122 type_
: ty
.clean(cx
),
2129 impl<'a
, A
: Copy
> Clean
<FnDecl
> for (&'a hir
::FnDecl
, A
)
2130 where (&'a
[hir
::Ty
], A
): Clean
<Arguments
>
2132 fn clean(&self, cx
: &DocContext
<'_
>) -> FnDecl
{
2134 inputs
: (&self.0.inputs
[..], self.1).clean(cx
),
2135 output
: self.0.output
.clean(cx
),
2136 c_variadic
: self.0.c_variadic
,
2137 attrs
: Attributes
::default(),
2142 impl<'tcx
> Clean
<FnDecl
> for (DefId
, ty
::PolyFnSig
<'tcx
>) {
2143 fn clean(&self, cx
: &DocContext
<'_
>) -> FnDecl
{
2144 let (did
, sig
) = *self;
2145 let mut names
= if cx
.tcx
.hir().as_local_hir_id(did
).is_some() {
2148 cx
.tcx
.fn_arg_names(did
).into_iter()
2152 output
: Return(sig
.skip_binder().output().clean(cx
)),
2153 attrs
: Attributes
::default(),
2154 c_variadic
: sig
.skip_binder().c_variadic
,
2156 values
: sig
.skip_binder().inputs().iter().map(|t
| {
2159 name
: names
.next().map_or(String
::new(), |name
| name
.to_string()),
2167 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2168 pub struct Argument
{
2173 #[derive(Clone, PartialEq, Debug)]
2176 SelfBorrowed(Option
<Lifetime
>, Mutability
),
2181 pub fn to_self(&self) -> Option
<SelfTy
> {
2182 if self.name
!= "self" {
2185 if self.type_
.is_self_type() {
2186 return Some(SelfValue
);
2189 BorrowedRef{ref lifetime, mutability, ref type_}
if type_
.is_self_type() => {
2190 Some(SelfBorrowed(lifetime
.clone(), mutability
))
2192 _
=> Some(SelfExplicit(self.type_
.clone()))
2197 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2198 pub enum FunctionRetTy
{
2203 impl Clean
<FunctionRetTy
> for hir
::FunctionRetTy
{
2204 fn clean(&self, cx
: &DocContext
<'_
>) -> FunctionRetTy
{
2206 hir
::Return(ref typ
) => Return(typ
.clean(cx
)),
2207 hir
::DefaultReturn(..) => DefaultReturn
,
2212 impl GetDefId
for FunctionRetTy
{
2213 fn def_id(&self) -> Option
<DefId
> {
2215 Return(ref ty
) => ty
.def_id(),
2216 DefaultReturn
=> None
,
2221 #[derive(Clone, Debug)]
2224 pub unsafety
: hir
::Unsafety
,
2225 pub items
: Vec
<Item
>,
2226 pub generics
: Generics
,
2227 pub bounds
: Vec
<GenericBound
>,
2228 pub is_spotlight
: bool
,
2232 impl Clean
<Item
> for doctree
::Trait
<'_
> {
2233 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
2234 let attrs
= self.attrs
.clean(cx
);
2235 let is_spotlight
= attrs
.has_doc_flag(sym
::spotlight
);
2237 name
: Some(self.name
.clean(cx
)),
2239 source
: self.whence
.clean(cx
),
2240 def_id
: cx
.tcx
.hir().local_def_id(self.id
),
2241 visibility
: self.vis
.clean(cx
),
2242 stability
: cx
.stability(self.id
).clean(cx
),
2243 deprecation
: cx
.deprecation(self.id
).clean(cx
),
2244 inner
: TraitItem(Trait
{
2245 auto: self.is_auto
.clean(cx
),
2246 unsafety
: self.unsafety
,
2247 items
: self.items
.iter().map(|ti
| ti
.clean(cx
)).collect(),
2248 generics
: self.generics
.clean(cx
),
2249 bounds
: self.bounds
.clean(cx
),
2251 is_auto
: self.is_auto
.clean(cx
),
2257 #[derive(Clone, Debug)]
2258 pub struct TraitAlias
{
2259 pub generics
: Generics
,
2260 pub bounds
: Vec
<GenericBound
>,
2263 impl Clean
<Item
> for doctree
::TraitAlias
<'_
> {
2264 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
2265 let attrs
= self.attrs
.clean(cx
);
2267 name
: Some(self.name
.clean(cx
)),
2269 source
: self.whence
.clean(cx
),
2270 def_id
: cx
.tcx
.hir().local_def_id(self.id
),
2271 visibility
: self.vis
.clean(cx
),
2272 stability
: cx
.stability(self.id
).clean(cx
),
2273 deprecation
: cx
.deprecation(self.id
).clean(cx
),
2274 inner
: TraitAliasItem(TraitAlias
{
2275 generics
: self.generics
.clean(cx
),
2276 bounds
: self.bounds
.clean(cx
),
2282 impl Clean
<bool
> for hir
::IsAuto
{
2283 fn clean(&self, _
: &DocContext
<'_
>) -> bool
{
2285 hir
::IsAuto
::Yes
=> true,
2286 hir
::IsAuto
::No
=> false,
2291 impl Clean
<Type
> for hir
::TraitRef
{
2292 fn clean(&self, cx
: &DocContext
<'_
>) -> Type
{
2293 resolve_type(cx
, self.path
.clean(cx
), self.hir_ref_id
)
2297 impl Clean
<PolyTrait
> for hir
::PolyTraitRef
{
2298 fn clean(&self, cx
: &DocContext
<'_
>) -> PolyTrait
{
2300 trait_
: self.trait_ref
.clean(cx
),
2301 generic_params
: self.bound_generic_params
.clean(cx
)
2306 impl Clean
<Item
> for hir
::TraitItem
{
2307 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
2308 let inner
= match self.kind
{
2309 hir
::TraitItemKind
::Const(ref ty
, default) => {
2310 AssocConstItem(ty
.clean(cx
),
2311 default.map(|e
| print_const_expr(cx
, e
)))
2313 hir
::TraitItemKind
::Method(ref sig
, hir
::TraitMethod
::Provided(body
)) => {
2314 MethodItem((sig
, &self.generics
, body
, None
).clean(cx
))
2316 hir
::TraitItemKind
::Method(ref sig
, hir
::TraitMethod
::Required(ref names
)) => {
2317 let (generics
, decl
) = enter_impl_trait(cx
, || {
2318 (self.generics
.clean(cx
), (&*sig
.decl
, &names
[..]).clean(cx
))
2320 let (all_types
, ret_types
) = get_all_types(&generics
, &decl
, cx
);
2321 TyMethodItem(TyMethod
{
2329 hir
::TraitItemKind
::Type(ref bounds
, ref default) => {
2330 AssocTypeItem(bounds
.clean(cx
), default.clean(cx
))
2333 let local_did
= cx
.tcx
.hir().local_def_id(self.hir_id
);
2335 name
: Some(self.ident
.name
.clean(cx
)),
2336 attrs
: self.attrs
.clean(cx
),
2337 source
: self.span
.clean(cx
),
2339 visibility
: Visibility
::Inherited
,
2340 stability
: get_stability(cx
, local_did
),
2341 deprecation
: get_deprecation(cx
, local_did
),
2347 impl Clean
<Item
> for hir
::ImplItem
{
2348 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
2349 let inner
= match self.kind
{
2350 hir
::ImplItemKind
::Const(ref ty
, expr
) => {
2351 AssocConstItem(ty
.clean(cx
),
2352 Some(print_const_expr(cx
, expr
)))
2354 hir
::ImplItemKind
::Method(ref sig
, body
) => {
2355 MethodItem((sig
, &self.generics
, body
, Some(self.defaultness
)).clean(cx
))
2357 hir
::ImplItemKind
::TyAlias(ref ty
) => TypedefItem(Typedef
{
2358 type_
: ty
.clean(cx
),
2359 generics
: Generics
::default(),
2361 hir
::ImplItemKind
::OpaqueTy(ref bounds
) => OpaqueTyItem(OpaqueTy
{
2362 bounds
: bounds
.clean(cx
),
2363 generics
: Generics
::default(),
2366 let local_did
= cx
.tcx
.hir().local_def_id(self.hir_id
);
2368 name
: Some(self.ident
.name
.clean(cx
)),
2369 source
: self.span
.clean(cx
),
2370 attrs
: self.attrs
.clean(cx
),
2372 visibility
: self.vis
.clean(cx
),
2373 stability
: get_stability(cx
, local_did
),
2374 deprecation
: get_deprecation(cx
, local_did
),
2380 impl Clean
<Item
> for ty
::AssocItem
{
2381 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
2382 let inner
= match self.kind
{
2383 ty
::AssocKind
::Const
=> {
2384 let ty
= cx
.tcx
.type_of(self.def_id
);
2385 let default = if self.defaultness
.has_value() {
2386 Some(inline
::print_inlined_const(cx
, self.def_id
))
2390 AssocConstItem(ty
.clean(cx
), default)
2392 ty
::AssocKind
::Method
=> {
2393 let generics
= (cx
.tcx
.generics_of(self.def_id
),
2394 cx
.tcx
.explicit_predicates_of(self.def_id
)).clean(cx
);
2395 let sig
= cx
.tcx
.fn_sig(self.def_id
);
2396 let mut decl
= (self.def_id
, sig
).clean(cx
);
2398 if self.method_has_self_argument
{
2399 let self_ty
= match self.container
{
2400 ty
::ImplContainer(def_id
) => {
2401 cx
.tcx
.type_of(def_id
)
2403 ty
::TraitContainer(_
) => cx
.tcx
.types
.self_param
,
2405 let self_arg_ty
= *sig
.input(0).skip_binder();
2406 if self_arg_ty
== self_ty
{
2407 decl
.inputs
.values
[0].type_
= Generic(String
::from("Self"));
2408 } else if let ty
::Ref(_
, ty
, _
) = self_arg_ty
.kind
{
2410 match decl
.inputs
.values
[0].type_
{
2411 BorrowedRef{ref mut type_, ..}
=> {
2412 **type_
= Generic(String
::from("Self"))
2414 _
=> unreachable
!(),
2420 let provided
= match self.container
{
2421 ty
::ImplContainer(_
) => true,
2422 ty
::TraitContainer(_
) => self.defaultness
.has_value()
2424 let (all_types
, ret_types
) = get_all_types(&generics
, &decl
, cx
);
2426 let constness
= if cx
.tcx
.is_min_const_fn(self.def_id
) {
2427 hir
::Constness
::Const
2429 hir
::Constness
::NotConst
2431 let asyncness
= cx
.tcx
.asyncness(self.def_id
);
2432 let defaultness
= match self.container
{
2433 ty
::ImplContainer(_
) => Some(self.defaultness
),
2434 ty
::TraitContainer(_
) => None
,
2439 header
: hir
::FnHeader
{
2440 unsafety
: sig
.unsafety(),
2450 TyMethodItem(TyMethod
{
2453 header
: hir
::FnHeader
{
2454 unsafety
: sig
.unsafety(),
2456 constness
: hir
::Constness
::NotConst
,
2457 asyncness
: hir
::IsAsync
::NotAsync
,
2464 ty
::AssocKind
::Type
=> {
2465 let my_name
= self.ident
.name
.clean(cx
);
2467 if let ty
::TraitContainer(did
) = self.container
{
2468 // When loading a cross-crate associated type, the bounds for this type
2469 // are actually located on the trait/impl itself, so we need to load
2470 // all of the generics from there and then look for bounds that are
2471 // applied to this associated type in question.
2472 let predicates
= cx
.tcx
.explicit_predicates_of(did
);
2473 let generics
= (cx
.tcx
.generics_of(did
), predicates
).clean(cx
);
2474 let mut bounds
= generics
.where_predicates
.iter().filter_map(|pred
| {
2475 let (name
, self_type
, trait_
, bounds
) = match *pred
{
2476 WherePredicate
::BoundPredicate
{
2477 ty
: QPath { ref name, ref self_type, ref trait_ }
,
2479 } => (name
, self_type
, trait_
, bounds
),
2482 if *name
!= my_name { return None }
2484 ResolvedPath { did, .. }
if did
== self.container
.id() => {}
2488 Generic(ref s
) if *s
== "Self" => {}
2492 }).flat_map(|i
| i
.iter().cloned()).collect
::<Vec
<_
>>();
2493 // Our Sized/?Sized bound didn't get handled when creating the generics
2494 // because we didn't actually get our whole set of bounds until just now
2495 // (some of them may have come from the trait). If we do have a sized
2496 // bound, we remove it, and if we don't then we add the `?Sized` bound
2498 match bounds
.iter().position(|b
| b
.is_sized_bound(cx
)) {
2499 Some(i
) => { bounds.remove(i); }
2500 None
=> bounds
.push(GenericBound
::maybe_sized(cx
)),
2503 let ty
= if self.defaultness
.has_value() {
2504 Some(cx
.tcx
.type_of(self.def_id
))
2509 AssocTypeItem(bounds
, ty
.clean(cx
))
2511 TypedefItem(Typedef
{
2512 type_
: cx
.tcx
.type_of(self.def_id
).clean(cx
),
2513 generics
: Generics
{
2515 where_predicates
: Vec
::new(),
2520 ty
::AssocKind
::OpaqueTy
=> unimplemented
!(),
2523 let visibility
= match self.container
{
2524 ty
::ImplContainer(_
) => self.vis
.clean(cx
),
2525 ty
::TraitContainer(_
) => Inherited
,
2529 name
: Some(self.ident
.name
.clean(cx
)),
2531 stability
: get_stability(cx
, self.def_id
),
2532 deprecation
: get_deprecation(cx
, self.def_id
),
2533 def_id
: self.def_id
,
2534 attrs
: inline
::load_attrs(cx
, self.def_id
).clean(cx
),
2535 source
: cx
.tcx
.def_span(self.def_id
).clean(cx
),
2541 /// A trait reference, which may have higher ranked lifetimes.
2542 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2543 pub struct PolyTrait
{
2545 pub generic_params
: Vec
<GenericParamDef
>,
2548 /// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
2549 /// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
2550 /// importantly, it does not preserve mutability or boxes.
2551 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2553 /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
2556 param_names
: Option
<Vec
<GenericBound
>>,
2558 /// `true` if is a `T::Name` path for associated types.
2561 /// For parameterized types, so the consumer of the JSON don't go
2562 /// looking for types which don't exist anywhere.
2564 /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
2565 /// arrays, slices, and tuples.
2566 Primitive(PrimitiveType
),
2567 /// `extern "ABI" fn`
2568 BareFunction(Box
<BareFunctionDecl
>),
2571 Array(Box
<Type
>, String
),
2573 RawPointer(Mutability
, Box
<Type
>),
2575 lifetime
: Option
<Lifetime
>,
2576 mutability
: Mutability
,
2580 // `<Type as Trait>::Name`
2583 self_type
: Box
<Type
>,
2590 // `impl TraitA + TraitB + ...`
2591 ImplTrait(Vec
<GenericBound
>),
2594 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
2595 pub enum PrimitiveType
{
2596 Isize
, I8
, I16
, I32
, I64
, I128
,
2597 Usize
, U8
, U16
, U32
, U64
, U128
,
2612 #[derive(Clone, Copy, Debug)]
2630 pub trait GetDefId
{
2631 fn def_id(&self) -> Option
<DefId
>;
2634 impl<T
: GetDefId
> GetDefId
for Option
<T
> {
2635 fn def_id(&self) -> Option
<DefId
> {
2636 self.as_ref().and_then(|d
| d
.def_id())
2641 pub fn primitive_type(&self) -> Option
<PrimitiveType
> {
2643 Primitive(p
) | BorrowedRef { type_: box Primitive(p), ..}
=> Some(p
),
2644 Slice(..) | BorrowedRef { type_: box Slice(..), .. }
=> Some(PrimitiveType
::Slice
),
2645 Array(..) | BorrowedRef { type_: box Array(..), .. }
=> Some(PrimitiveType
::Array
),
2646 Tuple(ref tys
) => if tys
.is_empty() {
2647 Some(PrimitiveType
::Unit
)
2649 Some(PrimitiveType
::Tuple
)
2651 RawPointer(..) => Some(PrimitiveType
::RawPointer
),
2652 BorrowedRef { type_: box Generic(..), .. }
=> Some(PrimitiveType
::Reference
),
2653 BareFunction(..) => Some(PrimitiveType
::Fn
),
2654 Never
=> Some(PrimitiveType
::Never
),
2659 pub fn is_generic(&self) -> bool
{
2661 ResolvedPath { is_generic, .. }
=> is_generic
,
2666 pub fn is_self_type(&self) -> bool
{
2668 Generic(ref name
) => name
== "Self",
2673 pub fn generics(&self) -> Option
<Vec
<Type
>> {
2675 ResolvedPath { ref path, .. }
=> {
2676 path
.segments
.last().and_then(|seg
| {
2677 if let GenericArgs
::AngleBracketed { ref args, .. }
= seg
.args
{
2678 Some(args
.iter().filter_map(|arg
| match arg
{
2679 GenericArg
::Type(ty
) => Some(ty
.clone()),
2691 pub fn bindings(&self) -> Option
<&[TypeBinding
]> {
2693 ResolvedPath { ref path, .. }
=> {
2694 path
.segments
.last().and_then(|seg
| {
2695 if let GenericArgs
::AngleBracketed { ref bindings, .. }
= seg
.args
{
2706 pub fn is_full_generic(&self) -> bool
{
2708 Type
::Generic(_
) => true,
2713 pub fn projection(&self) -> Option
<(&Type
, DefId
, &str)> {
2714 let (self_
, trait_
, name
) = match self {
2715 QPath { ref self_type, ref trait_, ref name }
=> {
2716 (self_type
, trait_
, name
)
2720 let trait_did
= match **trait_
{
2721 ResolvedPath { did, .. }
=> did
,
2724 Some((&self_
, trait_did
, name
))
2729 impl GetDefId
for Type
{
2730 fn def_id(&self) -> Option
<DefId
> {
2732 ResolvedPath { did, .. }
=> Some(did
),
2733 Primitive(p
) => crate::html
::render
::cache().primitive_locations
.get(&p
).cloned(),
2734 BorrowedRef { type_: box Generic(..), .. }
=>
2735 Primitive(PrimitiveType
::Reference
).def_id(),
2736 BorrowedRef { ref type_, .. }
=> type_
.def_id(),
2737 Tuple(ref tys
) => if tys
.is_empty() {
2738 Primitive(PrimitiveType
::Unit
).def_id()
2740 Primitive(PrimitiveType
::Tuple
).def_id()
2742 BareFunction(..) => Primitive(PrimitiveType
::Fn
).def_id(),
2743 Never
=> Primitive(PrimitiveType
::Never
).def_id(),
2744 Slice(..) => Primitive(PrimitiveType
::Slice
).def_id(),
2745 Array(..) => Primitive(PrimitiveType
::Array
).def_id(),
2746 RawPointer(..) => Primitive(PrimitiveType
::RawPointer
).def_id(),
2747 QPath { ref self_type, .. }
=> self_type
.def_id(),
2753 impl PrimitiveType
{
2754 fn from_str(s
: &str) -> Option
<PrimitiveType
> {
2756 "isize" => Some(PrimitiveType
::Isize
),
2757 "i8" => Some(PrimitiveType
::I8
),
2758 "i16" => Some(PrimitiveType
::I16
),
2759 "i32" => Some(PrimitiveType
::I32
),
2760 "i64" => Some(PrimitiveType
::I64
),
2761 "i128" => Some(PrimitiveType
::I128
),
2762 "usize" => Some(PrimitiveType
::Usize
),
2763 "u8" => Some(PrimitiveType
::U8
),
2764 "u16" => Some(PrimitiveType
::U16
),
2765 "u32" => Some(PrimitiveType
::U32
),
2766 "u64" => Some(PrimitiveType
::U64
),
2767 "u128" => Some(PrimitiveType
::U128
),
2768 "bool" => Some(PrimitiveType
::Bool
),
2769 "char" => Some(PrimitiveType
::Char
),
2770 "str" => Some(PrimitiveType
::Str
),
2771 "f32" => Some(PrimitiveType
::F32
),
2772 "f64" => Some(PrimitiveType
::F64
),
2773 "array" => Some(PrimitiveType
::Array
),
2774 "slice" => Some(PrimitiveType
::Slice
),
2775 "tuple" => Some(PrimitiveType
::Tuple
),
2776 "unit" => Some(PrimitiveType
::Unit
),
2777 "pointer" => Some(PrimitiveType
::RawPointer
),
2778 "reference" => Some(PrimitiveType
::Reference
),
2779 "fn" => Some(PrimitiveType
::Fn
),
2780 "never" => Some(PrimitiveType
::Never
),
2785 pub fn as_str(&self) -> &'
static str {
2786 use self::PrimitiveType
::*;
2809 RawPointer
=> "pointer",
2810 Reference
=> "reference",
2816 pub fn to_url_str(&self) -> &'
static str {
2821 impl From
<ast
::IntTy
> for PrimitiveType
{
2822 fn from(int_ty
: ast
::IntTy
) -> PrimitiveType
{
2824 ast
::IntTy
::Isize
=> PrimitiveType
::Isize
,
2825 ast
::IntTy
::I8
=> PrimitiveType
::I8
,
2826 ast
::IntTy
::I16
=> PrimitiveType
::I16
,
2827 ast
::IntTy
::I32
=> PrimitiveType
::I32
,
2828 ast
::IntTy
::I64
=> PrimitiveType
::I64
,
2829 ast
::IntTy
::I128
=> PrimitiveType
::I128
,
2834 impl From
<ast
::UintTy
> for PrimitiveType
{
2835 fn from(uint_ty
: ast
::UintTy
) -> PrimitiveType
{
2837 ast
::UintTy
::Usize
=> PrimitiveType
::Usize
,
2838 ast
::UintTy
::U8
=> PrimitiveType
::U8
,
2839 ast
::UintTy
::U16
=> PrimitiveType
::U16
,
2840 ast
::UintTy
::U32
=> PrimitiveType
::U32
,
2841 ast
::UintTy
::U64
=> PrimitiveType
::U64
,
2842 ast
::UintTy
::U128
=> PrimitiveType
::U128
,
2847 impl From
<ast
::FloatTy
> for PrimitiveType
{
2848 fn from(float_ty
: ast
::FloatTy
) -> PrimitiveType
{
2850 ast
::FloatTy
::F32
=> PrimitiveType
::F32
,
2851 ast
::FloatTy
::F64
=> PrimitiveType
::F64
,
2856 impl Clean
<Type
> for hir
::Ty
{
2857 fn clean(&self, cx
: &DocContext
<'_
>) -> Type
{
2861 TyKind
::Never
=> Never
,
2862 TyKind
::Ptr(ref m
) => RawPointer(m
.mutbl
.clean(cx
), box m
.ty
.clean(cx
)),
2863 TyKind
::Rptr(ref l
, ref m
) => {
2864 let lifetime
= if l
.is_elided() {
2869 BorrowedRef
{lifetime
, mutability
: m
.mutbl
.clean(cx
),
2870 type_
: box m
.ty
.clean(cx
)}
2872 TyKind
::Slice(ref ty
) => Slice(box ty
.clean(cx
)),
2873 TyKind
::Array(ref ty
, ref length
) => {
2874 let def_id
= cx
.tcx
.hir().local_def_id(length
.hir_id
);
2875 let param_env
= cx
.tcx
.param_env(def_id
);
2876 let substs
= InternalSubsts
::identity_for_item(cx
.tcx
, def_id
);
2877 let cid
= GlobalId
{
2878 instance
: ty
::Instance
::new(def_id
, substs
),
2881 let length
= match cx
.tcx
.const_eval(param_env
.and(cid
)) {
2882 Ok(length
) => print_const(cx
, length
),
2885 .span_to_snippet(cx
.tcx
.def_span(def_id
))
2886 .unwrap_or_else(|_
| "_".to_string()),
2888 Array(box ty
.clean(cx
), length
)
2890 TyKind
::Tup(ref tys
) => Tuple(tys
.clean(cx
)),
2891 TyKind
::Def(item_id
, _
) => {
2892 let item
= cx
.tcx
.hir().expect_item(item_id
.id
);
2893 if let hir
::ItemKind
::OpaqueTy(ref ty
) = item
.kind
{
2894 ImplTrait(ty
.bounds
.clean(cx
))
2899 TyKind
::Path(hir
::QPath
::Resolved(None
, ref path
)) => {
2900 if let Res
::Def(DefKind
::TyParam
, did
) = path
.res
{
2901 if let Some(new_ty
) = cx
.ty_substs
.borrow().get(&did
).cloned() {
2904 if let Some(bounds
) = cx
.impl_trait_bounds
.borrow_mut().remove(&did
.into()) {
2905 return ImplTrait(bounds
);
2909 let mut alias
= None
;
2910 if let Res
::Def(DefKind
::TyAlias
, def_id
) = path
.res
{
2911 // Substitute private type aliases
2912 if let Some(hir_id
) = cx
.tcx
.hir().as_local_hir_id(def_id
) {
2913 if !cx
.renderinfo
.borrow().access_levels
.is_exported(def_id
) {
2914 alias
= Some(&cx
.tcx
.hir().expect_item(hir_id
).kind
);
2919 if let Some(&hir
::ItemKind
::TyAlias(ref ty
, ref generics
)) = alias
{
2920 let provided_params
= &path
.segments
.last().expect("segments were empty");
2921 let mut ty_substs
= FxHashMap
::default();
2922 let mut lt_substs
= FxHashMap
::default();
2923 let mut ct_substs
= FxHashMap
::default();
2924 let generic_args
= provided_params
.generic_args();
2926 let mut indices
: GenericParamCount
= Default
::default();
2927 for param
in generics
.params
.iter() {
2929 hir
::GenericParamKind
::Lifetime { .. }
=> {
2931 let lifetime
= generic_args
.args
.iter().find_map(|arg
| {
2933 hir
::GenericArg
::Lifetime(lt
) => {
2934 if indices
.lifetimes
== j
{
2943 if let Some(lt
) = lifetime
.cloned() {
2944 if !lt
.is_elided() {
2946 cx
.tcx
.hir().local_def_id(param
.hir_id
);
2947 lt_substs
.insert(lt_def_id
, lt
.clean(cx
));
2950 indices
.lifetimes
+= 1;
2952 hir
::GenericParamKind
::Type { ref default, .. }
=> {
2953 let ty_param_def_id
=
2954 cx
.tcx
.hir().local_def_id(param
.hir_id
);
2956 let type_
= generic_args
.args
.iter().find_map(|arg
| {
2958 hir
::GenericArg
::Type(ty
) => {
2959 if indices
.types
== j
{
2968 if let Some(ty
) = type_
{
2969 ty_substs
.insert(ty_param_def_id
, ty
.clean(cx
));
2970 } else if let Some(default) = default.clone() {
2971 ty_substs
.insert(ty_param_def_id
,
2976 hir
::GenericParamKind
::Const { .. }
=> {
2977 let const_param_def_id
=
2978 cx
.tcx
.hir().local_def_id(param
.hir_id
);
2980 let const_
= generic_args
.args
.iter().find_map(|arg
| {
2982 hir
::GenericArg
::Const(ct
) => {
2983 if indices
.consts
== j
{
2992 if let Some(ct
) = const_
{
2993 ct_substs
.insert(const_param_def_id
, ct
.clean(cx
));
2995 // FIXME(const_generics:defaults)
2996 indices
.consts
+= 1;
3001 return cx
.enter_alias(ty_substs
, lt_substs
, ct_substs
, || ty
.clean(cx
));
3003 resolve_type(cx
, path
.clean(cx
), self.hir_id
)
3005 TyKind
::Path(hir
::QPath
::Resolved(Some(ref qself
), ref p
)) => {
3006 let segments
= if p
.is_global() { &p.segments[1..] }
else { &p.segments }
;
3007 let trait_segments
= &segments
[..segments
.len() - 1];
3008 let trait_path
= self::Path
{
3009 global
: p
.is_global(),
3012 cx
.tcx
.associated_item(p
.res
.def_id()).container
.id(),
3014 segments
: trait_segments
.clean(cx
),
3017 name
: p
.segments
.last().expect("segments were empty").ident
.name
.clean(cx
),
3018 self_type
: box qself
.clean(cx
),
3019 trait_
: box resolve_type(cx
, trait_path
, self.hir_id
)
3022 TyKind
::Path(hir
::QPath
::TypeRelative(ref qself
, ref segment
)) => {
3023 let mut res
= Res
::Err
;
3024 let ty
= hir_ty_to_ty(cx
.tcx
, self);
3025 if let ty
::Projection(proj
) = ty
.kind
{
3026 res
= Res
::Def(DefKind
::Trait
, proj
.trait_ref(cx
.tcx
).def_id
);
3028 let trait_path
= hir
::Path
{
3031 segments
: vec
![].into(),
3034 name
: segment
.ident
.name
.clean(cx
),
3035 self_type
: box qself
.clean(cx
),
3036 trait_
: box resolve_type(cx
, trait_path
.clean(cx
), self.hir_id
)
3039 TyKind
::TraitObject(ref bounds
, ref lifetime
) => {
3040 match bounds
[0].clean(cx
).trait_
{
3041 ResolvedPath { path, param_names: None, did, is_generic }
=> {
3042 let mut bounds
: Vec
<self::GenericBound
> = bounds
[1..].iter().map(|bound
| {
3043 self::GenericBound
::TraitBound(bound
.clean(cx
),
3044 hir
::TraitBoundModifier
::None
)
3046 if !lifetime
.is_elided() {
3047 bounds
.push(self::GenericBound
::Outlives(lifetime
.clean(cx
)));
3049 ResolvedPath { path, param_names: Some(bounds), did, is_generic, }
3051 _
=> Infer
, // shouldn't happen
3054 TyKind
::BareFn(ref barefn
) => BareFunction(box barefn
.clean(cx
)),
3055 TyKind
::Infer
| TyKind
::Err
=> Infer
,
3056 TyKind
::Typeof(..) => panic
!("unimplemented type {:?}", self.kind
),
3061 impl<'tcx
> Clean
<Type
> for Ty
<'tcx
> {
3062 fn clean(&self, cx
: &DocContext
<'_
>) -> Type
{
3063 debug
!("cleaning type: {:?}", self);
3066 ty
::Bool
=> Primitive(PrimitiveType
::Bool
),
3067 ty
::Char
=> Primitive(PrimitiveType
::Char
),
3068 ty
::Int(int_ty
) => Primitive(int_ty
.into()),
3069 ty
::Uint(uint_ty
) => Primitive(uint_ty
.into()),
3070 ty
::Float(float_ty
) => Primitive(float_ty
.into()),
3071 ty
::Str
=> Primitive(PrimitiveType
::Str
),
3072 ty
::Slice(ty
) => Slice(box ty
.clean(cx
)),
3073 ty
::Array(ty
, n
) => {
3074 let mut n
= cx
.tcx
.lift(&n
).expect("array lift failed");
3075 if let ConstValue
::Unevaluated(def_id
, substs
) = n
.val
{
3076 let param_env
= cx
.tcx
.param_env(def_id
);
3077 let cid
= GlobalId
{
3078 instance
: ty
::Instance
::new(def_id
, substs
),
3081 if let Ok(new_n
) = cx
.tcx
.const_eval(param_env
.and(cid
)) {
3085 let n
= print_const(cx
, n
);
3086 Array(box ty
.clean(cx
), n
)
3088 ty
::RawPtr(mt
) => RawPointer(mt
.mutbl
.clean(cx
), box mt
.ty
.clean(cx
)),
3089 ty
::Ref(r
, ty
, mutbl
) => BorrowedRef
{
3090 lifetime
: r
.clean(cx
),
3091 mutability
: mutbl
.clean(cx
),
3092 type_
: box ty
.clean(cx
),
3096 let ty
= cx
.tcx
.lift(self).expect("FnPtr lift failed");
3097 let sig
= ty
.fn_sig(cx
.tcx
);
3098 let local_def_id
= cx
.tcx
.hir().local_def_id_from_node_id(ast
::CRATE_NODE_ID
);
3099 BareFunction(box BareFunctionDecl
{
3100 unsafety
: sig
.unsafety(),
3101 generic_params
: Vec
::new(),
3102 decl
: (local_def_id
, sig
).clean(cx
),
3106 ty
::Adt(def
, substs
) => {
3108 let kind
= match def
.adt_kind() {
3109 AdtKind
::Struct
=> TypeKind
::Struct
,
3110 AdtKind
::Union
=> TypeKind
::Union
,
3111 AdtKind
::Enum
=> TypeKind
::Enum
,
3113 inline
::record_extern_fqn(cx
, did
, kind
);
3114 let path
= external_path(cx
, cx
.tcx
.item_name(did
), None
, false, vec
![], substs
);
3122 ty
::Foreign(did
) => {
3123 inline
::record_extern_fqn(cx
, did
, TypeKind
::Foreign
);
3124 let path
= external_path(cx
, cx
.tcx
.item_name(did
),
3125 None
, false, vec
![], InternalSubsts
::empty());
3133 ty
::Dynamic(ref obj
, ref reg
) => {
3134 // HACK: pick the first `did` as the `did` of the trait object. Someone
3135 // might want to implement "native" support for marker-trait-only
3137 let mut dids
= obj
.principal_def_id().into_iter().chain(obj
.auto_traits());
3138 let did
= dids
.next().unwrap_or_else(|| {
3139 panic
!("found trait object `{:?}` with no traits?", self)
3141 let substs
= match obj
.principal() {
3142 Some(principal
) => principal
.skip_binder().substs
,
3143 // marker traits have no substs.
3144 _
=> cx
.tcx
.intern_substs(&[])
3147 inline
::record_extern_fqn(cx
, did
, TypeKind
::Trait
);
3149 let mut param_names
= vec
![];
3150 reg
.clean(cx
).map(|b
| param_names
.push(GenericBound
::Outlives(b
)));
3152 let empty
= cx
.tcx
.intern_substs(&[]);
3153 let path
= external_path(cx
, cx
.tcx
.item_name(did
),
3154 Some(did
), false, vec
![], empty
);
3155 inline
::record_extern_fqn(cx
, did
, TypeKind
::Trait
);
3156 let bound
= GenericBound
::TraitBound(PolyTrait
{
3157 trait_
: ResolvedPath
{
3163 generic_params
: Vec
::new(),
3164 }, hir
::TraitBoundModifier
::None
);
3165 param_names
.push(bound
);
3168 let mut bindings
= vec
![];
3169 for pb
in obj
.projection_bounds() {
3170 bindings
.push(TypeBinding
{
3171 name
: cx
.tcx
.associated_item(pb
.item_def_id()).ident
.name
.clean(cx
),
3172 kind
: TypeBindingKind
::Equality
{
3173 ty
: pb
.skip_binder().ty
.clean(cx
)
3178 let path
= external_path(cx
, cx
.tcx
.item_name(did
), Some(did
),
3179 false, bindings
, substs
);
3182 param_names
: Some(param_names
),
3187 ty
::Tuple(ref t
) => {
3188 Tuple(t
.iter().map(|t
| t
.expect_ty()).collect
::<Vec
<_
>>().clean(cx
))
3191 ty
::Projection(ref data
) => data
.clean(cx
),
3193 ty
::Param(ref p
) => {
3194 if let Some(bounds
) = cx
.impl_trait_bounds
.borrow_mut().remove(&p
.index
.into()) {
3197 Generic(p
.name
.to_string())
3201 ty
::Opaque(def_id
, substs
) => {
3202 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
3203 // by looking up the projections associated with the def_id.
3204 let predicates_of
= cx
.tcx
.explicit_predicates_of(def_id
);
3205 let substs
= cx
.tcx
.lift(&substs
).expect("Opaque lift failed");
3206 let bounds
= predicates_of
.instantiate(cx
.tcx
, substs
);
3207 let mut regions
= vec
![];
3208 let mut has_sized
= false;
3209 let mut bounds
= bounds
.predicates
.iter().filter_map(|predicate
| {
3210 let trait_ref
= if let Some(tr
) = predicate
.to_opt_poly_trait_ref() {
3212 } else if let ty
::Predicate
::TypeOutlives(pred
) = *predicate
{
3213 // these should turn up at the end
3214 pred
.skip_binder().1.clean(cx
).map(|r
| {
3215 regions
.push(GenericBound
::Outlives(r
))
3222 if let Some(sized
) = cx
.tcx
.lang_items().sized_trait() {
3223 if trait_ref
.def_id() == sized
{
3229 let bounds
= bounds
.predicates
.iter().filter_map(|pred
|
3230 if let ty
::Predicate
::Projection(proj
) = *pred
{
3231 let proj
= proj
.skip_binder();
3232 if proj
.projection_ty
.trait_ref(cx
.tcx
) == *trait_ref
.skip_binder() {
3234 name
: cx
.tcx
.associated_item(proj
.projection_ty
.item_def_id
)
3235 .ident
.name
.clean(cx
),
3236 kind
: TypeBindingKind
::Equality
{
3237 ty
: proj
.ty
.clean(cx
),
3248 Some((trait_ref
.skip_binder(), bounds
).clean(cx
))
3249 }).collect
::<Vec
<_
>>();
3250 bounds
.extend(regions
);
3251 if !has_sized
&& !bounds
.is_empty() {
3252 bounds
.insert(0, GenericBound
::maybe_sized(cx
));
3257 ty
::Closure(..) | ty
::Generator(..) => Tuple(vec
![]), // FIXME(pcwalton)
3259 ty
::Bound(..) => panic
!("Bound"),
3260 ty
::Placeholder(..) => panic
!("Placeholder"),
3261 ty
::UnnormalizedProjection(..) => panic
!("UnnormalizedProjection"),
3262 ty
::GeneratorWitness(..) => panic
!("GeneratorWitness"),
3263 ty
::Infer(..) => panic
!("Infer"),
3264 ty
::Error
=> panic
!("Error"),
3269 impl<'tcx
> Clean
<Constant
> for ty
::Const
<'tcx
> {
3270 fn clean(&self, cx
: &DocContext
<'_
>) -> Constant
{
3272 type_
: self.ty
.clean(cx
),
3273 expr
: format
!("{}", self),
3278 impl Clean
<Item
> for hir
::StructField
{
3279 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3280 let local_did
= cx
.tcx
.hir().local_def_id(self.hir_id
);
3283 name
: Some(self.ident
.name
).clean(cx
),
3284 attrs
: self.attrs
.clean(cx
),
3285 source
: self.span
.clean(cx
),
3286 visibility
: self.vis
.clean(cx
),
3287 stability
: get_stability(cx
, local_did
),
3288 deprecation
: get_deprecation(cx
, local_did
),
3290 inner
: StructFieldItem(self.ty
.clean(cx
)),
3295 impl Clean
<Item
> for ty
::FieldDef
{
3296 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3298 name
: Some(self.ident
.name
).clean(cx
),
3299 attrs
: cx
.tcx
.get_attrs(self.did
).clean(cx
),
3300 source
: cx
.tcx
.def_span(self.did
).clean(cx
),
3301 visibility
: self.vis
.clean(cx
),
3302 stability
: get_stability(cx
, self.did
),
3303 deprecation
: get_deprecation(cx
, self.did
),
3305 inner
: StructFieldItem(cx
.tcx
.type_of(self.did
).clean(cx
)),
3310 #[derive(Clone, PartialEq, Eq, Debug)]
3311 pub enum Visibility
{
3315 Restricted(DefId
, Path
),
3318 impl Clean
<Visibility
> for hir
::Visibility
{
3319 fn clean(&self, cx
: &DocContext
<'_
>) -> Visibility
{
3321 hir
::VisibilityKind
::Public
=> Visibility
::Public
,
3322 hir
::VisibilityKind
::Inherited
=> Visibility
::Inherited
,
3323 hir
::VisibilityKind
::Crate(_
) => Visibility
::Crate
,
3324 hir
::VisibilityKind
::Restricted { ref path, .. }
=> {
3325 let path
= path
.clean(cx
);
3326 let did
= register_res(cx
, path
.res
);
3327 Visibility
::Restricted(did
, path
)
3333 impl Clean
<Visibility
> for ty
::Visibility
{
3334 fn clean(&self, _
: &DocContext
<'_
>) -> Visibility
{
3335 if *self == ty
::Visibility
::Public { Public }
else { Inherited }
3339 #[derive(Clone, Debug)]
3341 pub struct_type
: doctree
::StructType
,
3342 pub generics
: Generics
,
3343 pub fields
: Vec
<Item
>,
3344 pub fields_stripped
: bool
,
3347 #[derive(Clone, Debug)]
3349 pub struct_type
: doctree
::StructType
,
3350 pub generics
: Generics
,
3351 pub fields
: Vec
<Item
>,
3352 pub fields_stripped
: bool
,
3355 impl Clean
<Item
> for doctree
::Struct
<'_
> {
3356 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3358 name
: Some(self.name
.clean(cx
)),
3359 attrs
: self.attrs
.clean(cx
),
3360 source
: self.whence
.clean(cx
),
3361 def_id
: cx
.tcx
.hir().local_def_id(self.id
),
3362 visibility
: self.vis
.clean(cx
),
3363 stability
: cx
.stability(self.id
).clean(cx
),
3364 deprecation
: cx
.deprecation(self.id
).clean(cx
),
3365 inner
: StructItem(Struct
{
3366 struct_type
: self.struct_type
,
3367 generics
: self.generics
.clean(cx
),
3368 fields
: self.fields
.clean(cx
),
3369 fields_stripped
: false,
3375 impl Clean
<Item
> for doctree
::Union
<'_
> {
3376 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3378 name
: Some(self.name
.clean(cx
)),
3379 attrs
: self.attrs
.clean(cx
),
3380 source
: self.whence
.clean(cx
),
3381 def_id
: cx
.tcx
.hir().local_def_id(self.id
),
3382 visibility
: self.vis
.clean(cx
),
3383 stability
: cx
.stability(self.id
).clean(cx
),
3384 deprecation
: cx
.deprecation(self.id
).clean(cx
),
3385 inner
: UnionItem(Union
{
3386 struct_type
: self.struct_type
,
3387 generics
: self.generics
.clean(cx
),
3388 fields
: self.fields
.clean(cx
),
3389 fields_stripped
: false,
3395 /// This is a more limited form of the standard Struct, different in that
3396 /// it lacks the things most items have (name, id, parameterization). Found
3397 /// only as a variant in an enum.
3398 #[derive(Clone, Debug)]
3399 pub struct VariantStruct
{
3400 pub struct_type
: doctree
::StructType
,
3401 pub fields
: Vec
<Item
>,
3402 pub fields_stripped
: bool
,
3405 impl Clean
<VariantStruct
> for ::rustc
::hir
::VariantData
{
3406 fn clean(&self, cx
: &DocContext
<'_
>) -> VariantStruct
{
3408 struct_type
: doctree
::struct_type_from_def(self),
3409 fields
: self.fields().iter().map(|x
| x
.clean(cx
)).collect(),
3410 fields_stripped
: false,
3415 #[derive(Clone, Debug)]
3417 pub variants
: IndexVec
<VariantIdx
, Item
>,
3418 pub generics
: Generics
,
3419 pub variants_stripped
: bool
,
3422 impl Clean
<Item
> for doctree
::Enum
<'_
> {
3423 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3425 name
: Some(self.name
.clean(cx
)),
3426 attrs
: self.attrs
.clean(cx
),
3427 source
: self.whence
.clean(cx
),
3428 def_id
: cx
.tcx
.hir().local_def_id(self.id
),
3429 visibility
: self.vis
.clean(cx
),
3430 stability
: cx
.stability(self.id
).clean(cx
),
3431 deprecation
: cx
.deprecation(self.id
).clean(cx
),
3432 inner
: EnumItem(Enum
{
3433 variants
: self.variants
.iter().map(|v
| v
.clean(cx
)).collect(),
3434 generics
: self.generics
.clean(cx
),
3435 variants_stripped
: false,
3441 #[derive(Clone, Debug)]
3442 pub struct Variant
{
3443 pub kind
: VariantKind
,
3446 impl Clean
<Item
> for doctree
::Variant
<'_
> {
3447 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3449 name
: Some(self.name
.clean(cx
)),
3450 attrs
: self.attrs
.clean(cx
),
3451 source
: self.whence
.clean(cx
),
3452 visibility
: Inherited
,
3453 stability
: cx
.stability(self.id
).clean(cx
),
3454 deprecation
: cx
.deprecation(self.id
).clean(cx
),
3455 def_id
: cx
.tcx
.hir().local_def_id(self.id
),
3456 inner
: VariantItem(Variant
{
3457 kind
: self.def
.clean(cx
),
3463 impl Clean
<Item
> for ty
::VariantDef
{
3464 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3465 let kind
= match self.ctor_kind
{
3466 CtorKind
::Const
=> VariantKind
::CLike
,
3469 self.fields
.iter().map(|f
| cx
.tcx
.type_of(f
.did
).clean(cx
)).collect()
3472 CtorKind
::Fictive
=> {
3473 VariantKind
::Struct(VariantStruct
{
3474 struct_type
: doctree
::Plain
,
3475 fields_stripped
: false,
3476 fields
: self.fields
.iter().map(|field
| {
3478 source
: cx
.tcx
.def_span(field
.did
).clean(cx
),
3479 name
: Some(field
.ident
.name
.clean(cx
)),
3480 attrs
: cx
.tcx
.get_attrs(field
.did
).clean(cx
),
3481 visibility
: field
.vis
.clean(cx
),
3483 stability
: get_stability(cx
, field
.did
),
3484 deprecation
: get_deprecation(cx
, field
.did
),
3485 inner
: StructFieldItem(cx
.tcx
.type_of(field
.did
).clean(cx
))
3492 name
: Some(self.ident
.clean(cx
)),
3493 attrs
: inline
::load_attrs(cx
, self.def_id
).clean(cx
),
3494 source
: cx
.tcx
.def_span(self.def_id
).clean(cx
),
3495 visibility
: Inherited
,
3496 def_id
: self.def_id
,
3497 inner
: VariantItem(Variant { kind }
),
3498 stability
: get_stability(cx
, self.def_id
),
3499 deprecation
: get_deprecation(cx
, self.def_id
),
3504 #[derive(Clone, Debug)]
3505 pub enum VariantKind
{
3508 Struct(VariantStruct
),
3511 impl Clean
<VariantKind
> for hir
::VariantData
{
3512 fn clean(&self, cx
: &DocContext
<'_
>) -> VariantKind
{
3514 hir
::VariantData
::Struct(..) => VariantKind
::Struct(self.clean(cx
)),
3515 hir
::VariantData
::Tuple(..) =>
3516 VariantKind
::Tuple(self.fields().iter().map(|x
| x
.ty
.clean(cx
)).collect()),
3517 hir
::VariantData
::Unit(..) => VariantKind
::CLike
,
3522 #[derive(Clone, Debug)]
3524 pub filename
: FileName
,
3529 pub original
: syntax_pos
::Span
,
3533 pub fn empty() -> Span
{
3535 filename
: FileName
::Anon(0),
3536 loline
: 0, locol
: 0,
3537 hiline
: 0, hicol
: 0,
3538 original
: syntax_pos
::DUMMY_SP
,
3542 pub fn span(&self) -> syntax_pos
::Span
{
3547 impl Clean
<Span
> for syntax_pos
::Span
{
3548 fn clean(&self, cx
: &DocContext
<'_
>) -> Span
{
3549 if self.is_dummy() {
3550 return Span
::empty();
3553 let cm
= cx
.sess().source_map();
3554 let filename
= cm
.span_to_filename(*self);
3555 let lo
= cm
.lookup_char_pos(self.lo());
3556 let hi
= cm
.lookup_char_pos(self.hi());
3560 locol
: lo
.col
.to_usize(),
3562 hicol
: hi
.col
.to_usize(),
3568 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
3572 pub segments
: Vec
<PathSegment
>,
3576 pub fn last_name(&self) -> &str {
3577 self.segments
.last().expect("segments were empty").name
.as_str()
3581 impl Clean
<Path
> for hir
::Path
{
3582 fn clean(&self, cx
: &DocContext
<'_
>) -> Path
{
3584 global
: self.is_global(),
3586 segments
: if self.is_global() { &self.segments[1..] }
else { &self.segments }
.clean(cx
),
3591 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
3592 pub enum GenericArg
{
3598 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
3599 pub enum GenericArgs
{
3601 args
: Vec
<GenericArg
>,
3602 bindings
: Vec
<TypeBinding
>,
3606 output
: Option
<Type
>,
3610 impl Clean
<GenericArgs
> for hir
::GenericArgs
{
3611 fn clean(&self, cx
: &DocContext
<'_
>) -> GenericArgs
{
3612 if self.parenthesized
{
3613 let output
= self.bindings
[0].ty().clean(cx
);
3614 GenericArgs
::Parenthesized
{
3615 inputs
: self.inputs().clean(cx
),
3616 output
: if output
!= Type
::Tuple(Vec
::new()) { Some(output) }
else { None }
3619 let elide_lifetimes
= self.args
.iter().all(|arg
| match arg
{
3620 hir
::GenericArg
::Lifetime(lt
) => lt
.is_elided(),
3623 GenericArgs
::AngleBracketed
{
3624 args
: self.args
.iter().filter_map(|arg
| match arg
{
3625 hir
::GenericArg
::Lifetime(lt
) if !elide_lifetimes
=> {
3626 Some(GenericArg
::Lifetime(lt
.clean(cx
)))
3628 hir
::GenericArg
::Lifetime(_
) => None
,
3629 hir
::GenericArg
::Type(ty
) => Some(GenericArg
::Type(ty
.clean(cx
))),
3630 hir
::GenericArg
::Const(ct
) => Some(GenericArg
::Const(ct
.clean(cx
))),
3632 bindings
: self.bindings
.clean(cx
),
3638 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
3639 pub struct PathSegment
{
3641 pub args
: GenericArgs
,
3644 impl Clean
<PathSegment
> for hir
::PathSegment
{
3645 fn clean(&self, cx
: &DocContext
<'_
>) -> PathSegment
{
3647 name
: self.ident
.name
.clean(cx
),
3648 args
: self.generic_args().clean(cx
),
3653 fn strip_type(ty
: Type
) -> Type
{
3655 Type
::ResolvedPath { path, param_names, did, is_generic }
=> {
3656 Type
::ResolvedPath { path: strip_path(&path), param_names, did, is_generic }
3658 Type
::Tuple(inner_tys
) => {
3659 Type
::Tuple(inner_tys
.iter().map(|t
| strip_type(t
.clone())).collect())
3661 Type
::Slice(inner_ty
) => Type
::Slice(Box
::new(strip_type(*inner_ty
))),
3662 Type
::Array(inner_ty
, s
) => Type
::Array(Box
::new(strip_type(*inner_ty
)), s
),
3663 Type
::RawPointer(m
, inner_ty
) => Type
::RawPointer(m
, Box
::new(strip_type(*inner_ty
))),
3664 Type
::BorrowedRef { lifetime, mutability, type_ }
=> {
3665 Type
::BorrowedRef { lifetime, mutability, type_: Box::new(strip_type(*type_)) }
3667 Type
::QPath { name, self_type, trait_ }
=> {
3670 self_type
: Box
::new(strip_type(*self_type
)), trait_
: Box
::new(strip_type(*trait_
))
3677 fn strip_path(path
: &Path
) -> Path
{
3678 let segments
= path
.segments
.iter().map(|s
| {
3680 name
: s
.name
.clone(),
3681 args
: GenericArgs
::AngleBracketed
{
3689 global
: path
.global
,
3690 res
: path
.res
.clone(),
3695 fn qpath_to_string(p
: &hir
::QPath
) -> String
{
3696 let segments
= match *p
{
3697 hir
::QPath
::Resolved(_
, ref path
) => &path
.segments
,
3698 hir
::QPath
::TypeRelative(_
, ref segment
) => return segment
.ident
.to_string(),
3701 let mut s
= String
::new();
3702 for (i
, seg
) in segments
.iter().enumerate() {
3706 if seg
.ident
.name
!= kw
::PathRoot
{
3707 s
.push_str(&*seg
.ident
.as_str());
3713 impl Clean
<String
> for Ident
{
3715 fn clean(&self, cx
: &DocContext
<'_
>) -> String
{
3720 impl Clean
<String
> for ast
::Name
{
3722 fn clean(&self, _
: &DocContext
<'_
>) -> String
{
3727 #[derive(Clone, Debug)]
3728 pub struct Typedef
{
3730 pub generics
: Generics
,
3733 impl Clean
<Item
> for doctree
::Typedef
<'_
> {
3734 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3736 name
: Some(self.name
.clean(cx
)),
3737 attrs
: self.attrs
.clean(cx
),
3738 source
: self.whence
.clean(cx
),
3739 def_id
: cx
.tcx
.hir().local_def_id(self.id
),
3740 visibility
: self.vis
.clean(cx
),
3741 stability
: cx
.stability(self.id
).clean(cx
),
3742 deprecation
: cx
.deprecation(self.id
).clean(cx
),
3743 inner
: TypedefItem(Typedef
{
3744 type_
: self.ty
.clean(cx
),
3745 generics
: self.gen
.clean(cx
),
3751 #[derive(Clone, Debug)]
3752 pub struct OpaqueTy
{
3753 pub bounds
: Vec
<GenericBound
>,
3754 pub generics
: Generics
,
3757 impl Clean
<Item
> for doctree
::OpaqueTy
<'_
> {
3758 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3760 name
: Some(self.name
.clean(cx
)),
3761 attrs
: self.attrs
.clean(cx
),
3762 source
: self.whence
.clean(cx
),
3763 def_id
: cx
.tcx
.hir().local_def_id(self.id
),
3764 visibility
: self.vis
.clean(cx
),
3765 stability
: cx
.stability(self.id
).clean(cx
),
3766 deprecation
: cx
.deprecation(self.id
).clean(cx
),
3767 inner
: OpaqueTyItem(OpaqueTy
{
3768 bounds
: self.opaque_ty
.bounds
.clean(cx
),
3769 generics
: self.opaque_ty
.generics
.clean(cx
),
3775 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
3776 pub struct BareFunctionDecl
{
3777 pub unsafety
: hir
::Unsafety
,
3778 pub generic_params
: Vec
<GenericParamDef
>,
3783 impl Clean
<BareFunctionDecl
> for hir
::BareFnTy
{
3784 fn clean(&self, cx
: &DocContext
<'_
>) -> BareFunctionDecl
{
3785 let (generic_params
, decl
) = enter_impl_trait(cx
, || {
3786 (self.generic_params
.clean(cx
), (&*self.decl
, &self.param_names
[..]).clean(cx
))
3789 unsafety
: self.unsafety
,
3797 #[derive(Clone, Debug)]
3800 pub mutability
: Mutability
,
3801 /// It's useful to have the value of a static documented, but I have no
3802 /// desire to represent expressions (that'd basically be all of the AST,
3803 /// which is huge!). So, have a string.
3807 impl Clean
<Item
> for doctree
::Static
<'_
> {
3808 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3809 debug
!("cleaning static {}: {:?}", self.name
.clean(cx
), self);
3811 name
: Some(self.name
.clean(cx
)),
3812 attrs
: self.attrs
.clean(cx
),
3813 source
: self.whence
.clean(cx
),
3814 def_id
: cx
.tcx
.hir().local_def_id(self.id
),
3815 visibility
: self.vis
.clean(cx
),
3816 stability
: cx
.stability(self.id
).clean(cx
),
3817 deprecation
: cx
.deprecation(self.id
).clean(cx
),
3818 inner
: StaticItem(Static
{
3819 type_
: self.type_
.clean(cx
),
3820 mutability
: self.mutability
.clean(cx
),
3821 expr
: print_const_expr(cx
, self.expr
),
3827 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
3828 pub struct Constant
{
3833 impl Clean
<Item
> for doctree
::Constant
<'_
> {
3834 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
3836 name
: Some(self.name
.clean(cx
)),
3837 attrs
: self.attrs
.clean(cx
),
3838 source
: self.whence
.clean(cx
),
3839 def_id
: cx
.tcx
.hir().local_def_id(self.id
),
3840 visibility
: self.vis
.clean(cx
),
3841 stability
: cx
.stability(self.id
).clean(cx
),
3842 deprecation
: cx
.deprecation(self.id
).clean(cx
),
3843 inner
: ConstantItem(Constant
{
3844 type_
: self.type_
.clean(cx
),
3845 expr
: print_const_expr(cx
, self.expr
),
3851 #[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)]
3852 pub enum Mutability
{
3857 impl Clean
<Mutability
> for hir
::Mutability
{
3858 fn clean(&self, _
: &DocContext
<'_
>) -> Mutability
{
3860 &hir
::MutMutable
=> Mutable
,
3861 &hir
::MutImmutable
=> Immutable
,
3866 #[derive(Clone, PartialEq, Debug)]
3867 pub enum ImplPolarity
{
3872 impl Clean
<ImplPolarity
> for ty
::ImplPolarity
{
3873 fn clean(&self, _
: &DocContext
<'_
>) -> ImplPolarity
{
3875 &ty
::ImplPolarity
::Positive
|
3876 // FIXME: do we want to do something else here?
3877 &ty
::ImplPolarity
::Reservation
=> ImplPolarity
::Positive
,
3878 &ty
::ImplPolarity
::Negative
=> ImplPolarity
::Negative
,
3883 #[derive(Clone, Debug)]
3885 pub unsafety
: hir
::Unsafety
,
3886 pub generics
: Generics
,
3887 pub provided_trait_methods
: FxHashSet
<String
>,
3888 pub trait_
: Option
<Type
>,
3890 pub items
: Vec
<Item
>,
3891 pub polarity
: Option
<ImplPolarity
>,
3892 pub synthetic
: bool
,
3893 pub blanket_impl
: Option
<Type
>,
3896 pub fn get_auto_trait_and_blanket_impls(
3897 cx
: &DocContext
<'tcx
>,
3899 param_env_def_id
: DefId
,
3900 ) -> impl Iterator
<Item
= Item
> {
3901 AutoTraitFinder
::new(cx
).get_auto_trait_impls(ty
, param_env_def_id
).into_iter()
3902 .chain(BlanketImplFinder
::new(cx
).get_blanket_impls(ty
, param_env_def_id
))
3905 impl Clean
<Vec
<Item
>> for doctree
::Impl
<'_
> {
3906 fn clean(&self, cx
: &DocContext
<'_
>) -> Vec
<Item
> {
3907 let mut ret
= Vec
::new();
3908 let trait_
= self.trait_
.clean(cx
);
3909 let items
= self.items
.iter().map(|ii
| ii
.clean(cx
)).collect
::<Vec
<_
>>();
3910 let def_id
= cx
.tcx
.hir().local_def_id(self.id
);
3912 // If this impl block is an implementation of the Deref trait, then we
3913 // need to try inlining the target's inherent impl blocks as well.
3914 if trait_
.def_id() == cx
.tcx
.lang_items().deref_trait() {
3915 build_deref_target_impls(cx
, &items
, &mut ret
);
3918 let provided
= trait_
.def_id().map(|did
| {
3919 cx
.tcx
.provided_trait_methods(did
)
3921 .map(|meth
| meth
.ident
.to_string())
3923 }).unwrap_or_default();
3927 attrs
: self.attrs
.clean(cx
),
3928 source
: self.whence
.clean(cx
),
3930 visibility
: self.vis
.clean(cx
),
3931 stability
: cx
.stability(self.id
).clean(cx
),
3932 deprecation
: cx
.deprecation(self.id
).clean(cx
),
3933 inner
: ImplItem(Impl
{
3934 unsafety
: self.unsafety
,
3935 generics
: self.generics
.clean(cx
),
3936 provided_trait_methods
: provided
,
3938 for_
: self.for_
.clean(cx
),
3940 polarity
: Some(cx
.tcx
.impl_polarity(def_id
).clean(cx
)),
3949 fn build_deref_target_impls(cx
: &DocContext
<'_
>,
3951 ret
: &mut Vec
<Item
>) {
3952 use self::PrimitiveType
::*;
3956 let target
= match item
.inner
{
3957 TypedefItem(ref t
, true) => &t
.type_
,
3960 let primitive
= match *target
{
3961 ResolvedPath { did, .. }
if did
.is_local() => continue,
3962 ResolvedPath { did, .. }
=> {
3963 ret
.extend(inline
::build_impls(cx
, did
, None
));
3966 _
=> match target
.primitive_type() {
3971 let did
= match primitive
{
3972 Isize
=> tcx
.lang_items().isize_impl(),
3973 I8
=> tcx
.lang_items().i8_impl(),
3974 I16
=> tcx
.lang_items().i16_impl(),
3975 I32
=> tcx
.lang_items().i32_impl(),
3976 I64
=> tcx
.lang_items().i64_impl(),
3977 I128
=> tcx
.lang_items().i128_impl(),
3978 Usize
=> tcx
.lang_items().usize_impl(),
3979 U8
=> tcx
.lang_items().u8_impl(),
3980 U16
=> tcx
.lang_items().u16_impl(),
3981 U32
=> tcx
.lang_items().u32_impl(),
3982 U64
=> tcx
.lang_items().u64_impl(),
3983 U128
=> tcx
.lang_items().u128_impl(),
3984 F32
=> tcx
.lang_items().f32_impl(),
3985 F64
=> tcx
.lang_items().f64_impl(),
3986 Char
=> tcx
.lang_items().char_impl(),
3987 Bool
=> tcx
.lang_items().bool_impl(),
3988 Str
=> tcx
.lang_items().str_impl(),
3989 Slice
=> tcx
.lang_items().slice_impl(),
3990 Array
=> tcx
.lang_items().slice_impl(),
3993 RawPointer
=> tcx
.lang_items().const_ptr_impl(),
3998 if let Some(did
) = did
{
3999 if !did
.is_local() {
4000 inline
::build_impl(cx
, did
, None
, ret
);
4006 impl Clean
<Vec
<Item
>> for doctree
::ExternCrate
<'_
> {
4007 fn clean(&self, cx
: &DocContext
<'_
>) -> Vec
<Item
> {
4009 let please_inline
= self.vis
.node
.is_pub() && self.attrs
.iter().any(|a
| {
4010 a
.check_name(sym
::doc
) && match a
.meta_item_list() {
4011 Some(l
) => attr
::list_contains_name(&l
, sym
::inline
),
4017 let mut visited
= FxHashSet
::default();
4023 index
: CRATE_DEF_INDEX
,
4027 if let Some(items
) = inline
::try_inline(
4029 Some(rustc
::ty
::Attributes
::Borrowed(self.attrs
)),
4038 attrs
: self.attrs
.clean(cx
),
4039 source
: self.whence
.clean(cx
),
4040 def_id
: DefId { krate: self.cnum, index: CRATE_DEF_INDEX }
,
4041 visibility
: self.vis
.clean(cx
),
4044 inner
: ExternCrateItem(self.name
.clean(cx
), self.path
.clone())
4049 impl Clean
<Vec
<Item
>> for doctree
::Import
<'_
> {
4050 fn clean(&self, cx
: &DocContext
<'_
>) -> Vec
<Item
> {
4051 // We consider inlining the documentation of `pub use` statements, but we
4052 // forcefully don't inline if this is not public or if the
4053 // #[doc(no_inline)] attribute is present.
4054 // Don't inline doc(hidden) imports so they can be stripped at a later stage.
4055 let mut denied
= !self.vis
.node
.is_pub() || self.attrs
.iter().any(|a
| {
4056 a
.check_name(sym
::doc
) && match a
.meta_item_list() {
4057 Some(l
) => attr
::list_contains_name(&l
, sym
::no_inline
) ||
4058 attr
::list_contains_name(&l
, sym
::hidden
),
4062 // Also check whether imports were asked to be inlined, in case we're trying to re-export a
4063 // crate in Rust 2018+
4064 let please_inline
= self.attrs
.lists(sym
::doc
).has_word(sym
::inline
);
4065 let path
= self.path
.clean(cx
);
4066 let inner
= if self.glob
{
4068 let mut visited
= FxHashSet
::default();
4069 if let Some(items
) = inline
::try_inline_glob(cx
, path
.res
, &mut visited
) {
4074 Import
::Glob(resolve_use_source(cx
, path
))
4076 let name
= self.name
;
4079 Res
::Def(DefKind
::Mod
, did
) => {
4080 if !did
.is_local() && did
.index
== CRATE_DEF_INDEX
{
4081 // if we're `pub use`ing an extern crate root, don't inline it unless we
4082 // were specifically asked for it
4090 let mut visited
= FxHashSet
::default();
4091 if let Some(items
) = inline
::try_inline(
4093 Some(rustc
::ty
::Attributes
::Borrowed(self.attrs
)),
4099 Import
::Simple(name
.clean(cx
), resolve_use_source(cx
, path
))
4104 attrs
: self.attrs
.clean(cx
),
4105 source
: self.whence
.clean(cx
),
4106 def_id
: cx
.tcx
.hir().local_def_id_from_node_id(ast
::CRATE_NODE_ID
),
4107 visibility
: self.vis
.clean(cx
),
4110 inner
: ImportItem(inner
)
4115 #[derive(Clone, Debug)]
4117 // use source as str;
4118 Simple(String
, ImportSource
),
4123 #[derive(Clone, Debug)]
4124 pub struct ImportSource
{
4126 pub did
: Option
<DefId
>,
4129 impl Clean
<Item
> for doctree
::ForeignItem
<'_
> {
4130 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
4131 let inner
= match self.kind
{
4132 hir
::ForeignItemKind
::Fn(ref decl
, ref names
, ref generics
) => {
4133 let abi
= cx
.tcx
.hir().get_foreign_abi(self.id
);
4134 let (generics
, decl
) = enter_impl_trait(cx
, || {
4135 (generics
.clean(cx
), (&**decl
, &names
[..]).clean(cx
))
4137 let (all_types
, ret_types
) = get_all_types(&generics
, &decl
, cx
);
4138 ForeignFunctionItem(Function
{
4141 header
: hir
::FnHeader
{
4142 unsafety
: hir
::Unsafety
::Unsafe
,
4144 constness
: hir
::Constness
::NotConst
,
4145 asyncness
: hir
::IsAsync
::NotAsync
,
4151 hir
::ForeignItemKind
::Static(ref ty
, mutbl
) => {
4152 ForeignStaticItem(Static
{
4153 type_
: ty
.clean(cx
),
4154 mutability
: mutbl
.clean(cx
),
4155 expr
: String
::new(),
4158 hir
::ForeignItemKind
::Type
=> {
4164 name
: Some(self.name
.clean(cx
)),
4165 attrs
: self.attrs
.clean(cx
),
4166 source
: self.whence
.clean(cx
),
4167 def_id
: cx
.tcx
.hir().local_def_id(self.id
),
4168 visibility
: self.vis
.clean(cx
),
4169 stability
: cx
.stability(self.id
).clean(cx
),
4170 deprecation
: cx
.deprecation(self.id
).clean(cx
),
4178 pub trait ToSource
{
4179 fn to_src(&self, cx
: &DocContext
<'_
>) -> String
;
4182 impl ToSource
for syntax_pos
::Span
{
4183 fn to_src(&self, cx
: &DocContext
<'_
>) -> String
{
4184 debug
!("converting span {:?} to snippet", self.clean(cx
));
4185 let sn
= match cx
.sess().source_map().span_to_snippet(*self) {
4187 Err(_
) => String
::new()
4189 debug
!("got snippet {}", sn
);
4194 fn name_from_pat(p
: &hir
::Pat
) -> String
{
4196 debug
!("trying to get a name from pattern: {:?}", p
);
4199 PatKind
::Wild
=> "_".to_string(),
4200 PatKind
::Binding(_
, _
, ident
, _
) => ident
.to_string(),
4201 PatKind
::TupleStruct(ref p
, ..) | PatKind
::Path(ref p
) => qpath_to_string(p
),
4202 PatKind
::Struct(ref name
, ref fields
, etc
) => {
4203 format
!("{} {{ {}{} }}", qpath_to_string(name
),
4204 fields
.iter().map(|fp
| format
!("{}: {}", fp
.ident
, name_from_pat(&fp
.pat
)))
4205 .collect
::<Vec
<String
>>().join(", "),
4206 if etc { ", .." }
else { "" }
4209 PatKind
::Or(ref pats
) => {
4210 pats
.iter().map(|p
| name_from_pat(&**p
)).collect
::<Vec
<String
>>().join(" | ")
4212 PatKind
::Tuple(ref elts
, _
) => format
!("({})", elts
.iter().map(|p
| name_from_pat(&**p
))
4213 .collect
::<Vec
<String
>>().join(", ")),
4214 PatKind
::Box(ref p
) => name_from_pat(&**p
),
4215 PatKind
::Ref(ref p
, _
) => name_from_pat(&**p
),
4216 PatKind
::Lit(..) => {
4217 warn
!("tried to get argument name from PatKind::Lit, \
4218 which is silly in function arguments");
4221 PatKind
::Range(..) => panic
!("tried to get argument name from PatKind::Range, \
4222 which is not allowed in function arguments"),
4223 PatKind
::Slice(ref begin
, ref mid
, ref end
) => {
4224 let begin
= begin
.iter().map(|p
| name_from_pat(&**p
));
4225 let mid
= mid
.as_ref().map(|p
| format
!("..{}", name_from_pat(&**p
))).into_iter();
4226 let end
= end
.iter().map(|p
| name_from_pat(&**p
));
4227 format
!("[{}]", begin
.chain(mid
).chain(end
).collect
::<Vec
<_
>>().join(", "))
4232 fn print_const(cx
: &DocContext
<'_
>, n
: &ty
::Const
<'_
>) -> String
{
4234 ConstValue
::Unevaluated(def_id
, _
) => {
4235 if let Some(hir_id
) = cx
.tcx
.hir().as_local_hir_id(def_id
) {
4236 print_const_expr(cx
, cx
.tcx
.hir().body_owned_by(hir_id
))
4238 inline
::print_inlined_const(cx
, def_id
)
4242 let mut s
= n
.to_string();
4243 // array lengths are obviously usize
4244 if s
.ends_with("usize") {
4245 let n
= s
.len() - "usize".len();
4247 if s
.ends_with(": ") {
4248 let n
= s
.len() - ": ".len();
4257 fn print_const_expr(cx
: &DocContext
<'_
>, body
: hir
::BodyId
) -> String
{
4258 cx
.tcx
.hir().hir_to_pretty_string(body
.hir_id
)
4261 /// Given a type Path, resolve it to a Type using the TyCtxt
4262 fn resolve_type(cx
: &DocContext
<'_
>,
4264 id
: hir
::HirId
) -> Type
{
4265 if id
== hir
::DUMMY_HIR_ID
{
4266 debug
!("resolve_type({:?})", path
);
4268 debug
!("resolve_type({:?},{:?})", path
, id
);
4271 let is_generic
= match path
.res
{
4272 Res
::PrimTy(p
) => match p
{
4273 hir
::Str
=> return Primitive(PrimitiveType
::Str
),
4274 hir
::Bool
=> return Primitive(PrimitiveType
::Bool
),
4275 hir
::Char
=> return Primitive(PrimitiveType
::Char
),
4276 hir
::Int(int_ty
) => return Primitive(int_ty
.into()),
4277 hir
::Uint(uint_ty
) => return Primitive(uint_ty
.into()),
4278 hir
::Float(float_ty
) => return Primitive(float_ty
.into()),
4280 Res
::SelfTy(..) if path
.segments
.len() == 1 => {
4281 return Generic(kw
::SelfUpper
.to_string());
4283 Res
::Def(DefKind
::TyParam
, _
) if path
.segments
.len() == 1 => {
4284 return Generic(format
!("{:#}", path
.print()));
4287 | Res
::Def(DefKind
::TyParam
, _
)
4288 | Res
::Def(DefKind
::AssocTy
, _
) => true,
4291 let did
= register_res(&*cx
, path
.res
);
4292 ResolvedPath { path, param_names: None, did, is_generic }
4295 pub fn register_res(cx
: &DocContext
<'_
>, res
: Res
) -> DefId
{
4296 debug
!("register_res({:?})", res
);
4298 let (did
, kind
) = match res
{
4299 Res
::Def(DefKind
::Fn
, i
) => (i
, TypeKind
::Function
),
4300 Res
::Def(DefKind
::TyAlias
, i
) => (i
, TypeKind
::Typedef
),
4301 Res
::Def(DefKind
::Enum
, i
) => (i
, TypeKind
::Enum
),
4302 Res
::Def(DefKind
::Trait
, i
) => (i
, TypeKind
::Trait
),
4303 Res
::Def(DefKind
::Struct
, i
) => (i
, TypeKind
::Struct
),
4304 Res
::Def(DefKind
::Union
, i
) => (i
, TypeKind
::Union
),
4305 Res
::Def(DefKind
::Mod
, i
) => (i
, TypeKind
::Module
),
4306 Res
::Def(DefKind
::ForeignTy
, i
) => (i
, TypeKind
::Foreign
),
4307 Res
::Def(DefKind
::Const
, i
) => (i
, TypeKind
::Const
),
4308 Res
::Def(DefKind
::Static
, i
) => (i
, TypeKind
::Static
),
4309 Res
::Def(DefKind
::Variant
, i
) => (cx
.tcx
.parent(i
).expect("cannot get parent def id"),
4311 Res
::Def(DefKind
::Macro(mac_kind
), i
) => match mac_kind
{
4312 MacroKind
::Bang
=> (i
, TypeKind
::Macro
),
4313 MacroKind
::Attr
=> (i
, TypeKind
::Attr
),
4314 MacroKind
::Derive
=> (i
, TypeKind
::Derive
),
4316 Res
::Def(DefKind
::TraitAlias
, i
) => (i
, TypeKind
::TraitAlias
),
4317 Res
::SelfTy(Some(def_id
), _
) => (def_id
, TypeKind
::Trait
),
4318 Res
::SelfTy(_
, Some(impl_def_id
)) => return impl_def_id
,
4319 _
=> return res
.def_id()
4321 if did
.is_local() { return did }
4322 inline
::record_extern_fqn(cx
, did
, kind
);
4323 if let TypeKind
::Trait
= kind
{
4324 inline
::record_extern_trait(cx
, did
);
4329 fn resolve_use_source(cx
: &DocContext
<'_
>, path
: Path
) -> ImportSource
{
4331 did
: if path
.res
.opt_def_id().is_none() {
4334 Some(register_res(cx
, path
.res
))
4340 #[derive(Clone, Debug)]
4343 pub imported_from
: Option
<String
>,
4346 impl Clean
<Item
> for doctree
::Macro
<'_
> {
4347 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
4348 let name
= self.name
.clean(cx
);
4350 name
: Some(name
.clone()),
4351 attrs
: self.attrs
.clean(cx
),
4352 source
: self.whence
.clean(cx
),
4354 stability
: cx
.stability(self.hid
).clean(cx
),
4355 deprecation
: cx
.deprecation(self.hid
).clean(cx
),
4356 def_id
: self.def_id
,
4357 inner
: MacroItem(Macro
{
4358 source
: format
!("macro_rules! {} {{\n{}}}",
4360 self.matchers
.iter().map(|span
| {
4361 format
!(" {} => {{ ... }};\n", span
.to_src(cx
))
4362 }).collect
::<String
>()),
4363 imported_from
: self.imported_from
.clean(cx
),
4369 #[derive(Clone, Debug)]
4370 pub struct ProcMacro
{
4371 pub kind
: MacroKind
,
4372 pub helpers
: Vec
<String
>,
4375 impl Clean
<Item
> for doctree
::ProcMacro
<'_
> {
4376 fn clean(&self, cx
: &DocContext
<'_
>) -> Item
{
4378 name
: Some(self.name
.clean(cx
)),
4379 attrs
: self.attrs
.clean(cx
),
4380 source
: self.whence
.clean(cx
),
4382 stability
: cx
.stability(self.id
).clean(cx
),
4383 deprecation
: cx
.deprecation(self.id
).clean(cx
),
4384 def_id
: cx
.tcx
.hir().local_def_id(self.id
),
4385 inner
: ProcMacroItem(ProcMacro
{
4387 helpers
: self.helpers
.clean(cx
),
4393 #[derive(Clone, Debug)]
4394 pub struct Stability
{
4395 pub level
: stability
::StabilityLevel
,
4396 pub feature
: Option
<String
>,
4398 pub deprecation
: Option
<Deprecation
>,
4399 pub unstable_reason
: Option
<String
>,
4400 pub issue
: Option
<u32>,
4403 #[derive(Clone, Debug)]
4404 pub struct Deprecation
{
4405 pub since
: Option
<String
>,
4406 pub note
: Option
<String
>,
4409 impl Clean
<Stability
> for attr
::Stability
{
4410 fn clean(&self, _
: &DocContext
<'_
>) -> Stability
{
4412 level
: stability
::StabilityLevel
::from_attr_level(&self.level
),
4413 feature
: Some(self.feature
.to_string()).filter(|f
| !f
.is_empty()),
4414 since
: match self.level
{
4415 attr
::Stable {ref since}
=> since
.to_string(),
4418 deprecation
: self.rustc_depr
.as_ref().map(|d
| {
4420 note
: Some(d
.reason
.to_string()).filter(|r
| !r
.is_empty()),
4421 since
: Some(d
.since
.to_string()).filter(|d
| !d
.is_empty()),
4424 unstable_reason
: match self.level
{
4425 attr
::Unstable { reason: Some(ref reason), .. }
=> Some(reason
.to_string()),
4428 issue
: match self.level
{
4429 attr
::Unstable {issue, ..}
=> Some(issue
),
4436 impl<'a
> Clean
<Stability
> for &'a attr
::Stability
{
4437 fn clean(&self, dc
: &DocContext
<'_
>) -> Stability
{
4442 impl Clean
<Deprecation
> for attr
::Deprecation
{
4443 fn clean(&self, _
: &DocContext
<'_
>) -> Deprecation
{
4445 since
: self.since
.map(|s
| s
.to_string()).filter(|s
| !s
.is_empty()),
4446 note
: self.note
.map(|n
| n
.to_string()).filter(|n
| !n
.is_empty()),
4451 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
4452 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
4453 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
4454 pub struct TypeBinding
{
4456 pub kind
: TypeBindingKind
,
4459 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
4460 pub enum TypeBindingKind
{
4465 bounds
: Vec
<GenericBound
>,
4470 pub fn ty(&self) -> &Type
{
4472 TypeBindingKind
::Equality { ref ty }
=> ty
,
4473 _
=> panic
!("expected equality type binding for parenthesized generic args"),
4478 impl Clean
<TypeBinding
> for hir
::TypeBinding
{
4479 fn clean(&self, cx
: &DocContext
<'_
>) -> TypeBinding
{
4481 name
: self.ident
.name
.clean(cx
),
4482 kind
: self.kind
.clean(cx
),
4487 impl Clean
<TypeBindingKind
> for hir
::TypeBindingKind
{
4488 fn clean(&self, cx
: &DocContext
<'_
>) -> TypeBindingKind
{
4490 hir
::TypeBindingKind
::Equality { ref ty }
=>
4491 TypeBindingKind
::Equality
{
4494 hir
::TypeBindingKind
::Constraint { ref bounds }
=>
4495 TypeBindingKind
::Constraint
{
4496 bounds
: bounds
.into_iter().map(|b
| b
.clean(cx
)).collect(),
4502 pub fn enter_impl_trait
<F
, R
>(cx
: &DocContext
<'_
>, f
: F
) -> R
4506 let old_bounds
= mem
::take(&mut *cx
.impl_trait_bounds
.borrow_mut());
4508 assert
!(cx
.impl_trait_bounds
.borrow().is_empty());
4509 *cx
.impl_trait_bounds
.borrow_mut() = old_bounds
;
4513 #[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
4514 enum RegionTarget
<'tcx
> {
4515 Region(Region
<'tcx
>),
4516 RegionVid(RegionVid
)
4519 #[derive(Default, Debug, Clone)]
4520 struct RegionDeps
<'tcx
> {
4521 larger
: FxHashSet
<RegionTarget
<'tcx
>>,
4522 smaller
: FxHashSet
<RegionTarget
<'tcx
>>
4526 TraitBound(Vec
<PathSegment
>, Vec
<SimpleBound
>, Vec
<GenericParamDef
>, hir
::TraitBoundModifier
),
4530 impl From
<GenericBound
> for SimpleBound
{
4531 fn from(bound
: GenericBound
) -> Self {
4532 match bound
.clone() {
4533 GenericBound
::Outlives(l
) => SimpleBound
::Outlives(l
),
4534 GenericBound
::TraitBound(t
, mod_
) => match t
.trait_
{
4535 Type
::ResolvedPath { path, param_names, .. }
=> {
4536 SimpleBound
::TraitBound(path
.segments
,
4538 .map_or_else(|| Vec
::new(), |v
| v
.iter()
4539 .map(|p
| SimpleBound
::from(p
.clone()))
4544 _
=> panic
!("Unexpected bound {:?}", bound
),