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