]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/clean/types.rs
Rollup merge of #106690 - GuillaumeGomez:item-declaration-scrolling, r=notriddle
[rust.git] / src / librustdoc / clean / types.rs
1 use std::cell::RefCell;
2 use std::default::Default;
3 use std::hash::Hash;
4 use std::path::PathBuf;
5 use std::rc::Rc;
6 use std::sync::Arc;
7 use std::sync::OnceLock as OnceCell;
8 use std::{cmp, fmt, iter};
9
10 use arrayvec::ArrayVec;
11 use thin_vec::ThinVec;
12
13 use rustc_ast::util::comments::beautify_doc_string;
14 use rustc_ast::{self as ast, AttrStyle};
15 use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
16 use rustc_const_eval::const_eval::is_unstable_const_fn;
17 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
18 use rustc_hir as hir;
19 use rustc_hir::def::{CtorKind, DefKind, Res};
20 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
21 use rustc_hir::lang_items::LangItem;
22 use rustc_hir::{BodyId, Mutability};
23 use rustc_hir_analysis::check::intrinsic::intrinsic_operation_unsafety;
24 use rustc_index::vec::IndexVec;
25 use rustc_middle::ty::fast_reject::SimplifiedType;
26 use rustc_middle::ty::{self, DefIdTree, TyCtxt, Visibility};
27 use rustc_session::Session;
28 use rustc_span::hygiene::MacroKind;
29 use rustc_span::symbol::{kw, sym, Ident, Symbol};
30 use rustc_span::{self, FileName, Loc};
31 use rustc_target::abi::VariantIdx;
32 use rustc_target::spec::abi::Abi;
33
34 use crate::clean::cfg::Cfg;
35 use crate::clean::external_path;
36 use crate::clean::inline::{self, print_inlined_const};
37 use crate::clean::utils::{is_literal_expr, print_const_expr, print_evaluated_const};
38 use crate::core::DocContext;
39 use crate::formats::cache::Cache;
40 use crate::formats::item_type::ItemType;
41 use crate::html::render::Context;
42 use crate::passes::collect_intra_doc_links::UrlFragment;
43
44 pub(crate) use self::FnRetTy::*;
45 pub(crate) use self::ItemKind::*;
46 pub(crate) use self::SelfTy::*;
47 pub(crate) use self::Type::{
48     Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath,
49     RawPointer, Slice, Tuple,
50 };
51
52 #[cfg(test)]
53 mod tests;
54
55 pub(crate) type ItemIdSet = FxHashSet<ItemId>;
56
57 #[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
58 pub(crate) enum ItemId {
59     /// A "normal" item that uses a [`DefId`] for identification.
60     DefId(DefId),
61     /// Identifier that is used for auto traits.
62     Auto { trait_: DefId, for_: DefId },
63     /// Identifier that is used for blanket implementations.
64     Blanket { impl_id: DefId, for_: DefId },
65 }
66
67 impl ItemId {
68     #[inline]
69     pub(crate) fn is_local(self) -> bool {
70         match self {
71             ItemId::Auto { for_: id, .. }
72             | ItemId::Blanket { for_: id, .. }
73             | ItemId::DefId(id) => id.is_local(),
74         }
75     }
76
77     #[inline]
78     #[track_caller]
79     pub(crate) fn expect_def_id(self) -> DefId {
80         self.as_def_id()
81             .unwrap_or_else(|| panic!("ItemId::expect_def_id: `{:?}` isn't a DefId", self))
82     }
83
84     #[inline]
85     pub(crate) fn as_def_id(self) -> Option<DefId> {
86         match self {
87             ItemId::DefId(id) => Some(id),
88             _ => None,
89         }
90     }
91
92     #[inline]
93     pub(crate) fn krate(self) -> CrateNum {
94         match self {
95             ItemId::Auto { for_: id, .. }
96             | ItemId::Blanket { for_: id, .. }
97             | ItemId::DefId(id) => id.krate,
98         }
99     }
100 }
101
102 impl From<DefId> for ItemId {
103     fn from(id: DefId) -> Self {
104         Self::DefId(id)
105     }
106 }
107
108 /// The crate currently being documented.
109 #[derive(Clone, Debug)]
110 pub(crate) struct Crate {
111     pub(crate) module: Item,
112     /// Only here so that they can be filtered through the rustdoc passes.
113     pub(crate) external_traits: Rc<RefCell<FxHashMap<DefId, Trait>>>,
114 }
115
116 impl Crate {
117     pub(crate) fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
118         ExternalCrate::LOCAL.name(tcx)
119     }
120
121     pub(crate) fn src(&self, tcx: TyCtxt<'_>) -> FileName {
122         ExternalCrate::LOCAL.src(tcx)
123     }
124 }
125
126 #[derive(Copy, Clone, Debug)]
127 pub(crate) struct ExternalCrate {
128     pub(crate) crate_num: CrateNum,
129 }
130
131 impl ExternalCrate {
132     const LOCAL: Self = Self { crate_num: LOCAL_CRATE };
133
134     #[inline]
135     pub(crate) fn def_id(&self) -> DefId {
136         self.crate_num.as_def_id()
137     }
138
139     pub(crate) fn src(&self, tcx: TyCtxt<'_>) -> FileName {
140         let krate_span = tcx.def_span(self.def_id());
141         tcx.sess.source_map().span_to_filename(krate_span)
142     }
143
144     pub(crate) fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
145         tcx.crate_name(self.crate_num)
146     }
147
148     pub(crate) fn src_root(&self, tcx: TyCtxt<'_>) -> PathBuf {
149         match self.src(tcx) {
150             FileName::Real(ref p) => match p.local_path_if_available().parent() {
151                 Some(p) => p.to_path_buf(),
152                 None => PathBuf::new(),
153             },
154             _ => PathBuf::new(),
155         }
156     }
157
158     /// Attempts to find where an external crate is located, given that we're
159     /// rendering in to the specified source destination.
160     pub(crate) fn location(
161         &self,
162         extern_url: Option<&str>,
163         extern_url_takes_precedence: bool,
164         dst: &std::path::Path,
165         tcx: TyCtxt<'_>,
166     ) -> ExternalLocation {
167         use ExternalLocation::*;
168
169         fn to_remote(url: impl ToString) -> ExternalLocation {
170             let mut url = url.to_string();
171             if !url.ends_with('/') {
172                 url.push('/');
173             }
174             Remote(url)
175         }
176
177         // See if there's documentation generated into the local directory
178         // WARNING: since rustdoc creates these directories as it generates documentation, this check is only accurate before rendering starts.
179         // Make sure to call `location()` by that time.
180         let local_location = dst.join(self.name(tcx).as_str());
181         if local_location.is_dir() {
182             return Local;
183         }
184
185         if extern_url_takes_precedence {
186             if let Some(url) = extern_url {
187                 return to_remote(url);
188             }
189         }
190
191         // Failing that, see if there's an attribute specifying where to find this
192         // external crate
193         let did = self.crate_num.as_def_id();
194         tcx.get_attrs(did, sym::doc)
195             .flat_map(|attr| attr.meta_item_list().unwrap_or_default())
196             .filter(|a| a.has_name(sym::html_root_url))
197             .filter_map(|a| a.value_str())
198             .map(to_remote)
199             .next()
200             .or_else(|| extern_url.map(to_remote)) // NOTE: only matters if `extern_url_takes_precedence` is false
201             .unwrap_or(Unknown) // Well, at least we tried.
202     }
203
204     pub(crate) fn keywords(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, Symbol)> {
205         let root = self.def_id();
206
207         let as_keyword = |res: Res<!>| {
208             if let Res::Def(DefKind::Mod, def_id) = res {
209                 let mut keyword = None;
210                 let meta_items = tcx
211                     .get_attrs(def_id, sym::doc)
212                     .flat_map(|attr| attr.meta_item_list().unwrap_or_default());
213                 for meta in meta_items {
214                     if meta.has_name(sym::keyword) {
215                         if let Some(v) = meta.value_str() {
216                             keyword = Some(v);
217                             break;
218                         }
219                     }
220                 }
221                 return keyword.map(|p| (def_id, p));
222             }
223             None
224         };
225         if root.is_local() {
226             tcx.hir()
227                 .root_module()
228                 .item_ids
229                 .iter()
230                 .filter_map(|&id| {
231                     let item = tcx.hir().item(id);
232                     match item.kind {
233                         hir::ItemKind::Mod(_) => {
234                             as_keyword(Res::Def(DefKind::Mod, id.owner_id.to_def_id()))
235                         }
236                         hir::ItemKind::Use(path, hir::UseKind::Single)
237                             if tcx.visibility(id.owner_id).is_public() =>
238                         {
239                             path.res
240                                 .iter()
241                                 .find_map(|res| as_keyword(res.expect_non_local()))
242                                 .map(|(_, prim)| (id.owner_id.to_def_id(), prim))
243                         }
244                         _ => None,
245                     }
246                 })
247                 .collect()
248         } else {
249             tcx.module_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect()
250         }
251     }
252
253     pub(crate) fn primitives(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, PrimitiveType)> {
254         let root = self.def_id();
255
256         // Collect all inner modules which are tagged as implementations of
257         // primitives.
258         //
259         // Note that this loop only searches the top-level items of the crate,
260         // and this is intentional. If we were to search the entire crate for an
261         // item tagged with `#[doc(primitive)]` then we would also have to
262         // search the entirety of external modules for items tagged
263         // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
264         // all that metadata unconditionally).
265         //
266         // In order to keep the metadata load under control, the
267         // `#[doc(primitive)]` feature is explicitly designed to only allow the
268         // primitive tags to show up as the top level items in a crate.
269         //
270         // Also note that this does not attempt to deal with modules tagged
271         // duplicately for the same primitive. This is handled later on when
272         // rendering by delegating everything to a hash map.
273         let as_primitive = |res: Res<!>| {
274             if let Res::Def(DefKind::Mod, def_id) = res {
275                 let mut prim = None;
276                 let meta_items = tcx
277                     .get_attrs(def_id, sym::doc)
278                     .flat_map(|attr| attr.meta_item_list().unwrap_or_default());
279                 for meta in meta_items {
280                     if let Some(v) = meta.value_str() {
281                         if meta.has_name(sym::primitive) {
282                             prim = PrimitiveType::from_symbol(v);
283                             if prim.is_some() {
284                                 break;
285                             }
286                             // FIXME: should warn on unknown primitives?
287                         }
288                     }
289                 }
290                 return prim.map(|p| (def_id, p));
291             }
292             None
293         };
294
295         if root.is_local() {
296             tcx.hir()
297                 .root_module()
298                 .item_ids
299                 .iter()
300                 .filter_map(|&id| {
301                     let item = tcx.hir().item(id);
302                     match item.kind {
303                         hir::ItemKind::Mod(_) => {
304                             as_primitive(Res::Def(DefKind::Mod, id.owner_id.to_def_id()))
305                         }
306                         hir::ItemKind::Use(path, hir::UseKind::Single)
307                             if tcx.visibility(id.owner_id).is_public() =>
308                         {
309                             path.res
310                                 .iter()
311                                 .find_map(|res| as_primitive(res.expect_non_local()))
312                                 // Pretend the primitive is local.
313                                 .map(|(_, prim)| (id.owner_id.to_def_id(), prim))
314                         }
315                         _ => None,
316                     }
317                 })
318                 .collect()
319         } else {
320             tcx.module_children(root).iter().map(|item| item.res).filter_map(as_primitive).collect()
321         }
322     }
323 }
324
325 /// Indicates where an external crate can be found.
326 #[derive(Debug)]
327 pub(crate) enum ExternalLocation {
328     /// Remote URL root of the external crate
329     Remote(String),
330     /// This external crate can be found in the local doc/ folder
331     Local,
332     /// The external crate could not be found.
333     Unknown,
334 }
335
336 /// Anything with a source location and set of attributes and, optionally, a
337 /// name. That is, anything that can be documented. This doesn't correspond
338 /// directly to the AST's concept of an item; it's a strict superset.
339 #[derive(Clone)]
340 pub(crate) struct Item {
341     /// The name of this item.
342     /// Optional because not every item has a name, e.g. impls.
343     pub(crate) name: Option<Symbol>,
344     pub(crate) attrs: Box<Attributes>,
345     /// Information about this item that is specific to what kind of item it is.
346     /// E.g., struct vs enum vs function.
347     pub(crate) kind: Box<ItemKind>,
348     pub(crate) item_id: ItemId,
349     /// This is the `DefId` of the `use` statement if the item was inlined.
350     pub(crate) inline_stmt_id: Option<DefId>,
351     pub(crate) cfg: Option<Arc<Cfg>>,
352 }
353
354 /// NOTE: this does NOT unconditionally print every item, to avoid thousands of lines of logs.
355 /// If you want to see the debug output for attributes and the `kind` as well, use `{:#?}` instead of `{:?}`.
356 impl fmt::Debug for Item {
357     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
358         let alternate = f.alternate();
359         // hand-picked fields that don't bloat the logs too much
360         let mut fmt = f.debug_struct("Item");
361         fmt.field("name", &self.name).field("item_id", &self.item_id);
362         // allow printing the full item if someone really wants to
363         if alternate {
364             fmt.field("attrs", &self.attrs).field("kind", &self.kind).field("cfg", &self.cfg);
365         } else {
366             fmt.field("kind", &self.type_());
367             fmt.field("docs", &self.doc_value());
368         }
369         fmt.finish()
370     }
371 }
372
373 pub(crate) fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
374     Span::new(def_id.as_local().map_or_else(
375         || tcx.def_span(def_id),
376         |local| {
377             let hir = tcx.hir();
378             hir.span_with_body(hir.local_def_id_to_hir_id(local))
379         },
380     ))
381 }
382
383 fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
384     let parent = tcx.parent(def_id);
385     match tcx.def_kind(parent) {
386         DefKind::Struct | DefKind::Union => false,
387         DefKind::Variant => true,
388         parent_kind => panic!("unexpected parent kind: {:?}", parent_kind),
389     }
390 }
391
392 impl Item {
393     pub(crate) fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<Stability> {
394         self.item_id.as_def_id().and_then(|did| tcx.lookup_stability(did))
395     }
396
397     pub(crate) fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<ConstStability> {
398         self.item_id.as_def_id().and_then(|did| tcx.lookup_const_stability(did))
399     }
400
401     pub(crate) fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
402         self.item_id.as_def_id().and_then(|did| tcx.lookup_deprecation(did))
403     }
404
405     pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
406         self.item_id
407             .as_def_id()
408             .map(|did| tcx.get_attrs_unchecked(did).inner_docs())
409             .unwrap_or(false)
410     }
411
412     pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option<Span> {
413         let kind = match &*self.kind {
414             ItemKind::StrippedItem(k) => k,
415             _ => &*self.kind,
416         };
417         match kind {
418             ItemKind::ModuleItem(Module { span, .. }) => Some(*span),
419             ItemKind::ImplItem(box Impl { kind: ImplKind::Auto, .. }) => None,
420             ItemKind::ImplItem(box Impl { kind: ImplKind::Blanket(_), .. }) => {
421                 if let ItemId::Blanket { impl_id, .. } = self.item_id {
422                     Some(rustc_span(impl_id, tcx))
423                 } else {
424                     panic!("blanket impl item has non-blanket ID")
425                 }
426             }
427             _ => self.item_id.as_def_id().map(|did| rustc_span(did, tcx)),
428         }
429     }
430
431     pub(crate) fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
432         crate::passes::span_of_attrs(&self.attrs)
433             .unwrap_or_else(|| self.span(tcx).map_or(rustc_span::DUMMY_SP, |span| span.inner()))
434     }
435
436     /// Finds the `doc` attribute as a NameValue and returns the corresponding
437     /// value found.
438     pub(crate) fn doc_value(&self) -> Option<String> {
439         self.attrs.doc_value()
440     }
441
442     /// Convenience wrapper around [`Self::from_def_id_and_parts`] which converts
443     /// `hir_id` to a [`DefId`]
444     pub(crate) fn from_hir_id_and_parts(
445         hir_id: hir::HirId,
446         name: Option<Symbol>,
447         kind: ItemKind,
448         cx: &mut DocContext<'_>,
449     ) -> Item {
450         Item::from_def_id_and_parts(cx.tcx.hir().local_def_id(hir_id).to_def_id(), name, kind, cx)
451     }
452
453     pub(crate) fn from_def_id_and_parts(
454         def_id: DefId,
455         name: Option<Symbol>,
456         kind: ItemKind,
457         cx: &mut DocContext<'_>,
458     ) -> Item {
459         let ast_attrs = cx.tcx.get_attrs_unchecked(def_id);
460
461         Self::from_def_id_and_attrs_and_parts(
462             def_id,
463             name,
464             kind,
465             Box::new(Attributes::from_ast(ast_attrs)),
466             ast_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
467         )
468     }
469
470     pub(crate) fn from_def_id_and_attrs_and_parts(
471         def_id: DefId,
472         name: Option<Symbol>,
473         kind: ItemKind,
474         attrs: Box<Attributes>,
475         cfg: Option<Arc<Cfg>>,
476     ) -> Item {
477         trace!("name={:?}, def_id={:?} cfg={:?}", name, def_id, cfg);
478
479         Item {
480             item_id: def_id.into(),
481             kind: Box::new(kind),
482             name,
483             attrs,
484             cfg,
485             inline_stmt_id: None,
486         }
487     }
488
489     /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
490     /// with newlines.
491     pub(crate) fn collapsed_doc_value(&self) -> Option<String> {
492         self.attrs.collapsed_doc_value()
493     }
494
495     pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
496         use crate::html::format::href;
497
498         cx.cache()
499             .intra_doc_links
500             .get(&self.item_id)
501             .map_or(&[][..], |v| v.as_slice())
502             .iter()
503             .filter_map(|ItemLink { link: s, link_text, page_id: did, ref fragment }| {
504                 debug!(?did);
505                 if let Ok((mut href, ..)) = href(*did, cx) {
506                     debug!(?href);
507                     if let Some(ref fragment) = *fragment {
508                         fragment.render(&mut href, cx.tcx())
509                     }
510                     Some(RenderedLink {
511                         original_text: s.clone(),
512                         new_text: link_text.clone(),
513                         href,
514                     })
515                 } else {
516                     None
517                 }
518             })
519             .collect()
520     }
521
522     /// Find a list of all link names, without finding their href.
523     ///
524     /// This is used for generating summary text, which does not include
525     /// the link text, but does need to know which `[]`-bracketed names
526     /// are actually links.
527     pub(crate) fn link_names(&self, cache: &Cache) -> Vec<RenderedLink> {
528         cache
529             .intra_doc_links
530             .get(&self.item_id)
531             .map_or(&[][..], |v| v.as_slice())
532             .iter()
533             .map(|ItemLink { link: s, link_text, .. }| RenderedLink {
534                 original_text: s.clone(),
535                 new_text: link_text.clone(),
536                 href: String::new(),
537             })
538             .collect()
539     }
540
541     pub(crate) fn is_crate(&self) -> bool {
542         self.is_mod() && self.item_id.as_def_id().map_or(false, |did| did.is_crate_root())
543     }
544     pub(crate) fn is_mod(&self) -> bool {
545         self.type_() == ItemType::Module
546     }
547     pub(crate) fn is_trait(&self) -> bool {
548         self.type_() == ItemType::Trait
549     }
550     pub(crate) fn is_struct(&self) -> bool {
551         self.type_() == ItemType::Struct
552     }
553     pub(crate) fn is_enum(&self) -> bool {
554         self.type_() == ItemType::Enum
555     }
556     pub(crate) fn is_variant(&self) -> bool {
557         self.type_() == ItemType::Variant
558     }
559     pub(crate) fn is_associated_type(&self) -> bool {
560         matches!(&*self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..)))
561     }
562     pub(crate) fn is_ty_associated_type(&self) -> bool {
563         matches!(&*self.kind, TyAssocTypeItem(..) | StrippedItem(box TyAssocTypeItem(..)))
564     }
565     pub(crate) fn is_associated_const(&self) -> bool {
566         matches!(&*self.kind, AssocConstItem(..) | StrippedItem(box AssocConstItem(..)))
567     }
568     pub(crate) fn is_ty_associated_const(&self) -> bool {
569         matches!(&*self.kind, TyAssocConstItem(..) | StrippedItem(box TyAssocConstItem(..)))
570     }
571     pub(crate) fn is_method(&self) -> bool {
572         self.type_() == ItemType::Method
573     }
574     pub(crate) fn is_ty_method(&self) -> bool {
575         self.type_() == ItemType::TyMethod
576     }
577     pub(crate) fn is_typedef(&self) -> bool {
578         self.type_() == ItemType::Typedef
579     }
580     pub(crate) fn is_primitive(&self) -> bool {
581         self.type_() == ItemType::Primitive
582     }
583     pub(crate) fn is_union(&self) -> bool {
584         self.type_() == ItemType::Union
585     }
586     pub(crate) fn is_import(&self) -> bool {
587         self.type_() == ItemType::Import
588     }
589     pub(crate) fn is_extern_crate(&self) -> bool {
590         self.type_() == ItemType::ExternCrate
591     }
592     pub(crate) fn is_keyword(&self) -> bool {
593         self.type_() == ItemType::Keyword
594     }
595     pub(crate) fn is_stripped(&self) -> bool {
596         match *self.kind {
597             StrippedItem(..) => true,
598             ImportItem(ref i) => !i.should_be_displayed,
599             _ => false,
600         }
601     }
602     pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
603         match *self.kind {
604             StructItem(ref struct_) => Some(struct_.has_stripped_entries()),
605             UnionItem(ref union_) => Some(union_.has_stripped_entries()),
606             EnumItem(ref enum_) => Some(enum_.has_stripped_entries()),
607             VariantItem(ref v) => v.has_stripped_entries(),
608             _ => None,
609         }
610     }
611
612     pub(crate) fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
613         self.stability(tcx).as_ref().and_then(|s| {
614             let mut classes = Vec::with_capacity(2);
615
616             if s.is_unstable() {
617                 classes.push("unstable");
618             }
619
620             // FIXME: what about non-staged API items that are deprecated?
621             if self.deprecation(tcx).is_some() {
622                 classes.push("deprecated");
623             }
624
625             if !classes.is_empty() { Some(classes.join(" ")) } else { None }
626         })
627     }
628
629     pub(crate) fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<Symbol> {
630         match self.stability(tcx)?.level {
631             StabilityLevel::Stable { since, .. } => Some(since),
632             StabilityLevel::Unstable { .. } => None,
633         }
634     }
635
636     pub(crate) fn const_stable_since(&self, tcx: TyCtxt<'_>) -> Option<Symbol> {
637         match self.const_stability(tcx)?.level {
638             StabilityLevel::Stable { since, .. } => Some(since),
639             StabilityLevel::Unstable { .. } => None,
640         }
641     }
642
643     pub(crate) fn is_non_exhaustive(&self) -> bool {
644         self.attrs.other_attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
645     }
646
647     /// Returns a documentation-level item type from the item.
648     pub(crate) fn type_(&self) -> ItemType {
649         ItemType::from(self)
650     }
651
652     pub(crate) fn is_default(&self) -> bool {
653         match *self.kind {
654             ItemKind::MethodItem(_, Some(defaultness)) => {
655                 defaultness.has_value() && !defaultness.is_final()
656             }
657             _ => false,
658         }
659     }
660
661     /// Returns a `FnHeader` if `self` is a function item, otherwise returns `None`.
662     pub(crate) fn fn_header(&self, tcx: TyCtxt<'_>) -> Option<hir::FnHeader> {
663         fn build_fn_header(
664             def_id: DefId,
665             tcx: TyCtxt<'_>,
666             asyncness: hir::IsAsync,
667         ) -> hir::FnHeader {
668             let sig = tcx.fn_sig(def_id);
669             let constness =
670                 if tcx.is_const_fn(def_id) && is_unstable_const_fn(tcx, def_id).is_none() {
671                     hir::Constness::Const
672                 } else {
673                     hir::Constness::NotConst
674                 };
675             hir::FnHeader { unsafety: sig.unsafety(), abi: sig.abi(), constness, asyncness }
676         }
677         let header = match *self.kind {
678             ItemKind::ForeignFunctionItem(_) => {
679                 let abi = tcx.fn_sig(self.item_id.as_def_id().unwrap()).abi();
680                 hir::FnHeader {
681                     unsafety: if abi == Abi::RustIntrinsic {
682                         intrinsic_operation_unsafety(tcx, self.item_id.as_def_id().unwrap())
683                     } else {
684                         hir::Unsafety::Unsafe
685                     },
686                     abi,
687                     constness: hir::Constness::NotConst,
688                     asyncness: hir::IsAsync::NotAsync,
689                 }
690             }
691             ItemKind::FunctionItem(_) | ItemKind::MethodItem(_, _) | ItemKind::TyMethodItem(_) => {
692                 let def_id = self.item_id.as_def_id().unwrap();
693                 build_fn_header(def_id, tcx, tcx.asyncness(def_id))
694             }
695             _ => return None,
696         };
697         Some(header)
698     }
699
700     /// Returns the visibility of the current item. If the visibility is "inherited", then `None`
701     /// is returned.
702     pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option<Visibility<DefId>> {
703         let def_id = match self.item_id {
704             // Anything but DefId *shouldn't* matter, but return a reasonable value anyway.
705             ItemId::Auto { .. } | ItemId::Blanket { .. } => return None,
706             ItemId::DefId(def_id) => def_id,
707         };
708
709         match *self.kind {
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             ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) => return Some(Visibility::Public),
714             // Variant fields inherit their enum's visibility.
715             StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => {
716                 return None;
717             }
718             // Variants always inherit visibility
719             VariantItem(..) => return None,
720             // Trait items inherit the trait's visibility
721             AssocConstItem(..) | TyAssocConstItem(..) | AssocTypeItem(..) | TyAssocTypeItem(..)
722             | TyMethodItem(..) | MethodItem(..) => {
723                 let assoc_item = tcx.associated_item(def_id);
724                 let is_trait_item = match assoc_item.container {
725                     ty::TraitContainer => true,
726                     ty::ImplContainer => {
727                         // Trait impl items always inherit the impl's visibility --
728                         // we don't want to show `pub`.
729                         tcx.impl_trait_ref(tcx.parent(assoc_item.def_id)).is_some()
730                     }
731                 };
732                 if is_trait_item {
733                     return None;
734                 }
735             }
736             _ => {}
737         }
738         let def_id = match self.inline_stmt_id {
739             Some(inlined) => inlined,
740             None => def_id,
741         };
742         Some(tcx.visibility(def_id))
743     }
744 }
745
746 #[derive(Clone, Debug)]
747 pub(crate) enum ItemKind {
748     ExternCrateItem {
749         /// The crate's name, *not* the name it's imported as.
750         src: Option<Symbol>,
751     },
752     ImportItem(Import),
753     StructItem(Struct),
754     UnionItem(Union),
755     EnumItem(Enum),
756     FunctionItem(Box<Function>),
757     ModuleItem(Module),
758     TypedefItem(Box<Typedef>),
759     OpaqueTyItem(OpaqueTy),
760     StaticItem(Static),
761     ConstantItem(Constant),
762     TraitItem(Box<Trait>),
763     TraitAliasItem(TraitAlias),
764     ImplItem(Box<Impl>),
765     /// A required method in a trait declaration meaning it's only a function signature.
766     TyMethodItem(Box<Function>),
767     /// A method in a trait impl or a provided method in a trait declaration.
768     ///
769     /// Compared to [TyMethodItem], it also contains a method body.
770     MethodItem(Box<Function>, Option<hir::Defaultness>),
771     StructFieldItem(Type),
772     VariantItem(Variant),
773     /// `fn`s from an extern block
774     ForeignFunctionItem(Box<Function>),
775     /// `static`s from an extern block
776     ForeignStaticItem(Static),
777     /// `type`s from an extern block
778     ForeignTypeItem,
779     MacroItem(Macro),
780     ProcMacroItem(ProcMacro),
781     PrimitiveItem(PrimitiveType),
782     /// A required associated constant in a trait declaration.
783     TyAssocConstItem(Type),
784     /// An associated associated constant in a trait impl or a provided one in a trait declaration.
785     AssocConstItem(Type, ConstantKind),
786     /// A required associated type in a trait declaration.
787     ///
788     /// The bounds may be non-empty if there is a `where` clause.
789     TyAssocTypeItem(Generics, Vec<GenericBound>),
790     /// An associated type in a trait impl or a provided one in a trait declaration.
791     AssocTypeItem(Box<Typedef>, Vec<GenericBound>),
792     /// An item that has been stripped by a rustdoc pass
793     StrippedItem(Box<ItemKind>),
794     KeywordItem,
795 }
796
797 impl ItemKind {
798     /// Some items contain others such as structs (for their fields) and Enums
799     /// (for their variants). This method returns those contained items.
800     pub(crate) fn inner_items(&self) -> impl Iterator<Item = &Item> {
801         match self {
802             StructItem(s) => s.fields.iter(),
803             UnionItem(u) => u.fields.iter(),
804             VariantItem(v) => match &v.kind {
805                 VariantKind::CLike => [].iter(),
806                 VariantKind::Tuple(t) => t.iter(),
807                 VariantKind::Struct(s) => s.fields.iter(),
808             },
809             EnumItem(e) => e.variants.iter(),
810             TraitItem(t) => t.items.iter(),
811             ImplItem(i) => i.items.iter(),
812             ModuleItem(m) => m.items.iter(),
813             ExternCrateItem { .. }
814             | ImportItem(_)
815             | FunctionItem(_)
816             | TypedefItem(_)
817             | OpaqueTyItem(_)
818             | StaticItem(_)
819             | ConstantItem(_)
820             | TraitAliasItem(_)
821             | TyMethodItem(_)
822             | MethodItem(_, _)
823             | StructFieldItem(_)
824             | ForeignFunctionItem(_)
825             | ForeignStaticItem(_)
826             | ForeignTypeItem
827             | MacroItem(_)
828             | ProcMacroItem(_)
829             | PrimitiveItem(_)
830             | TyAssocConstItem(_)
831             | AssocConstItem(_, _)
832             | TyAssocTypeItem(..)
833             | AssocTypeItem(..)
834             | StrippedItem(_)
835             | KeywordItem => [].iter(),
836         }
837     }
838
839     /// Returns `true` if this item does not appear inside an impl block.
840     pub(crate) fn is_non_assoc(&self) -> bool {
841         matches!(
842             self,
843             StructItem(_)
844                 | UnionItem(_)
845                 | EnumItem(_)
846                 | TraitItem(_)
847                 | ModuleItem(_)
848                 | ExternCrateItem { .. }
849                 | FunctionItem(_)
850                 | TypedefItem(_)
851                 | OpaqueTyItem(_)
852                 | StaticItem(_)
853                 | ConstantItem(_)
854                 | TraitAliasItem(_)
855                 | ForeignFunctionItem(_)
856                 | ForeignStaticItem(_)
857                 | ForeignTypeItem
858                 | MacroItem(_)
859                 | ProcMacroItem(_)
860                 | PrimitiveItem(_)
861         )
862     }
863 }
864
865 #[derive(Clone, Debug)]
866 pub(crate) struct Module {
867     pub(crate) items: Vec<Item>,
868     pub(crate) span: Span,
869 }
870
871 pub(crate) trait AttributesExt {
872     type AttributeIterator<'a>: Iterator<Item = ast::NestedMetaItem>
873     where
874         Self: 'a;
875
876     fn lists<'a>(&'a self, name: Symbol) -> Self::AttributeIterator<'a>;
877
878     fn span(&self) -> Option<rustc_span::Span>;
879
880     fn inner_docs(&self) -> bool;
881
882     fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>>;
883 }
884
885 impl AttributesExt for [ast::Attribute] {
886     type AttributeIterator<'a> = impl Iterator<Item = ast::NestedMetaItem> + 'a;
887
888     fn lists<'a>(&'a self, name: Symbol) -> Self::AttributeIterator<'a> {
889         self.iter()
890             .filter(move |attr| attr.has_name(name))
891             .filter_map(ast::Attribute::meta_item_list)
892             .flatten()
893     }
894
895     /// Return the span of the first doc-comment, if it exists.
896     fn span(&self) -> Option<rustc_span::Span> {
897         self.iter().find(|attr| attr.doc_str().is_some()).map(|attr| attr.span)
898     }
899
900     /// Returns whether the first doc-comment is an inner attribute.
901     ///
902     //// If there are no doc-comments, return true.
903     /// FIXME(#78591): Support both inner and outer attributes on the same item.
904     fn inner_docs(&self) -> bool {
905         self.iter().find(|a| a.doc_str().is_some()).map_or(true, |a| a.style == AttrStyle::Inner)
906     }
907
908     fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>> {
909         let sess = tcx.sess;
910         let doc_cfg_active = tcx.features().doc_cfg;
911         let doc_auto_cfg_active = tcx.features().doc_auto_cfg;
912
913         fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
914             let mut iter = it.into_iter();
915             let item = iter.next()?;
916             if iter.next().is_some() {
917                 return None;
918             }
919             Some(item)
920         }
921
922         let mut cfg = if doc_cfg_active || doc_auto_cfg_active {
923             let mut doc_cfg = self
924                 .iter()
925                 .filter(|attr| attr.has_name(sym::doc))
926                 .flat_map(|attr| attr.meta_item_list().unwrap_or_default())
927                 .filter(|attr| attr.has_name(sym::cfg))
928                 .peekable();
929             if doc_cfg.peek().is_some() && doc_cfg_active {
930                 doc_cfg
931                     .filter_map(|attr| Cfg::parse(attr.meta_item()?).ok())
932                     .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
933             } else if doc_auto_cfg_active {
934                 self.iter()
935                     .filter(|attr| attr.has_name(sym::cfg))
936                     .filter_map(|attr| single(attr.meta_item_list()?))
937                     .filter_map(|attr| {
938                         Cfg::parse_without(attr.meta_item()?, hidden_cfg).ok().flatten()
939                     })
940                     .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
941             } else {
942                 Cfg::True
943             }
944         } else {
945             Cfg::True
946         };
947
948         for attr in self.iter() {
949             // #[doc]
950             if attr.doc_str().is_none() && attr.has_name(sym::doc) {
951                 // #[doc(...)]
952                 if let Some(list) = attr.meta().as_ref().and_then(|mi| mi.meta_item_list()) {
953                     for item in list {
954                         // #[doc(hidden)]
955                         if !item.has_name(sym::cfg) {
956                             continue;
957                         }
958                         // #[doc(cfg(...))]
959                         if let Some(cfg_mi) = item
960                             .meta_item()
961                             .and_then(|item| rustc_expand::config::parse_cfg(item, sess))
962                         {
963                             match Cfg::parse(cfg_mi) {
964                                 Ok(new_cfg) => cfg &= new_cfg,
965                                 Err(e) => {
966                                     sess.span_err(e.span, e.msg);
967                                 }
968                             }
969                         }
970                     }
971                 }
972             }
973         }
974
975         // treat #[target_feature(enable = "feat")] attributes as if they were
976         // #[doc(cfg(target_feature = "feat"))] attributes as well
977         for attr in self.lists(sym::target_feature) {
978             if attr.has_name(sym::enable) {
979                 if attr.value_str().is_some() {
980                     // Clone `enable = "feat"`, change to `target_feature = "feat"`.
981                     // Unwrap is safe because `value_str` succeeded above.
982                     let mut meta = attr.meta_item().unwrap().clone();
983                     meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature));
984
985                     if let Ok(feat_cfg) = Cfg::parse(&meta) {
986                         cfg &= feat_cfg;
987                     }
988                 }
989             }
990         }
991
992         if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) }
993     }
994 }
995
996 pub(crate) trait NestedAttributesExt {
997     /// Returns `true` if the attribute list contains a specific `word`
998     fn has_word(self, word: Symbol) -> bool
999     where
1000         Self: std::marker::Sized,
1001     {
1002         <Self as NestedAttributesExt>::get_word_attr(self, word).is_some()
1003     }
1004
1005     /// Returns `Some(attr)` if the attribute list contains 'attr'
1006     /// corresponding to a specific `word`
1007     fn get_word_attr(self, word: Symbol) -> Option<ast::NestedMetaItem>;
1008 }
1009
1010 impl<I: Iterator<Item = ast::NestedMetaItem>> NestedAttributesExt for I {
1011     fn get_word_attr(mut self, word: Symbol) -> Option<ast::NestedMetaItem> {
1012         self.find(|attr| attr.is_word() && attr.has_name(word))
1013     }
1014 }
1015
1016 /// A portion of documentation, extracted from a `#[doc]` attribute.
1017 ///
1018 /// Each variant contains the line number within the complete doc-comment where the fragment
1019 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
1020 ///
1021 /// Included files are kept separate from inline doc comments so that proper line-number
1022 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
1023 /// kept separate because of issue #42760.
1024 #[derive(Clone, PartialEq, Eq, Debug)]
1025 pub(crate) struct DocFragment {
1026     pub(crate) span: rustc_span::Span,
1027     /// The module this doc-comment came from.
1028     ///
1029     /// This allows distinguishing between the original documentation and a pub re-export.
1030     /// If it is `None`, the item was not re-exported.
1031     pub(crate) parent_module: Option<DefId>,
1032     pub(crate) doc: Symbol,
1033     pub(crate) kind: DocFragmentKind,
1034     pub(crate) indent: usize,
1035 }
1036
1037 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
1038 pub(crate) enum DocFragmentKind {
1039     /// A doc fragment created from a `///` or `//!` doc comment.
1040     SugaredDoc,
1041     /// A doc fragment created from a "raw" `#[doc=""]` attribute.
1042     RawDoc,
1043 }
1044
1045 /// The goal of this function is to apply the `DocFragment` transformation that is required when
1046 /// transforming into the final Markdown, which is applying the computed indent to each line in
1047 /// each doc fragment (a `DocFragment` can contain multiple lines in case of `#[doc = ""]`).
1048 ///
1049 /// Note: remove the trailing newline where appropriate
1050 fn add_doc_fragment(out: &mut String, frag: &DocFragment) {
1051     let s = frag.doc.as_str();
1052     let mut iter = s.lines();
1053     if s.is_empty() {
1054         out.push('\n');
1055         return;
1056     }
1057     while let Some(line) = iter.next() {
1058         if line.chars().any(|c| !c.is_whitespace()) {
1059             assert!(line.len() >= frag.indent);
1060             out.push_str(&line[frag.indent..]);
1061         } else {
1062             out.push_str(line);
1063         }
1064         out.push('\n');
1065     }
1066 }
1067
1068 /// Collapse a collection of [`DocFragment`]s into one string,
1069 /// handling indentation and newlines as needed.
1070 pub(crate) fn collapse_doc_fragments(doc_strings: &[DocFragment]) -> String {
1071     let mut acc = String::new();
1072     for frag in doc_strings {
1073         add_doc_fragment(&mut acc, frag);
1074     }
1075     acc.pop();
1076     acc
1077 }
1078
1079 /// Removes excess indentation on comments in order for the Markdown
1080 /// to be parsed correctly. This is necessary because the convention for
1081 /// writing documentation is to provide a space between the /// or //! marker
1082 /// and the doc text, but Markdown is whitespace-sensitive. For example,
1083 /// a block of text with four-space indentation is parsed as a code block,
1084 /// so if we didn't unindent comments, these list items
1085 ///
1086 /// /// A list:
1087 /// ///
1088 /// ///    - Foo
1089 /// ///    - Bar
1090 ///
1091 /// would be parsed as if they were in a code block, which is likely not what the user intended.
1092 fn unindent_doc_fragments(docs: &mut Vec<DocFragment>) {
1093     // `add` is used in case the most common sugared doc syntax is used ("/// "). The other
1094     // fragments kind's lines are never starting with a whitespace unless they are using some
1095     // markdown formatting requiring it. Therefore, if the doc block have a mix between the two,
1096     // we need to take into account the fact that the minimum indent minus one (to take this
1097     // whitespace into account).
1098     //
1099     // For example:
1100     //
1101     // /// hello!
1102     // #[doc = "another"]
1103     //
1104     // In this case, you want "hello! another" and not "hello!  another".
1105     let add = if docs.windows(2).any(|arr| arr[0].kind != arr[1].kind)
1106         && docs.iter().any(|d| d.kind == DocFragmentKind::SugaredDoc)
1107     {
1108         // In case we have a mix of sugared doc comments and "raw" ones, we want the sugared one to
1109         // "decide" how much the minimum indent will be.
1110         1
1111     } else {
1112         0
1113     };
1114
1115     // `min_indent` is used to know how much whitespaces from the start of each lines must be
1116     // removed. Example:
1117     //
1118     // ///     hello!
1119     // #[doc = "another"]
1120     //
1121     // In here, the `min_indent` is 1 (because non-sugared fragment are always counted with minimum
1122     // 1 whitespace), meaning that "hello!" will be considered a codeblock because it starts with 4
1123     // (5 - 1) whitespaces.
1124     let Some(min_indent) = docs
1125         .iter()
1126         .map(|fragment| {
1127             fragment.doc.as_str().lines().fold(usize::MAX, |min_indent, line| {
1128                 if line.chars().all(|c| c.is_whitespace()) {
1129                     min_indent
1130                 } else {
1131                     // Compare against either space or tab, ignoring whether they are
1132                     // mixed or not.
1133                     let whitespace = line.chars().take_while(|c| *c == ' ' || *c == '\t').count();
1134                     cmp::min(min_indent, whitespace)
1135                         + if fragment.kind == DocFragmentKind::SugaredDoc { 0 } else { add }
1136                 }
1137             })
1138         })
1139         .min()
1140     else {
1141         return;
1142     };
1143
1144     for fragment in docs {
1145         if fragment.doc == kw::Empty {
1146             continue;
1147         }
1148
1149         let min_indent = if fragment.kind != DocFragmentKind::SugaredDoc && min_indent > 0 {
1150             min_indent - add
1151         } else {
1152             min_indent
1153         };
1154
1155         fragment.indent = min_indent;
1156     }
1157 }
1158
1159 /// A link that has not yet been rendered.
1160 ///
1161 /// This link will be turned into a rendered link by [`Item::links`].
1162 #[derive(Clone, Debug, PartialEq, Eq)]
1163 pub(crate) struct ItemLink {
1164     /// The original link written in the markdown
1165     pub(crate) link: String,
1166     /// The link text displayed in the HTML.
1167     ///
1168     /// This may not be the same as `link` if there was a disambiguator
1169     /// in an intra-doc link (e.g. \[`fn@f`\])
1170     pub(crate) link_text: String,
1171     /// The `DefId` of the Item whose **HTML Page** contains the item being
1172     /// linked to. This will be different to `item_id` on item's that don't
1173     /// have their own page, such as struct fields and enum variants.
1174     pub(crate) page_id: DefId,
1175     /// The url fragment to append to the link
1176     pub(crate) fragment: Option<UrlFragment>,
1177 }
1178
1179 pub struct RenderedLink {
1180     /// The text the link was original written as.
1181     ///
1182     /// This could potentially include disambiguators and backticks.
1183     pub(crate) original_text: String,
1184     /// The text to display in the HTML
1185     pub(crate) new_text: String,
1186     /// The URL to put in the `href`
1187     pub(crate) href: String,
1188 }
1189
1190 /// The attributes on an [`Item`], including attributes like `#[derive(...)]` and `#[inline]`,
1191 /// as well as doc comments.
1192 #[derive(Clone, Debug, Default)]
1193 pub(crate) struct Attributes {
1194     pub(crate) doc_strings: Vec<DocFragment>,
1195     pub(crate) other_attrs: ast::AttrVec,
1196 }
1197
1198 impl Attributes {
1199     pub(crate) fn lists(&self, name: Symbol) -> impl Iterator<Item = ast::NestedMetaItem> + '_ {
1200         self.other_attrs.lists(name)
1201     }
1202
1203     pub(crate) fn has_doc_flag(&self, flag: Symbol) -> bool {
1204         for attr in &self.other_attrs {
1205             if !attr.has_name(sym::doc) {
1206                 continue;
1207             }
1208
1209             if let Some(items) = attr.meta_item_list() {
1210                 if items.iter().filter_map(|i| i.meta_item()).any(|it| it.has_name(flag)) {
1211                     return true;
1212                 }
1213             }
1214         }
1215
1216         false
1217     }
1218
1219     pub(crate) fn from_ast(attrs: &[ast::Attribute]) -> Attributes {
1220         Attributes::from_ast_iter(attrs.iter().map(|attr| (attr, None)), false)
1221     }
1222
1223     pub(crate) fn from_ast_with_additional(
1224         attrs: &[ast::Attribute],
1225         (additional_attrs, def_id): (&[ast::Attribute], DefId),
1226     ) -> Attributes {
1227         // Additional documentation should be shown before the original documentation.
1228         let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id)));
1229         let attrs2 = attrs.iter().map(|attr| (attr, None));
1230         Attributes::from_ast_iter(attrs1.chain(attrs2), false)
1231     }
1232
1233     pub(crate) fn from_ast_iter<'a>(
1234         attrs: impl Iterator<Item = (&'a ast::Attribute, Option<DefId>)>,
1235         doc_only: bool,
1236     ) -> Attributes {
1237         let mut doc_strings = Vec::new();
1238         let mut other_attrs = ast::AttrVec::new();
1239         for (attr, parent_module) in attrs {
1240             if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() {
1241                 trace!("got doc_str={doc_str:?}");
1242                 let doc = beautify_doc_string(doc_str, comment_kind);
1243                 let kind = if attr.is_doc_comment() {
1244                     DocFragmentKind::SugaredDoc
1245                 } else {
1246                     DocFragmentKind::RawDoc
1247                 };
1248                 let fragment = DocFragment { span: attr.span, doc, kind, parent_module, indent: 0 };
1249                 doc_strings.push(fragment);
1250             } else if !doc_only {
1251                 other_attrs.push(attr.clone());
1252             }
1253         }
1254
1255         unindent_doc_fragments(&mut doc_strings);
1256
1257         Attributes { doc_strings, other_attrs }
1258     }
1259
1260     /// Finds the `doc` attribute as a NameValue and returns the corresponding
1261     /// value found.
1262     pub(crate) fn doc_value(&self) -> Option<String> {
1263         let mut iter = self.doc_strings.iter();
1264
1265         let ori = iter.next()?;
1266         let mut out = String::new();
1267         add_doc_fragment(&mut out, ori);
1268         for new_frag in iter {
1269             add_doc_fragment(&mut out, new_frag);
1270         }
1271         out.pop();
1272         if out.is_empty() { None } else { Some(out) }
1273     }
1274
1275     /// Return the doc-comments on this item, grouped by the module they came from.
1276     /// The module can be different if this is a re-export with added documentation.
1277     ///
1278     /// The last newline is not trimmed so the produced strings are reusable between
1279     /// early and late doc link resolution regardless of their position.
1280     pub(crate) fn prepare_to_doc_link_resolution(&self) -> FxHashMap<Option<DefId>, String> {
1281         let mut res = FxHashMap::default();
1282         for fragment in &self.doc_strings {
1283             let out_str = res.entry(fragment.parent_module).or_default();
1284             add_doc_fragment(out_str, fragment);
1285         }
1286         res
1287     }
1288
1289     /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
1290     /// with newlines.
1291     pub(crate) fn collapsed_doc_value(&self) -> Option<String> {
1292         if self.doc_strings.is_empty() {
1293             None
1294         } else {
1295             Some(collapse_doc_fragments(&self.doc_strings))
1296         }
1297     }
1298
1299     pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> {
1300         let mut aliases = FxHashSet::default();
1301
1302         for attr in self.other_attrs.lists(sym::doc).filter(|a| a.has_name(sym::alias)) {
1303             if let Some(values) = attr.meta_item_list() {
1304                 for l in values {
1305                     match l.lit().unwrap().kind {
1306                         ast::LitKind::Str(s, _) => {
1307                             aliases.insert(s);
1308                         }
1309                         _ => unreachable!(),
1310                     }
1311                 }
1312             } else {
1313                 aliases.insert(attr.value_str().unwrap());
1314             }
1315         }
1316         aliases.into_iter().collect::<Vec<_>>().into()
1317     }
1318 }
1319
1320 impl PartialEq for Attributes {
1321     fn eq(&self, rhs: &Self) -> bool {
1322         self.doc_strings == rhs.doc_strings
1323             && self
1324                 .other_attrs
1325                 .iter()
1326                 .map(|attr| attr.id)
1327                 .eq(rhs.other_attrs.iter().map(|attr| attr.id))
1328     }
1329 }
1330
1331 impl Eq for Attributes {}
1332
1333 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1334 pub(crate) enum GenericBound {
1335     TraitBound(PolyTrait, hir::TraitBoundModifier),
1336     Outlives(Lifetime),
1337 }
1338
1339 impl GenericBound {
1340     pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1341         let did = cx.tcx.require_lang_item(LangItem::Sized, None);
1342         let empty = ty::Binder::dummy(ty::InternalSubsts::empty());
1343         let path = external_path(cx, did, false, ThinVec::new(), empty);
1344         inline::record_extern_fqn(cx, did, ItemType::Trait);
1345         GenericBound::TraitBound(
1346             PolyTrait { trait_: path, generic_params: Vec::new() },
1347             hir::TraitBoundModifier::Maybe,
1348         )
1349     }
1350
1351     pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1352         use rustc_hir::TraitBoundModifier as TBM;
1353         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
1354             if Some(trait_.def_id()) == cx.tcx.lang_items().sized_trait() {
1355                 return true;
1356             }
1357         }
1358         false
1359     }
1360
1361     pub(crate) fn get_poly_trait(&self) -> Option<PolyTrait> {
1362         if let GenericBound::TraitBound(ref p, _) = *self {
1363             return Some(p.clone());
1364         }
1365         None
1366     }
1367
1368     pub(crate) fn get_trait_path(&self) -> Option<Path> {
1369         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1370             Some(trait_.clone())
1371         } else {
1372             None
1373         }
1374     }
1375 }
1376
1377 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1378 pub(crate) struct Lifetime(pub Symbol);
1379
1380 impl Lifetime {
1381     pub(crate) fn statik() -> Lifetime {
1382         Lifetime(kw::StaticLifetime)
1383     }
1384
1385     pub(crate) fn elided() -> Lifetime {
1386         Lifetime(kw::UnderscoreLifetime)
1387     }
1388 }
1389
1390 #[derive(Clone, Debug)]
1391 pub(crate) enum WherePredicate {
1392     BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<Lifetime> },
1393     RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1394     EqPredicate { lhs: Box<Type>, rhs: Box<Term>, bound_params: Vec<Lifetime> },
1395 }
1396
1397 impl WherePredicate {
1398     pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1399         match *self {
1400             WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
1401             WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
1402             _ => None,
1403         }
1404     }
1405
1406     pub(crate) fn get_bound_params(&self) -> Option<&[Lifetime]> {
1407         match self {
1408             Self::BoundPredicate { bound_params, .. } | Self::EqPredicate { bound_params, .. } => {
1409                 Some(bound_params)
1410             }
1411             _ => None,
1412         }
1413     }
1414 }
1415
1416 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1417 pub(crate) enum GenericParamDefKind {
1418     Lifetime { outlives: Vec<Lifetime> },
1419     Type { did: DefId, bounds: Vec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
1420     Const { did: DefId, ty: Box<Type>, default: Option<Box<String>> },
1421 }
1422
1423 impl GenericParamDefKind {
1424     pub(crate) fn is_type(&self) -> bool {
1425         matches!(self, GenericParamDefKind::Type { .. })
1426     }
1427 }
1428
1429 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1430 pub(crate) struct GenericParamDef {
1431     pub(crate) name: Symbol,
1432     pub(crate) kind: GenericParamDefKind,
1433 }
1434
1435 impl GenericParamDef {
1436     pub(crate) fn lifetime(name: Symbol) -> Self {
1437         Self { name, kind: GenericParamDefKind::Lifetime { outlives: Vec::new() } }
1438     }
1439
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>, Box<str>),
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 bounds.get(0).map(|b| b.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::SimplifiedType::*;
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) ctor_kind: Option<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) fields: Vec<Item>,
2109 }
2110
2111 impl VariantStruct {
2112     pub(crate) fn has_stripped_entries(&self) -> bool {
2113         self.fields.iter().any(|f| f.is_stripped())
2114     }
2115 }
2116
2117 #[derive(Clone, Debug)]
2118 pub(crate) struct Enum {
2119     pub(crate) variants: IndexVec<VariantIdx, Item>,
2120     pub(crate) generics: Generics,
2121 }
2122
2123 impl Enum {
2124     pub(crate) fn has_stripped_entries(&self) -> bool {
2125         self.variants.iter().any(|f| f.is_stripped())
2126     }
2127
2128     pub(crate) fn variants(&self) -> impl Iterator<Item = &Item> {
2129         self.variants.iter().filter(|v| !v.is_stripped())
2130     }
2131 }
2132
2133 #[derive(Clone, Debug)]
2134 pub(crate) struct Variant {
2135     pub kind: VariantKind,
2136     pub discriminant: Option<Discriminant>,
2137 }
2138
2139 #[derive(Clone, Debug)]
2140 pub(crate) enum VariantKind {
2141     CLike,
2142     Tuple(Vec<Item>),
2143     Struct(VariantStruct),
2144 }
2145
2146 impl Variant {
2147     pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
2148         match &self.kind {
2149             VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()),
2150             VariantKind::CLike | VariantKind::Tuple(_) => None,
2151         }
2152     }
2153 }
2154
2155 #[derive(Clone, Debug)]
2156 pub(crate) struct Discriminant {
2157     // In the case of cross crate re-exports, we don't have the nessesary information
2158     // to reconstruct the expression of the discriminant, only the value.
2159     pub(super) expr: Option<BodyId>,
2160     pub(super) value: DefId,
2161 }
2162
2163 impl Discriminant {
2164     /// Will be `None` in the case of cross-crate reexports, and may be
2165     /// simplified
2166     pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
2167         self.expr.map(|body| print_const_expr(tcx, body))
2168     }
2169     /// Will always be a machine readable number, without underscores or suffixes.
2170     pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> String {
2171         print_evaluated_const(tcx, self.value, false).unwrap()
2172     }
2173 }
2174
2175 /// Small wrapper around [`rustc_span::Span`] that adds helper methods
2176 /// and enforces calling [`rustc_span::Span::source_callsite()`].
2177 #[derive(Copy, Clone, Debug)]
2178 pub(crate) struct Span(rustc_span::Span);
2179
2180 impl Span {
2181     /// Wraps a [`rustc_span::Span`]. In case this span is the result of a macro expansion, the
2182     /// span will be updated to point to the macro invocation instead of the macro definition.
2183     ///
2184     /// (See rust-lang/rust#39726)
2185     pub(crate) fn new(sp: rustc_span::Span) -> Self {
2186         Self(sp.source_callsite())
2187     }
2188
2189     pub(crate) fn inner(&self) -> rustc_span::Span {
2190         self.0
2191     }
2192
2193     pub(crate) fn filename(&self, sess: &Session) -> FileName {
2194         sess.source_map().span_to_filename(self.0)
2195     }
2196
2197     pub(crate) fn lo(&self, sess: &Session) -> Loc {
2198         sess.source_map().lookup_char_pos(self.0.lo())
2199     }
2200
2201     pub(crate) fn hi(&self, sess: &Session) -> Loc {
2202         sess.source_map().lookup_char_pos(self.0.hi())
2203     }
2204
2205     pub(crate) fn cnum(&self, sess: &Session) -> CrateNum {
2206         // FIXME: is there a time when the lo and hi crate would be different?
2207         self.lo(sess).file.cnum
2208     }
2209 }
2210
2211 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2212 pub(crate) struct Path {
2213     pub(crate) res: Res,
2214     pub(crate) segments: ThinVec<PathSegment>,
2215 }
2216
2217 impl Path {
2218     pub(crate) fn def_id(&self) -> DefId {
2219         self.res.def_id()
2220     }
2221
2222     pub(crate) fn last_opt(&self) -> Option<Symbol> {
2223         self.segments.last().map(|s| s.name)
2224     }
2225
2226     pub(crate) fn last(&self) -> Symbol {
2227         self.last_opt().expect("segments were empty")
2228     }
2229
2230     pub(crate) fn whole_name(&self) -> String {
2231         self.segments
2232             .iter()
2233             .map(|s| if s.name == kw::PathRoot { "" } else { s.name.as_str() })
2234             .intersperse("::")
2235             .collect()
2236     }
2237
2238     /// Checks if this is a `T::Name` path for an associated type.
2239     pub(crate) fn is_assoc_ty(&self) -> bool {
2240         match self.res {
2241             Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _)
2242                 if self.segments.len() != 1 =>
2243             {
2244                 true
2245             }
2246             Res::Def(DefKind::AssocTy, _) => true,
2247             _ => false,
2248         }
2249     }
2250
2251     pub(crate) fn generics(&self) -> Option<Vec<&Type>> {
2252         self.segments.last().and_then(|seg| {
2253             if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2254                 Some(
2255                     args.iter()
2256                         .filter_map(|arg| match arg {
2257                             GenericArg::Type(ty) => Some(ty),
2258                             _ => None,
2259                         })
2260                         .collect(),
2261                 )
2262             } else {
2263                 None
2264             }
2265         })
2266     }
2267
2268     pub(crate) fn bindings(&self) -> Option<&[TypeBinding]> {
2269         self.segments.last().and_then(|seg| {
2270             if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
2271                 Some(&**bindings)
2272             } else {
2273                 None
2274             }
2275         })
2276     }
2277 }
2278
2279 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2280 pub(crate) enum GenericArg {
2281     Lifetime(Lifetime),
2282     Type(Type),
2283     Const(Box<Constant>),
2284     Infer,
2285 }
2286
2287 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2288 pub(crate) enum GenericArgs {
2289     AngleBracketed { args: Box<[GenericArg]>, bindings: ThinVec<TypeBinding> },
2290     Parenthesized { inputs: Box<[Type]>, output: Option<Box<Type>> },
2291 }
2292
2293 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2294 pub(crate) struct PathSegment {
2295     pub(crate) name: Symbol,
2296     pub(crate) args: GenericArgs,
2297 }
2298
2299 #[derive(Clone, Debug)]
2300 pub(crate) struct Typedef {
2301     pub(crate) type_: Type,
2302     pub(crate) generics: Generics,
2303     /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
2304     /// alias instead of the final type. This will always have the final type, regardless of whether
2305     /// `type_` came from HIR or from metadata.
2306     ///
2307     /// If `item_type.is_none()`, `type_` is guaranteed to come from metadata (and therefore hold the
2308     /// final type).
2309     pub(crate) item_type: Option<Type>,
2310 }
2311
2312 #[derive(Clone, Debug)]
2313 pub(crate) struct OpaqueTy {
2314     pub(crate) bounds: Vec<GenericBound>,
2315     pub(crate) generics: Generics,
2316 }
2317
2318 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2319 pub(crate) struct BareFunctionDecl {
2320     pub(crate) unsafety: hir::Unsafety,
2321     pub(crate) generic_params: Vec<GenericParamDef>,
2322     pub(crate) decl: FnDecl,
2323     pub(crate) abi: Abi,
2324 }
2325
2326 #[derive(Clone, Debug)]
2327 pub(crate) struct Static {
2328     pub(crate) type_: Type,
2329     pub(crate) mutability: Mutability,
2330     pub(crate) expr: Option<BodyId>,
2331 }
2332
2333 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2334 pub(crate) struct Constant {
2335     pub(crate) type_: Type,
2336     pub(crate) kind: ConstantKind,
2337 }
2338
2339 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2340 pub(crate) enum Term {
2341     Type(Type),
2342     Constant(Constant),
2343 }
2344
2345 impl Term {
2346     pub(crate) fn ty(&self) -> Option<&Type> {
2347         if let Term::Type(ty) = self { Some(ty) } else { None }
2348     }
2349 }
2350
2351 impl From<Type> for Term {
2352     fn from(ty: Type) -> Self {
2353         Term::Type(ty)
2354     }
2355 }
2356
2357 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2358 pub(crate) enum ConstantKind {
2359     /// This is the wrapper around `ty::Const` for a non-local constant. Because it doesn't have a
2360     /// `BodyId`, we need to handle it on its own.
2361     ///
2362     /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified
2363     /// by a DefId. So this field must be different from `Extern`.
2364     TyConst { expr: Box<str> },
2365     /// A constant (expression) that's not an item or associated item. These are usually found
2366     /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
2367     /// used to define explicit discriminant values for enum variants.
2368     Anonymous { body: BodyId },
2369     /// A constant from a different crate.
2370     Extern { def_id: DefId },
2371     /// `const FOO: u32 = ...;`
2372     Local { def_id: DefId, body: BodyId },
2373 }
2374
2375 impl Constant {
2376     pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2377         self.kind.expr(tcx)
2378     }
2379
2380     pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2381         self.kind.value(tcx)
2382     }
2383
2384     pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2385         self.kind.is_literal(tcx)
2386     }
2387 }
2388
2389 impl ConstantKind {
2390     pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2391         match *self {
2392             ConstantKind::TyConst { ref expr } => expr.to_string(),
2393             ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2394             ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2395                 print_const_expr(tcx, body)
2396             }
2397         }
2398     }
2399
2400     pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2401         match *self {
2402             ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
2403             ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2404                 print_evaluated_const(tcx, def_id, true)
2405             }
2406         }
2407     }
2408
2409     pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2410         match *self {
2411             ConstantKind::TyConst { .. } => false,
2412             ConstantKind::Extern { def_id } => def_id.as_local().map_or(false, |def_id| {
2413                 is_literal_expr(tcx, tcx.hir().local_def_id_to_hir_id(def_id))
2414             }),
2415             ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2416                 is_literal_expr(tcx, body.hir_id)
2417             }
2418         }
2419     }
2420 }
2421
2422 #[derive(Clone, Debug)]
2423 pub(crate) struct Impl {
2424     pub(crate) unsafety: hir::Unsafety,
2425     pub(crate) generics: Generics,
2426     pub(crate) trait_: Option<Path>,
2427     pub(crate) for_: Type,
2428     pub(crate) items: Vec<Item>,
2429     pub(crate) polarity: ty::ImplPolarity,
2430     pub(crate) kind: ImplKind,
2431 }
2432
2433 impl Impl {
2434     pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxHashSet<Symbol> {
2435         self.trait_
2436             .as_ref()
2437             .map(|t| t.def_id())
2438             .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name).collect())
2439             .unwrap_or_default()
2440     }
2441 }
2442
2443 #[derive(Clone, Debug)]
2444 pub(crate) enum ImplKind {
2445     Normal,
2446     Auto,
2447     FakeVaradic,
2448     Blanket(Box<Type>),
2449 }
2450
2451 impl ImplKind {
2452     pub(crate) fn is_auto(&self) -> bool {
2453         matches!(self, ImplKind::Auto)
2454     }
2455
2456     pub(crate) fn is_blanket(&self) -> bool {
2457         matches!(self, ImplKind::Blanket(_))
2458     }
2459
2460     pub(crate) fn is_fake_variadic(&self) -> bool {
2461         matches!(self, ImplKind::FakeVaradic)
2462     }
2463
2464     pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
2465         match self {
2466             ImplKind::Blanket(ty) => Some(ty),
2467             _ => None,
2468         }
2469     }
2470 }
2471
2472 #[derive(Clone, Debug)]
2473 pub(crate) struct Import {
2474     pub(crate) kind: ImportKind,
2475     pub(crate) source: ImportSource,
2476     pub(crate) should_be_displayed: bool,
2477 }
2478
2479 impl Import {
2480     pub(crate) fn new_simple(
2481         name: Symbol,
2482         source: ImportSource,
2483         should_be_displayed: bool,
2484     ) -> Self {
2485         Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2486     }
2487
2488     pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2489         Self { kind: ImportKind::Glob, source, should_be_displayed }
2490     }
2491
2492     pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool {
2493         match self.source.did {
2494             Some(did) => tcx
2495                 .get_attrs(did, sym::doc)
2496                 .filter_map(ast::Attribute::meta_item_list)
2497                 .flatten()
2498                 .has_word(sym::hidden),
2499             None => false,
2500         }
2501     }
2502 }
2503
2504 #[derive(Clone, Debug)]
2505 pub(crate) enum ImportKind {
2506     // use source as str;
2507     Simple(Symbol),
2508     // use source::*;
2509     Glob,
2510 }
2511
2512 #[derive(Clone, Debug)]
2513 pub(crate) struct ImportSource {
2514     pub(crate) path: Path,
2515     pub(crate) did: Option<DefId>,
2516 }
2517
2518 #[derive(Clone, Debug)]
2519 pub(crate) struct Macro {
2520     pub(crate) source: String,
2521 }
2522
2523 #[derive(Clone, Debug)]
2524 pub(crate) struct ProcMacro {
2525     pub(crate) kind: MacroKind,
2526     pub(crate) helpers: Vec<Symbol>,
2527 }
2528
2529 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
2530 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
2531 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2532 pub(crate) struct TypeBinding {
2533     pub(crate) assoc: PathSegment,
2534     pub(crate) kind: TypeBindingKind,
2535 }
2536
2537 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2538 pub(crate) enum TypeBindingKind {
2539     Equality { term: Term },
2540     Constraint { bounds: Vec<GenericBound> },
2541 }
2542
2543 impl TypeBinding {
2544     pub(crate) fn term(&self) -> &Term {
2545         match self.kind {
2546             TypeBindingKind::Equality { ref term } => term,
2547             _ => panic!("expected equality type binding for parenthesized generic args"),
2548         }
2549     }
2550 }
2551
2552 /// The type, lifetime, or constant that a private type alias's parameter should be
2553 /// replaced with when expanding a use of that type alias.
2554 ///
2555 /// For example:
2556 ///
2557 /// ```
2558 /// type PrivAlias<T> = Vec<T>;
2559 ///
2560 /// pub fn public_fn() -> PrivAlias<i32> { vec![] }
2561 /// ```
2562 ///
2563 /// `public_fn`'s docs will show it as returning `Vec<i32>`, since `PrivAlias` is private.
2564 /// [`SubstParam`] is used to record that `T` should be mapped to `i32`.
2565 pub(crate) enum SubstParam {
2566     Type(Type),
2567     Lifetime(Lifetime),
2568     Constant(Constant),
2569 }
2570
2571 impl SubstParam {
2572     pub(crate) fn as_ty(&self) -> Option<&Type> {
2573         if let Self::Type(ty) = self { Some(ty) } else { None }
2574     }
2575
2576     pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
2577         if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2578     }
2579 }
2580
2581 // Some nodes are used a lot. Make sure they don't unintentionally get bigger.
2582 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2583 mod size_asserts {
2584     use super::*;
2585     use rustc_data_structures::static_assert_size;
2586     // tidy-alphabetical-start
2587     static_assert_size!(Crate, 64); // frequently moved by-value
2588     static_assert_size!(DocFragment, 32);
2589     static_assert_size!(GenericArg, 32);
2590     static_assert_size!(GenericArgs, 32);
2591     static_assert_size!(GenericParamDef, 56);
2592     static_assert_size!(Generics, 16);
2593     static_assert_size!(Item, 56);
2594     static_assert_size!(ItemKind, 64);
2595     static_assert_size!(PathSegment, 40);
2596     static_assert_size!(Type, 32);
2597     // tidy-alphabetical-end
2598 }