]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/clean/types.rs
81aa8c6cf8e19053cd23b51a12e1105e4d6b8772
[rust.git] / src / librustdoc / clean / types.rs
1 use std::cell::RefCell;
2 use std::default::Default;
3 use std::hash::Hash;
4 use std::path::PathBuf;
5 use std::rc::Rc;
6 use std::sync::Arc;
7 use std::sync::OnceLock as OnceCell;
8 use std::{cmp, fmt, iter};
9
10 use arrayvec::ArrayVec;
11
12 use rustc_ast::attr;
13 use rustc_ast::util::comments::beautify_doc_string;
14 use rustc_ast::{self as ast, AttrStyle};
15 use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
16 use rustc_const_eval::const_eval::is_unstable_const_fn;
17 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
18 use rustc_data_structures::thin_vec::ThinVec;
19 use rustc_hir as hir;
20 use rustc_hir::def::{CtorKind, DefKind, Res};
21 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
22 use rustc_hir::lang_items::LangItem;
23 use rustc_hir::{BodyId, Mutability};
24 use rustc_index::vec::IndexVec;
25 use rustc_middle::ty::fast_reject::SimplifiedType;
26 use rustc_middle::ty::{self, TyCtxt};
27 use rustc_session::Session;
28 use rustc_span::hygiene::MacroKind;
29 use rustc_span::source_map::DUMMY_SP;
30 use rustc_span::symbol::{kw, sym, Ident, Symbol};
31 use rustc_span::{self, FileName, Loc};
32 use rustc_target::abi::VariantIdx;
33 use rustc_target::spec::abi::Abi;
34 use rustc_typeck::check::intrinsic::intrinsic_operation_unsafety;
35
36 use crate::clean::cfg::Cfg;
37 use crate::clean::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())
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.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_default())
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)]
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.is_empty() {
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 impl Generics {
1414     pub(crate) fn is_empty(&self) -> bool {
1415         self.params.is_empty() && self.where_predicates.is_empty()
1416     }
1417 }
1418
1419 #[derive(Clone, Debug)]
1420 pub(crate) struct Function {
1421     pub(crate) decl: FnDecl,
1422     pub(crate) generics: Generics,
1423 }
1424
1425 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1426 pub(crate) struct FnDecl {
1427     pub(crate) inputs: Arguments,
1428     pub(crate) output: FnRetTy,
1429     pub(crate) c_variadic: bool,
1430 }
1431
1432 impl FnDecl {
1433     pub(crate) fn self_type(&self) -> Option<SelfTy> {
1434         self.inputs.values.get(0).and_then(|v| v.to_self())
1435     }
1436
1437     /// Returns the sugared return type for an async function.
1438     ///
1439     /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
1440     /// will return `i32`.
1441     ///
1442     /// # Panics
1443     ///
1444     /// This function will panic if the return type does not match the expected sugaring for async
1445     /// functions.
1446     pub(crate) fn sugared_async_return_type(&self) -> FnRetTy {
1447         match &self.output {
1448             FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
1449                 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
1450                     let bindings = trait_.bindings().unwrap();
1451                     let ret_ty = bindings[0].term();
1452                     let ty = ret_ty.ty().expect("Unexpected constant return term");
1453                     FnRetTy::Return(ty.clone())
1454                 }
1455                 _ => panic!("unexpected desugaring of async function"),
1456             },
1457             _ => panic!("unexpected desugaring of async function"),
1458         }
1459     }
1460 }
1461
1462 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1463 pub(crate) struct Arguments {
1464     pub(crate) values: Vec<Argument>,
1465 }
1466
1467 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1468 pub(crate) struct Argument {
1469     pub(crate) type_: Type,
1470     pub(crate) name: Symbol,
1471     /// This field is used to represent "const" arguments from the `rustc_legacy_const_generics`
1472     /// feature. More information in <https://github.com/rust-lang/rust/issues/83167>.
1473     pub(crate) is_const: bool,
1474 }
1475
1476 #[derive(Clone, PartialEq, Debug)]
1477 pub(crate) enum SelfTy {
1478     SelfValue,
1479     SelfBorrowed(Option<Lifetime>, Mutability),
1480     SelfExplicit(Type),
1481 }
1482
1483 impl Argument {
1484     pub(crate) fn to_self(&self) -> Option<SelfTy> {
1485         if self.name != kw::SelfLower {
1486             return None;
1487         }
1488         if self.type_.is_self_type() {
1489             return Some(SelfValue);
1490         }
1491         match self.type_ {
1492             BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
1493                 Some(SelfBorrowed(lifetime.clone(), mutability))
1494             }
1495             _ => Some(SelfExplicit(self.type_.clone())),
1496         }
1497     }
1498 }
1499
1500 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1501 pub(crate) enum FnRetTy {
1502     Return(Type),
1503     DefaultReturn,
1504 }
1505
1506 impl FnRetTy {
1507     pub(crate) fn as_return(&self) -> Option<&Type> {
1508         match self {
1509             Return(ret) => Some(ret),
1510             DefaultReturn => None,
1511         }
1512     }
1513 }
1514
1515 #[derive(Clone, Debug)]
1516 pub(crate) struct Trait {
1517     pub(crate) unsafety: hir::Unsafety,
1518     pub(crate) items: Vec<Item>,
1519     pub(crate) generics: Generics,
1520     pub(crate) bounds: Vec<GenericBound>,
1521     pub(crate) is_auto: bool,
1522 }
1523
1524 #[derive(Clone, Debug)]
1525 pub(crate) struct TraitAlias {
1526     pub(crate) generics: Generics,
1527     pub(crate) bounds: Vec<GenericBound>,
1528 }
1529
1530 /// A trait reference, which may have higher ranked lifetimes.
1531 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1532 pub(crate) struct PolyTrait {
1533     pub(crate) trait_: Path,
1534     pub(crate) generic_params: Vec<GenericParamDef>,
1535 }
1536
1537 /// Rustdoc's representation of types, mostly based on the [`hir::Ty`].
1538 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1539 pub(crate) enum Type {
1540     /// A named type, which could be a trait.
1541     ///
1542     /// This is mostly Rustdoc's version of [`hir::Path`].
1543     /// It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics.
1544     Path { path: Path },
1545     /// A `dyn Trait` object: `dyn for<'a> Trait<'a> + Send + 'static`
1546     DynTrait(Vec<PolyTrait>, Option<Lifetime>),
1547     /// A type parameter.
1548     Generic(Symbol),
1549     /// A primitive (aka, builtin) type.
1550     Primitive(PrimitiveType),
1551     /// A function pointer: `extern "ABI" fn(...) -> ...`
1552     BareFunction(Box<BareFunctionDecl>),
1553     /// A tuple type: `(i32, &str)`.
1554     Tuple(Vec<Type>),
1555     /// A slice type (does *not* include the `&`): `[i32]`
1556     Slice(Box<Type>),
1557     /// An array type.
1558     ///
1559     /// The `String` field is a stringified version of the array's length parameter.
1560     Array(Box<Type>, String),
1561     /// A raw pointer type: `*const i32`, `*mut i32`
1562     RawPointer(Mutability, Box<Type>),
1563     /// A reference type: `&i32`, `&'a mut Foo`
1564     BorrowedRef { lifetime: Option<Lifetime>, mutability: Mutability, type_: Box<Type> },
1565
1566     /// A qualified path to an associated item: `<Type as Trait>::Name`
1567     QPath {
1568         assoc: Box<PathSegment>,
1569         self_type: Box<Type>,
1570         /// FIXME: compute this field on demand.
1571         should_show_cast: bool,
1572         trait_: Path,
1573     },
1574
1575     /// A type that is inferred: `_`
1576     Infer,
1577
1578     /// An `impl Trait`: `impl TraitA + TraitB + ...`
1579     ImplTrait(Vec<GenericBound>),
1580 }
1581
1582 // `Type` is used a lot. Make sure it doesn't unintentionally get bigger.
1583 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
1584 rustc_data_structures::static_assert_size!(Type, 72);
1585
1586 impl Type {
1587     /// When comparing types for equality, it can help to ignore `&` wrapping.
1588     pub(crate) fn without_borrowed_ref(&self) -> &Type {
1589         let mut result = self;
1590         while let Type::BorrowedRef { type_, .. } = result {
1591             result = &*type_;
1592         }
1593         result
1594     }
1595
1596     /// Check if two types are "potentially the same".
1597     /// This is different from `Eq`, because it knows that things like
1598     /// `Placeholder` are possible matches for everything.
1599     pub(crate) fn is_same(&self, other: &Self, cache: &Cache) -> bool {
1600         match (self, other) {
1601             // Recursive cases.
1602             (Type::Tuple(a), Type::Tuple(b)) => {
1603                 a.len() == b.len() && a.iter().zip(b).all(|(a, b)| a.is_same(b, cache))
1604             }
1605             (Type::Slice(a), Type::Slice(b)) => a.is_same(b, cache),
1606             (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_same(b, cache),
1607             (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
1608                 mutability == b_mutability && type_.is_same(b_type_, cache)
1609             }
1610             (
1611                 Type::BorrowedRef { mutability, type_, .. },
1612                 Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
1613             ) => mutability == b_mutability && type_.is_same(b_type_, cache),
1614             // Placeholders and generics are equal to all other types.
1615             (Type::Infer, _) | (_, Type::Infer) => true,
1616             (Type::Generic(_), _) | (_, Type::Generic(_)) => true,
1617             // Other cases, such as primitives, just use recursion.
1618             (a, b) => a
1619                 .def_id(cache)
1620                 .and_then(|a| Some((a, b.def_id(cache)?)))
1621                 .map(|(a, b)| a == b)
1622                 .unwrap_or(false),
1623         }
1624     }
1625
1626     pub(crate) fn primitive_type(&self) -> Option<PrimitiveType> {
1627         match *self {
1628             Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1629             Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1630             Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1631             Tuple(ref tys) => {
1632                 if tys.is_empty() {
1633                     Some(PrimitiveType::Unit)
1634                 } else {
1635                     Some(PrimitiveType::Tuple)
1636                 }
1637             }
1638             RawPointer(..) => Some(PrimitiveType::RawPointer),
1639             BareFunction(..) => Some(PrimitiveType::Fn),
1640             _ => None,
1641         }
1642     }
1643
1644     /// Checks if this is a `T::Name` path for an associated type.
1645     pub(crate) fn is_assoc_ty(&self) -> bool {
1646         match self {
1647             Type::Path { path, .. } => path.is_assoc_ty(),
1648             _ => false,
1649         }
1650     }
1651
1652     pub(crate) fn is_self_type(&self) -> bool {
1653         match *self {
1654             Generic(name) => name == kw::SelfUpper,
1655             _ => false,
1656         }
1657     }
1658
1659     pub(crate) fn generics(&self) -> Option<Vec<&Type>> {
1660         match self {
1661             Type::Path { path, .. } => path.generics(),
1662             _ => None,
1663         }
1664     }
1665
1666     pub(crate) fn is_full_generic(&self) -> bool {
1667         matches!(self, Type::Generic(_))
1668     }
1669
1670     pub(crate) fn is_impl_trait(&self) -> bool {
1671         matches!(self, Type::ImplTrait(_))
1672     }
1673
1674     pub(crate) fn projection(&self) -> Option<(&Type, DefId, PathSegment)> {
1675         if let QPath { self_type, trait_, assoc, .. } = self {
1676             Some((self_type, trait_.def_id(), *assoc.clone()))
1677         } else {
1678             None
1679         }
1680     }
1681
1682     fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
1683         let t: PrimitiveType = match *self {
1684             Type::Path { ref path } => return Some(path.def_id()),
1685             DynTrait(ref bounds, _) => return Some(bounds[0].trait_.def_id()),
1686             Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
1687             BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
1688             BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache),
1689             Tuple(ref tys) => {
1690                 if tys.is_empty() {
1691                     PrimitiveType::Unit
1692                 } else {
1693                     PrimitiveType::Tuple
1694                 }
1695             }
1696             BareFunction(..) => PrimitiveType::Fn,
1697             Slice(..) => PrimitiveType::Slice,
1698             Array(..) => PrimitiveType::Array,
1699             RawPointer(..) => PrimitiveType::RawPointer,
1700             QPath { ref self_type, .. } => return self_type.inner_def_id(cache),
1701             Generic(_) | Infer | ImplTrait(_) => return None,
1702         };
1703         cache.and_then(|c| Primitive(t).def_id(c))
1704     }
1705
1706     /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s.
1707     ///
1708     /// [clean]: crate::clean
1709     pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
1710         self.inner_def_id(Some(cache))
1711     }
1712 }
1713
1714 /// A primitive (aka, builtin) type.
1715 ///
1716 /// This represents things like `i32`, `str`, etc.
1717 ///
1718 /// N.B. This has to be different from [`hir::PrimTy`] because it also includes types that aren't
1719 /// paths, like [`Self::Unit`].
1720 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1721 pub(crate) enum PrimitiveType {
1722     Isize,
1723     I8,
1724     I16,
1725     I32,
1726     I64,
1727     I128,
1728     Usize,
1729     U8,
1730     U16,
1731     U32,
1732     U64,
1733     U128,
1734     F32,
1735     F64,
1736     Char,
1737     Bool,
1738     Str,
1739     Slice,
1740     Array,
1741     Tuple,
1742     Unit,
1743     RawPointer,
1744     Reference,
1745     Fn,
1746     Never,
1747 }
1748
1749 type SimplifiedTypes = FxHashMap<PrimitiveType, ArrayVec<SimplifiedType, 3>>;
1750 impl PrimitiveType {
1751     pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1752         use ast::{FloatTy, IntTy, UintTy};
1753         match prim {
1754             hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1755             hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1756             hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1757             hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1758             hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1759             hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1760             hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1761             hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1762             hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1763             hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1764             hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1765             hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1766             hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1767             hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1768             hir::PrimTy::Str => PrimitiveType::Str,
1769             hir::PrimTy::Bool => PrimitiveType::Bool,
1770             hir::PrimTy::Char => PrimitiveType::Char,
1771         }
1772     }
1773
1774     pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1775         match s {
1776             sym::isize => Some(PrimitiveType::Isize),
1777             sym::i8 => Some(PrimitiveType::I8),
1778             sym::i16 => Some(PrimitiveType::I16),
1779             sym::i32 => Some(PrimitiveType::I32),
1780             sym::i64 => Some(PrimitiveType::I64),
1781             sym::i128 => Some(PrimitiveType::I128),
1782             sym::usize => Some(PrimitiveType::Usize),
1783             sym::u8 => Some(PrimitiveType::U8),
1784             sym::u16 => Some(PrimitiveType::U16),
1785             sym::u32 => Some(PrimitiveType::U32),
1786             sym::u64 => Some(PrimitiveType::U64),
1787             sym::u128 => Some(PrimitiveType::U128),
1788             sym::bool => Some(PrimitiveType::Bool),
1789             sym::char => Some(PrimitiveType::Char),
1790             sym::str => Some(PrimitiveType::Str),
1791             sym::f32 => Some(PrimitiveType::F32),
1792             sym::f64 => Some(PrimitiveType::F64),
1793             sym::array => Some(PrimitiveType::Array),
1794             sym::slice => Some(PrimitiveType::Slice),
1795             sym::tuple => Some(PrimitiveType::Tuple),
1796             sym::unit => Some(PrimitiveType::Unit),
1797             sym::pointer => Some(PrimitiveType::RawPointer),
1798             sym::reference => Some(PrimitiveType::Reference),
1799             kw::Fn => Some(PrimitiveType::Fn),
1800             sym::never => Some(PrimitiveType::Never),
1801             _ => None,
1802         }
1803     }
1804
1805     pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
1806         use ty::fast_reject::SimplifiedTypeGen::*;
1807         use ty::{FloatTy, IntTy, UintTy};
1808         use PrimitiveType::*;
1809         static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
1810
1811         let single = |x| iter::once(x).collect();
1812         CELL.get_or_init(move || {
1813             map! {
1814                 Isize => single(IntSimplifiedType(IntTy::Isize)),
1815                 I8 => single(IntSimplifiedType(IntTy::I8)),
1816                 I16 => single(IntSimplifiedType(IntTy::I16)),
1817                 I32 => single(IntSimplifiedType(IntTy::I32)),
1818                 I64 => single(IntSimplifiedType(IntTy::I64)),
1819                 I128 => single(IntSimplifiedType(IntTy::I128)),
1820                 Usize => single(UintSimplifiedType(UintTy::Usize)),
1821                 U8 => single(UintSimplifiedType(UintTy::U8)),
1822                 U16 => single(UintSimplifiedType(UintTy::U16)),
1823                 U32 => single(UintSimplifiedType(UintTy::U32)),
1824                 U64 => single(UintSimplifiedType(UintTy::U64)),
1825                 U128 => single(UintSimplifiedType(UintTy::U128)),
1826                 F32 => single(FloatSimplifiedType(FloatTy::F32)),
1827                 F64 => single(FloatSimplifiedType(FloatTy::F64)),
1828                 Str => single(StrSimplifiedType),
1829                 Bool => single(BoolSimplifiedType),
1830                 Char => single(CharSimplifiedType),
1831                 Array => single(ArraySimplifiedType),
1832                 Slice => single(SliceSimplifiedType),
1833                 // FIXME: If we ever add an inherent impl for tuples
1834                 // with different lengths, they won't show in rustdoc.
1835                 //
1836                 // Either manually update this arrayvec at this point
1837                 // or start with a more complex refactoring.
1838                 Tuple => [TupleSimplifiedType(1), TupleSimplifiedType(2), TupleSimplifiedType(3)].into(),
1839                 Unit => single(TupleSimplifiedType(0)),
1840                 RawPointer => [PtrSimplifiedType(Mutability::Not), PtrSimplifiedType(Mutability::Mut)].into_iter().collect(),
1841                 Reference => [RefSimplifiedType(Mutability::Not), RefSimplifiedType(Mutability::Mut)].into_iter().collect(),
1842                 // FIXME: This will be wrong if we ever add inherent impls
1843                 // for function pointers.
1844                 Fn => ArrayVec::new(),
1845                 Never => single(NeverSimplifiedType),
1846             }
1847         })
1848     }
1849
1850     pub(crate) fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = DefId> + 'tcx {
1851         Self::simplified_types()
1852             .get(self)
1853             .into_iter()
1854             .flatten()
1855             .flat_map(move |&simp| tcx.incoherent_impls(simp))
1856             .copied()
1857     }
1858
1859     pub(crate) fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> + '_ {
1860         Self::simplified_types()
1861             .values()
1862             .flatten()
1863             .flat_map(move |&simp| tcx.incoherent_impls(simp))
1864             .copied()
1865     }
1866
1867     pub(crate) fn as_sym(&self) -> Symbol {
1868         use PrimitiveType::*;
1869         match self {
1870             Isize => sym::isize,
1871             I8 => sym::i8,
1872             I16 => sym::i16,
1873             I32 => sym::i32,
1874             I64 => sym::i64,
1875             I128 => sym::i128,
1876             Usize => sym::usize,
1877             U8 => sym::u8,
1878             U16 => sym::u16,
1879             U32 => sym::u32,
1880             U64 => sym::u64,
1881             U128 => sym::u128,
1882             F32 => sym::f32,
1883             F64 => sym::f64,
1884             Str => sym::str,
1885             Bool => sym::bool,
1886             Char => sym::char,
1887             Array => sym::array,
1888             Slice => sym::slice,
1889             Tuple => sym::tuple,
1890             Unit => sym::unit,
1891             RawPointer => sym::pointer,
1892             Reference => sym::reference,
1893             Fn => kw::Fn,
1894             Never => sym::never,
1895         }
1896     }
1897
1898     /// Returns the DefId of the module with `doc(primitive)` for this primitive type.
1899     /// Panics if there is no such module.
1900     ///
1901     /// This gives precedence to primitives defined in the current crate, and deprioritizes primitives defined in `core`,
1902     /// but otherwise, if multiple crates define the same primitive, there is no guarantee of which will be picked.
1903     /// In particular, if a crate depends on both `std` and another crate that also defines `doc(primitive)`, then
1904     /// it's entirely random whether `std` or the other crate is picked. (no_std crates are usually fine unless multiple dependencies define a primitive.)
1905     pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxHashMap<PrimitiveType, DefId> {
1906         static PRIMITIVE_LOCATIONS: OnceCell<FxHashMap<PrimitiveType, DefId>> = OnceCell::new();
1907         PRIMITIVE_LOCATIONS.get_or_init(|| {
1908             let mut primitive_locations = FxHashMap::default();
1909             // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate.
1910             // This is a degenerate case that I don't plan to support.
1911             for &crate_num in tcx.crates(()) {
1912                 let e = ExternalCrate { crate_num };
1913                 let crate_name = e.name(tcx);
1914                 debug!(?crate_num, ?crate_name);
1915                 for &(def_id, prim) in &e.primitives(tcx) {
1916                     // HACK: try to link to std instead where possible
1917                     if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1918                         continue;
1919                     }
1920                     primitive_locations.insert(prim, def_id);
1921                 }
1922             }
1923             let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1924             for (def_id, prim) in local_primitives {
1925                 primitive_locations.insert(prim, def_id);
1926             }
1927             primitive_locations
1928         })
1929     }
1930 }
1931
1932 impl From<ast::IntTy> for PrimitiveType {
1933     fn from(int_ty: ast::IntTy) -> PrimitiveType {
1934         match int_ty {
1935             ast::IntTy::Isize => PrimitiveType::Isize,
1936             ast::IntTy::I8 => PrimitiveType::I8,
1937             ast::IntTy::I16 => PrimitiveType::I16,
1938             ast::IntTy::I32 => PrimitiveType::I32,
1939             ast::IntTy::I64 => PrimitiveType::I64,
1940             ast::IntTy::I128 => PrimitiveType::I128,
1941         }
1942     }
1943 }
1944
1945 impl From<ast::UintTy> for PrimitiveType {
1946     fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1947         match uint_ty {
1948             ast::UintTy::Usize => PrimitiveType::Usize,
1949             ast::UintTy::U8 => PrimitiveType::U8,
1950             ast::UintTy::U16 => PrimitiveType::U16,
1951             ast::UintTy::U32 => PrimitiveType::U32,
1952             ast::UintTy::U64 => PrimitiveType::U64,
1953             ast::UintTy::U128 => PrimitiveType::U128,
1954         }
1955     }
1956 }
1957
1958 impl From<ast::FloatTy> for PrimitiveType {
1959     fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1960         match float_ty {
1961             ast::FloatTy::F32 => PrimitiveType::F32,
1962             ast::FloatTy::F64 => PrimitiveType::F64,
1963         }
1964     }
1965 }
1966
1967 impl From<ty::IntTy> for PrimitiveType {
1968     fn from(int_ty: ty::IntTy) -> PrimitiveType {
1969         match int_ty {
1970             ty::IntTy::Isize => PrimitiveType::Isize,
1971             ty::IntTy::I8 => PrimitiveType::I8,
1972             ty::IntTy::I16 => PrimitiveType::I16,
1973             ty::IntTy::I32 => PrimitiveType::I32,
1974             ty::IntTy::I64 => PrimitiveType::I64,
1975             ty::IntTy::I128 => PrimitiveType::I128,
1976         }
1977     }
1978 }
1979
1980 impl From<ty::UintTy> for PrimitiveType {
1981     fn from(uint_ty: ty::UintTy) -> PrimitiveType {
1982         match uint_ty {
1983             ty::UintTy::Usize => PrimitiveType::Usize,
1984             ty::UintTy::U8 => PrimitiveType::U8,
1985             ty::UintTy::U16 => PrimitiveType::U16,
1986             ty::UintTy::U32 => PrimitiveType::U32,
1987             ty::UintTy::U64 => PrimitiveType::U64,
1988             ty::UintTy::U128 => PrimitiveType::U128,
1989         }
1990     }
1991 }
1992
1993 impl From<ty::FloatTy> for PrimitiveType {
1994     fn from(float_ty: ty::FloatTy) -> PrimitiveType {
1995         match float_ty {
1996             ty::FloatTy::F32 => PrimitiveType::F32,
1997             ty::FloatTy::F64 => PrimitiveType::F64,
1998         }
1999     }
2000 }
2001
2002 impl From<hir::PrimTy> for PrimitiveType {
2003     fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
2004         match prim_ty {
2005             hir::PrimTy::Int(int_ty) => int_ty.into(),
2006             hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
2007             hir::PrimTy::Float(float_ty) => float_ty.into(),
2008             hir::PrimTy::Str => PrimitiveType::Str,
2009             hir::PrimTy::Bool => PrimitiveType::Bool,
2010             hir::PrimTy::Char => PrimitiveType::Char,
2011         }
2012     }
2013 }
2014
2015 #[derive(Copy, Clone, Debug)]
2016 pub(crate) enum Visibility {
2017     /// `pub`
2018     Public,
2019     /// Visibility inherited from parent.
2020     ///
2021     /// For example, this is the visibility of private items and of enum variants.
2022     Inherited,
2023     /// `pub(crate)`, `pub(super)`, or `pub(in path::to::somewhere)`
2024     Restricted(DefId),
2025 }
2026
2027 impl Visibility {
2028     pub(crate) fn is_public(&self) -> bool {
2029         matches!(self, Visibility::Public)
2030     }
2031 }
2032
2033 #[derive(Clone, Debug)]
2034 pub(crate) struct Struct {
2035     pub(crate) struct_type: CtorKind,
2036     pub(crate) generics: Generics,
2037     pub(crate) fields: Vec<Item>,
2038 }
2039
2040 impl Struct {
2041     pub(crate) fn has_stripped_entries(&self) -> bool {
2042         self.fields.iter().any(|f| f.is_stripped())
2043     }
2044 }
2045
2046 #[derive(Clone, Debug)]
2047 pub(crate) struct Union {
2048     pub(crate) generics: Generics,
2049     pub(crate) fields: Vec<Item>,
2050 }
2051
2052 impl Union {
2053     pub(crate) fn has_stripped_entries(&self) -> bool {
2054         self.fields.iter().any(|f| f.is_stripped())
2055     }
2056 }
2057
2058 /// This is a more limited form of the standard Struct, different in that
2059 /// it lacks the things most items have (name, id, parameterization). Found
2060 /// only as a variant in an enum.
2061 #[derive(Clone, Debug)]
2062 pub(crate) struct VariantStruct {
2063     pub(crate) struct_type: CtorKind,
2064     pub(crate) fields: Vec<Item>,
2065 }
2066
2067 impl VariantStruct {
2068     pub(crate) fn has_stripped_entries(&self) -> bool {
2069         self.fields.iter().any(|f| f.is_stripped())
2070     }
2071 }
2072
2073 #[derive(Clone, Debug)]
2074 pub(crate) struct Enum {
2075     pub(crate) variants: IndexVec<VariantIdx, Item>,
2076     pub(crate) generics: Generics,
2077 }
2078
2079 impl Enum {
2080     pub(crate) fn has_stripped_entries(&self) -> bool {
2081         self.variants.iter().any(|f| f.is_stripped())
2082     }
2083
2084     pub(crate) fn variants(&self) -> impl Iterator<Item = &Item> {
2085         self.variants.iter().filter(|v| !v.is_stripped())
2086     }
2087 }
2088
2089 #[derive(Clone, Debug)]
2090 pub(crate) enum Variant {
2091     CLike,
2092     Tuple(Vec<Item>),
2093     Struct(VariantStruct),
2094 }
2095
2096 impl Variant {
2097     pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
2098         match *self {
2099             Self::Struct(ref struct_) => Some(struct_.has_stripped_entries()),
2100             Self::CLike | Self::Tuple(_) => None,
2101         }
2102     }
2103 }
2104
2105 /// Small wrapper around [`rustc_span::Span`] that adds helper methods
2106 /// and enforces calling [`rustc_span::Span::source_callsite()`].
2107 #[derive(Copy, Clone, Debug)]
2108 pub(crate) struct Span(rustc_span::Span);
2109
2110 impl Span {
2111     /// Wraps a [`rustc_span::Span`]. In case this span is the result of a macro expansion, the
2112     /// span will be updated to point to the macro invocation instead of the macro definition.
2113     ///
2114     /// (See rust-lang/rust#39726)
2115     pub(crate) fn new(sp: rustc_span::Span) -> Self {
2116         Self(sp.source_callsite())
2117     }
2118
2119     pub(crate) fn inner(&self) -> rustc_span::Span {
2120         self.0
2121     }
2122
2123     pub(crate) fn dummy() -> Self {
2124         Self(rustc_span::DUMMY_SP)
2125     }
2126
2127     pub(crate) fn is_dummy(&self) -> bool {
2128         self.0.is_dummy()
2129     }
2130
2131     pub(crate) fn filename(&self, sess: &Session) -> FileName {
2132         sess.source_map().span_to_filename(self.0)
2133     }
2134
2135     pub(crate) fn lo(&self, sess: &Session) -> Loc {
2136         sess.source_map().lookup_char_pos(self.0.lo())
2137     }
2138
2139     pub(crate) fn hi(&self, sess: &Session) -> Loc {
2140         sess.source_map().lookup_char_pos(self.0.hi())
2141     }
2142
2143     pub(crate) fn cnum(&self, sess: &Session) -> CrateNum {
2144         // FIXME: is there a time when the lo and hi crate would be different?
2145         self.lo(sess).file.cnum
2146     }
2147 }
2148
2149 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2150 pub(crate) struct Path {
2151     pub(crate) res: Res,
2152     pub(crate) segments: Vec<PathSegment>,
2153 }
2154
2155 impl Path {
2156     pub(crate) fn def_id(&self) -> DefId {
2157         self.res.def_id()
2158     }
2159
2160     pub(crate) fn last_opt(&self) -> Option<Symbol> {
2161         self.segments.last().map(|s| s.name)
2162     }
2163
2164     pub(crate) fn last(&self) -> Symbol {
2165         self.last_opt().expect("segments were empty")
2166     }
2167
2168     pub(crate) fn whole_name(&self) -> String {
2169         self.segments
2170             .iter()
2171             .map(|s| if s.name == kw::PathRoot { String::new() } else { s.name.to_string() })
2172             .intersperse("::".into())
2173             .collect()
2174     }
2175
2176     /// Checks if this is a `T::Name` path for an associated type.
2177     pub(crate) fn is_assoc_ty(&self) -> bool {
2178         match self.res {
2179             Res::SelfTy { .. } if self.segments.len() != 1 => true,
2180             Res::Def(DefKind::TyParam, _) if self.segments.len() != 1 => true,
2181             Res::Def(DefKind::AssocTy, _) => true,
2182             _ => false,
2183         }
2184     }
2185
2186     pub(crate) fn generics(&self) -> Option<Vec<&Type>> {
2187         self.segments.last().and_then(|seg| {
2188             if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2189                 Some(
2190                     args.iter()
2191                         .filter_map(|arg| match arg {
2192                             GenericArg::Type(ty) => Some(ty),
2193                             _ => None,
2194                         })
2195                         .collect(),
2196                 )
2197             } else {
2198                 None
2199             }
2200         })
2201     }
2202
2203     pub(crate) fn bindings(&self) -> Option<&[TypeBinding]> {
2204         self.segments.last().and_then(|seg| {
2205             if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
2206                 Some(&**bindings)
2207             } else {
2208                 None
2209             }
2210         })
2211     }
2212 }
2213
2214 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2215 pub(crate) enum GenericArg {
2216     Lifetime(Lifetime),
2217     Type(Type),
2218     Const(Box<Constant>),
2219     Infer,
2220 }
2221
2222 // `GenericArg` can occur many times in a single `Path`, so make sure it
2223 // doesn't increase in size unexpectedly.
2224 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2225 rustc_data_structures::static_assert_size!(GenericArg, 80);
2226
2227 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2228 pub(crate) enum GenericArgs {
2229     AngleBracketed { args: Box<[GenericArg]>, bindings: ThinVec<TypeBinding> },
2230     Parenthesized { inputs: Box<[Type]>, output: Option<Box<Type>> },
2231 }
2232
2233 // `GenericArgs` is in every `PathSegment`, so its size can significantly
2234 // affect rustdoc's memory usage.
2235 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2236 rustc_data_structures::static_assert_size!(GenericArgs, 32);
2237
2238 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2239 pub(crate) struct PathSegment {
2240     pub(crate) name: Symbol,
2241     pub(crate) args: GenericArgs,
2242 }
2243
2244 // `PathSegment` usually occurs multiple times in every `Path`, so its size can
2245 // significantly affect rustdoc's memory usage.
2246 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2247 rustc_data_structures::static_assert_size!(PathSegment, 40);
2248
2249 #[derive(Clone, Debug)]
2250 pub(crate) struct Typedef {
2251     pub(crate) type_: Type,
2252     pub(crate) generics: Generics,
2253     /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
2254     /// alias instead of the final type. This will always have the final type, regardless of whether
2255     /// `type_` came from HIR or from metadata.
2256     ///
2257     /// If `item_type.is_none()`, `type_` is guaranteed to come from metadata (and therefore hold the
2258     /// final type).
2259     pub(crate) item_type: Option<Type>,
2260 }
2261
2262 #[derive(Clone, Debug)]
2263 pub(crate) struct OpaqueTy {
2264     pub(crate) bounds: Vec<GenericBound>,
2265     pub(crate) generics: Generics,
2266 }
2267
2268 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2269 pub(crate) struct BareFunctionDecl {
2270     pub(crate) unsafety: hir::Unsafety,
2271     pub(crate) generic_params: Vec<GenericParamDef>,
2272     pub(crate) decl: FnDecl,
2273     pub(crate) abi: Abi,
2274 }
2275
2276 #[derive(Clone, Debug)]
2277 pub(crate) struct Static {
2278     pub(crate) type_: Type,
2279     pub(crate) mutability: Mutability,
2280     pub(crate) expr: Option<BodyId>,
2281 }
2282
2283 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2284 pub(crate) struct Constant {
2285     pub(crate) type_: Type,
2286     pub(crate) kind: ConstantKind,
2287 }
2288
2289 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2290 pub(crate) enum Term {
2291     Type(Type),
2292     Constant(Constant),
2293 }
2294
2295 impl Term {
2296     pub(crate) fn ty(&self) -> Option<&Type> {
2297         if let Term::Type(ty) = self { Some(ty) } else { None }
2298     }
2299 }
2300
2301 impl From<Type> for Term {
2302     fn from(ty: Type) -> Self {
2303         Term::Type(ty)
2304     }
2305 }
2306
2307 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2308 pub(crate) enum ConstantKind {
2309     /// This is the wrapper around `ty::Const` for a non-local constant. Because it doesn't have a
2310     /// `BodyId`, we need to handle it on its own.
2311     ///
2312     /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified
2313     /// by a DefId. So this field must be different from `Extern`.
2314     TyConst { expr: String },
2315     /// A constant (expression) that's not an item or associated item. These are usually found
2316     /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
2317     /// used to define explicit discriminant values for enum variants.
2318     Anonymous { body: BodyId },
2319     /// A constant from a different crate.
2320     Extern { def_id: DefId },
2321     /// `const FOO: u32 = ...;`
2322     Local { def_id: DefId, body: BodyId },
2323 }
2324
2325 impl Constant {
2326     pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2327         self.kind.expr(tcx)
2328     }
2329
2330     pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2331         self.kind.value(tcx)
2332     }
2333
2334     pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2335         self.kind.is_literal(tcx)
2336     }
2337 }
2338
2339 impl ConstantKind {
2340     pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2341         match *self {
2342             ConstantKind::TyConst { ref expr } => expr.clone(),
2343             ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2344             ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2345                 print_const_expr(tcx, body)
2346             }
2347         }
2348     }
2349
2350     pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2351         match *self {
2352             ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
2353             ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2354                 print_evaluated_const(tcx, def_id)
2355             }
2356         }
2357     }
2358
2359     pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2360         match *self {
2361             ConstantKind::TyConst { .. } => false,
2362             ConstantKind::Extern { def_id } => def_id.as_local().map_or(false, |def_id| {
2363                 is_literal_expr(tcx, tcx.hir().local_def_id_to_hir_id(def_id))
2364             }),
2365             ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2366                 is_literal_expr(tcx, body.hir_id)
2367             }
2368         }
2369     }
2370 }
2371
2372 #[derive(Clone, Debug)]
2373 pub(crate) struct Impl {
2374     pub(crate) unsafety: hir::Unsafety,
2375     pub(crate) generics: Generics,
2376     pub(crate) trait_: Option<Path>,
2377     pub(crate) for_: Type,
2378     pub(crate) items: Vec<Item>,
2379     pub(crate) polarity: ty::ImplPolarity,
2380     pub(crate) kind: ImplKind,
2381 }
2382
2383 impl Impl {
2384     pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxHashSet<Symbol> {
2385         self.trait_
2386             .as_ref()
2387             .map(|t| t.def_id())
2388             .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name).collect())
2389             .unwrap_or_default()
2390     }
2391 }
2392
2393 #[derive(Clone, Debug)]
2394 pub(crate) enum ImplKind {
2395     Normal,
2396     Auto,
2397     TupleVaradic,
2398     Blanket(Box<Type>),
2399 }
2400
2401 impl ImplKind {
2402     pub(crate) fn is_auto(&self) -> bool {
2403         matches!(self, ImplKind::Auto)
2404     }
2405
2406     pub(crate) fn is_blanket(&self) -> bool {
2407         matches!(self, ImplKind::Blanket(_))
2408     }
2409
2410     pub(crate) fn is_tuple_variadic(&self) -> bool {
2411         matches!(self, ImplKind::TupleVaradic)
2412     }
2413
2414     pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
2415         match self {
2416             ImplKind::Blanket(ty) => Some(ty),
2417             _ => None,
2418         }
2419     }
2420 }
2421
2422 #[derive(Clone, Debug)]
2423 pub(crate) struct Import {
2424     pub(crate) kind: ImportKind,
2425     pub(crate) source: ImportSource,
2426     pub(crate) should_be_displayed: bool,
2427 }
2428
2429 impl Import {
2430     pub(crate) fn new_simple(
2431         name: Symbol,
2432         source: ImportSource,
2433         should_be_displayed: bool,
2434     ) -> Self {
2435         Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2436     }
2437
2438     pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2439         Self { kind: ImportKind::Glob, source, should_be_displayed }
2440     }
2441 }
2442
2443 #[derive(Clone, Debug)]
2444 pub(crate) enum ImportKind {
2445     // use source as str;
2446     Simple(Symbol),
2447     // use source::*;
2448     Glob,
2449 }
2450
2451 #[derive(Clone, Debug)]
2452 pub(crate) struct ImportSource {
2453     pub(crate) path: Path,
2454     pub(crate) did: Option<DefId>,
2455 }
2456
2457 #[derive(Clone, Debug)]
2458 pub(crate) struct Macro {
2459     pub(crate) source: String,
2460 }
2461
2462 #[derive(Clone, Debug)]
2463 pub(crate) struct ProcMacro {
2464     pub(crate) kind: MacroKind,
2465     pub(crate) helpers: Vec<Symbol>,
2466 }
2467
2468 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
2469 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
2470 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2471 pub(crate) struct TypeBinding {
2472     pub(crate) assoc: PathSegment,
2473     pub(crate) kind: TypeBindingKind,
2474 }
2475
2476 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2477 pub(crate) enum TypeBindingKind {
2478     Equality { term: Term },
2479     Constraint { bounds: Vec<GenericBound> },
2480 }
2481
2482 impl TypeBinding {
2483     pub(crate) fn term(&self) -> &Term {
2484         match self.kind {
2485             TypeBindingKind::Equality { ref term } => term,
2486             _ => panic!("expected equality type binding for parenthesized generic args"),
2487         }
2488     }
2489 }
2490
2491 /// The type, lifetime, or constant that a private type alias's parameter should be
2492 /// replaced with when expanding a use of that type alias.
2493 ///
2494 /// For example:
2495 ///
2496 /// ```
2497 /// type PrivAlias<T> = Vec<T>;
2498 ///
2499 /// pub fn public_fn() -> PrivAlias<i32> { vec![] }
2500 /// ```
2501 ///
2502 /// `public_fn`'s docs will show it as returning `Vec<i32>`, since `PrivAlias` is private.
2503 /// [`SubstParam`] is used to record that `T` should be mapped to `i32`.
2504 pub(crate) enum SubstParam {
2505     Type(Type),
2506     Lifetime(Lifetime),
2507     Constant(Constant),
2508 }
2509
2510 impl SubstParam {
2511     pub(crate) fn as_ty(&self) -> Option<&Type> {
2512         if let Self::Type(ty) = self { Some(ty) } else { None }
2513     }
2514
2515     pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
2516         if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2517     }
2518 }