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