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