]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/clean/types.rs
Rollup merge of #99415 - ferrocene:pa-reuse-initial, r=Mark-Simulacrum
[rust.git] / src / librustdoc / clean / types.rs
1 use std::cell::RefCell;
2 use std::default::Default;
3 use std::hash::Hash;
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
12 use rustc_ast::attr;
13 use rustc_ast::util::comments::beautify_doc_string;
14 use rustc_ast::{self as ast, AttrStyle};
15 use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
16 use rustc_const_eval::const_eval::is_unstable_const_fn;
17 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
18 use rustc_data_structures::thin_vec::ThinVec;
19 use rustc_hir as hir;
20 use rustc_hir::def::{CtorKind, DefKind, Res};
21 use rustc_hir::def_id::{CrateNum, DefId, 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={:?}", name, def_id);
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(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
806 #[derive(Clone, Debug)]
807 pub(crate) struct Module {
808     pub(crate) items: Vec<Item>,
809     pub(crate) span: Span,
810 }
811
812 pub(crate) trait AttributesExt {
813     type AttributeIterator<'a>: Iterator<Item = ast::NestedMetaItem>
814     where
815         Self: 'a;
816
817     fn lists<'a>(&'a self, name: Symbol) -> Self::AttributeIterator<'a>;
818
819     fn span(&self) -> Option<rustc_span::Span>;
820
821     fn inner_docs(&self) -> bool;
822
823     fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>>;
824 }
825
826 impl AttributesExt for [ast::Attribute] {
827     type AttributeIterator<'a> = impl Iterator<Item = ast::NestedMetaItem> + 'a;
828
829     fn lists<'a>(&'a self, name: Symbol) -> Self::AttributeIterator<'a> {
830         self.iter()
831             .filter(move |attr| attr.has_name(name))
832             .filter_map(ast::Attribute::meta_item_list)
833             .flatten()
834     }
835
836     /// Return the span of the first doc-comment, if it exists.
837     fn span(&self) -> Option<rustc_span::Span> {
838         self.iter().find(|attr| attr.doc_str().is_some()).map(|attr| attr.span)
839     }
840
841     /// Returns whether the first doc-comment is an inner attribute.
842     ///
843     //// If there are no doc-comments, return true.
844     /// FIXME(#78591): Support both inner and outer attributes on the same item.
845     fn inner_docs(&self) -> bool {
846         self.iter().find(|a| a.doc_str().is_some()).map_or(true, |a| a.style == AttrStyle::Inner)
847     }
848
849     fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>> {
850         let sess = tcx.sess;
851         let doc_cfg_active = tcx.features().doc_cfg;
852         let doc_auto_cfg_active = tcx.features().doc_auto_cfg;
853
854         fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
855             let mut iter = it.into_iter();
856             let item = iter.next()?;
857             if iter.next().is_some() {
858                 return None;
859             }
860             Some(item)
861         }
862
863         let mut cfg = if doc_cfg_active || doc_auto_cfg_active {
864             let mut doc_cfg = self
865                 .iter()
866                 .filter(|attr| attr.has_name(sym::doc))
867                 .flat_map(|attr| attr.meta_item_list().unwrap_or_default())
868                 .filter(|attr| attr.has_name(sym::cfg))
869                 .peekable();
870             if doc_cfg.peek().is_some() && doc_cfg_active {
871                 doc_cfg
872                     .filter_map(|attr| Cfg::parse(attr.meta_item()?).ok())
873                     .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
874             } else if doc_auto_cfg_active {
875                 self.iter()
876                     .filter(|attr| attr.has_name(sym::cfg))
877                     .filter_map(|attr| single(attr.meta_item_list()?))
878                     .filter_map(|attr| {
879                         Cfg::parse_without(attr.meta_item()?, hidden_cfg).ok().flatten()
880                     })
881                     .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
882             } else {
883                 Cfg::True
884             }
885         } else {
886             Cfg::True
887         };
888
889         for attr in self.iter() {
890             // #[doc]
891             if attr.doc_str().is_none() && attr.has_name(sym::doc) {
892                 // #[doc(...)]
893                 if let Some(list) = attr.meta().as_ref().and_then(|mi| mi.meta_item_list()) {
894                     for item in list {
895                         // #[doc(hidden)]
896                         if !item.has_name(sym::cfg) {
897                             continue;
898                         }
899                         // #[doc(cfg(...))]
900                         if let Some(cfg_mi) = item
901                             .meta_item()
902                             .and_then(|item| rustc_expand::config::parse_cfg(item, sess))
903                         {
904                             match Cfg::parse(cfg_mi) {
905                                 Ok(new_cfg) => cfg &= new_cfg,
906                                 Err(e) => {
907                                     sess.span_err(e.span, e.msg);
908                                 }
909                             }
910                         }
911                     }
912                 }
913             }
914         }
915
916         // treat #[target_feature(enable = "feat")] attributes as if they were
917         // #[doc(cfg(target_feature = "feat"))] attributes as well
918         for attr in self.lists(sym::target_feature) {
919             if attr.has_name(sym::enable) {
920                 if let Some(feat) = attr.value_str() {
921                     let meta = attr::mk_name_value_item_str(
922                         Ident::with_dummy_span(sym::target_feature),
923                         feat,
924                         DUMMY_SP,
925                     );
926                     if let Ok(feat_cfg) = Cfg::parse(&meta) {
927                         cfg &= feat_cfg;
928                     }
929                 }
930             }
931         }
932
933         if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) }
934     }
935 }
936
937 pub(crate) trait NestedAttributesExt {
938     /// Returns `true` if the attribute list contains a specific `word`
939     fn has_word(self, word: Symbol) -> bool
940     where
941         Self: std::marker::Sized,
942     {
943         <Self as NestedAttributesExt>::get_word_attr(self, word).is_some()
944     }
945
946     /// Returns `Some(attr)` if the attribute list contains 'attr'
947     /// corresponding to a specific `word`
948     fn get_word_attr(self, word: Symbol) -> Option<ast::NestedMetaItem>;
949 }
950
951 impl<I: Iterator<Item = ast::NestedMetaItem>> NestedAttributesExt for I {
952     fn get_word_attr(mut self, word: Symbol) -> Option<ast::NestedMetaItem> {
953         self.find(|attr| attr.is_word() && attr.has_name(word))
954     }
955 }
956
957 /// A portion of documentation, extracted from a `#[doc]` attribute.
958 ///
959 /// Each variant contains the line number within the complete doc-comment where the fragment
960 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
961 ///
962 /// Included files are kept separate from inline doc comments so that proper line-number
963 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
964 /// kept separate because of issue #42760.
965 #[derive(Clone, PartialEq, Eq, Debug)]
966 pub(crate) struct DocFragment {
967     pub(crate) span: rustc_span::Span,
968     /// The module this doc-comment came from.
969     ///
970     /// This allows distinguishing between the original documentation and a pub re-export.
971     /// If it is `None`, the item was not re-exported.
972     pub(crate) parent_module: Option<DefId>,
973     pub(crate) doc: Symbol,
974     pub(crate) kind: DocFragmentKind,
975     pub(crate) indent: usize,
976 }
977
978 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
979 pub(crate) enum DocFragmentKind {
980     /// A doc fragment created from a `///` or `//!` doc comment.
981     SugaredDoc,
982     /// A doc fragment created from a "raw" `#[doc=""]` attribute.
983     RawDoc,
984 }
985
986 /// The goal of this function is to apply the `DocFragment` transformation that is required when
987 /// transforming into the final Markdown, which is applying the computed indent to each line in
988 /// each doc fragment (a `DocFragment` can contain multiple lines in case of `#[doc = ""]`).
989 ///
990 /// Note: remove the trailing newline where appropriate
991 fn add_doc_fragment(out: &mut String, frag: &DocFragment) {
992     let s = frag.doc.as_str();
993     let mut iter = s.lines();
994     if s.is_empty() {
995         out.push('\n');
996         return;
997     }
998     while let Some(line) = iter.next() {
999         if line.chars().any(|c| !c.is_whitespace()) {
1000             assert!(line.len() >= frag.indent);
1001             out.push_str(&line[frag.indent..]);
1002         } else {
1003             out.push_str(line);
1004         }
1005         out.push('\n');
1006     }
1007 }
1008
1009 /// Collapse a collection of [`DocFragment`]s into one string,
1010 /// handling indentation and newlines as needed.
1011 pub(crate) fn collapse_doc_fragments(doc_strings: &[DocFragment]) -> String {
1012     let mut acc = String::new();
1013     for frag in doc_strings {
1014         add_doc_fragment(&mut acc, frag);
1015     }
1016     acc.pop();
1017     acc
1018 }
1019
1020 /// Removes excess indentation on comments in order for the Markdown
1021 /// to be parsed correctly. This is necessary because the convention for
1022 /// writing documentation is to provide a space between the /// or //! marker
1023 /// and the doc text, but Markdown is whitespace-sensitive. For example,
1024 /// a block of text with four-space indentation is parsed as a code block,
1025 /// so if we didn't unindent comments, these list items
1026 ///
1027 /// /// A list:
1028 /// ///
1029 /// ///    - Foo
1030 /// ///    - Bar
1031 ///
1032 /// would be parsed as if they were in a code block, which is likely not what the user intended.
1033 fn unindent_doc_fragments(docs: &mut Vec<DocFragment>) {
1034     // `add` is used in case the most common sugared doc syntax is used ("/// "). The other
1035     // fragments kind's lines are never starting with a whitespace unless they are using some
1036     // markdown formatting requiring it. Therefore, if the doc block have a mix between the two,
1037     // we need to take into account the fact that the minimum indent minus one (to take this
1038     // whitespace into account).
1039     //
1040     // For example:
1041     //
1042     // /// hello!
1043     // #[doc = "another"]
1044     //
1045     // In this case, you want "hello! another" and not "hello!  another".
1046     let add = if docs.windows(2).any(|arr| arr[0].kind != arr[1].kind)
1047         && docs.iter().any(|d| d.kind == DocFragmentKind::SugaredDoc)
1048     {
1049         // In case we have a mix of sugared doc comments and "raw" ones, we want the sugared one to
1050         // "decide" how much the minimum indent will be.
1051         1
1052     } else {
1053         0
1054     };
1055
1056     // `min_indent` is used to know how much whitespaces from the start of each lines must be
1057     // removed. Example:
1058     //
1059     // ///     hello!
1060     // #[doc = "another"]
1061     //
1062     // In here, the `min_indent` is 1 (because non-sugared fragment are always counted with minimum
1063     // 1 whitespace), meaning that "hello!" will be considered a codeblock because it starts with 4
1064     // (5 - 1) whitespaces.
1065     let Some(min_indent) = docs
1066         .iter()
1067         .map(|fragment| {
1068             fragment.doc.as_str().lines().fold(usize::MAX, |min_indent, line| {
1069                 if line.chars().all(|c| c.is_whitespace()) {
1070                     min_indent
1071                 } else {
1072                     // Compare against either space or tab, ignoring whether they are
1073                     // mixed or not.
1074                     let whitespace = line.chars().take_while(|c| *c == ' ' || *c == '\t').count();
1075                     cmp::min(min_indent, whitespace)
1076                         + if fragment.kind == DocFragmentKind::SugaredDoc { 0 } else { add }
1077                 }
1078             })
1079         })
1080         .min()
1081     else {
1082         return;
1083     };
1084
1085     for fragment in docs {
1086         if fragment.doc == kw::Empty {
1087             continue;
1088         }
1089
1090         let min_indent = if fragment.kind != DocFragmentKind::SugaredDoc && min_indent > 0 {
1091             min_indent - add
1092         } else {
1093             min_indent
1094         };
1095
1096         fragment.indent = min_indent;
1097     }
1098 }
1099
1100 /// A link that has not yet been rendered.
1101 ///
1102 /// This link will be turned into a rendered link by [`Item::links`].
1103 #[derive(Clone, Debug, PartialEq, Eq)]
1104 pub(crate) struct ItemLink {
1105     /// The original link written in the markdown
1106     pub(crate) link: String,
1107     /// The link text displayed in the HTML.
1108     ///
1109     /// This may not be the same as `link` if there was a disambiguator
1110     /// in an intra-doc link (e.g. \[`fn@f`\])
1111     pub(crate) link_text: String,
1112     pub(crate) did: DefId,
1113     /// The url fragment to append to the link
1114     pub(crate) fragment: Option<UrlFragment>,
1115 }
1116
1117 pub struct RenderedLink {
1118     /// The text the link was original written as.
1119     ///
1120     /// This could potentially include disambiguators and backticks.
1121     pub(crate) original_text: String,
1122     /// The text to display in the HTML
1123     pub(crate) new_text: String,
1124     /// The URL to put in the `href`
1125     pub(crate) href: String,
1126 }
1127
1128 /// The attributes on an [`Item`], including attributes like `#[derive(...)]` and `#[inline]`,
1129 /// as well as doc comments.
1130 #[derive(Clone, Debug, Default)]
1131 pub(crate) struct Attributes {
1132     pub(crate) doc_strings: Vec<DocFragment>,
1133     pub(crate) other_attrs: Vec<ast::Attribute>,
1134 }
1135
1136 impl Attributes {
1137     pub(crate) fn lists(&self, name: Symbol) -> impl Iterator<Item = ast::NestedMetaItem> + '_ {
1138         self.other_attrs.lists(name)
1139     }
1140
1141     pub(crate) fn has_doc_flag(&self, flag: Symbol) -> bool {
1142         for attr in &self.other_attrs {
1143             if !attr.has_name(sym::doc) {
1144                 continue;
1145             }
1146
1147             if let Some(items) = attr.meta_item_list() {
1148                 if items.iter().filter_map(|i| i.meta_item()).any(|it| it.has_name(flag)) {
1149                     return true;
1150                 }
1151             }
1152         }
1153
1154         false
1155     }
1156
1157     pub(crate) fn from_ast(attrs: &[ast::Attribute]) -> Attributes {
1158         Attributes::from_ast_iter(attrs.iter().map(|attr| (attr, None)), false)
1159     }
1160
1161     pub(crate) fn from_ast_with_additional(
1162         attrs: &[ast::Attribute],
1163         (additional_attrs, def_id): (&[ast::Attribute], DefId),
1164     ) -> Attributes {
1165         // Additional documentation should be shown before the original documentation.
1166         let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id)));
1167         let attrs2 = attrs.iter().map(|attr| (attr, None));
1168         Attributes::from_ast_iter(attrs1.chain(attrs2), false)
1169     }
1170
1171     pub(crate) fn from_ast_iter<'a>(
1172         attrs: impl Iterator<Item = (&'a ast::Attribute, Option<DefId>)>,
1173         doc_only: bool,
1174     ) -> Attributes {
1175         let mut doc_strings = Vec::new();
1176         let mut other_attrs = Vec::new();
1177         for (attr, parent_module) in attrs {
1178             if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() {
1179                 trace!("got doc_str={doc_str:?}");
1180                 let doc = beautify_doc_string(doc_str, comment_kind);
1181                 let kind = if attr.is_doc_comment() {
1182                     DocFragmentKind::SugaredDoc
1183                 } else {
1184                     DocFragmentKind::RawDoc
1185                 };
1186                 let fragment = DocFragment { span: attr.span, doc, kind, parent_module, indent: 0 };
1187                 doc_strings.push(fragment);
1188             } else if !doc_only {
1189                 other_attrs.push(attr.clone());
1190             }
1191         }
1192
1193         unindent_doc_fragments(&mut doc_strings);
1194
1195         Attributes { doc_strings, other_attrs }
1196     }
1197
1198     /// Finds the `doc` attribute as a NameValue and returns the corresponding
1199     /// value found.
1200     pub(crate) fn doc_value(&self) -> Option<String> {
1201         let mut iter = self.doc_strings.iter();
1202
1203         let ori = iter.next()?;
1204         let mut out = String::new();
1205         add_doc_fragment(&mut out, ori);
1206         for new_frag in iter {
1207             add_doc_fragment(&mut out, new_frag);
1208         }
1209         out.pop();
1210         if out.is_empty() { None } else { Some(out) }
1211     }
1212
1213     /// Return the doc-comments on this item, grouped by the module they came from.
1214     /// The module can be different if this is a re-export with added documentation.
1215     ///
1216     /// The last newline is not trimmed so the produced strings are reusable between
1217     /// early and late doc link resolution regardless of their position.
1218     pub(crate) fn prepare_to_doc_link_resolution(&self) -> FxHashMap<Option<DefId>, String> {
1219         let mut res = FxHashMap::default();
1220         for fragment in &self.doc_strings {
1221             let out_str = res.entry(fragment.parent_module).or_default();
1222             add_doc_fragment(out_str, fragment);
1223         }
1224         res
1225     }
1226
1227     /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
1228     /// with newlines.
1229     pub(crate) fn collapsed_doc_value(&self) -> Option<String> {
1230         if self.doc_strings.is_empty() {
1231             None
1232         } else {
1233             Some(collapse_doc_fragments(&self.doc_strings))
1234         }
1235     }
1236
1237     pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> {
1238         let mut aliases = FxHashSet::default();
1239
1240         for attr in self.other_attrs.lists(sym::doc).filter(|a| a.has_name(sym::alias)) {
1241             if let Some(values) = attr.meta_item_list() {
1242                 for l in values {
1243                     match l.literal().unwrap().kind {
1244                         ast::LitKind::Str(s, _) => {
1245                             aliases.insert(s);
1246                         }
1247                         _ => unreachable!(),
1248                     }
1249                 }
1250             } else {
1251                 aliases.insert(attr.value_str().unwrap());
1252             }
1253         }
1254         aliases.into_iter().collect::<Vec<_>>().into()
1255     }
1256 }
1257
1258 impl PartialEq for Attributes {
1259     fn eq(&self, rhs: &Self) -> bool {
1260         self.doc_strings == rhs.doc_strings
1261             && self
1262                 .other_attrs
1263                 .iter()
1264                 .map(|attr| attr.id)
1265                 .eq(rhs.other_attrs.iter().map(|attr| attr.id))
1266     }
1267 }
1268
1269 impl Eq for Attributes {}
1270
1271 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1272 pub(crate) enum GenericBound {
1273     TraitBound(PolyTrait, hir::TraitBoundModifier),
1274     Outlives(Lifetime),
1275 }
1276
1277 impl GenericBound {
1278     pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1279         let did = cx.tcx.require_lang_item(LangItem::Sized, None);
1280         let empty = cx.tcx.intern_substs(&[]);
1281         let path = external_path(cx, did, false, vec![], empty);
1282         inline::record_extern_fqn(cx, did, ItemType::Trait);
1283         GenericBound::TraitBound(
1284             PolyTrait { trait_: path, generic_params: Vec::new() },
1285             hir::TraitBoundModifier::Maybe,
1286         )
1287     }
1288
1289     pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1290         use rustc_hir::TraitBoundModifier as TBM;
1291         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
1292             if Some(trait_.def_id()) == cx.tcx.lang_items().sized_trait() {
1293                 return true;
1294             }
1295         }
1296         false
1297     }
1298
1299     pub(crate) fn get_poly_trait(&self) -> Option<PolyTrait> {
1300         if let GenericBound::TraitBound(ref p, _) = *self {
1301             return Some(p.clone());
1302         }
1303         None
1304     }
1305
1306     pub(crate) fn get_trait_path(&self) -> Option<Path> {
1307         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1308             Some(trait_.clone())
1309         } else {
1310             None
1311         }
1312     }
1313 }
1314
1315 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1316 pub(crate) struct Lifetime(pub Symbol);
1317
1318 impl Lifetime {
1319     pub(crate) fn statik() -> Lifetime {
1320         Lifetime(kw::StaticLifetime)
1321     }
1322
1323     pub(crate) fn elided() -> Lifetime {
1324         Lifetime(kw::UnderscoreLifetime)
1325     }
1326 }
1327
1328 #[derive(Clone, Debug)]
1329 pub(crate) enum WherePredicate {
1330     BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<Lifetime> },
1331     RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1332     EqPredicate { lhs: Type, rhs: Term },
1333 }
1334
1335 impl WherePredicate {
1336     pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1337         match *self {
1338             WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
1339             WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
1340             _ => None,
1341         }
1342     }
1343 }
1344
1345 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1346 pub(crate) enum GenericParamDefKind {
1347     Lifetime { outlives: Vec<Lifetime> },
1348     Type { did: DefId, bounds: Vec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
1349     Const { did: DefId, ty: Box<Type>, default: Option<Box<String>> },
1350 }
1351
1352 impl GenericParamDefKind {
1353     pub(crate) fn is_type(&self) -> bool {
1354         matches!(self, GenericParamDefKind::Type { .. })
1355     }
1356 }
1357
1358 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1359 pub(crate) struct GenericParamDef {
1360     pub(crate) name: Symbol,
1361     pub(crate) kind: GenericParamDefKind,
1362 }
1363
1364 impl GenericParamDef {
1365     pub(crate) fn is_synthetic_type_param(&self) -> bool {
1366         match self.kind {
1367             GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
1368             GenericParamDefKind::Type { synthetic, .. } => synthetic,
1369         }
1370     }
1371
1372     pub(crate) fn is_type(&self) -> bool {
1373         self.kind.is_type()
1374     }
1375
1376     pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1377         match self.kind {
1378             GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1379             _ => None,
1380         }
1381     }
1382 }
1383
1384 // maybe use a Generic enum and use Vec<Generic>?
1385 #[derive(Clone, Debug, Default)]
1386 pub(crate) struct Generics {
1387     pub(crate) params: Vec<GenericParamDef>,
1388     pub(crate) where_predicates: Vec<WherePredicate>,
1389 }
1390
1391 impl Generics {
1392     pub(crate) fn is_empty(&self) -> bool {
1393         self.params.is_empty() && self.where_predicates.is_empty()
1394     }
1395 }
1396
1397 #[derive(Clone, Debug)]
1398 pub(crate) struct Function {
1399     pub(crate) decl: FnDecl,
1400     pub(crate) generics: Generics,
1401 }
1402
1403 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1404 pub(crate) struct FnDecl {
1405     pub(crate) inputs: Arguments,
1406     pub(crate) output: FnRetTy,
1407     pub(crate) c_variadic: bool,
1408 }
1409
1410 impl FnDecl {
1411     pub(crate) fn self_type(&self) -> Option<SelfTy> {
1412         self.inputs.values.get(0).and_then(|v| v.to_self())
1413     }
1414
1415     /// Returns the sugared return type for an async function.
1416     ///
1417     /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
1418     /// will return `i32`.
1419     ///
1420     /// # Panics
1421     ///
1422     /// This function will panic if the return type does not match the expected sugaring for async
1423     /// functions.
1424     pub(crate) fn sugared_async_return_type(&self) -> FnRetTy {
1425         match &self.output {
1426             FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
1427                 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
1428                     let bindings = trait_.bindings().unwrap();
1429                     let ret_ty = bindings[0].term();
1430                     let ty = ret_ty.ty().expect("Unexpected constant return term");
1431                     FnRetTy::Return(ty.clone())
1432                 }
1433                 _ => panic!("unexpected desugaring of async function"),
1434             },
1435             _ => panic!("unexpected desugaring of async function"),
1436         }
1437     }
1438 }
1439
1440 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1441 pub(crate) struct Arguments {
1442     pub(crate) values: Vec<Argument>,
1443 }
1444
1445 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1446 pub(crate) struct Argument {
1447     pub(crate) type_: Type,
1448     pub(crate) name: Symbol,
1449     /// This field is used to represent "const" arguments from the `rustc_legacy_const_generics`
1450     /// feature. More information in <https://github.com/rust-lang/rust/issues/83167>.
1451     pub(crate) is_const: bool,
1452 }
1453
1454 #[derive(Clone, PartialEq, Debug)]
1455 pub(crate) enum SelfTy {
1456     SelfValue,
1457     SelfBorrowed(Option<Lifetime>, Mutability),
1458     SelfExplicit(Type),
1459 }
1460
1461 impl Argument {
1462     pub(crate) fn to_self(&self) -> Option<SelfTy> {
1463         if self.name != kw::SelfLower {
1464             return None;
1465         }
1466         if self.type_.is_self_type() {
1467             return Some(SelfValue);
1468         }
1469         match self.type_ {
1470             BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
1471                 Some(SelfBorrowed(lifetime.clone(), mutability))
1472             }
1473             _ => Some(SelfExplicit(self.type_.clone())),
1474         }
1475     }
1476 }
1477
1478 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1479 pub(crate) enum FnRetTy {
1480     Return(Type),
1481     DefaultReturn,
1482 }
1483
1484 impl FnRetTy {
1485     pub(crate) fn as_return(&self) -> Option<&Type> {
1486         match self {
1487             Return(ret) => Some(ret),
1488             DefaultReturn => None,
1489         }
1490     }
1491 }
1492
1493 #[derive(Clone, Debug)]
1494 pub(crate) struct Trait {
1495     pub(crate) def_id: DefId,
1496     pub(crate) items: Vec<Item>,
1497     pub(crate) generics: Generics,
1498     pub(crate) bounds: Vec<GenericBound>,
1499 }
1500
1501 impl Trait {
1502     pub(crate) fn is_auto(&self, tcx: TyCtxt<'_>) -> bool {
1503         tcx.trait_is_auto(self.def_id)
1504     }
1505     pub(crate) fn unsafety(&self, tcx: TyCtxt<'_>) -> hir::Unsafety {
1506         tcx.trait_def(self.def_id).unsafety
1507     }
1508 }
1509
1510 #[derive(Clone, Debug)]
1511 pub(crate) struct TraitAlias {
1512     pub(crate) generics: Generics,
1513     pub(crate) bounds: Vec<GenericBound>,
1514 }
1515
1516 /// A trait reference, which may have higher ranked lifetimes.
1517 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1518 pub(crate) struct PolyTrait {
1519     pub(crate) trait_: Path,
1520     pub(crate) generic_params: Vec<GenericParamDef>,
1521 }
1522
1523 /// Rustdoc's representation of types, mostly based on the [`hir::Ty`].
1524 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1525 pub(crate) enum Type {
1526     /// A named type, which could be a trait.
1527     ///
1528     /// This is mostly Rustdoc's version of [`hir::Path`].
1529     /// It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics.
1530     Path { path: Path },
1531     /// A `dyn Trait` object: `dyn for<'a> Trait<'a> + Send + 'static`
1532     DynTrait(Vec<PolyTrait>, Option<Lifetime>),
1533     /// A type parameter.
1534     Generic(Symbol),
1535     /// A primitive (aka, builtin) type.
1536     Primitive(PrimitiveType),
1537     /// A function pointer: `extern "ABI" fn(...) -> ...`
1538     BareFunction(Box<BareFunctionDecl>),
1539     /// A tuple type: `(i32, &str)`.
1540     Tuple(Vec<Type>),
1541     /// A slice type (does *not* include the `&`): `[i32]`
1542     Slice(Box<Type>),
1543     /// An array type.
1544     ///
1545     /// The `String` field is a stringified version of the array's length parameter.
1546     Array(Box<Type>, String),
1547     /// A raw pointer type: `*const i32`, `*mut i32`
1548     RawPointer(Mutability, Box<Type>),
1549     /// A reference type: `&i32`, `&'a mut Foo`
1550     BorrowedRef { lifetime: Option<Lifetime>, mutability: Mutability, type_: Box<Type> },
1551
1552     /// A qualified path to an associated item: `<Type as Trait>::Name`
1553     QPath {
1554         assoc: Box<PathSegment>,
1555         self_type: Box<Type>,
1556         /// FIXME: compute this field on demand.
1557         should_show_cast: bool,
1558         trait_: Path,
1559     },
1560
1561     /// A type that is inferred: `_`
1562     Infer,
1563
1564     /// An `impl Trait`: `impl TraitA + TraitB + ...`
1565     ImplTrait(Vec<GenericBound>),
1566 }
1567
1568 impl Type {
1569     /// When comparing types for equality, it can help to ignore `&` wrapping.
1570     pub(crate) fn without_borrowed_ref(&self) -> &Type {
1571         let mut result = self;
1572         while let Type::BorrowedRef { type_, .. } = result {
1573             result = &*type_;
1574         }
1575         result
1576     }
1577
1578     /// Check if two types are "potentially the same".
1579     /// This is different from `Eq`, because it knows that things like
1580     /// `Placeholder` are possible matches for everything.
1581     pub(crate) fn is_same(&self, other: &Self, cache: &Cache) -> bool {
1582         match (self, other) {
1583             // Recursive cases.
1584             (Type::Tuple(a), Type::Tuple(b)) => {
1585                 a.len() == b.len() && a.iter().zip(b).all(|(a, b)| a.is_same(b, cache))
1586             }
1587             (Type::Slice(a), Type::Slice(b)) => a.is_same(b, cache),
1588             (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_same(b, cache),
1589             (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
1590                 mutability == b_mutability && type_.is_same(b_type_, cache)
1591             }
1592             (
1593                 Type::BorrowedRef { mutability, type_, .. },
1594                 Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
1595             ) => mutability == b_mutability && type_.is_same(b_type_, cache),
1596             // Placeholders and generics are equal to all other types.
1597             (Type::Infer, _) | (_, Type::Infer) => true,
1598             (Type::Generic(_), _) | (_, Type::Generic(_)) => true,
1599             // Other cases, such as primitives, just use recursion.
1600             (a, b) => a
1601                 .def_id(cache)
1602                 .and_then(|a| Some((a, b.def_id(cache)?)))
1603                 .map(|(a, b)| a == b)
1604                 .unwrap_or(false),
1605         }
1606     }
1607
1608     pub(crate) fn primitive_type(&self) -> Option<PrimitiveType> {
1609         match *self {
1610             Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1611             Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1612             Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1613             Tuple(ref tys) => {
1614                 if tys.is_empty() {
1615                     Some(PrimitiveType::Unit)
1616                 } else {
1617                     Some(PrimitiveType::Tuple)
1618                 }
1619             }
1620             RawPointer(..) => Some(PrimitiveType::RawPointer),
1621             BareFunction(..) => Some(PrimitiveType::Fn),
1622             _ => None,
1623         }
1624     }
1625
1626     /// Checks if this is a `T::Name` path for an associated type.
1627     pub(crate) fn is_assoc_ty(&self) -> bool {
1628         match self {
1629             Type::Path { path, .. } => path.is_assoc_ty(),
1630             _ => false,
1631         }
1632     }
1633
1634     pub(crate) fn is_self_type(&self) -> bool {
1635         match *self {
1636             Generic(name) => name == kw::SelfUpper,
1637             _ => false,
1638         }
1639     }
1640
1641     pub(crate) fn generics(&self) -> Option<Vec<&Type>> {
1642         match self {
1643             Type::Path { path, .. } => path.generics(),
1644             _ => None,
1645         }
1646     }
1647
1648     pub(crate) fn is_full_generic(&self) -> bool {
1649         matches!(self, Type::Generic(_))
1650     }
1651
1652     pub(crate) fn is_impl_trait(&self) -> bool {
1653         matches!(self, Type::ImplTrait(_))
1654     }
1655
1656     pub(crate) fn projection(&self) -> Option<(&Type, DefId, PathSegment)> {
1657         if let QPath { self_type, trait_, assoc, .. } = self {
1658             Some((self_type, trait_.def_id(), *assoc.clone()))
1659         } else {
1660             None
1661         }
1662     }
1663
1664     fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
1665         let t: PrimitiveType = match *self {
1666             Type::Path { ref path } => return Some(path.def_id()),
1667             DynTrait(ref bounds, _) => return Some(bounds[0].trait_.def_id()),
1668             Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
1669             BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
1670             BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache),
1671             Tuple(ref tys) => {
1672                 if tys.is_empty() {
1673                     PrimitiveType::Unit
1674                 } else {
1675                     PrimitiveType::Tuple
1676                 }
1677             }
1678             BareFunction(..) => PrimitiveType::Fn,
1679             Slice(..) => PrimitiveType::Slice,
1680             Array(..) => PrimitiveType::Array,
1681             RawPointer(..) => PrimitiveType::RawPointer,
1682             QPath { ref self_type, .. } => return self_type.inner_def_id(cache),
1683             Generic(_) | Infer | ImplTrait(_) => return None,
1684         };
1685         cache.and_then(|c| Primitive(t).def_id(c))
1686     }
1687
1688     /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s.
1689     ///
1690     /// [clean]: crate::clean
1691     pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
1692         self.inner_def_id(Some(cache))
1693     }
1694 }
1695
1696 /// A primitive (aka, builtin) type.
1697 ///
1698 /// This represents things like `i32`, `str`, etc.
1699 ///
1700 /// N.B. This has to be different from [`hir::PrimTy`] because it also includes types that aren't
1701 /// paths, like [`Self::Unit`].
1702 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1703 pub(crate) enum PrimitiveType {
1704     Isize,
1705     I8,
1706     I16,
1707     I32,
1708     I64,
1709     I128,
1710     Usize,
1711     U8,
1712     U16,
1713     U32,
1714     U64,
1715     U128,
1716     F32,
1717     F64,
1718     Char,
1719     Bool,
1720     Str,
1721     Slice,
1722     Array,
1723     Tuple,
1724     Unit,
1725     RawPointer,
1726     Reference,
1727     Fn,
1728     Never,
1729 }
1730
1731 type SimplifiedTypes = FxHashMap<PrimitiveType, ArrayVec<SimplifiedType, 3>>;
1732 impl PrimitiveType {
1733     pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1734         use ast::{FloatTy, IntTy, UintTy};
1735         match prim {
1736             hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1737             hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1738             hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1739             hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1740             hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1741             hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1742             hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1743             hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1744             hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1745             hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1746             hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1747             hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1748             hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1749             hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1750             hir::PrimTy::Str => PrimitiveType::Str,
1751             hir::PrimTy::Bool => PrimitiveType::Bool,
1752             hir::PrimTy::Char => PrimitiveType::Char,
1753         }
1754     }
1755
1756     pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1757         match s {
1758             sym::isize => Some(PrimitiveType::Isize),
1759             sym::i8 => Some(PrimitiveType::I8),
1760             sym::i16 => Some(PrimitiveType::I16),
1761             sym::i32 => Some(PrimitiveType::I32),
1762             sym::i64 => Some(PrimitiveType::I64),
1763             sym::i128 => Some(PrimitiveType::I128),
1764             sym::usize => Some(PrimitiveType::Usize),
1765             sym::u8 => Some(PrimitiveType::U8),
1766             sym::u16 => Some(PrimitiveType::U16),
1767             sym::u32 => Some(PrimitiveType::U32),
1768             sym::u64 => Some(PrimitiveType::U64),
1769             sym::u128 => Some(PrimitiveType::U128),
1770             sym::bool => Some(PrimitiveType::Bool),
1771             sym::char => Some(PrimitiveType::Char),
1772             sym::str => Some(PrimitiveType::Str),
1773             sym::f32 => Some(PrimitiveType::F32),
1774             sym::f64 => Some(PrimitiveType::F64),
1775             sym::array => Some(PrimitiveType::Array),
1776             sym::slice => Some(PrimitiveType::Slice),
1777             sym::tuple => Some(PrimitiveType::Tuple),
1778             sym::unit => Some(PrimitiveType::Unit),
1779             sym::pointer => Some(PrimitiveType::RawPointer),
1780             sym::reference => Some(PrimitiveType::Reference),
1781             kw::Fn => Some(PrimitiveType::Fn),
1782             sym::never => Some(PrimitiveType::Never),
1783             _ => None,
1784         }
1785     }
1786
1787     pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
1788         use ty::fast_reject::SimplifiedTypeGen::*;
1789         use ty::{FloatTy, IntTy, UintTy};
1790         use PrimitiveType::*;
1791         static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
1792
1793         let single = |x| iter::once(x).collect();
1794         CELL.get_or_init(move || {
1795             map! {
1796                 Isize => single(IntSimplifiedType(IntTy::Isize)),
1797                 I8 => single(IntSimplifiedType(IntTy::I8)),
1798                 I16 => single(IntSimplifiedType(IntTy::I16)),
1799                 I32 => single(IntSimplifiedType(IntTy::I32)),
1800                 I64 => single(IntSimplifiedType(IntTy::I64)),
1801                 I128 => single(IntSimplifiedType(IntTy::I128)),
1802                 Usize => single(UintSimplifiedType(UintTy::Usize)),
1803                 U8 => single(UintSimplifiedType(UintTy::U8)),
1804                 U16 => single(UintSimplifiedType(UintTy::U16)),
1805                 U32 => single(UintSimplifiedType(UintTy::U32)),
1806                 U64 => single(UintSimplifiedType(UintTy::U64)),
1807                 U128 => single(UintSimplifiedType(UintTy::U128)),
1808                 F32 => single(FloatSimplifiedType(FloatTy::F32)),
1809                 F64 => single(FloatSimplifiedType(FloatTy::F64)),
1810                 Str => single(StrSimplifiedType),
1811                 Bool => single(BoolSimplifiedType),
1812                 Char => single(CharSimplifiedType),
1813                 Array => single(ArraySimplifiedType),
1814                 Slice => single(SliceSimplifiedType),
1815                 // FIXME: If we ever add an inherent impl for tuples
1816                 // with different lengths, they won't show in rustdoc.
1817                 //
1818                 // Either manually update this arrayvec at this point
1819                 // or start with a more complex refactoring.
1820                 Tuple => [TupleSimplifiedType(1), TupleSimplifiedType(2), TupleSimplifiedType(3)].into(),
1821                 Unit => single(TupleSimplifiedType(0)),
1822                 RawPointer => [PtrSimplifiedType(Mutability::Not), PtrSimplifiedType(Mutability::Mut)].into_iter().collect(),
1823                 Reference => [RefSimplifiedType(Mutability::Not), RefSimplifiedType(Mutability::Mut)].into_iter().collect(),
1824                 // FIXME: This will be wrong if we ever add inherent impls
1825                 // for function pointers.
1826                 Fn => single(FunctionSimplifiedType(1)),
1827                 Never => single(NeverSimplifiedType),
1828             }
1829         })
1830     }
1831
1832     pub(crate) fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = DefId> + 'tcx {
1833         Self::simplified_types()
1834             .get(self)
1835             .into_iter()
1836             .flatten()
1837             .flat_map(move |&simp| tcx.incoherent_impls(simp))
1838             .copied()
1839     }
1840
1841     pub(crate) fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> + '_ {
1842         Self::simplified_types()
1843             .values()
1844             .flatten()
1845             .flat_map(move |&simp| tcx.incoherent_impls(simp))
1846             .copied()
1847     }
1848
1849     pub(crate) fn as_sym(&self) -> Symbol {
1850         use PrimitiveType::*;
1851         match self {
1852             Isize => sym::isize,
1853             I8 => sym::i8,
1854             I16 => sym::i16,
1855             I32 => sym::i32,
1856             I64 => sym::i64,
1857             I128 => sym::i128,
1858             Usize => sym::usize,
1859             U8 => sym::u8,
1860             U16 => sym::u16,
1861             U32 => sym::u32,
1862             U64 => sym::u64,
1863             U128 => sym::u128,
1864             F32 => sym::f32,
1865             F64 => sym::f64,
1866             Str => sym::str,
1867             Bool => sym::bool,
1868             Char => sym::char,
1869             Array => sym::array,
1870             Slice => sym::slice,
1871             Tuple => sym::tuple,
1872             Unit => sym::unit,
1873             RawPointer => sym::pointer,
1874             Reference => sym::reference,
1875             Fn => kw::Fn,
1876             Never => sym::never,
1877         }
1878     }
1879
1880     /// Returns the DefId of the module with `doc(primitive)` for this primitive type.
1881     /// Panics if there is no such module.
1882     ///
1883     /// This gives precedence to primitives defined in the current crate, and deprioritizes primitives defined in `core`,
1884     /// but otherwise, if multiple crates define the same primitive, there is no guarantee of which will be picked.
1885     /// In particular, if a crate depends on both `std` and another crate that also defines `doc(primitive)`, then
1886     /// it's entirely random whether `std` or the other crate is picked. (no_std crates are usually fine unless multiple dependencies define a primitive.)
1887     pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxHashMap<PrimitiveType, DefId> {
1888         static PRIMITIVE_LOCATIONS: OnceCell<FxHashMap<PrimitiveType, DefId>> = OnceCell::new();
1889         PRIMITIVE_LOCATIONS.get_or_init(|| {
1890             let mut primitive_locations = FxHashMap::default();
1891             // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate.
1892             // This is a degenerate case that I don't plan to support.
1893             for &crate_num in tcx.crates(()) {
1894                 let e = ExternalCrate { crate_num };
1895                 let crate_name = e.name(tcx);
1896                 debug!(?crate_num, ?crate_name);
1897                 for &(def_id, prim) in &e.primitives(tcx) {
1898                     // HACK: try to link to std instead where possible
1899                     if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1900                         continue;
1901                     }
1902                     primitive_locations.insert(prim, def_id);
1903                 }
1904             }
1905             let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1906             for (def_id, prim) in local_primitives {
1907                 primitive_locations.insert(prim, def_id);
1908             }
1909             primitive_locations
1910         })
1911     }
1912 }
1913
1914 impl From<ast::IntTy> for PrimitiveType {
1915     fn from(int_ty: ast::IntTy) -> PrimitiveType {
1916         match int_ty {
1917             ast::IntTy::Isize => PrimitiveType::Isize,
1918             ast::IntTy::I8 => PrimitiveType::I8,
1919             ast::IntTy::I16 => PrimitiveType::I16,
1920             ast::IntTy::I32 => PrimitiveType::I32,
1921             ast::IntTy::I64 => PrimitiveType::I64,
1922             ast::IntTy::I128 => PrimitiveType::I128,
1923         }
1924     }
1925 }
1926
1927 impl From<ast::UintTy> for PrimitiveType {
1928     fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1929         match uint_ty {
1930             ast::UintTy::Usize => PrimitiveType::Usize,
1931             ast::UintTy::U8 => PrimitiveType::U8,
1932             ast::UintTy::U16 => PrimitiveType::U16,
1933             ast::UintTy::U32 => PrimitiveType::U32,
1934             ast::UintTy::U64 => PrimitiveType::U64,
1935             ast::UintTy::U128 => PrimitiveType::U128,
1936         }
1937     }
1938 }
1939
1940 impl From<ast::FloatTy> for PrimitiveType {
1941     fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1942         match float_ty {
1943             ast::FloatTy::F32 => PrimitiveType::F32,
1944             ast::FloatTy::F64 => PrimitiveType::F64,
1945         }
1946     }
1947 }
1948
1949 impl From<ty::IntTy> for PrimitiveType {
1950     fn from(int_ty: ty::IntTy) -> PrimitiveType {
1951         match int_ty {
1952             ty::IntTy::Isize => PrimitiveType::Isize,
1953             ty::IntTy::I8 => PrimitiveType::I8,
1954             ty::IntTy::I16 => PrimitiveType::I16,
1955             ty::IntTy::I32 => PrimitiveType::I32,
1956             ty::IntTy::I64 => PrimitiveType::I64,
1957             ty::IntTy::I128 => PrimitiveType::I128,
1958         }
1959     }
1960 }
1961
1962 impl From<ty::UintTy> for PrimitiveType {
1963     fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1964         match uint_ty {
1965             ty::UintTy::Usize => PrimitiveType::Usize,
1966             ty::UintTy::U8 => PrimitiveType::U8,
1967             ty::UintTy::U16 => PrimitiveType::U16,
1968             ty::UintTy::U32 => PrimitiveType::U32,
1969             ty::UintTy::U64 => PrimitiveType::U64,
1970             ty::UintTy::U128 => PrimitiveType::U128,
1971         }
1972     }
1973 }
1974
1975 impl From<ty::FloatTy> for PrimitiveType {
1976     fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1977         match float_ty {
1978             ty::FloatTy::F32 => PrimitiveType::F32,
1979             ty::FloatTy::F64 => PrimitiveType::F64,
1980         }
1981     }
1982 }
1983
1984 impl From<hir::PrimTy> for PrimitiveType {
1985     fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1986         match prim_ty {
1987             hir::PrimTy::Int(int_ty) => int_ty.into(),
1988             hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1989             hir::PrimTy::Float(float_ty) => float_ty.into(),
1990             hir::PrimTy::Str => PrimitiveType::Str,
1991             hir::PrimTy::Bool => PrimitiveType::Bool,
1992             hir::PrimTy::Char => PrimitiveType::Char,
1993         }
1994     }
1995 }
1996
1997 #[derive(Copy, Clone, Debug)]
1998 pub(crate) enum Visibility {
1999     /// `pub`
2000     Public,
2001     /// Visibility inherited from parent.
2002     ///
2003     /// For example, this is the visibility of private items and of enum variants.
2004     Inherited,
2005     /// `pub(crate)`, `pub(super)`, or `pub(in path::to::somewhere)`
2006     Restricted(DefId),
2007 }
2008
2009 impl Visibility {
2010     pub(crate) fn is_public(&self) -> bool {
2011         matches!(self, Visibility::Public)
2012     }
2013 }
2014
2015 #[derive(Clone, Debug)]
2016 pub(crate) struct Struct {
2017     pub(crate) struct_type: CtorKind,
2018     pub(crate) generics: Generics,
2019     pub(crate) fields: Vec<Item>,
2020 }
2021
2022 impl Struct {
2023     pub(crate) fn has_stripped_entries(&self) -> bool {
2024         self.fields.iter().any(|f| f.is_stripped())
2025     }
2026 }
2027
2028 #[derive(Clone, Debug)]
2029 pub(crate) struct Union {
2030     pub(crate) generics: Generics,
2031     pub(crate) fields: Vec<Item>,
2032 }
2033
2034 impl Union {
2035     pub(crate) fn has_stripped_entries(&self) -> bool {
2036         self.fields.iter().any(|f| f.is_stripped())
2037     }
2038 }
2039
2040 /// This is a more limited form of the standard Struct, different in that
2041 /// it lacks the things most items have (name, id, parameterization). Found
2042 /// only as a variant in an enum.
2043 #[derive(Clone, Debug)]
2044 pub(crate) struct VariantStruct {
2045     pub(crate) struct_type: CtorKind,
2046     pub(crate) fields: Vec<Item>,
2047 }
2048
2049 impl VariantStruct {
2050     pub(crate) fn has_stripped_entries(&self) -> bool {
2051         self.fields.iter().any(|f| f.is_stripped())
2052     }
2053 }
2054
2055 #[derive(Clone, Debug)]
2056 pub(crate) struct Enum {
2057     pub(crate) variants: IndexVec<VariantIdx, Item>,
2058     pub(crate) generics: Generics,
2059 }
2060
2061 impl Enum {
2062     pub(crate) fn has_stripped_entries(&self) -> bool {
2063         self.variants.iter().any(|f| f.is_stripped())
2064     }
2065
2066     pub(crate) fn variants(&self) -> impl Iterator<Item = &Item> {
2067         self.variants.iter().filter(|v| !v.is_stripped())
2068     }
2069 }
2070
2071 #[derive(Clone, Debug)]
2072 pub(crate) enum Variant {
2073     CLike,
2074     Tuple(Vec<Item>),
2075     Struct(VariantStruct),
2076 }
2077
2078 impl Variant {
2079     pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
2080         match *self {
2081             Self::Struct(ref struct_) => Some(struct_.has_stripped_entries()),
2082             Self::CLike | Self::Tuple(_) => None,
2083         }
2084     }
2085 }
2086
2087 /// Small wrapper around [`rustc_span::Span`] that adds helper methods
2088 /// and enforces calling [`rustc_span::Span::source_callsite()`].
2089 #[derive(Copy, Clone, Debug)]
2090 pub(crate) struct Span(rustc_span::Span);
2091
2092 impl Span {
2093     /// Wraps a [`rustc_span::Span`]. In case this span is the result of a macro expansion, the
2094     /// span will be updated to point to the macro invocation instead of the macro definition.
2095     ///
2096     /// (See rust-lang/rust#39726)
2097     pub(crate) fn new(sp: rustc_span::Span) -> Self {
2098         Self(sp.source_callsite())
2099     }
2100
2101     pub(crate) fn inner(&self) -> rustc_span::Span {
2102         self.0
2103     }
2104
2105     pub(crate) fn filename(&self, sess: &Session) -> FileName {
2106         sess.source_map().span_to_filename(self.0)
2107     }
2108
2109     pub(crate) fn lo(&self, sess: &Session) -> Loc {
2110         sess.source_map().lookup_char_pos(self.0.lo())
2111     }
2112
2113     pub(crate) fn hi(&self, sess: &Session) -> Loc {
2114         sess.source_map().lookup_char_pos(self.0.hi())
2115     }
2116
2117     pub(crate) fn cnum(&self, sess: &Session) -> CrateNum {
2118         // FIXME: is there a time when the lo and hi crate would be different?
2119         self.lo(sess).file.cnum
2120     }
2121 }
2122
2123 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2124 pub(crate) struct Path {
2125     pub(crate) res: Res,
2126     pub(crate) segments: Vec<PathSegment>,
2127 }
2128
2129 impl Path {
2130     pub(crate) fn def_id(&self) -> DefId {
2131         self.res.def_id()
2132     }
2133
2134     pub(crate) fn last_opt(&self) -> Option<Symbol> {
2135         self.segments.last().map(|s| s.name)
2136     }
2137
2138     pub(crate) fn last(&self) -> Symbol {
2139         self.last_opt().expect("segments were empty")
2140     }
2141
2142     pub(crate) fn whole_name(&self) -> String {
2143         self.segments
2144             .iter()
2145             .map(|s| if s.name == kw::PathRoot { "" } else { s.name.as_str() })
2146             .intersperse("::")
2147             .collect()
2148     }
2149
2150     /// Checks if this is a `T::Name` path for an associated type.
2151     pub(crate) fn is_assoc_ty(&self) -> bool {
2152         match self.res {
2153             Res::SelfTy { .. } if self.segments.len() != 1 => true,
2154             Res::Def(DefKind::TyParam, _) if self.segments.len() != 1 => true,
2155             Res::Def(DefKind::AssocTy, _) => true,
2156             _ => false,
2157         }
2158     }
2159
2160     pub(crate) fn generics(&self) -> Option<Vec<&Type>> {
2161         self.segments.last().and_then(|seg| {
2162             if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2163                 Some(
2164                     args.iter()
2165                         .filter_map(|arg| match arg {
2166                             GenericArg::Type(ty) => Some(ty),
2167                             _ => None,
2168                         })
2169                         .collect(),
2170                 )
2171             } else {
2172                 None
2173             }
2174         })
2175     }
2176
2177     pub(crate) fn bindings(&self) -> Option<&[TypeBinding]> {
2178         self.segments.last().and_then(|seg| {
2179             if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
2180                 Some(&**bindings)
2181             } else {
2182                 None
2183             }
2184         })
2185     }
2186 }
2187
2188 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2189 pub(crate) enum GenericArg {
2190     Lifetime(Lifetime),
2191     Type(Type),
2192     Const(Box<Constant>),
2193     Infer,
2194 }
2195
2196 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2197 pub(crate) enum GenericArgs {
2198     AngleBracketed { args: Box<[GenericArg]>, bindings: ThinVec<TypeBinding> },
2199     Parenthesized { inputs: Box<[Type]>, output: Option<Box<Type>> },
2200 }
2201
2202 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2203 pub(crate) struct PathSegment {
2204     pub(crate) name: Symbol,
2205     pub(crate) args: GenericArgs,
2206 }
2207
2208 #[derive(Clone, Debug)]
2209 pub(crate) struct Typedef {
2210     pub(crate) type_: Type,
2211     pub(crate) generics: Generics,
2212     /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
2213     /// alias instead of the final type. This will always have the final type, regardless of whether
2214     /// `type_` came from HIR or from metadata.
2215     ///
2216     /// If `item_type.is_none()`, `type_` is guaranteed to come from metadata (and therefore hold the
2217     /// final type).
2218     pub(crate) item_type: Option<Type>,
2219 }
2220
2221 #[derive(Clone, Debug)]
2222 pub(crate) struct OpaqueTy {
2223     pub(crate) bounds: Vec<GenericBound>,
2224     pub(crate) generics: Generics,
2225 }
2226
2227 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2228 pub(crate) struct BareFunctionDecl {
2229     pub(crate) unsafety: hir::Unsafety,
2230     pub(crate) generic_params: Vec<GenericParamDef>,
2231     pub(crate) decl: FnDecl,
2232     pub(crate) abi: Abi,
2233 }
2234
2235 #[derive(Clone, Debug)]
2236 pub(crate) struct Static {
2237     pub(crate) type_: Type,
2238     pub(crate) mutability: Mutability,
2239     pub(crate) expr: Option<BodyId>,
2240 }
2241
2242 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2243 pub(crate) struct Constant {
2244     pub(crate) type_: Type,
2245     pub(crate) kind: ConstantKind,
2246 }
2247
2248 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2249 pub(crate) enum Term {
2250     Type(Type),
2251     Constant(Constant),
2252 }
2253
2254 impl Term {
2255     pub(crate) fn ty(&self) -> Option<&Type> {
2256         if let Term::Type(ty) = self { Some(ty) } else { None }
2257     }
2258 }
2259
2260 impl From<Type> for Term {
2261     fn from(ty: Type) -> Self {
2262         Term::Type(ty)
2263     }
2264 }
2265
2266 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2267 pub(crate) enum ConstantKind {
2268     /// This is the wrapper around `ty::Const` for a non-local constant. Because it doesn't have a
2269     /// `BodyId`, we need to handle it on its own.
2270     ///
2271     /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified
2272     /// by a DefId. So this field must be different from `Extern`.
2273     TyConst { expr: String },
2274     /// A constant (expression) that's not an item or associated item. These are usually found
2275     /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
2276     /// used to define explicit discriminant values for enum variants.
2277     Anonymous { body: BodyId },
2278     /// A constant from a different crate.
2279     Extern { def_id: DefId },
2280     /// `const FOO: u32 = ...;`
2281     Local { def_id: DefId, body: BodyId },
2282 }
2283
2284 impl Constant {
2285     pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2286         self.kind.expr(tcx)
2287     }
2288
2289     pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2290         self.kind.value(tcx)
2291     }
2292
2293     pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2294         self.kind.is_literal(tcx)
2295     }
2296 }
2297
2298 impl ConstantKind {
2299     pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2300         match *self {
2301             ConstantKind::TyConst { ref expr } => expr.clone(),
2302             ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2303             ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2304                 print_const_expr(tcx, body)
2305             }
2306         }
2307     }
2308
2309     pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2310         match *self {
2311             ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
2312             ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2313                 print_evaluated_const(tcx, def_id)
2314             }
2315         }
2316     }
2317
2318     pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2319         match *self {
2320             ConstantKind::TyConst { .. } => false,
2321             ConstantKind::Extern { def_id } => def_id.as_local().map_or(false, |def_id| {
2322                 is_literal_expr(tcx, tcx.hir().local_def_id_to_hir_id(def_id))
2323             }),
2324             ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2325                 is_literal_expr(tcx, body.hir_id)
2326             }
2327         }
2328     }
2329 }
2330
2331 #[derive(Clone, Debug)]
2332 pub(crate) struct Impl {
2333     pub(crate) unsafety: hir::Unsafety,
2334     pub(crate) generics: Generics,
2335     pub(crate) trait_: Option<Path>,
2336     pub(crate) for_: Type,
2337     pub(crate) items: Vec<Item>,
2338     pub(crate) polarity: ty::ImplPolarity,
2339     pub(crate) kind: ImplKind,
2340 }
2341
2342 impl Impl {
2343     pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxHashSet<Symbol> {
2344         self.trait_
2345             .as_ref()
2346             .map(|t| t.def_id())
2347             .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name).collect())
2348             .unwrap_or_default()
2349     }
2350 }
2351
2352 #[derive(Clone, Debug)]
2353 pub(crate) enum ImplKind {
2354     Normal,
2355     Auto,
2356     FakeVaradic,
2357     Blanket(Box<Type>),
2358 }
2359
2360 impl ImplKind {
2361     pub(crate) fn is_auto(&self) -> bool {
2362         matches!(self, ImplKind::Auto)
2363     }
2364
2365     pub(crate) fn is_blanket(&self) -> bool {
2366         matches!(self, ImplKind::Blanket(_))
2367     }
2368
2369     pub(crate) fn is_fake_variadic(&self) -> bool {
2370         matches!(self, ImplKind::FakeVaradic)
2371     }
2372
2373     pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
2374         match self {
2375             ImplKind::Blanket(ty) => Some(ty),
2376             _ => None,
2377         }
2378     }
2379 }
2380
2381 #[derive(Clone, Debug)]
2382 pub(crate) struct Import {
2383     pub(crate) kind: ImportKind,
2384     pub(crate) source: ImportSource,
2385     pub(crate) should_be_displayed: bool,
2386 }
2387
2388 impl Import {
2389     pub(crate) fn new_simple(
2390         name: Symbol,
2391         source: ImportSource,
2392         should_be_displayed: bool,
2393     ) -> Self {
2394         Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2395     }
2396
2397     pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2398         Self { kind: ImportKind::Glob, source, should_be_displayed }
2399     }
2400 }
2401
2402 #[derive(Clone, Debug)]
2403 pub(crate) enum ImportKind {
2404     // use source as str;
2405     Simple(Symbol),
2406     // use source::*;
2407     Glob,
2408 }
2409
2410 #[derive(Clone, Debug)]
2411 pub(crate) struct ImportSource {
2412     pub(crate) path: Path,
2413     pub(crate) did: Option<DefId>,
2414 }
2415
2416 #[derive(Clone, Debug)]
2417 pub(crate) struct Macro {
2418     pub(crate) source: String,
2419 }
2420
2421 #[derive(Clone, Debug)]
2422 pub(crate) struct ProcMacro {
2423     pub(crate) kind: MacroKind,
2424     pub(crate) helpers: Vec<Symbol>,
2425 }
2426
2427 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
2428 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
2429 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2430 pub(crate) struct TypeBinding {
2431     pub(crate) assoc: PathSegment,
2432     pub(crate) kind: TypeBindingKind,
2433 }
2434
2435 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2436 pub(crate) enum TypeBindingKind {
2437     Equality { term: Term },
2438     Constraint { bounds: Vec<GenericBound> },
2439 }
2440
2441 impl TypeBinding {
2442     pub(crate) fn term(&self) -> &Term {
2443         match self.kind {
2444             TypeBindingKind::Equality { ref term } => term,
2445             _ => panic!("expected equality type binding for parenthesized generic args"),
2446         }
2447     }
2448 }
2449
2450 /// The type, lifetime, or constant that a private type alias's parameter should be
2451 /// replaced with when expanding a use of that type alias.
2452 ///
2453 /// For example:
2454 ///
2455 /// ```
2456 /// type PrivAlias<T> = Vec<T>;
2457 ///
2458 /// pub fn public_fn() -> PrivAlias<i32> { vec![] }
2459 /// ```
2460 ///
2461 /// `public_fn`'s docs will show it as returning `Vec<i32>`, since `PrivAlias` is private.
2462 /// [`SubstParam`] is used to record that `T` should be mapped to `i32`.
2463 pub(crate) enum SubstParam {
2464     Type(Type),
2465     Lifetime(Lifetime),
2466     Constant(Constant),
2467 }
2468
2469 impl SubstParam {
2470     pub(crate) fn as_ty(&self) -> Option<&Type> {
2471         if let Self::Type(ty) = self { Some(ty) } else { None }
2472     }
2473
2474     pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
2475         if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2476     }
2477 }
2478
2479 // Some nodes are used a lot. Make sure they don't unintentionally get bigger.
2480 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2481 mod size_asserts {
2482     use super::*;
2483     use rustc_data_structures::static_assert_size;
2484     // These are in alphabetical order, which is easy to maintain.
2485     static_assert_size!(Crate, 72); // frequently moved by-value
2486     static_assert_size!(DocFragment, 32);
2487     static_assert_size!(GenericArg, 80);
2488     static_assert_size!(GenericArgs, 32);
2489     static_assert_size!(GenericParamDef, 56);
2490     static_assert_size!(Item, 56);
2491     static_assert_size!(ItemKind, 112);
2492     static_assert_size!(PathSegment, 40);
2493     static_assert_size!(Type, 72);
2494 }