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