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