]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/clean/types.rs
Rollup merge of #100930 - cuviper:podman-keep-id, r=jyn514
[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(Box<Trait>),
731     TraitAliasItem(TraitAlias),
732     ImplItem(Box<Impl>),
733     /// A required method in a trait declaration meaning it's only a function signature.
734     TyMethodItem(Box<Function>),
735     /// A method in a trait impl or a provided method in a trait declaration.
736     ///
737     /// Compared to [TyMethodItem], it also contains a method body.
738     MethodItem(Box<Function>, Option<hir::Defaultness>),
739     StructFieldItem(Type),
740     VariantItem(Variant),
741     /// `fn`s from an extern block
742     ForeignFunctionItem(Box<Function>),
743     /// `static`s from an extern block
744     ForeignStaticItem(Static),
745     /// `type`s from an extern block
746     ForeignTypeItem,
747     MacroItem(Macro),
748     ProcMacroItem(ProcMacro),
749     PrimitiveItem(PrimitiveType),
750     /// A required associated constant in a trait declaration.
751     TyAssocConstItem(Type),
752     /// An associated associated constant in a trait impl or a provided one in a trait declaration.
753     AssocConstItem(Type, ConstantKind),
754     /// A required associated type in a trait declaration.
755     ///
756     /// The bounds may be non-empty if there is a `where` clause.
757     TyAssocTypeItem(Box<Generics>, Vec<GenericBound>),
758     /// An associated type in a trait impl or a provided one in a trait declaration.
759     AssocTypeItem(Box<Typedef>, Vec<GenericBound>),
760     /// An item that has been stripped by a rustdoc pass
761     StrippedItem(Box<ItemKind>),
762     KeywordItem,
763 }
764
765 impl ItemKind {
766     /// Some items contain others such as structs (for their fields) and Enums
767     /// (for their variants). This method returns those contained items.
768     pub(crate) fn inner_items(&self) -> impl Iterator<Item = &Item> {
769         match self {
770             StructItem(s) => s.fields.iter(),
771             UnionItem(u) => u.fields.iter(),
772             VariantItem(Variant::Struct(v)) => v.fields.iter(),
773             VariantItem(Variant::Tuple(v)) => v.iter(),
774             EnumItem(e) => e.variants.iter(),
775             TraitItem(t) => t.items.iter(),
776             ImplItem(i) => i.items.iter(),
777             ModuleItem(m) => m.items.iter(),
778             ExternCrateItem { .. }
779             | ImportItem(_)
780             | FunctionItem(_)
781             | TypedefItem(_)
782             | OpaqueTyItem(_)
783             | StaticItem(_)
784             | ConstantItem(_)
785             | TraitAliasItem(_)
786             | TyMethodItem(_)
787             | MethodItem(_, _)
788             | StructFieldItem(_)
789             | VariantItem(_)
790             | ForeignFunctionItem(_)
791             | ForeignStaticItem(_)
792             | ForeignTypeItem
793             | MacroItem(_)
794             | ProcMacroItem(_)
795             | PrimitiveItem(_)
796             | TyAssocConstItem(_)
797             | AssocConstItem(_, _)
798             | TyAssocTypeItem(..)
799             | AssocTypeItem(..)
800             | StrippedItem(_)
801             | KeywordItem => [].iter(),
802         }
803     }
804 }
805
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: ast::AttrVec,
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 = ast::AttrVec::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(Box<QPathData>),
1554
1555     /// A type that is inferred: `_`
1556     Infer,
1557
1558     /// An `impl Trait`: `impl TraitA + TraitB + ...`
1559     ImplTrait(Vec<GenericBound>),
1560 }
1561
1562 impl Type {
1563     /// When comparing types for equality, it can help to ignore `&` wrapping.
1564     pub(crate) fn without_borrowed_ref(&self) -> &Type {
1565         let mut result = self;
1566         while let Type::BorrowedRef { type_, .. } = result {
1567             result = &*type_;
1568         }
1569         result
1570     }
1571
1572     /// Check if two types are "potentially the same".
1573     /// This is different from `Eq`, because it knows that things like
1574     /// `Placeholder` are possible matches for everything.
1575     pub(crate) fn is_same(&self, other: &Self, cache: &Cache) -> bool {
1576         match (self, other) {
1577             // Recursive cases.
1578             (Type::Tuple(a), Type::Tuple(b)) => {
1579                 a.len() == b.len() && a.iter().zip(b).all(|(a, b)| a.is_same(b, cache))
1580             }
1581             (Type::Slice(a), Type::Slice(b)) => a.is_same(b, cache),
1582             (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_same(b, cache),
1583             (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
1584                 mutability == b_mutability && type_.is_same(b_type_, cache)
1585             }
1586             (
1587                 Type::BorrowedRef { mutability, type_, .. },
1588                 Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
1589             ) => mutability == b_mutability && type_.is_same(b_type_, cache),
1590             // Placeholders and generics are equal to all other types.
1591             (Type::Infer, _) | (_, Type::Infer) => true,
1592             (Type::Generic(_), _) | (_, Type::Generic(_)) => true,
1593             // Other cases, such as primitives, just use recursion.
1594             (a, b) => a
1595                 .def_id(cache)
1596                 .and_then(|a| Some((a, b.def_id(cache)?)))
1597                 .map(|(a, b)| a == b)
1598                 .unwrap_or(false),
1599         }
1600     }
1601
1602     pub(crate) fn primitive_type(&self) -> Option<PrimitiveType> {
1603         match *self {
1604             Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1605             Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1606             Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1607             Tuple(ref tys) => {
1608                 if tys.is_empty() {
1609                     Some(PrimitiveType::Unit)
1610                 } else {
1611                     Some(PrimitiveType::Tuple)
1612                 }
1613             }
1614             RawPointer(..) => Some(PrimitiveType::RawPointer),
1615             BareFunction(..) => Some(PrimitiveType::Fn),
1616             _ => None,
1617         }
1618     }
1619
1620     /// Checks if this is a `T::Name` path for an associated type.
1621     pub(crate) fn is_assoc_ty(&self) -> bool {
1622         match self {
1623             Type::Path { path, .. } => path.is_assoc_ty(),
1624             _ => false,
1625         }
1626     }
1627
1628     pub(crate) fn is_self_type(&self) -> bool {
1629         match *self {
1630             Generic(name) => name == kw::SelfUpper,
1631             _ => false,
1632         }
1633     }
1634
1635     pub(crate) fn generics(&self) -> Option<Vec<&Type>> {
1636         match self {
1637             Type::Path { path, .. } => path.generics(),
1638             _ => None,
1639         }
1640     }
1641
1642     pub(crate) fn is_full_generic(&self) -> bool {
1643         matches!(self, Type::Generic(_))
1644     }
1645
1646     pub(crate) fn is_impl_trait(&self) -> bool {
1647         matches!(self, Type::ImplTrait(_))
1648     }
1649
1650     pub(crate) fn projection(&self) -> Option<(&Type, DefId, PathSegment)> {
1651         if let QPath(box QPathData { self_type, trait_, assoc, .. }) = self {
1652             Some((self_type, trait_.def_id(), assoc.clone()))
1653         } else {
1654             None
1655         }
1656     }
1657
1658     fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
1659         let t: PrimitiveType = match *self {
1660             Type::Path { ref path } => return Some(path.def_id()),
1661             DynTrait(ref bounds, _) => return Some(bounds[0].trait_.def_id()),
1662             Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
1663             BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
1664             BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache),
1665             Tuple(ref tys) => {
1666                 if tys.is_empty() {
1667                     PrimitiveType::Unit
1668                 } else {
1669                     PrimitiveType::Tuple
1670                 }
1671             }
1672             BareFunction(..) => PrimitiveType::Fn,
1673             Slice(..) => PrimitiveType::Slice,
1674             Array(..) => PrimitiveType::Array,
1675             RawPointer(..) => PrimitiveType::RawPointer,
1676             QPath(box QPathData { ref self_type, .. }) => return self_type.inner_def_id(cache),
1677             Generic(_) | Infer | ImplTrait(_) => return None,
1678         };
1679         cache.and_then(|c| Primitive(t).def_id(c))
1680     }
1681
1682     /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s.
1683     ///
1684     /// [clean]: crate::clean
1685     pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
1686         self.inner_def_id(Some(cache))
1687     }
1688 }
1689
1690 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1691 pub(crate) struct QPathData {
1692     pub assoc: PathSegment,
1693     pub self_type: Type,
1694     /// FIXME: compute this field on demand.
1695     pub should_show_cast: bool,
1696     pub trait_: Path,
1697 }
1698
1699 /// A primitive (aka, builtin) type.
1700 ///
1701 /// This represents things like `i32`, `str`, etc.
1702 ///
1703 /// N.B. This has to be different from [`hir::PrimTy`] because it also includes types that aren't
1704 /// paths, like [`Self::Unit`].
1705 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1706 pub(crate) enum PrimitiveType {
1707     Isize,
1708     I8,
1709     I16,
1710     I32,
1711     I64,
1712     I128,
1713     Usize,
1714     U8,
1715     U16,
1716     U32,
1717     U64,
1718     U128,
1719     F32,
1720     F64,
1721     Char,
1722     Bool,
1723     Str,
1724     Slice,
1725     Array,
1726     Tuple,
1727     Unit,
1728     RawPointer,
1729     Reference,
1730     Fn,
1731     Never,
1732 }
1733
1734 type SimplifiedTypes = FxHashMap<PrimitiveType, ArrayVec<SimplifiedType, 3>>;
1735 impl PrimitiveType {
1736     pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1737         use ast::{FloatTy, IntTy, UintTy};
1738         match prim {
1739             hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1740             hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1741             hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1742             hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1743             hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1744             hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1745             hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1746             hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1747             hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1748             hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1749             hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1750             hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1751             hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1752             hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1753             hir::PrimTy::Str => PrimitiveType::Str,
1754             hir::PrimTy::Bool => PrimitiveType::Bool,
1755             hir::PrimTy::Char => PrimitiveType::Char,
1756         }
1757     }
1758
1759     pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1760         match s {
1761             sym::isize => Some(PrimitiveType::Isize),
1762             sym::i8 => Some(PrimitiveType::I8),
1763             sym::i16 => Some(PrimitiveType::I16),
1764             sym::i32 => Some(PrimitiveType::I32),
1765             sym::i64 => Some(PrimitiveType::I64),
1766             sym::i128 => Some(PrimitiveType::I128),
1767             sym::usize => Some(PrimitiveType::Usize),
1768             sym::u8 => Some(PrimitiveType::U8),
1769             sym::u16 => Some(PrimitiveType::U16),
1770             sym::u32 => Some(PrimitiveType::U32),
1771             sym::u64 => Some(PrimitiveType::U64),
1772             sym::u128 => Some(PrimitiveType::U128),
1773             sym::bool => Some(PrimitiveType::Bool),
1774             sym::char => Some(PrimitiveType::Char),
1775             sym::str => Some(PrimitiveType::Str),
1776             sym::f32 => Some(PrimitiveType::F32),
1777             sym::f64 => Some(PrimitiveType::F64),
1778             sym::array => Some(PrimitiveType::Array),
1779             sym::slice => Some(PrimitiveType::Slice),
1780             sym::tuple => Some(PrimitiveType::Tuple),
1781             sym::unit => Some(PrimitiveType::Unit),
1782             sym::pointer => Some(PrimitiveType::RawPointer),
1783             sym::reference => Some(PrimitiveType::Reference),
1784             kw::Fn => Some(PrimitiveType::Fn),
1785             sym::never => Some(PrimitiveType::Never),
1786             _ => None,
1787         }
1788     }
1789
1790     pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
1791         use ty::fast_reject::SimplifiedTypeGen::*;
1792         use ty::{FloatTy, IntTy, UintTy};
1793         use PrimitiveType::*;
1794         static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
1795
1796         let single = |x| iter::once(x).collect();
1797         CELL.get_or_init(move || {
1798             map! {
1799                 Isize => single(IntSimplifiedType(IntTy::Isize)),
1800                 I8 => single(IntSimplifiedType(IntTy::I8)),
1801                 I16 => single(IntSimplifiedType(IntTy::I16)),
1802                 I32 => single(IntSimplifiedType(IntTy::I32)),
1803                 I64 => single(IntSimplifiedType(IntTy::I64)),
1804                 I128 => single(IntSimplifiedType(IntTy::I128)),
1805                 Usize => single(UintSimplifiedType(UintTy::Usize)),
1806                 U8 => single(UintSimplifiedType(UintTy::U8)),
1807                 U16 => single(UintSimplifiedType(UintTy::U16)),
1808                 U32 => single(UintSimplifiedType(UintTy::U32)),
1809                 U64 => single(UintSimplifiedType(UintTy::U64)),
1810                 U128 => single(UintSimplifiedType(UintTy::U128)),
1811                 F32 => single(FloatSimplifiedType(FloatTy::F32)),
1812                 F64 => single(FloatSimplifiedType(FloatTy::F64)),
1813                 Str => single(StrSimplifiedType),
1814                 Bool => single(BoolSimplifiedType),
1815                 Char => single(CharSimplifiedType),
1816                 Array => single(ArraySimplifiedType),
1817                 Slice => single(SliceSimplifiedType),
1818                 // FIXME: If we ever add an inherent impl for tuples
1819                 // with different lengths, they won't show in rustdoc.
1820                 //
1821                 // Either manually update this arrayvec at this point
1822                 // or start with a more complex refactoring.
1823                 Tuple => [TupleSimplifiedType(1), TupleSimplifiedType(2), TupleSimplifiedType(3)].into(),
1824                 Unit => single(TupleSimplifiedType(0)),
1825                 RawPointer => [PtrSimplifiedType(Mutability::Not), PtrSimplifiedType(Mutability::Mut)].into_iter().collect(),
1826                 Reference => [RefSimplifiedType(Mutability::Not), RefSimplifiedType(Mutability::Mut)].into_iter().collect(),
1827                 // FIXME: This will be wrong if we ever add inherent impls
1828                 // for function pointers.
1829                 Fn => single(FunctionSimplifiedType(1)),
1830                 Never => single(NeverSimplifiedType),
1831             }
1832         })
1833     }
1834
1835     pub(crate) fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = DefId> + 'tcx {
1836         Self::simplified_types()
1837             .get(self)
1838             .into_iter()
1839             .flatten()
1840             .flat_map(move |&simp| tcx.incoherent_impls(simp))
1841             .copied()
1842     }
1843
1844     pub(crate) fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> + '_ {
1845         Self::simplified_types()
1846             .values()
1847             .flatten()
1848             .flat_map(move |&simp| tcx.incoherent_impls(simp))
1849             .copied()
1850     }
1851
1852     pub(crate) fn as_sym(&self) -> Symbol {
1853         use PrimitiveType::*;
1854         match self {
1855             Isize => sym::isize,
1856             I8 => sym::i8,
1857             I16 => sym::i16,
1858             I32 => sym::i32,
1859             I64 => sym::i64,
1860             I128 => sym::i128,
1861             Usize => sym::usize,
1862             U8 => sym::u8,
1863             U16 => sym::u16,
1864             U32 => sym::u32,
1865             U64 => sym::u64,
1866             U128 => sym::u128,
1867             F32 => sym::f32,
1868             F64 => sym::f64,
1869             Str => sym::str,
1870             Bool => sym::bool,
1871             Char => sym::char,
1872             Array => sym::array,
1873             Slice => sym::slice,
1874             Tuple => sym::tuple,
1875             Unit => sym::unit,
1876             RawPointer => sym::pointer,
1877             Reference => sym::reference,
1878             Fn => kw::Fn,
1879             Never => sym::never,
1880         }
1881     }
1882
1883     /// Returns the DefId of the module with `doc(primitive)` for this primitive type.
1884     /// Panics if there is no such module.
1885     ///
1886     /// This gives precedence to primitives defined in the current crate, and deprioritizes primitives defined in `core`,
1887     /// but otherwise, if multiple crates define the same primitive, there is no guarantee of which will be picked.
1888     /// In particular, if a crate depends on both `std` and another crate that also defines `doc(primitive)`, then
1889     /// it's entirely random whether `std` or the other crate is picked. (no_std crates are usually fine unless multiple dependencies define a primitive.)
1890     pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxHashMap<PrimitiveType, DefId> {
1891         static PRIMITIVE_LOCATIONS: OnceCell<FxHashMap<PrimitiveType, DefId>> = OnceCell::new();
1892         PRIMITIVE_LOCATIONS.get_or_init(|| {
1893             let mut primitive_locations = FxHashMap::default();
1894             // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate.
1895             // This is a degenerate case that I don't plan to support.
1896             for &crate_num in tcx.crates(()) {
1897                 let e = ExternalCrate { crate_num };
1898                 let crate_name = e.name(tcx);
1899                 debug!(?crate_num, ?crate_name);
1900                 for &(def_id, prim) in &e.primitives(tcx) {
1901                     // HACK: try to link to std instead where possible
1902                     if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1903                         continue;
1904                     }
1905                     primitive_locations.insert(prim, def_id);
1906                 }
1907             }
1908             let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1909             for (def_id, prim) in local_primitives {
1910                 primitive_locations.insert(prim, def_id);
1911             }
1912             primitive_locations
1913         })
1914     }
1915 }
1916
1917 impl From<ast::IntTy> for PrimitiveType {
1918     fn from(int_ty: ast::IntTy) -> PrimitiveType {
1919         match int_ty {
1920             ast::IntTy::Isize => PrimitiveType::Isize,
1921             ast::IntTy::I8 => PrimitiveType::I8,
1922             ast::IntTy::I16 => PrimitiveType::I16,
1923             ast::IntTy::I32 => PrimitiveType::I32,
1924             ast::IntTy::I64 => PrimitiveType::I64,
1925             ast::IntTy::I128 => PrimitiveType::I128,
1926         }
1927     }
1928 }
1929
1930 impl From<ast::UintTy> for PrimitiveType {
1931     fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1932         match uint_ty {
1933             ast::UintTy::Usize => PrimitiveType::Usize,
1934             ast::UintTy::U8 => PrimitiveType::U8,
1935             ast::UintTy::U16 => PrimitiveType::U16,
1936             ast::UintTy::U32 => PrimitiveType::U32,
1937             ast::UintTy::U64 => PrimitiveType::U64,
1938             ast::UintTy::U128 => PrimitiveType::U128,
1939         }
1940     }
1941 }
1942
1943 impl From<ast::FloatTy> for PrimitiveType {
1944     fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1945         match float_ty {
1946             ast::FloatTy::F32 => PrimitiveType::F32,
1947             ast::FloatTy::F64 => PrimitiveType::F64,
1948         }
1949     }
1950 }
1951
1952 impl From<ty::IntTy> for PrimitiveType {
1953     fn from(int_ty: ty::IntTy) -> PrimitiveType {
1954         match int_ty {
1955             ty::IntTy::Isize => PrimitiveType::Isize,
1956             ty::IntTy::I8 => PrimitiveType::I8,
1957             ty::IntTy::I16 => PrimitiveType::I16,
1958             ty::IntTy::I32 => PrimitiveType::I32,
1959             ty::IntTy::I64 => PrimitiveType::I64,
1960             ty::IntTy::I128 => PrimitiveType::I128,
1961         }
1962     }
1963 }
1964
1965 impl From<ty::UintTy> for PrimitiveType {
1966     fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1967         match uint_ty {
1968             ty::UintTy::Usize => PrimitiveType::Usize,
1969             ty::UintTy::U8 => PrimitiveType::U8,
1970             ty::UintTy::U16 => PrimitiveType::U16,
1971             ty::UintTy::U32 => PrimitiveType::U32,
1972             ty::UintTy::U64 => PrimitiveType::U64,
1973             ty::UintTy::U128 => PrimitiveType::U128,
1974         }
1975     }
1976 }
1977
1978 impl From<ty::FloatTy> for PrimitiveType {
1979     fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1980         match float_ty {
1981             ty::FloatTy::F32 => PrimitiveType::F32,
1982             ty::FloatTy::F64 => PrimitiveType::F64,
1983         }
1984     }
1985 }
1986
1987 impl From<hir::PrimTy> for PrimitiveType {
1988     fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1989         match prim_ty {
1990             hir::PrimTy::Int(int_ty) => int_ty.into(),
1991             hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1992             hir::PrimTy::Float(float_ty) => float_ty.into(),
1993             hir::PrimTy::Str => PrimitiveType::Str,
1994             hir::PrimTy::Bool => PrimitiveType::Bool,
1995             hir::PrimTy::Char => PrimitiveType::Char,
1996         }
1997     }
1998 }
1999
2000 #[derive(Copy, Clone, Debug)]
2001 pub(crate) enum Visibility {
2002     /// `pub`
2003     Public,
2004     /// Visibility inherited from parent.
2005     ///
2006     /// For example, this is the visibility of private items and of enum variants.
2007     Inherited,
2008     /// `pub(crate)`, `pub(super)`, or `pub(in path::to::somewhere)`
2009     Restricted(DefId),
2010 }
2011
2012 impl Visibility {
2013     pub(crate) fn is_public(&self) -> bool {
2014         matches!(self, Visibility::Public)
2015     }
2016 }
2017
2018 #[derive(Clone, Debug)]
2019 pub(crate) struct Struct {
2020     pub(crate) struct_type: CtorKind,
2021     pub(crate) generics: Generics,
2022     pub(crate) fields: Vec<Item>,
2023 }
2024
2025 impl Struct {
2026     pub(crate) fn has_stripped_entries(&self) -> bool {
2027         self.fields.iter().any(|f| f.is_stripped())
2028     }
2029 }
2030
2031 #[derive(Clone, Debug)]
2032 pub(crate) struct Union {
2033     pub(crate) generics: Generics,
2034     pub(crate) fields: Vec<Item>,
2035 }
2036
2037 impl Union {
2038     pub(crate) fn has_stripped_entries(&self) -> bool {
2039         self.fields.iter().any(|f| f.is_stripped())
2040     }
2041 }
2042
2043 /// This is a more limited form of the standard Struct, different in that
2044 /// it lacks the things most items have (name, id, parameterization). Found
2045 /// only as a variant in an enum.
2046 #[derive(Clone, Debug)]
2047 pub(crate) struct VariantStruct {
2048     pub(crate) struct_type: CtorKind,
2049     pub(crate) fields: Vec<Item>,
2050 }
2051
2052 impl VariantStruct {
2053     pub(crate) fn has_stripped_entries(&self) -> bool {
2054         self.fields.iter().any(|f| f.is_stripped())
2055     }
2056 }
2057
2058 #[derive(Clone, Debug)]
2059 pub(crate) struct Enum {
2060     pub(crate) variants: IndexVec<VariantIdx, Item>,
2061     pub(crate) generics: Generics,
2062 }
2063
2064 impl Enum {
2065     pub(crate) fn has_stripped_entries(&self) -> bool {
2066         self.variants.iter().any(|f| f.is_stripped())
2067     }
2068
2069     pub(crate) fn variants(&self) -> impl Iterator<Item = &Item> {
2070         self.variants.iter().filter(|v| !v.is_stripped())
2071     }
2072 }
2073
2074 #[derive(Clone, Debug)]
2075 pub(crate) enum Variant {
2076     CLike,
2077     Tuple(Vec<Item>),
2078     Struct(VariantStruct),
2079 }
2080
2081 impl Variant {
2082     pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
2083         match *self {
2084             Self::Struct(ref struct_) => Some(struct_.has_stripped_entries()),
2085             Self::CLike | Self::Tuple(_) => None,
2086         }
2087     }
2088 }
2089
2090 /// Small wrapper around [`rustc_span::Span`] that adds helper methods
2091 /// and enforces calling [`rustc_span::Span::source_callsite()`].
2092 #[derive(Copy, Clone, Debug)]
2093 pub(crate) struct Span(rustc_span::Span);
2094
2095 impl Span {
2096     /// Wraps a [`rustc_span::Span`]. In case this span is the result of a macro expansion, the
2097     /// span will be updated to point to the macro invocation instead of the macro definition.
2098     ///
2099     /// (See rust-lang/rust#39726)
2100     pub(crate) fn new(sp: rustc_span::Span) -> Self {
2101         Self(sp.source_callsite())
2102     }
2103
2104     pub(crate) fn inner(&self) -> rustc_span::Span {
2105         self.0
2106     }
2107
2108     pub(crate) fn filename(&self, sess: &Session) -> FileName {
2109         sess.source_map().span_to_filename(self.0)
2110     }
2111
2112     pub(crate) fn lo(&self, sess: &Session) -> Loc {
2113         sess.source_map().lookup_char_pos(self.0.lo())
2114     }
2115
2116     pub(crate) fn hi(&self, sess: &Session) -> Loc {
2117         sess.source_map().lookup_char_pos(self.0.hi())
2118     }
2119
2120     pub(crate) fn cnum(&self, sess: &Session) -> CrateNum {
2121         // FIXME: is there a time when the lo and hi crate would be different?
2122         self.lo(sess).file.cnum
2123     }
2124 }
2125
2126 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2127 pub(crate) struct Path {
2128     pub(crate) res: Res,
2129     pub(crate) segments: Vec<PathSegment>,
2130 }
2131
2132 impl Path {
2133     pub(crate) fn def_id(&self) -> DefId {
2134         self.res.def_id()
2135     }
2136
2137     pub(crate) fn last_opt(&self) -> Option<Symbol> {
2138         self.segments.last().map(|s| s.name)
2139     }
2140
2141     pub(crate) fn last(&self) -> Symbol {
2142         self.last_opt().expect("segments were empty")
2143     }
2144
2145     pub(crate) fn whole_name(&self) -> String {
2146         self.segments
2147             .iter()
2148             .map(|s| if s.name == kw::PathRoot { "" } else { s.name.as_str() })
2149             .intersperse("::")
2150             .collect()
2151     }
2152
2153     /// Checks if this is a `T::Name` path for an associated type.
2154     pub(crate) fn is_assoc_ty(&self) -> bool {
2155         match self.res {
2156             Res::SelfTy { .. } if self.segments.len() != 1 => true,
2157             Res::Def(DefKind::TyParam, _) if self.segments.len() != 1 => true,
2158             Res::Def(DefKind::AssocTy, _) => true,
2159             _ => false,
2160         }
2161     }
2162
2163     pub(crate) fn generics(&self) -> Option<Vec<&Type>> {
2164         self.segments.last().and_then(|seg| {
2165             if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2166                 Some(
2167                     args.iter()
2168                         .filter_map(|arg| match arg {
2169                             GenericArg::Type(ty) => Some(ty),
2170                             _ => None,
2171                         })
2172                         .collect(),
2173                 )
2174             } else {
2175                 None
2176             }
2177         })
2178     }
2179
2180     pub(crate) fn bindings(&self) -> Option<&[TypeBinding]> {
2181         self.segments.last().and_then(|seg| {
2182             if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
2183                 Some(&**bindings)
2184             } else {
2185                 None
2186             }
2187         })
2188     }
2189 }
2190
2191 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2192 pub(crate) enum GenericArg {
2193     Lifetime(Lifetime),
2194     Type(Type),
2195     Const(Box<Constant>),
2196     Infer,
2197 }
2198
2199 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2200 pub(crate) enum GenericArgs {
2201     AngleBracketed { args: Box<[GenericArg]>, bindings: ThinVec<TypeBinding> },
2202     Parenthesized { inputs: Box<[Type]>, output: Option<Box<Type>> },
2203 }
2204
2205 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2206 pub(crate) struct PathSegment {
2207     pub(crate) name: Symbol,
2208     pub(crate) args: GenericArgs,
2209 }
2210
2211 #[derive(Clone, Debug)]
2212 pub(crate) struct Typedef {
2213     pub(crate) type_: Type,
2214     pub(crate) generics: Generics,
2215     /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
2216     /// alias instead of the final type. This will always have the final type, regardless of whether
2217     /// `type_` came from HIR or from metadata.
2218     ///
2219     /// If `item_type.is_none()`, `type_` is guaranteed to come from metadata (and therefore hold the
2220     /// final type).
2221     pub(crate) item_type: Option<Type>,
2222 }
2223
2224 #[derive(Clone, Debug)]
2225 pub(crate) struct OpaqueTy {
2226     pub(crate) bounds: Vec<GenericBound>,
2227     pub(crate) generics: Generics,
2228 }
2229
2230 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2231 pub(crate) struct BareFunctionDecl {
2232     pub(crate) unsafety: hir::Unsafety,
2233     pub(crate) generic_params: Vec<GenericParamDef>,
2234     pub(crate) decl: FnDecl,
2235     pub(crate) abi: Abi,
2236 }
2237
2238 #[derive(Clone, Debug)]
2239 pub(crate) struct Static {
2240     pub(crate) type_: Type,
2241     pub(crate) mutability: Mutability,
2242     pub(crate) expr: Option<BodyId>,
2243 }
2244
2245 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2246 pub(crate) struct Constant {
2247     pub(crate) type_: Type,
2248     pub(crate) kind: ConstantKind,
2249 }
2250
2251 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2252 pub(crate) enum Term {
2253     Type(Type),
2254     Constant(Constant),
2255 }
2256
2257 impl Term {
2258     pub(crate) fn ty(&self) -> Option<&Type> {
2259         if let Term::Type(ty) = self { Some(ty) } else { None }
2260     }
2261 }
2262
2263 impl From<Type> for Term {
2264     fn from(ty: Type) -> Self {
2265         Term::Type(ty)
2266     }
2267 }
2268
2269 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2270 pub(crate) enum ConstantKind {
2271     /// This is the wrapper around `ty::Const` for a non-local constant. Because it doesn't have a
2272     /// `BodyId`, we need to handle it on its own.
2273     ///
2274     /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified
2275     /// by a DefId. So this field must be different from `Extern`.
2276     TyConst { expr: String },
2277     /// A constant (expression) that's not an item or associated item. These are usually found
2278     /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
2279     /// used to define explicit discriminant values for enum variants.
2280     Anonymous { body: BodyId },
2281     /// A constant from a different crate.
2282     Extern { def_id: DefId },
2283     /// `const FOO: u32 = ...;`
2284     Local { def_id: DefId, body: BodyId },
2285 }
2286
2287 impl Constant {
2288     pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2289         self.kind.expr(tcx)
2290     }
2291
2292     pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2293         self.kind.value(tcx)
2294     }
2295
2296     pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2297         self.kind.is_literal(tcx)
2298     }
2299 }
2300
2301 impl ConstantKind {
2302     pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2303         match *self {
2304             ConstantKind::TyConst { ref expr } => expr.clone(),
2305             ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2306             ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2307                 print_const_expr(tcx, body)
2308             }
2309         }
2310     }
2311
2312     pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2313         match *self {
2314             ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
2315             ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2316                 print_evaluated_const(tcx, def_id)
2317             }
2318         }
2319     }
2320
2321     pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2322         match *self {
2323             ConstantKind::TyConst { .. } => false,
2324             ConstantKind::Extern { def_id } => def_id.as_local().map_or(false, |def_id| {
2325                 is_literal_expr(tcx, tcx.hir().local_def_id_to_hir_id(def_id))
2326             }),
2327             ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2328                 is_literal_expr(tcx, body.hir_id)
2329             }
2330         }
2331     }
2332 }
2333
2334 #[derive(Clone, Debug)]
2335 pub(crate) struct Impl {
2336     pub(crate) unsafety: hir::Unsafety,
2337     pub(crate) generics: Generics,
2338     pub(crate) trait_: Option<Path>,
2339     pub(crate) for_: Type,
2340     pub(crate) items: Vec<Item>,
2341     pub(crate) polarity: ty::ImplPolarity,
2342     pub(crate) kind: ImplKind,
2343 }
2344
2345 impl Impl {
2346     pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxHashSet<Symbol> {
2347         self.trait_
2348             .as_ref()
2349             .map(|t| t.def_id())
2350             .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name).collect())
2351             .unwrap_or_default()
2352     }
2353 }
2354
2355 #[derive(Clone, Debug)]
2356 pub(crate) enum ImplKind {
2357     Normal,
2358     Auto,
2359     FakeVaradic,
2360     Blanket(Box<Type>),
2361 }
2362
2363 impl ImplKind {
2364     pub(crate) fn is_auto(&self) -> bool {
2365         matches!(self, ImplKind::Auto)
2366     }
2367
2368     pub(crate) fn is_blanket(&self) -> bool {
2369         matches!(self, ImplKind::Blanket(_))
2370     }
2371
2372     pub(crate) fn is_fake_variadic(&self) -> bool {
2373         matches!(self, ImplKind::FakeVaradic)
2374     }
2375
2376     pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
2377         match self {
2378             ImplKind::Blanket(ty) => Some(ty),
2379             _ => None,
2380         }
2381     }
2382 }
2383
2384 #[derive(Clone, Debug)]
2385 pub(crate) struct Import {
2386     pub(crate) kind: ImportKind,
2387     pub(crate) source: ImportSource,
2388     pub(crate) should_be_displayed: bool,
2389 }
2390
2391 impl Import {
2392     pub(crate) fn new_simple(
2393         name: Symbol,
2394         source: ImportSource,
2395         should_be_displayed: bool,
2396     ) -> Self {
2397         Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2398     }
2399
2400     pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2401         Self { kind: ImportKind::Glob, source, should_be_displayed }
2402     }
2403 }
2404
2405 #[derive(Clone, Debug)]
2406 pub(crate) enum ImportKind {
2407     // use source as str;
2408     Simple(Symbol),
2409     // use source::*;
2410     Glob,
2411 }
2412
2413 #[derive(Clone, Debug)]
2414 pub(crate) struct ImportSource {
2415     pub(crate) path: Path,
2416     pub(crate) did: Option<DefId>,
2417 }
2418
2419 #[derive(Clone, Debug)]
2420 pub(crate) struct Macro {
2421     pub(crate) source: String,
2422 }
2423
2424 #[derive(Clone, Debug)]
2425 pub(crate) struct ProcMacro {
2426     pub(crate) kind: MacroKind,
2427     pub(crate) helpers: Vec<Symbol>,
2428 }
2429
2430 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
2431 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
2432 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2433 pub(crate) struct TypeBinding {
2434     pub(crate) assoc: PathSegment,
2435     pub(crate) kind: TypeBindingKind,
2436 }
2437
2438 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2439 pub(crate) enum TypeBindingKind {
2440     Equality { term: Term },
2441     Constraint { bounds: Vec<GenericBound> },
2442 }
2443
2444 impl TypeBinding {
2445     pub(crate) fn term(&self) -> &Term {
2446         match self.kind {
2447             TypeBindingKind::Equality { ref term } => term,
2448             _ => panic!("expected equality type binding for parenthesized generic args"),
2449         }
2450     }
2451 }
2452
2453 /// The type, lifetime, or constant that a private type alias's parameter should be
2454 /// replaced with when expanding a use of that type alias.
2455 ///
2456 /// For example:
2457 ///
2458 /// ```
2459 /// type PrivAlias<T> = Vec<T>;
2460 ///
2461 /// pub fn public_fn() -> PrivAlias<i32> { vec![] }
2462 /// ```
2463 ///
2464 /// `public_fn`'s docs will show it as returning `Vec<i32>`, since `PrivAlias` is private.
2465 /// [`SubstParam`] is used to record that `T` should be mapped to `i32`.
2466 pub(crate) enum SubstParam {
2467     Type(Type),
2468     Lifetime(Lifetime),
2469     Constant(Constant),
2470 }
2471
2472 impl SubstParam {
2473     pub(crate) fn as_ty(&self) -> Option<&Type> {
2474         if let Self::Type(ty) = self { Some(ty) } else { None }
2475     }
2476
2477     pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
2478         if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2479     }
2480 }
2481
2482 // Some nodes are used a lot. Make sure they don't unintentionally get bigger.
2483 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2484 mod size_asserts {
2485     use super::*;
2486     use rustc_data_structures::static_assert_size;
2487     // These are in alphabetical order, which is easy to maintain.
2488     static_assert_size!(Crate, 72); // frequently moved by-value
2489     static_assert_size!(DocFragment, 32);
2490     static_assert_size!(GenericArg, 64);
2491     static_assert_size!(GenericArgs, 32);
2492     static_assert_size!(GenericParamDef, 56);
2493     static_assert_size!(Item, 56);
2494     static_assert_size!(ItemKind, 96);
2495     static_assert_size!(PathSegment, 40);
2496     static_assert_size!(Type, 56);
2497 }