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