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