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