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