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