]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/clean/types.rs
Rollup merge of #89256 - danielg1111:fix_typo, r=Mark-Simulacrum
[rust.git] / src / librustdoc / clean / types.rs
1 use std::cell::RefCell;
2 use std::default::Default;
3 use std::hash::{Hash, Hasher};
4 use std::iter::FromIterator;
5 use std::lazy::SyncOnceCell as OnceCell;
6 use std::path::PathBuf;
7 use std::rc::Rc;
8 use std::sync::Arc;
9 use std::{slice, vec};
10
11 use arrayvec::ArrayVec;
12
13 use rustc_ast::attr;
14 use rustc_ast::util::comments::beautify_doc_string;
15 use rustc_ast::{self as ast, AttrStyle};
16 use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
17 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
18 use rustc_data_structures::thin_vec::ThinVec;
19 use rustc_hir as hir;
20 use rustc_hir::def::{CtorKind, DefKind, Res};
21 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
22 use rustc_hir::lang_items::LangItem;
23 use rustc_hir::{BodyId, Mutability};
24 use rustc_index::vec::IndexVec;
25 use rustc_middle::ty::{self, TyCtxt};
26 use rustc_session::Session;
27 use rustc_span::hygiene::MacroKind;
28 use rustc_span::source_map::DUMMY_SP;
29 use rustc_span::symbol::{kw, sym, Ident, Symbol, SymbolStr};
30 use rustc_span::{self, FileName, Loc};
31 use rustc_target::abi::VariantIdx;
32 use rustc_target::spec::abi::Abi;
33
34 use crate::clean::cfg::Cfg;
35 use crate::clean::external_path;
36 use crate::clean::inline::{self, print_inlined_const};
37 use crate::clean::types::Type::{QPath, ResolvedPath};
38 use crate::clean::utils::{is_literal_expr, print_const_expr, print_evaluated_const};
39 use crate::clean::Clean;
40 use crate::core::DocContext;
41 use crate::formats::cache::Cache;
42 use crate::formats::item_type::ItemType;
43 use crate::html::render::cache::ExternalLocation;
44 use crate::html::render::Context;
45
46 use self::FnRetTy::*;
47 use self::ItemKind::*;
48 use self::SelfTy::*;
49 use self::Type::*;
50
51 crate type ItemIdSet = FxHashSet<ItemId>;
52
53 #[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
54 crate enum ItemId {
55     /// A "normal" item that uses a [`DefId`] for identification.
56     DefId(DefId),
57     /// Identifier that is used for auto traits.
58     Auto { trait_: DefId, for_: DefId },
59     /// Identifier that is used for blanket implementations.
60     Blanket { impl_id: DefId, for_: DefId },
61     /// Identifier for primitive types.
62     Primitive(PrimitiveType, CrateNum),
63 }
64
65 impl ItemId {
66     #[inline]
67     crate fn is_local(self) -> bool {
68         match self {
69             ItemId::Auto { for_: id, .. }
70             | ItemId::Blanket { for_: id, .. }
71             | ItemId::DefId(id) => id.is_local(),
72             ItemId::Primitive(_, krate) => krate == LOCAL_CRATE,
73         }
74     }
75
76     #[inline]
77     #[track_caller]
78     crate fn expect_def_id(self) -> DefId {
79         self.as_def_id()
80             .unwrap_or_else(|| panic!("ItemId::expect_def_id: `{:?}` isn't a DefId", self))
81     }
82
83     #[inline]
84     crate fn as_def_id(self) -> Option<DefId> {
85         match self {
86             ItemId::DefId(id) => Some(id),
87             _ => None,
88         }
89     }
90
91     #[inline]
92     crate fn krate(self) -> CrateNum {
93         match self {
94             ItemId::Auto { for_: id, .. }
95             | ItemId::Blanket { for_: id, .. }
96             | ItemId::DefId(id) => id.krate,
97             ItemId::Primitive(_, krate) => krate,
98         }
99     }
100
101     #[inline]
102     crate fn index(self) -> Option<DefIndex> {
103         match self {
104             ItemId::DefId(id) => Some(id.index),
105             _ => None,
106         }
107     }
108 }
109
110 impl From<DefId> for ItemId {
111     fn from(id: DefId) -> Self {
112         Self::DefId(id)
113     }
114 }
115
116 #[derive(Clone, Debug)]
117 crate struct Crate {
118     crate name: Symbol,
119     crate src: FileName,
120     crate module: Item,
121     crate externs: Vec<ExternalCrate>,
122     crate primitives: ThinVec<(DefId, PrimitiveType)>,
123     // These are later on moved into `CACHEKEY`, leaving the map empty.
124     // Only here so that they can be filtered through the rustdoc passes.
125     crate external_traits: Rc<RefCell<FxHashMap<DefId, TraitWithExtraInfo>>>,
126     crate collapsed: bool,
127 }
128
129 /// This struct is used to wrap additional information added by rustdoc on a `trait` item.
130 #[derive(Clone, Debug)]
131 crate struct TraitWithExtraInfo {
132     crate trait_: Trait,
133     crate is_notable: bool,
134 }
135
136 #[derive(Copy, Clone, Debug)]
137 crate struct ExternalCrate {
138     crate crate_num: CrateNum,
139 }
140
141 impl ExternalCrate {
142     #[inline]
143     crate fn def_id(&self) -> DefId {
144         DefId { krate: self.crate_num, index: CRATE_DEF_INDEX }
145     }
146
147     crate fn src(&self, tcx: TyCtxt<'_>) -> FileName {
148         let krate_span = tcx.def_span(self.def_id());
149         tcx.sess.source_map().span_to_filename(krate_span)
150     }
151
152     crate fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
153         tcx.crate_name(self.crate_num)
154     }
155
156     crate fn src_root(&self, tcx: TyCtxt<'_>) -> PathBuf {
157         match self.src(tcx) {
158             FileName::Real(ref p) => match p.local_path_if_available().parent() {
159                 Some(p) => p.to_path_buf(),
160                 None => PathBuf::new(),
161             },
162             _ => PathBuf::new(),
163         }
164     }
165
166     /// Attempts to find where an external crate is located, given that we're
167     /// rendering in to the specified source destination.
168     crate fn location(
169         &self,
170         extern_url: Option<&str>,
171         extern_url_takes_precedence: bool,
172         dst: &std::path::Path,
173         tcx: TyCtxt<'_>,
174     ) -> ExternalLocation {
175         use ExternalLocation::*;
176
177         fn to_remote(url: impl ToString) -> ExternalLocation {
178             let mut url = url.to_string();
179             if !url.ends_with('/') {
180                 url.push('/');
181             }
182             Remote(url)
183         }
184
185         // See if there's documentation generated into the local directory
186         // WARNING: since rustdoc creates these directories as it generates documentation, this check is only accurate before rendering starts.
187         // Make sure to call `location()` by that time.
188         let local_location = dst.join(&*self.name(tcx).as_str());
189         if local_location.is_dir() {
190             return Local;
191         }
192
193         if extern_url_takes_precedence {
194             if let Some(url) = extern_url {
195                 return to_remote(url);
196             }
197         }
198
199         // Failing that, see if there's an attribute specifying where to find this
200         // external crate
201         let did = DefId { krate: self.crate_num, index: CRATE_DEF_INDEX };
202         tcx.get_attrs(did)
203             .lists(sym::doc)
204             .filter(|a| a.has_name(sym::html_root_url))
205             .filter_map(|a| a.value_str())
206             .map(to_remote)
207             .next()
208             .or(extern_url.map(to_remote)) // NOTE: only matters if `extern_url_takes_precedence` is false
209             .unwrap_or(Unknown) // Well, at least we tried.
210     }
211
212     crate fn keywords(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, Symbol)> {
213         let root = self.def_id();
214
215         let as_keyword = |res: Res<!>| {
216             if let Res::Def(DefKind::Mod, def_id) = res {
217                 let attrs = tcx.get_attrs(def_id);
218                 let mut keyword = None;
219                 for attr in attrs.lists(sym::doc) {
220                     if attr.has_name(sym::keyword) {
221                         if let Some(v) = attr.value_str() {
222                             keyword = Some(v);
223                             break;
224                         }
225                     }
226                 }
227                 return keyword.map(|p| (def_id, p));
228             }
229             None
230         };
231         if root.is_local() {
232             tcx.hir()
233                 .krate()
234                 .module()
235                 .item_ids
236                 .iter()
237                 .filter_map(|&id| {
238                     let item = tcx.hir().item(id);
239                     match item.kind {
240                         hir::ItemKind::Mod(_) => {
241                             as_keyword(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
242                         }
243                         hir::ItemKind::Use(ref path, hir::UseKind::Single)
244                             if item.vis.node.is_pub() =>
245                         {
246                             as_keyword(path.res.expect_non_local())
247                                 .map(|(_, prim)| (id.def_id.to_def_id(), prim))
248                         }
249                         _ => None,
250                     }
251                 })
252                 .collect()
253         } else {
254             tcx.item_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect()
255         }
256     }
257
258     crate fn primitives(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, PrimitiveType)> {
259         let root = self.def_id();
260
261         // Collect all inner modules which are tagged as implementations of
262         // primitives.
263         //
264         // Note that this loop only searches the top-level items of the crate,
265         // and this is intentional. If we were to search the entire crate for an
266         // item tagged with `#[doc(primitive)]` then we would also have to
267         // search the entirety of external modules for items tagged
268         // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
269         // all that metadata unconditionally).
270         //
271         // In order to keep the metadata load under control, the
272         // `#[doc(primitive)]` feature is explicitly designed to only allow the
273         // primitive tags to show up as the top level items in a crate.
274         //
275         // Also note that this does not attempt to deal with modules tagged
276         // duplicately for the same primitive. This is handled later on when
277         // rendering by delegating everything to a hash map.
278         let as_primitive = |res: Res<!>| {
279             if let Res::Def(DefKind::Mod, def_id) = res {
280                 let attrs = tcx.get_attrs(def_id);
281                 let mut prim = None;
282                 for attr in attrs.lists(sym::doc) {
283                     if let Some(v) = attr.value_str() {
284                         if attr.has_name(sym::primitive) {
285                             prim = PrimitiveType::from_symbol(v);
286                             if prim.is_some() {
287                                 break;
288                             }
289                             // FIXME: should warn on unknown primitives?
290                         }
291                     }
292                 }
293                 return prim.map(|p| (def_id, p));
294             }
295             None
296         };
297
298         if root.is_local() {
299             tcx.hir()
300                 .krate()
301                 .module()
302                 .item_ids
303                 .iter()
304                 .filter_map(|&id| {
305                     let item = tcx.hir().item(id);
306                     match item.kind {
307                         hir::ItemKind::Mod(_) => {
308                             as_primitive(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
309                         }
310                         hir::ItemKind::Use(ref path, hir::UseKind::Single)
311                             if item.vis.node.is_pub() =>
312                         {
313                             as_primitive(path.res.expect_non_local()).map(|(_, prim)| {
314                                 // Pretend the primitive is local.
315                                 (id.def_id.to_def_id(), prim)
316                             })
317                         }
318                         _ => None,
319                     }
320                 })
321                 .collect()
322         } else {
323             tcx.item_children(root).iter().map(|item| item.res).filter_map(as_primitive).collect()
324         }
325     }
326 }
327
328 /// Anything with a source location and set of attributes and, optionally, a
329 /// name. That is, anything that can be documented. This doesn't correspond
330 /// directly to the AST's concept of an item; it's a strict superset.
331 #[derive(Clone, Debug)]
332 crate struct Item {
333     /// The name of this item.
334     /// Optional because not every item has a name, e.g. impls.
335     crate name: Option<Symbol>,
336     crate attrs: Box<Attributes>,
337     crate visibility: Visibility,
338     /// Information about this item that is specific to what kind of item it is.
339     /// E.g., struct vs enum vs function.
340     crate kind: Box<ItemKind>,
341     crate def_id: ItemId,
342
343     crate cfg: Option<Arc<Cfg>>,
344 }
345
346 // `Item` is used a lot. Make sure it doesn't unintentionally get bigger.
347 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
348 rustc_data_structures::static_assert_size!(Item, 56);
349
350 crate fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
351     Span::new(def_id.as_local().map_or_else(
352         || tcx.def_span(def_id),
353         |local| {
354             let hir = tcx.hir();
355             hir.span_with_body(hir.local_def_id_to_hir_id(local))
356         },
357     ))
358 }
359
360 impl Item {
361     crate fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx Stability> {
362         self.def_id.as_def_id().and_then(|did| tcx.lookup_stability(did))
363     }
364
365     crate fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ConstStability> {
366         self.def_id.as_def_id().and_then(|did| tcx.lookup_const_stability(did))
367     }
368
369     crate fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
370         self.def_id.as_def_id().and_then(|did| tcx.lookup_deprecation(did))
371     }
372
373     crate fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
374         self.def_id.as_def_id().map(|did| tcx.get_attrs(did).inner_docs()).unwrap_or(false)
375     }
376
377     crate fn span(&self, tcx: TyCtxt<'_>) -> Span {
378         let kind = match &*self.kind {
379             ItemKind::StrippedItem(k) => k,
380             _ => &*self.kind,
381         };
382         if let ItemKind::ModuleItem(Module { span, .. }) | ItemKind::ImplItem(Impl { span, .. }) =
383             kind
384         {
385             *span
386         } else {
387             self.def_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(|| Span::dummy())
388         }
389     }
390
391     crate fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
392         crate::passes::span_of_attrs(&self.attrs).unwrap_or_else(|| self.span(tcx).inner())
393     }
394
395     /// Finds the `doc` attribute as a NameValue and returns the corresponding
396     /// value found.
397     crate fn doc_value(&self) -> Option<String> {
398         self.attrs.doc_value()
399     }
400
401     /// Convenience wrapper around [`Self::from_def_id_and_parts`] which converts
402     /// `hir_id` to a [`DefId`]
403     pub fn from_hir_id_and_parts(
404         hir_id: hir::HirId,
405         name: Option<Symbol>,
406         kind: ItemKind,
407         cx: &mut DocContext<'_>,
408     ) -> Item {
409         Item::from_def_id_and_parts(cx.tcx.hir().local_def_id(hir_id).to_def_id(), name, kind, cx)
410     }
411
412     pub fn from_def_id_and_parts(
413         def_id: DefId,
414         name: Option<Symbol>,
415         kind: ItemKind,
416         cx: &mut DocContext<'_>,
417     ) -> Item {
418         let ast_attrs = cx.tcx.get_attrs(def_id);
419
420         Self::from_def_id_and_attrs_and_parts(
421             def_id,
422             name,
423             kind,
424             box ast_attrs.clean(cx),
425             cx,
426             ast_attrs.cfg(cx.sess()),
427         )
428     }
429
430     pub fn from_def_id_and_attrs_and_parts(
431         def_id: DefId,
432         name: Option<Symbol>,
433         kind: ItemKind,
434         attrs: Box<Attributes>,
435         cx: &mut DocContext<'_>,
436         cfg: Option<Arc<Cfg>>,
437     ) -> Item {
438         trace!("name={:?}, def_id={:?}", name, def_id);
439
440         Item {
441             def_id: def_id.into(),
442             kind: box kind,
443             name,
444             attrs,
445             visibility: cx.tcx.visibility(def_id).clean(cx),
446             cfg,
447         }
448     }
449
450     /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
451     /// with newlines.
452     crate fn collapsed_doc_value(&self) -> Option<String> {
453         self.attrs.collapsed_doc_value()
454     }
455
456     crate fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
457         use crate::html::format::href;
458
459         cx.cache()
460             .intra_doc_links
461             .get(&self.def_id)
462             .map_or(&[][..], |v| v.as_slice())
463             .iter()
464             .filter_map(|ItemLink { link: s, link_text, did, ref fragment }| {
465                 debug!(?did);
466                 if let Ok((mut href, ..)) = href(*did, cx) {
467                     debug!(?href);
468                     if let Some(ref fragment) = *fragment {
469                         href.push('#');
470                         href.push_str(fragment);
471                     }
472                     Some(RenderedLink {
473                         original_text: s.clone(),
474                         new_text: link_text.clone(),
475                         href,
476                     })
477                 } else {
478                     None
479                 }
480             })
481             .collect()
482     }
483
484     /// Find a list of all link names, without finding their href.
485     ///
486     /// This is used for generating summary text, which does not include
487     /// the link text, but does need to know which `[]`-bracketed names
488     /// are actually links.
489     crate fn link_names(&self, cache: &Cache) -> Vec<RenderedLink> {
490         cache
491             .intra_doc_links
492             .get(&self.def_id)
493             .map_or(&[][..], |v| v.as_slice())
494             .iter()
495             .map(|ItemLink { link: s, link_text, .. }| RenderedLink {
496                 original_text: s.clone(),
497                 new_text: link_text.clone(),
498                 href: String::new(),
499             })
500             .collect()
501     }
502
503     crate fn is_crate(&self) -> bool {
504         self.is_mod() && self.def_id.as_def_id().map_or(false, |did| did.index == CRATE_DEF_INDEX)
505     }
506     crate fn is_mod(&self) -> bool {
507         self.type_() == ItemType::Module
508     }
509     crate fn is_trait(&self) -> bool {
510         self.type_() == ItemType::Trait
511     }
512     crate fn is_struct(&self) -> bool {
513         self.type_() == ItemType::Struct
514     }
515     crate fn is_enum(&self) -> bool {
516         self.type_() == ItemType::Enum
517     }
518     crate fn is_variant(&self) -> bool {
519         self.type_() == ItemType::Variant
520     }
521     crate fn is_associated_type(&self) -> bool {
522         self.type_() == ItemType::AssocType
523     }
524     crate fn is_associated_const(&self) -> bool {
525         self.type_() == ItemType::AssocConst
526     }
527     crate fn is_method(&self) -> bool {
528         self.type_() == ItemType::Method
529     }
530     crate fn is_ty_method(&self) -> bool {
531         self.type_() == ItemType::TyMethod
532     }
533     crate fn is_typedef(&self) -> bool {
534         self.type_() == ItemType::Typedef
535     }
536     crate fn is_primitive(&self) -> bool {
537         self.type_() == ItemType::Primitive
538     }
539     crate fn is_union(&self) -> bool {
540         self.type_() == ItemType::Union
541     }
542     crate fn is_import(&self) -> bool {
543         self.type_() == ItemType::Import
544     }
545     crate fn is_extern_crate(&self) -> bool {
546         self.type_() == ItemType::ExternCrate
547     }
548     crate fn is_keyword(&self) -> bool {
549         self.type_() == ItemType::Keyword
550     }
551     crate fn is_stripped(&self) -> bool {
552         match *self.kind {
553             StrippedItem(..) => true,
554             ImportItem(ref i) => !i.should_be_displayed,
555             _ => false,
556         }
557     }
558     crate fn has_stripped_fields(&self) -> Option<bool> {
559         match *self.kind {
560             StructItem(ref _struct) => Some(_struct.fields_stripped),
561             UnionItem(ref union) => Some(union.fields_stripped),
562             VariantItem(Variant::Struct(ref vstruct)) => Some(vstruct.fields_stripped),
563             _ => None,
564         }
565     }
566
567     crate fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
568         self.stability(tcx).as_ref().and_then(|ref s| {
569             let mut classes = Vec::with_capacity(2);
570
571             if s.level.is_unstable() {
572                 classes.push("unstable");
573             }
574
575             // FIXME: what about non-staged API items that are deprecated?
576             if self.deprecation(tcx).is_some() {
577                 classes.push("deprecated");
578             }
579
580             if !classes.is_empty() { Some(classes.join(" ")) } else { None }
581         })
582     }
583
584     crate fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
585         match self.stability(tcx)?.level {
586             StabilityLevel::Stable { since, .. } => Some(since.as_str()),
587             StabilityLevel::Unstable { .. } => None,
588         }
589     }
590
591     crate fn const_stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
592         match self.const_stability(tcx)?.level {
593             StabilityLevel::Stable { since, .. } => Some(since.as_str()),
594             StabilityLevel::Unstable { .. } => None,
595         }
596     }
597
598     crate fn is_non_exhaustive(&self) -> bool {
599         self.attrs.other_attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
600     }
601
602     /// Returns a documentation-level item type from the item.
603     crate fn type_(&self) -> ItemType {
604         ItemType::from(self)
605     }
606
607     crate fn is_default(&self) -> bool {
608         match *self.kind {
609             ItemKind::MethodItem(_, Some(defaultness)) => {
610                 defaultness.has_value() && !defaultness.is_final()
611             }
612             _ => false,
613         }
614     }
615 }
616
617 #[derive(Clone, Debug)]
618 crate enum ItemKind {
619     ExternCrateItem {
620         /// The crate's name, *not* the name it's imported as.
621         src: Option<Symbol>,
622     },
623     ImportItem(Import),
624     StructItem(Struct),
625     UnionItem(Union),
626     EnumItem(Enum),
627     FunctionItem(Function),
628     ModuleItem(Module),
629     TypedefItem(Typedef, bool /* is associated type */),
630     OpaqueTyItem(OpaqueTy),
631     StaticItem(Static),
632     ConstantItem(Constant),
633     TraitItem(Trait),
634     TraitAliasItem(TraitAlias),
635     ImplItem(Impl),
636     /// A method signature only. Used for required methods in traits (ie,
637     /// non-default-methods).
638     TyMethodItem(Function),
639     /// A method with a body.
640     MethodItem(Function, Option<hir::Defaultness>),
641     StructFieldItem(Type),
642     VariantItem(Variant),
643     /// `fn`s from an extern block
644     ForeignFunctionItem(Function),
645     /// `static`s from an extern block
646     ForeignStaticItem(Static),
647     /// `type`s from an extern block
648     ForeignTypeItem,
649     MacroItem(Macro),
650     ProcMacroItem(ProcMacro),
651     PrimitiveItem(PrimitiveType),
652     AssocConstItem(Type, Option<String>),
653     /// An associated item in a trait or trait impl.
654     ///
655     /// The bounds may be non-empty if there is a `where` clause.
656     /// The `Option<Type>` is the default concrete type (e.g. `trait Trait { type Target = usize; }`)
657     AssocTypeItem(Vec<GenericBound>, Option<Type>),
658     /// An item that has been stripped by a rustdoc pass
659     StrippedItem(Box<ItemKind>),
660     KeywordItem(Symbol),
661 }
662
663 impl ItemKind {
664     /// Some items contain others such as structs (for their fields) and Enums
665     /// (for their variants). This method returns those contained items.
666     crate fn inner_items(&self) -> impl Iterator<Item = &Item> {
667         match self {
668             StructItem(s) => s.fields.iter(),
669             UnionItem(u) => u.fields.iter(),
670             VariantItem(Variant::Struct(v)) => v.fields.iter(),
671             VariantItem(Variant::Tuple(v)) => v.iter(),
672             EnumItem(e) => e.variants.iter(),
673             TraitItem(t) => t.items.iter(),
674             ImplItem(i) => i.items.iter(),
675             ModuleItem(m) => m.items.iter(),
676             ExternCrateItem { .. }
677             | ImportItem(_)
678             | FunctionItem(_)
679             | TypedefItem(_, _)
680             | OpaqueTyItem(_)
681             | StaticItem(_)
682             | ConstantItem(_)
683             | TraitAliasItem(_)
684             | TyMethodItem(_)
685             | MethodItem(_, _)
686             | StructFieldItem(_)
687             | VariantItem(_)
688             | ForeignFunctionItem(_)
689             | ForeignStaticItem(_)
690             | ForeignTypeItem
691             | MacroItem(_)
692             | ProcMacroItem(_)
693             | PrimitiveItem(_)
694             | AssocConstItem(_, _)
695             | AssocTypeItem(_, _)
696             | StrippedItem(_)
697             | KeywordItem(_) => [].iter(),
698         }
699     }
700 }
701
702 #[derive(Clone, Debug)]
703 crate struct Module {
704     crate items: Vec<Item>,
705     crate span: Span,
706 }
707
708 crate struct ListAttributesIter<'a> {
709     attrs: slice::Iter<'a, ast::Attribute>,
710     current_list: vec::IntoIter<ast::NestedMetaItem>,
711     name: Symbol,
712 }
713
714 impl<'a> Iterator for ListAttributesIter<'a> {
715     type Item = ast::NestedMetaItem;
716
717     fn next(&mut self) -> Option<Self::Item> {
718         if let Some(nested) = self.current_list.next() {
719             return Some(nested);
720         }
721
722         for attr in &mut self.attrs {
723             if let Some(list) = attr.meta_item_list() {
724                 if attr.has_name(self.name) {
725                     self.current_list = list.into_iter();
726                     if let Some(nested) = self.current_list.next() {
727                         return Some(nested);
728                     }
729                 }
730             }
731         }
732
733         None
734     }
735
736     fn size_hint(&self) -> (usize, Option<usize>) {
737         let lower = self.current_list.len();
738         (lower, None)
739     }
740 }
741
742 crate trait AttributesExt {
743     /// Finds an attribute as List and returns the list of attributes nested inside.
744     fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
745
746     fn span(&self) -> Option<rustc_span::Span>;
747
748     fn inner_docs(&self) -> bool;
749
750     fn other_attrs(&self) -> Vec<ast::Attribute>;
751
752     fn cfg(&self, sess: &Session) -> Option<Arc<Cfg>>;
753 }
754
755 impl AttributesExt for [ast::Attribute] {
756     fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
757         ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), name }
758     }
759
760     /// Return the span of the first doc-comment, if it exists.
761     fn span(&self) -> Option<rustc_span::Span> {
762         self.iter().find(|attr| attr.doc_str().is_some()).map(|attr| attr.span)
763     }
764
765     /// Returns whether the first doc-comment is an inner attribute.
766     ///
767     //// If there are no doc-comments, return true.
768     /// FIXME(#78591): Support both inner and outer attributes on the same item.
769     fn inner_docs(&self) -> bool {
770         self.iter().find(|a| a.doc_str().is_some()).map_or(true, |a| a.style == AttrStyle::Inner)
771     }
772
773     fn other_attrs(&self) -> Vec<ast::Attribute> {
774         self.iter().filter(|attr| attr.doc_str().is_none()).cloned().collect()
775     }
776
777     fn cfg(&self, sess: &Session) -> Option<Arc<Cfg>> {
778         let mut cfg = Cfg::True;
779
780         for attr in self.iter() {
781             // #[doc]
782             if attr.doc_str().is_none() && attr.has_name(sym::doc) {
783                 // #[doc(...)]
784                 if let Some(list) = attr.meta().as_ref().and_then(|mi| mi.meta_item_list()) {
785                     for item in list {
786                         // #[doc(hidden)]
787                         if !item.has_name(sym::cfg) {
788                             continue;
789                         }
790                         // #[doc(cfg(...))]
791                         if let Some(cfg_mi) = item
792                             .meta_item()
793                             .and_then(|item| rustc_expand::config::parse_cfg(&item, sess))
794                         {
795                             match Cfg::parse(&cfg_mi) {
796                                 Ok(new_cfg) => cfg &= new_cfg,
797                                 Err(e) => sess.span_err(e.span, e.msg),
798                             }
799                         }
800                     }
801                 }
802             }
803         }
804
805         for attr in self.lists(sym::target_feature) {
806             if attr.has_name(sym::enable) {
807                 if let Some(feat) = attr.value_str() {
808                     let meta = attr::mk_name_value_item_str(
809                         Ident::with_dummy_span(sym::target_feature),
810                         feat,
811                         DUMMY_SP,
812                     );
813                     if let Ok(feat_cfg) = Cfg::parse(&meta) {
814                         cfg &= feat_cfg;
815                     }
816                 }
817             }
818         }
819
820         if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) }
821     }
822 }
823
824 crate trait NestedAttributesExt {
825     /// Returns `true` if the attribute list contains a specific `Word`
826     fn has_word(self, word: Symbol) -> bool;
827     fn get_word_attr(self, word: Symbol) -> Option<ast::NestedMetaItem>;
828 }
829
830 impl<I: Iterator<Item = ast::NestedMetaItem> + IntoIterator<Item = ast::NestedMetaItem>>
831     NestedAttributesExt for I
832 {
833     fn has_word(self, word: Symbol) -> bool {
834         self.into_iter().any(|attr| attr.is_word() && attr.has_name(word))
835     }
836
837     fn get_word_attr(mut self, word: Symbol) -> Option<ast::NestedMetaItem> {
838         self.find(|attr| attr.is_word() && attr.has_name(word))
839     }
840 }
841
842 /// A portion of documentation, extracted from a `#[doc]` attribute.
843 ///
844 /// Each variant contains the line number within the complete doc-comment where the fragment
845 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
846 ///
847 /// Included files are kept separate from inline doc comments so that proper line-number
848 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
849 /// kept separate because of issue #42760.
850 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
851 crate struct DocFragment {
852     crate line: usize,
853     crate span: rustc_span::Span,
854     /// The module this doc-comment came from.
855     ///
856     /// This allows distinguishing between the original documentation and a pub re-export.
857     /// If it is `None`, the item was not re-exported.
858     crate parent_module: Option<DefId>,
859     crate doc: Symbol,
860     crate kind: DocFragmentKind,
861     crate need_backline: bool,
862     crate indent: usize,
863 }
864
865 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
866 crate enum DocFragmentKind {
867     /// A doc fragment created from a `///` or `//!` doc comment.
868     SugaredDoc,
869     /// A doc fragment created from a "raw" `#[doc=""]` attribute.
870     RawDoc,
871 }
872
873 // The goal of this function is to apply the `DocFragment` transformations that are required when
874 // transforming into the final markdown. So the transformations in here are:
875 //
876 // * Applying the computed indent to each lines in each doc fragment (a `DocFragment` can contain
877 //   multiple lines in case of `#[doc = ""]`).
878 // * Adding backlines between `DocFragment`s and adding an extra one if required (stored in the
879 //   `need_backline` field).
880 fn add_doc_fragment(out: &mut String, frag: &DocFragment) {
881     let s = frag.doc.as_str();
882     let mut iter = s.lines().peekable();
883     while let Some(line) = iter.next() {
884         if line.chars().any(|c| !c.is_whitespace()) {
885             assert!(line.len() >= frag.indent);
886             out.push_str(&line[frag.indent..]);
887         } else {
888             out.push_str(line);
889         }
890         if iter.peek().is_some() {
891             out.push('\n');
892         }
893     }
894     if frag.need_backline {
895         out.push('\n');
896     }
897 }
898
899 impl<'a> FromIterator<&'a DocFragment> for String {
900     fn from_iter<T>(iter: T) -> Self
901     where
902         T: IntoIterator<Item = &'a DocFragment>,
903     {
904         iter.into_iter().fold(String::new(), |mut acc, frag| {
905             add_doc_fragment(&mut acc, &frag);
906             acc
907         })
908     }
909 }
910
911 /// The attributes on an [`Item`], including attributes like `#[derive(...)]` and `#[inline]`,
912 /// as well as doc comments.
913 #[derive(Clone, Debug, Default)]
914 crate struct Attributes {
915     crate doc_strings: Vec<DocFragment>,
916     crate other_attrs: Vec<ast::Attribute>,
917 }
918
919 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
920 /// A link that has not yet been rendered.
921 ///
922 /// This link will be turned into a rendered link by [`Item::links`].
923 crate struct ItemLink {
924     /// The original link written in the markdown
925     pub(crate) link: String,
926     /// The link text displayed in the HTML.
927     ///
928     /// This may not be the same as `link` if there was a disambiguator
929     /// in an intra-doc link (e.g. \[`fn@f`\])
930     pub(crate) link_text: String,
931     pub(crate) did: DefId,
932     /// The url fragment to append to the link
933     pub(crate) fragment: Option<String>,
934 }
935
936 pub struct RenderedLink {
937     /// The text the link was original written as.
938     ///
939     /// This could potentially include disambiguators and backticks.
940     pub(crate) original_text: String,
941     /// The text to display in the HTML
942     pub(crate) new_text: String,
943     /// The URL to put in the `href`
944     pub(crate) href: String,
945 }
946
947 impl Attributes {
948     crate fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
949         self.other_attrs.lists(name)
950     }
951
952     crate fn has_doc_flag(&self, flag: Symbol) -> bool {
953         for attr in &self.other_attrs {
954             if !attr.has_name(sym::doc) {
955                 continue;
956             }
957
958             if let Some(items) = attr.meta_item_list() {
959                 if items.iter().filter_map(|i| i.meta_item()).any(|it| it.has_name(flag)) {
960                     return true;
961                 }
962             }
963         }
964
965         false
966     }
967
968     crate fn from_ast(
969         attrs: &[ast::Attribute],
970         additional_attrs: Option<(&[ast::Attribute], DefId)>,
971     ) -> Attributes {
972         let mut doc_strings: Vec<DocFragment> = vec![];
973         let mut doc_line = 0;
974
975         fn update_need_backline(doc_strings: &mut Vec<DocFragment>) {
976             if let Some(prev) = doc_strings.last_mut() {
977                 prev.need_backline = true;
978             }
979         }
980
981         let clean_attr = |(attr, parent_module): (&ast::Attribute, Option<DefId>)| {
982             if let Some(value) = attr.doc_str() {
983                 trace!("got doc_str={:?}", value);
984                 let value = beautify_doc_string(value);
985                 let kind = if attr.is_doc_comment() {
986                     DocFragmentKind::SugaredDoc
987                 } else {
988                     DocFragmentKind::RawDoc
989                 };
990
991                 let line = doc_line;
992                 doc_line += value.as_str().lines().count();
993                 let frag = DocFragment {
994                     line,
995                     span: attr.span,
996                     doc: value,
997                     kind,
998                     parent_module,
999                     need_backline: false,
1000                     indent: 0,
1001                 };
1002
1003                 update_need_backline(&mut doc_strings);
1004
1005                 doc_strings.push(frag);
1006
1007                 None
1008             } else {
1009                 Some(attr.clone())
1010             }
1011         };
1012
1013         // Additional documentation should be shown before the original documentation
1014         let other_attrs = additional_attrs
1015             .into_iter()
1016             .map(|(attrs, id)| attrs.iter().map(move |attr| (attr, Some(id))))
1017             .flatten()
1018             .chain(attrs.iter().map(|attr| (attr, None)))
1019             .filter_map(clean_attr)
1020             .collect();
1021
1022         Attributes { doc_strings, other_attrs }
1023     }
1024
1025     /// Finds the `doc` attribute as a NameValue and returns the corresponding
1026     /// value found.
1027     crate fn doc_value(&self) -> Option<String> {
1028         let mut iter = self.doc_strings.iter();
1029
1030         let ori = iter.next()?;
1031         let mut out = String::new();
1032         add_doc_fragment(&mut out, &ori);
1033         while let Some(new_frag) = iter.next() {
1034             if new_frag.kind != ori.kind || new_frag.parent_module != ori.parent_module {
1035                 break;
1036             }
1037             add_doc_fragment(&mut out, &new_frag);
1038         }
1039         if out.is_empty() { None } else { Some(out) }
1040     }
1041
1042     /// Return the doc-comments on this item, grouped by the module they came from.
1043     ///
1044     /// The module can be different if this is a re-export with added documentation.
1045     crate fn collapsed_doc_value_by_module_level(&self) -> FxHashMap<Option<DefId>, String> {
1046         let mut ret = FxHashMap::default();
1047
1048         for new_frag in self.doc_strings.iter() {
1049             let out = ret.entry(new_frag.parent_module).or_default();
1050             add_doc_fragment(out, &new_frag);
1051         }
1052         ret
1053     }
1054
1055     /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
1056     /// with newlines.
1057     crate fn collapsed_doc_value(&self) -> Option<String> {
1058         if self.doc_strings.is_empty() { None } else { Some(self.doc_strings.iter().collect()) }
1059     }
1060
1061     crate fn get_doc_aliases(&self) -> Box<[String]> {
1062         let mut aliases = FxHashSet::default();
1063
1064         for attr in self.other_attrs.lists(sym::doc).filter(|a| a.has_name(sym::alias)) {
1065             if let Some(values) = attr.meta_item_list() {
1066                 for l in values {
1067                     match l.literal().unwrap().kind {
1068                         ast::LitKind::Str(s, _) => {
1069                             aliases.insert(s.as_str().to_string());
1070                         }
1071                         _ => unreachable!(),
1072                     }
1073                 }
1074             } else {
1075                 aliases.insert(attr.value_str().map(|s| s.to_string()).unwrap());
1076             }
1077         }
1078         aliases.into_iter().collect::<Vec<String>>().into()
1079     }
1080 }
1081
1082 impl PartialEq for Attributes {
1083     fn eq(&self, rhs: &Self) -> bool {
1084         self.doc_strings == rhs.doc_strings
1085             && self
1086                 .other_attrs
1087                 .iter()
1088                 .map(|attr| attr.id)
1089                 .eq(rhs.other_attrs.iter().map(|attr| attr.id))
1090     }
1091 }
1092
1093 impl Eq for Attributes {}
1094
1095 impl Hash for Attributes {
1096     fn hash<H: Hasher>(&self, hasher: &mut H) {
1097         self.doc_strings.hash(hasher);
1098         for attr in &self.other_attrs {
1099             attr.id.hash(hasher);
1100         }
1101     }
1102 }
1103
1104 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1105 crate enum GenericBound {
1106     TraitBound(PolyTrait, hir::TraitBoundModifier),
1107     Outlives(Lifetime),
1108 }
1109
1110 impl GenericBound {
1111     crate fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1112         let did = cx.tcx.require_lang_item(LangItem::Sized, None);
1113         let empty = cx.tcx.intern_substs(&[]);
1114         let path = external_path(cx, did, false, vec![], empty);
1115         inline::record_extern_fqn(cx, did, ItemType::Trait);
1116         GenericBound::TraitBound(
1117             PolyTrait { trait_: ResolvedPath { path, did }, generic_params: Vec::new() },
1118             hir::TraitBoundModifier::Maybe,
1119         )
1120     }
1121
1122     crate fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1123         use rustc_hir::TraitBoundModifier as TBM;
1124         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
1125             if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
1126                 return true;
1127             }
1128         }
1129         false
1130     }
1131
1132     crate fn get_poly_trait(&self) -> Option<PolyTrait> {
1133         if let GenericBound::TraitBound(ref p, _) = *self {
1134             return Some(p.clone());
1135         }
1136         None
1137     }
1138
1139     crate fn get_trait_type(&self) -> Option<Type> {
1140         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1141             Some(trait_.clone())
1142         } else {
1143             None
1144         }
1145     }
1146 }
1147
1148 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1149 crate struct Lifetime(pub Symbol);
1150
1151 impl Lifetime {
1152     crate fn get_ref(&self) -> SymbolStr {
1153         self.0.as_str()
1154     }
1155
1156     crate fn statik() -> Lifetime {
1157         Lifetime(kw::StaticLifetime)
1158     }
1159
1160     crate fn elided() -> Lifetime {
1161         Lifetime(kw::UnderscoreLifetime)
1162     }
1163 }
1164
1165 #[derive(Clone, Debug)]
1166 crate enum WherePredicate {
1167     BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<Lifetime> },
1168     RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1169     EqPredicate { lhs: Type, rhs: Type },
1170 }
1171
1172 impl WherePredicate {
1173     crate fn get_bounds(&self) -> Option<&[GenericBound]> {
1174         match *self {
1175             WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
1176             WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
1177             _ => None,
1178         }
1179     }
1180 }
1181
1182 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1183 crate enum GenericParamDefKind {
1184     Lifetime {
1185         outlives: Vec<Lifetime>,
1186     },
1187     Type {
1188         did: DefId,
1189         bounds: Vec<GenericBound>,
1190         default: Option<Type>,
1191         synthetic: Option<hir::SyntheticTyParamKind>,
1192     },
1193     Const {
1194         did: DefId,
1195         ty: Type,
1196         default: Option<String>,
1197     },
1198 }
1199
1200 impl GenericParamDefKind {
1201     crate fn is_type(&self) -> bool {
1202         matches!(self, GenericParamDefKind::Type { .. })
1203     }
1204
1205     // FIXME(eddyb) this either returns the default of a type parameter, or the
1206     // type of a `const` parameter. It seems that the intention is to *visit*
1207     // any embedded types, but `get_type` seems to be the wrong name for that.
1208     crate fn get_type(&self) -> Option<Type> {
1209         match self {
1210             GenericParamDefKind::Type { default, .. } => default.clone(),
1211             GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
1212             GenericParamDefKind::Lifetime { .. } => None,
1213         }
1214     }
1215 }
1216
1217 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1218 crate struct GenericParamDef {
1219     crate name: Symbol,
1220     crate kind: GenericParamDefKind,
1221 }
1222
1223 impl GenericParamDef {
1224     crate fn is_synthetic_type_param(&self) -> bool {
1225         match self.kind {
1226             GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
1227             GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
1228         }
1229     }
1230
1231     crate fn is_type(&self) -> bool {
1232         self.kind.is_type()
1233     }
1234
1235     crate fn get_type(&self) -> Option<Type> {
1236         self.kind.get_type()
1237     }
1238
1239     crate fn get_bounds(&self) -> Option<&[GenericBound]> {
1240         match self.kind {
1241             GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1242             _ => None,
1243         }
1244     }
1245 }
1246
1247 // maybe use a Generic enum and use Vec<Generic>?
1248 #[derive(Clone, Debug, Default)]
1249 crate struct Generics {
1250     crate params: Vec<GenericParamDef>,
1251     crate where_predicates: Vec<WherePredicate>,
1252 }
1253
1254 #[derive(Clone, Debug)]
1255 crate struct Function {
1256     crate decl: FnDecl,
1257     crate generics: Generics,
1258     crate header: hir::FnHeader,
1259 }
1260
1261 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1262 crate struct FnDecl {
1263     crate inputs: Arguments,
1264     crate output: FnRetTy,
1265     crate c_variadic: bool,
1266 }
1267
1268 impl FnDecl {
1269     crate fn self_type(&self) -> Option<SelfTy> {
1270         self.inputs.values.get(0).and_then(|v| v.to_self())
1271     }
1272
1273     /// Returns the sugared return type for an async function.
1274     ///
1275     /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
1276     /// will return `i32`.
1277     ///
1278     /// # Panics
1279     ///
1280     /// This function will panic if the return type does not match the expected sugaring for async
1281     /// functions.
1282     crate fn sugared_async_return_type(&self) -> FnRetTy {
1283         match &self.output {
1284             FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
1285                 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
1286                     let bindings = trait_.bindings().unwrap();
1287                     FnRetTy::Return(bindings[0].ty().clone())
1288                 }
1289                 _ => panic!("unexpected desugaring of async function"),
1290             },
1291             _ => panic!("unexpected desugaring of async function"),
1292         }
1293     }
1294 }
1295
1296 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1297 crate struct Arguments {
1298     crate values: Vec<Argument>,
1299 }
1300
1301 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1302 crate struct Argument {
1303     crate type_: Type,
1304     crate name: Symbol,
1305 }
1306
1307 #[derive(Clone, PartialEq, Debug)]
1308 crate enum SelfTy {
1309     SelfValue,
1310     SelfBorrowed(Option<Lifetime>, Mutability),
1311     SelfExplicit(Type),
1312 }
1313
1314 impl Argument {
1315     crate fn to_self(&self) -> Option<SelfTy> {
1316         if self.name != kw::SelfLower {
1317             return None;
1318         }
1319         if self.type_.is_self_type() {
1320             return Some(SelfValue);
1321         }
1322         match self.type_ {
1323             BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
1324                 Some(SelfBorrowed(lifetime.clone(), mutability))
1325             }
1326             _ => Some(SelfExplicit(self.type_.clone())),
1327         }
1328     }
1329 }
1330
1331 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1332 crate enum FnRetTy {
1333     Return(Type),
1334     DefaultReturn,
1335 }
1336
1337 impl GetDefId for FnRetTy {
1338     fn def_id(&self) -> Option<DefId> {
1339         match *self {
1340             Return(ref ty) => ty.def_id(),
1341             DefaultReturn => None,
1342         }
1343     }
1344
1345     fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
1346         match *self {
1347             Return(ref ty) => ty.def_id_full(cache),
1348             DefaultReturn => None,
1349         }
1350     }
1351 }
1352
1353 #[derive(Clone, Debug)]
1354 crate struct Trait {
1355     crate unsafety: hir::Unsafety,
1356     crate items: Vec<Item>,
1357     crate generics: Generics,
1358     crate bounds: Vec<GenericBound>,
1359     crate is_auto: bool,
1360 }
1361
1362 #[derive(Clone, Debug)]
1363 crate struct TraitAlias {
1364     crate generics: Generics,
1365     crate bounds: Vec<GenericBound>,
1366 }
1367
1368 /// A trait reference, which may have higher ranked lifetimes.
1369 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1370 crate struct PolyTrait {
1371     crate trait_: Type,
1372     crate generic_params: Vec<GenericParamDef>,
1373 }
1374
1375 /// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
1376 /// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
1377 /// importantly, it does not preserve mutability or boxes.
1378 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1379 crate enum Type {
1380     /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
1381     ResolvedPath {
1382         path: Path,
1383         did: DefId,
1384     },
1385     /// `dyn for<'a> Trait<'a> + Send + 'static`
1386     DynTrait(Vec<PolyTrait>, Option<Lifetime>),
1387     /// For parameterized types, so the consumer of the JSON don't go
1388     /// looking for types which don't exist anywhere.
1389     Generic(Symbol),
1390     /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
1391     /// arrays, slices, and tuples.
1392     Primitive(PrimitiveType),
1393     /// `extern "ABI" fn`
1394     BareFunction(Box<BareFunctionDecl>),
1395     Tuple(Vec<Type>),
1396     Slice(Box<Type>),
1397     /// The `String` field is about the size or the constant representing the array's length.
1398     Array(Box<Type>, String),
1399     Never,
1400     RawPointer(Mutability, Box<Type>),
1401     BorrowedRef {
1402         lifetime: Option<Lifetime>,
1403         mutability: Mutability,
1404         type_: Box<Type>,
1405     },
1406
1407     // `<Type as Trait>::Name`
1408     QPath {
1409         name: Symbol,
1410         self_type: Box<Type>,
1411         self_def_id: Option<DefId>,
1412         trait_: Box<Type>,
1413     },
1414
1415     // `_`
1416     Infer,
1417
1418     // `impl TraitA + TraitB + ...`
1419     ImplTrait(Vec<GenericBound>),
1420 }
1421
1422 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1423 /// N.B. this has to be different from `hir::PrimTy` because it also includes types that aren't
1424 /// paths, like `Unit`.
1425 crate enum PrimitiveType {
1426     Isize,
1427     I8,
1428     I16,
1429     I32,
1430     I64,
1431     I128,
1432     Usize,
1433     U8,
1434     U16,
1435     U32,
1436     U64,
1437     U128,
1438     F32,
1439     F64,
1440     Char,
1441     Bool,
1442     Str,
1443     Slice,
1444     Array,
1445     Tuple,
1446     Unit,
1447     RawPointer,
1448     Reference,
1449     Fn,
1450     Never,
1451 }
1452
1453 crate trait GetDefId {
1454     /// Use this method to get the [`DefId`] of a [`clean`] AST node.
1455     /// This will return [`None`] when called on a primitive [`clean::Type`].
1456     /// Use [`Self::def_id_full`] if you want to include primitives.
1457     ///
1458     /// [`clean`]: crate::clean
1459     /// [`clean::Type`]: crate::clean::Type
1460     // FIXME: get rid of this function and always use `def_id_full`
1461     fn def_id(&self) -> Option<DefId>;
1462
1463     /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s.
1464     ///
1465     /// See [`Self::def_id`] for more.
1466     ///
1467     /// [clean]: crate::clean
1468     fn def_id_full(&self, cache: &Cache) -> Option<DefId>;
1469 }
1470
1471 impl<T: GetDefId> GetDefId for Option<T> {
1472     fn def_id(&self) -> Option<DefId> {
1473         self.as_ref().and_then(|d| d.def_id())
1474     }
1475
1476     fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
1477         self.as_ref().and_then(|d| d.def_id_full(cache))
1478     }
1479 }
1480
1481 impl Type {
1482     crate fn primitive_type(&self) -> Option<PrimitiveType> {
1483         match *self {
1484             Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1485             Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1486             Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1487             Tuple(ref tys) => {
1488                 if tys.is_empty() {
1489                     Some(PrimitiveType::Unit)
1490                 } else {
1491                     Some(PrimitiveType::Tuple)
1492                 }
1493             }
1494             RawPointer(..) => Some(PrimitiveType::RawPointer),
1495             BareFunction(..) => Some(PrimitiveType::Fn),
1496             Never => Some(PrimitiveType::Never),
1497             _ => None,
1498         }
1499     }
1500
1501     /// Checks if this is a `T::Name` path for an associated type.
1502     crate fn is_assoc_ty(&self) -> bool {
1503         match self {
1504             ResolvedPath { path, .. } => path.is_assoc_ty(),
1505             _ => false,
1506         }
1507     }
1508
1509     crate fn is_self_type(&self) -> bool {
1510         match *self {
1511             Generic(name) => name == kw::SelfUpper,
1512             _ => false,
1513         }
1514     }
1515
1516     crate fn generics(&self) -> Option<Vec<&Type>> {
1517         match *self {
1518             ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1519                 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
1520                     Some(
1521                         args.iter()
1522                             .filter_map(|arg| match arg {
1523                                 GenericArg::Type(ty) => Some(ty),
1524                                 _ => None,
1525                             })
1526                             .collect(),
1527                     )
1528                 } else {
1529                     None
1530                 }
1531             }),
1532             _ => None,
1533         }
1534     }
1535
1536     crate fn bindings(&self) -> Option<&[TypeBinding]> {
1537         match *self {
1538             ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1539                 if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
1540                     Some(&**bindings)
1541                 } else {
1542                     None
1543                 }
1544             }),
1545             _ => None,
1546         }
1547     }
1548
1549     crate fn is_full_generic(&self) -> bool {
1550         matches!(self, Type::Generic(_))
1551     }
1552
1553     crate fn is_primitive(&self) -> bool {
1554         self.primitive_type().is_some()
1555     }
1556
1557     crate fn projection(&self) -> Option<(&Type, DefId, Symbol)> {
1558         let (self_, trait_, name) = match self {
1559             QPath { self_type, trait_, name, .. } => (self_type, trait_, name),
1560             _ => return None,
1561         };
1562         let trait_did = match **trait_ {
1563             ResolvedPath { did, .. } => did,
1564             _ => return None,
1565         };
1566         Some((&self_, trait_did, *name))
1567     }
1568 }
1569
1570 impl Type {
1571     fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
1572         let t: PrimitiveType = match *self {
1573             ResolvedPath { did, .. } => return Some(did),
1574             DynTrait(ref bounds, _) => return bounds[0].trait_.inner_def_id(cache),
1575             Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
1576             BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
1577             BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache),
1578             Tuple(ref tys) => {
1579                 if tys.is_empty() {
1580                     PrimitiveType::Unit
1581                 } else {
1582                     PrimitiveType::Tuple
1583                 }
1584             }
1585             BareFunction(..) => PrimitiveType::Fn,
1586             Never => PrimitiveType::Never,
1587             Slice(..) => PrimitiveType::Slice,
1588             Array(..) => PrimitiveType::Array,
1589             RawPointer(..) => PrimitiveType::RawPointer,
1590             QPath { ref self_type, .. } => return self_type.inner_def_id(cache),
1591             Generic(_) | Infer | ImplTrait(_) => return None,
1592         };
1593         cache.and_then(|c| Primitive(t).def_id_full(c))
1594     }
1595 }
1596
1597 impl GetDefId for Type {
1598     fn def_id(&self) -> Option<DefId> {
1599         self.inner_def_id(None)
1600     }
1601
1602     fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
1603         self.inner_def_id(Some(cache))
1604     }
1605 }
1606
1607 impl PrimitiveType {
1608     crate fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1609         use ast::{FloatTy, IntTy, UintTy};
1610         match prim {
1611             hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1612             hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1613             hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1614             hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1615             hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1616             hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1617             hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1618             hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1619             hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1620             hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1621             hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1622             hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1623             hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1624             hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1625             hir::PrimTy::Str => PrimitiveType::Str,
1626             hir::PrimTy::Bool => PrimitiveType::Bool,
1627             hir::PrimTy::Char => PrimitiveType::Char,
1628         }
1629     }
1630
1631     crate fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1632         match s {
1633             sym::isize => Some(PrimitiveType::Isize),
1634             sym::i8 => Some(PrimitiveType::I8),
1635             sym::i16 => Some(PrimitiveType::I16),
1636             sym::i32 => Some(PrimitiveType::I32),
1637             sym::i64 => Some(PrimitiveType::I64),
1638             sym::i128 => Some(PrimitiveType::I128),
1639             sym::usize => Some(PrimitiveType::Usize),
1640             sym::u8 => Some(PrimitiveType::U8),
1641             sym::u16 => Some(PrimitiveType::U16),
1642             sym::u32 => Some(PrimitiveType::U32),
1643             sym::u64 => Some(PrimitiveType::U64),
1644             sym::u128 => Some(PrimitiveType::U128),
1645             sym::bool => Some(PrimitiveType::Bool),
1646             sym::char => Some(PrimitiveType::Char),
1647             sym::str => Some(PrimitiveType::Str),
1648             sym::f32 => Some(PrimitiveType::F32),
1649             sym::f64 => Some(PrimitiveType::F64),
1650             sym::array => Some(PrimitiveType::Array),
1651             sym::slice => Some(PrimitiveType::Slice),
1652             sym::tuple => Some(PrimitiveType::Tuple),
1653             sym::unit => Some(PrimitiveType::Unit),
1654             sym::pointer => Some(PrimitiveType::RawPointer),
1655             sym::reference => Some(PrimitiveType::Reference),
1656             kw::Fn => Some(PrimitiveType::Fn),
1657             sym::never => Some(PrimitiveType::Never),
1658             _ => None,
1659         }
1660     }
1661
1662     crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static ArrayVec<DefId, 4> {
1663         Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
1664     }
1665
1666     crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, ArrayVec<DefId, 4>> {
1667         static CELL: OnceCell<FxHashMap<PrimitiveType, ArrayVec<DefId, 4>>> = OnceCell::new();
1668
1669         CELL.get_or_init(move || {
1670             use self::PrimitiveType::*;
1671
1672             let single = |a: Option<DefId>| a.into_iter().collect();
1673             let both = |a: Option<DefId>, b: Option<DefId>| -> ArrayVec<_, 4> {
1674                 a.into_iter().chain(b).collect()
1675             };
1676
1677             let lang_items = tcx.lang_items();
1678             map! {
1679                 Isize => single(lang_items.isize_impl()),
1680                 I8 => single(lang_items.i8_impl()),
1681                 I16 => single(lang_items.i16_impl()),
1682                 I32 => single(lang_items.i32_impl()),
1683                 I64 => single(lang_items.i64_impl()),
1684                 I128 => single(lang_items.i128_impl()),
1685                 Usize => single(lang_items.usize_impl()),
1686                 U8 => single(lang_items.u8_impl()),
1687                 U16 => single(lang_items.u16_impl()),
1688                 U32 => single(lang_items.u32_impl()),
1689                 U64 => single(lang_items.u64_impl()),
1690                 U128 => single(lang_items.u128_impl()),
1691                 F32 => both(lang_items.f32_impl(), lang_items.f32_runtime_impl()),
1692                 F64 => both(lang_items.f64_impl(), lang_items.f64_runtime_impl()),
1693                 Char => single(lang_items.char_impl()),
1694                 Bool => single(lang_items.bool_impl()),
1695                 Str => both(lang_items.str_impl(), lang_items.str_alloc_impl()),
1696                 Slice => {
1697                     lang_items
1698                         .slice_impl()
1699                         .into_iter()
1700                         .chain(lang_items.slice_u8_impl())
1701                         .chain(lang_items.slice_alloc_impl())
1702                         .chain(lang_items.slice_u8_alloc_impl())
1703                         .collect()
1704                 },
1705                 Array => single(lang_items.array_impl()),
1706                 Tuple => ArrayVec::new(),
1707                 Unit => ArrayVec::new(),
1708                 RawPointer => {
1709                     lang_items
1710                         .const_ptr_impl()
1711                         .into_iter()
1712                         .chain(lang_items.mut_ptr_impl())
1713                         .chain(lang_items.const_slice_ptr_impl())
1714                         .chain(lang_items.mut_slice_ptr_impl())
1715                         .collect()
1716                 },
1717                 Reference => ArrayVec::new(),
1718                 Fn => ArrayVec::new(),
1719                 Never => ArrayVec::new(),
1720             }
1721         })
1722     }
1723
1724     crate fn as_sym(&self) -> Symbol {
1725         use PrimitiveType::*;
1726         match self {
1727             Isize => sym::isize,
1728             I8 => sym::i8,
1729             I16 => sym::i16,
1730             I32 => sym::i32,
1731             I64 => sym::i64,
1732             I128 => sym::i128,
1733             Usize => sym::usize,
1734             U8 => sym::u8,
1735             U16 => sym::u16,
1736             U32 => sym::u32,
1737             U64 => sym::u64,
1738             U128 => sym::u128,
1739             F32 => sym::f32,
1740             F64 => sym::f64,
1741             Str => sym::str,
1742             Bool => sym::bool,
1743             Char => sym::char,
1744             Array => sym::array,
1745             Slice => sym::slice,
1746             Tuple => sym::tuple,
1747             Unit => sym::unit,
1748             RawPointer => sym::pointer,
1749             Reference => sym::reference,
1750             Fn => kw::Fn,
1751             Never => sym::never,
1752         }
1753     }
1754
1755     /// Returns the DefId of the module with `doc(primitive)` for this primitive type.
1756     /// Panics if there is no such module.
1757     ///
1758     /// This gives precedence to primitives defined in the current crate, and deprioritizes primitives defined in `core`,
1759     /// but otherwise, if multiple crates define the same primitive, there is no guarantee of which will be picked.
1760     /// In particular, if a crate depends on both `std` and another crate that also defines `doc(primitive)`, then
1761     /// it's entirely random whether `std` or the other crate is picked. (no_std crates are usually fine unless multiple dependencies define a primitive.)
1762     crate fn primitive_locations(tcx: TyCtxt<'_>) -> &FxHashMap<PrimitiveType, DefId> {
1763         static PRIMITIVE_LOCATIONS: OnceCell<FxHashMap<PrimitiveType, DefId>> = OnceCell::new();
1764         PRIMITIVE_LOCATIONS.get_or_init(|| {
1765             let mut primitive_locations = FxHashMap::default();
1766             // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate.
1767             // This is a degenerate case that I don't plan to support.
1768             for &crate_num in tcx.crates(()) {
1769                 let e = ExternalCrate { crate_num };
1770                 let crate_name = e.name(tcx);
1771                 debug!(?crate_num, ?crate_name);
1772                 for &(def_id, prim) in &e.primitives(tcx) {
1773                     // HACK: try to link to std instead where possible
1774                     if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1775                         continue;
1776                     }
1777                     primitive_locations.insert(prim, def_id);
1778                 }
1779             }
1780             let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1781             for (def_id, prim) in local_primitives {
1782                 primitive_locations.insert(prim, def_id);
1783             }
1784             primitive_locations
1785         })
1786     }
1787 }
1788
1789 impl From<ast::IntTy> for PrimitiveType {
1790     fn from(int_ty: ast::IntTy) -> PrimitiveType {
1791         match int_ty {
1792             ast::IntTy::Isize => PrimitiveType::Isize,
1793             ast::IntTy::I8 => PrimitiveType::I8,
1794             ast::IntTy::I16 => PrimitiveType::I16,
1795             ast::IntTy::I32 => PrimitiveType::I32,
1796             ast::IntTy::I64 => PrimitiveType::I64,
1797             ast::IntTy::I128 => PrimitiveType::I128,
1798         }
1799     }
1800 }
1801
1802 impl From<ast::UintTy> for PrimitiveType {
1803     fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1804         match uint_ty {
1805             ast::UintTy::Usize => PrimitiveType::Usize,
1806             ast::UintTy::U8 => PrimitiveType::U8,
1807             ast::UintTy::U16 => PrimitiveType::U16,
1808             ast::UintTy::U32 => PrimitiveType::U32,
1809             ast::UintTy::U64 => PrimitiveType::U64,
1810             ast::UintTy::U128 => PrimitiveType::U128,
1811         }
1812     }
1813 }
1814
1815 impl From<ast::FloatTy> for PrimitiveType {
1816     fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1817         match float_ty {
1818             ast::FloatTy::F32 => PrimitiveType::F32,
1819             ast::FloatTy::F64 => PrimitiveType::F64,
1820         }
1821     }
1822 }
1823
1824 impl From<ty::IntTy> for PrimitiveType {
1825     fn from(int_ty: ty::IntTy) -> PrimitiveType {
1826         match int_ty {
1827             ty::IntTy::Isize => PrimitiveType::Isize,
1828             ty::IntTy::I8 => PrimitiveType::I8,
1829             ty::IntTy::I16 => PrimitiveType::I16,
1830             ty::IntTy::I32 => PrimitiveType::I32,
1831             ty::IntTy::I64 => PrimitiveType::I64,
1832             ty::IntTy::I128 => PrimitiveType::I128,
1833         }
1834     }
1835 }
1836
1837 impl From<ty::UintTy> for PrimitiveType {
1838     fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1839         match uint_ty {
1840             ty::UintTy::Usize => PrimitiveType::Usize,
1841             ty::UintTy::U8 => PrimitiveType::U8,
1842             ty::UintTy::U16 => PrimitiveType::U16,
1843             ty::UintTy::U32 => PrimitiveType::U32,
1844             ty::UintTy::U64 => PrimitiveType::U64,
1845             ty::UintTy::U128 => PrimitiveType::U128,
1846         }
1847     }
1848 }
1849
1850 impl From<ty::FloatTy> for PrimitiveType {
1851     fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1852         match float_ty {
1853             ty::FloatTy::F32 => PrimitiveType::F32,
1854             ty::FloatTy::F64 => PrimitiveType::F64,
1855         }
1856     }
1857 }
1858
1859 impl From<hir::PrimTy> for PrimitiveType {
1860     fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1861         match prim_ty {
1862             hir::PrimTy::Int(int_ty) => int_ty.into(),
1863             hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1864             hir::PrimTy::Float(float_ty) => float_ty.into(),
1865             hir::PrimTy::Str => PrimitiveType::Str,
1866             hir::PrimTy::Bool => PrimitiveType::Bool,
1867             hir::PrimTy::Char => PrimitiveType::Char,
1868         }
1869     }
1870 }
1871
1872 #[derive(Copy, Clone, Debug)]
1873 crate enum Visibility {
1874     /// `pub`
1875     Public,
1876     /// Visibility inherited from parent.
1877     ///
1878     /// For example, this is the visibility of private items and of enum variants.
1879     Inherited,
1880     /// `pub(crate)`, `pub(super)`, or `pub(in path::to::somewhere)`
1881     Restricted(DefId),
1882 }
1883
1884 impl Visibility {
1885     crate fn is_public(&self) -> bool {
1886         matches!(self, Visibility::Public)
1887     }
1888 }
1889
1890 #[derive(Clone, Debug)]
1891 crate struct Struct {
1892     crate struct_type: CtorKind,
1893     crate generics: Generics,
1894     crate fields: Vec<Item>,
1895     crate fields_stripped: bool,
1896 }
1897
1898 #[derive(Clone, Debug)]
1899 crate struct Union {
1900     crate generics: Generics,
1901     crate fields: Vec<Item>,
1902     crate fields_stripped: bool,
1903 }
1904
1905 /// This is a more limited form of the standard Struct, different in that
1906 /// it lacks the things most items have (name, id, parameterization). Found
1907 /// only as a variant in an enum.
1908 #[derive(Clone, Debug)]
1909 crate struct VariantStruct {
1910     crate struct_type: CtorKind,
1911     crate fields: Vec<Item>,
1912     crate fields_stripped: bool,
1913 }
1914
1915 #[derive(Clone, Debug)]
1916 crate struct Enum {
1917     crate variants: IndexVec<VariantIdx, Item>,
1918     crate generics: Generics,
1919     crate variants_stripped: bool,
1920 }
1921
1922 #[derive(Clone, Debug)]
1923 crate enum Variant {
1924     CLike,
1925     Tuple(Vec<Item>),
1926     Struct(VariantStruct),
1927 }
1928
1929 /// Small wrapper around [`rustc_span::Span`] that adds helper methods
1930 /// and enforces calling [`rustc_span::Span::source_callsite()`].
1931 #[derive(Copy, Clone, Debug)]
1932 crate struct Span(rustc_span::Span);
1933
1934 impl Span {
1935     /// Wraps a [`rustc_span::Span`]. In case this span is the result of a macro expansion, the
1936     /// span will be updated to point to the macro invocation instead of the macro definition.
1937     ///
1938     /// (See rust-lang/rust#39726)
1939     crate fn new(sp: rustc_span::Span) -> Self {
1940         Self(sp.source_callsite())
1941     }
1942
1943     crate fn inner(&self) -> rustc_span::Span {
1944         self.0
1945     }
1946
1947     crate fn dummy() -> Self {
1948         Self(rustc_span::DUMMY_SP)
1949     }
1950
1951     crate fn is_dummy(&self) -> bool {
1952         self.0.is_dummy()
1953     }
1954
1955     crate fn filename(&self, sess: &Session) -> FileName {
1956         sess.source_map().span_to_filename(self.0)
1957     }
1958
1959     crate fn lo(&self, sess: &Session) -> Loc {
1960         sess.source_map().lookup_char_pos(self.0.lo())
1961     }
1962
1963     crate fn hi(&self, sess: &Session) -> Loc {
1964         sess.source_map().lookup_char_pos(self.0.hi())
1965     }
1966
1967     crate fn cnum(&self, sess: &Session) -> CrateNum {
1968         // FIXME: is there a time when the lo and hi crate would be different?
1969         self.lo(sess).file.cnum
1970     }
1971 }
1972
1973 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1974 crate struct Path {
1975     crate global: bool,
1976     crate res: Res,
1977     crate segments: Vec<PathSegment>,
1978 }
1979
1980 impl Path {
1981     crate fn last(&self) -> Symbol {
1982         self.segments.last().expect("segments were empty").name
1983     }
1984
1985     crate fn last_name(&self) -> SymbolStr {
1986         self.segments.last().expect("segments were empty").name.as_str()
1987     }
1988
1989     crate fn whole_name(&self) -> String {
1990         String::from(if self.global { "::" } else { "" })
1991             + &self.segments.iter().map(|s| s.name.to_string()).collect::<Vec<_>>().join("::")
1992     }
1993
1994     /// Checks if this is a `T::Name` path for an associated type.
1995     crate fn is_assoc_ty(&self) -> bool {
1996         match self.res {
1997             Res::SelfTy(..) if self.segments.len() != 1 => true,
1998             Res::Def(DefKind::TyParam, _) if self.segments.len() != 1 => true,
1999             Res::Def(DefKind::AssocTy, _) => true,
2000             _ => false,
2001         }
2002     }
2003 }
2004
2005 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2006 crate enum GenericArg {
2007     Lifetime(Lifetime),
2008     Type(Type),
2009     Const(Box<Constant>),
2010     Infer,
2011 }
2012
2013 // `GenericArg` can occur many times in a single `Path`, so make sure it
2014 // doesn't increase in size unexpectedly.
2015 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2016 rustc_data_structures::static_assert_size!(GenericArg, 80);
2017
2018 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2019 crate enum GenericArgs {
2020     AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
2021     Parenthesized { inputs: Vec<Type>, output: Option<Box<Type>> },
2022 }
2023
2024 // `GenericArgs` is in every `PathSegment`, so its size can significantly
2025 // affect rustdoc's memory usage.
2026 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2027 rustc_data_structures::static_assert_size!(GenericArgs, 56);
2028
2029 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2030 crate struct PathSegment {
2031     crate name: Symbol,
2032     crate args: GenericArgs,
2033 }
2034
2035 // `PathSegment` usually occurs multiple times in every `Path`, so its size can
2036 // significantly affect rustdoc's memory usage.
2037 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2038 rustc_data_structures::static_assert_size!(PathSegment, 64);
2039
2040 #[derive(Clone, Debug)]
2041 crate struct Typedef {
2042     crate type_: Type,
2043     crate generics: Generics,
2044     /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
2045     /// alias instead of the final type. This will always have the final type, regardless of whether
2046     /// `type_` came from HIR or from metadata.
2047     ///
2048     /// If `item_type.is_none()`, `type_` is guarenteed to come from metadata (and therefore hold the
2049     /// final type).
2050     crate item_type: Option<Type>,
2051 }
2052
2053 impl GetDefId for Typedef {
2054     fn def_id(&self) -> Option<DefId> {
2055         self.type_.def_id()
2056     }
2057
2058     fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
2059         self.type_.def_id_full(cache)
2060     }
2061 }
2062
2063 #[derive(Clone, Debug)]
2064 crate struct OpaqueTy {
2065     crate bounds: Vec<GenericBound>,
2066     crate generics: Generics,
2067 }
2068
2069 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2070 crate struct BareFunctionDecl {
2071     crate unsafety: hir::Unsafety,
2072     crate generic_params: Vec<GenericParamDef>,
2073     crate decl: FnDecl,
2074     crate abi: Abi,
2075 }
2076
2077 #[derive(Clone, Debug)]
2078 crate struct Static {
2079     crate type_: Type,
2080     crate mutability: Mutability,
2081     crate expr: Option<BodyId>,
2082 }
2083
2084 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2085 crate struct Constant {
2086     crate type_: Type,
2087     crate kind: ConstantKind,
2088 }
2089
2090 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2091 crate enum ConstantKind {
2092     /// This is the wrapper around `ty::Const` for a non-local constant. Because it doesn't have a
2093     /// `BodyId`, we need to handle it on its own.
2094     ///
2095     /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified
2096     /// by a DefId. So this field must be different from `Extern`.
2097     TyConst { expr: String },
2098     /// A constant (expression) that's not an item or associated item. These are usually found
2099     /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
2100     /// used to define explicit discriminant values for enum variants.
2101     Anonymous { body: BodyId },
2102     /// A constant from a different crate.
2103     Extern { def_id: DefId },
2104     /// `const FOO: u32 = ...;`
2105     Local { def_id: DefId, body: BodyId },
2106 }
2107
2108 impl Constant {
2109     crate fn expr(&self, tcx: TyCtxt<'_>) -> String {
2110         match self.kind {
2111             ConstantKind::TyConst { ref expr } => expr.clone(),
2112             ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2113             ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2114                 print_const_expr(tcx, body)
2115             }
2116         }
2117     }
2118
2119     crate fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2120         match self.kind {
2121             ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
2122             ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2123                 print_evaluated_const(tcx, def_id)
2124             }
2125         }
2126     }
2127
2128     crate fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2129         match self.kind {
2130             ConstantKind::TyConst { .. } => false,
2131             ConstantKind::Extern { def_id } => def_id.as_local().map_or(false, |def_id| {
2132                 is_literal_expr(tcx, tcx.hir().local_def_id_to_hir_id(def_id))
2133             }),
2134             ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2135                 is_literal_expr(tcx, body.hir_id)
2136             }
2137         }
2138     }
2139 }
2140
2141 #[derive(Clone, Debug)]
2142 crate struct Impl {
2143     crate span: Span,
2144     crate unsafety: hir::Unsafety,
2145     crate generics: Generics,
2146     crate trait_: Option<Type>,
2147     crate for_: Type,
2148     crate items: Vec<Item>,
2149     crate negative_polarity: bool,
2150     crate synthetic: bool,
2151     crate blanket_impl: Option<Box<Type>>,
2152 }
2153
2154 impl Impl {
2155     crate fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxHashSet<Symbol> {
2156         self.trait_
2157             .def_id()
2158             .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.ident.name).collect())
2159             .unwrap_or_default()
2160     }
2161 }
2162
2163 #[derive(Clone, Debug)]
2164 crate struct Import {
2165     crate kind: ImportKind,
2166     crate source: ImportSource,
2167     crate should_be_displayed: bool,
2168 }
2169
2170 impl Import {
2171     crate fn new_simple(name: Symbol, source: ImportSource, should_be_displayed: bool) -> Self {
2172         Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2173     }
2174
2175     crate fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2176         Self { kind: ImportKind::Glob, source, should_be_displayed }
2177     }
2178 }
2179
2180 #[derive(Clone, Debug)]
2181 crate enum ImportKind {
2182     // use source as str;
2183     Simple(Symbol),
2184     // use source::*;
2185     Glob,
2186 }
2187
2188 #[derive(Clone, Debug)]
2189 crate struct ImportSource {
2190     crate path: Path,
2191     crate did: Option<DefId>,
2192 }
2193
2194 #[derive(Clone, Debug)]
2195 crate struct Macro {
2196     crate source: String,
2197 }
2198
2199 #[derive(Clone, Debug)]
2200 crate struct ProcMacro {
2201     crate kind: MacroKind,
2202     crate helpers: Vec<Symbol>,
2203 }
2204
2205 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
2206 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
2207 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2208 crate struct TypeBinding {
2209     crate name: Symbol,
2210     crate kind: TypeBindingKind,
2211 }
2212
2213 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2214 crate enum TypeBindingKind {
2215     Equality { ty: Type },
2216     Constraint { bounds: Vec<GenericBound> },
2217 }
2218
2219 impl TypeBinding {
2220     crate fn ty(&self) -> &Type {
2221         match self.kind {
2222             TypeBindingKind::Equality { ref ty } => ty,
2223             _ => panic!("expected equality type binding for parenthesized generic args"),
2224         }
2225     }
2226 }