]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/clean/types.rs
Rollup merge of #105526 - Xiretza:iter-from-generator-derive, r=scottmcm
[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 def_id = self.item_id.as_def_id().unwrap();
680                 let abi = tcx.fn_sig(def_id).abi();
681                 hir::FnHeader {
682                     unsafety: if abi == Abi::RustIntrinsic {
683                         intrinsic_operation_unsafety(tcx, self.item_id.as_def_id().unwrap())
684                     } else {
685                         hir::Unsafety::Unsafe
686                     },
687                     abi,
688                     constness: if abi == Abi::RustIntrinsic
689                         && tcx.is_const_fn(def_id)
690                         && is_unstable_const_fn(tcx, def_id).is_none()
691                     {
692                         hir::Constness::Const
693                     } else {
694                         hir::Constness::NotConst
695                     },
696                     asyncness: hir::IsAsync::NotAsync,
697                 }
698             }
699             ItemKind::FunctionItem(_) | ItemKind::MethodItem(_, _) | ItemKind::TyMethodItem(_) => {
700                 let def_id = self.item_id.as_def_id().unwrap();
701                 build_fn_header(def_id, tcx, tcx.asyncness(def_id))
702             }
703             _ => return None,
704         };
705         Some(header)
706     }
707
708     /// Returns the visibility of the current item. If the visibility is "inherited", then `None`
709     /// is returned.
710     pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option<Visibility<DefId>> {
711         let def_id = match self.item_id {
712             // Anything but DefId *shouldn't* matter, but return a reasonable value anyway.
713             ItemId::Auto { .. } | ItemId::Blanket { .. } => return None,
714             ItemId::DefId(def_id) => def_id,
715         };
716
717         match *self.kind {
718             // Primitives and Keywords are written in the source code as private modules.
719             // The modules need to be private so that nobody actually uses them, but the
720             // keywords and primitives that they are documenting are public.
721             ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) => return Some(Visibility::Public),
722             // Variant fields inherit their enum's visibility.
723             StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => {
724                 return None;
725             }
726             // Variants always inherit visibility
727             VariantItem(..) => return None,
728             // Trait items inherit the trait's visibility
729             AssocConstItem(..) | TyAssocConstItem(..) | AssocTypeItem(..) | TyAssocTypeItem(..)
730             | TyMethodItem(..) | MethodItem(..) => {
731                 let assoc_item = tcx.associated_item(def_id);
732                 let is_trait_item = match assoc_item.container {
733                     ty::TraitContainer => true,
734                     ty::ImplContainer => {
735                         // Trait impl items always inherit the impl's visibility --
736                         // we don't want to show `pub`.
737                         tcx.impl_trait_ref(tcx.parent(assoc_item.def_id)).is_some()
738                     }
739                 };
740                 if is_trait_item {
741                     return None;
742                 }
743             }
744             _ => {}
745         }
746         let def_id = match self.inline_stmt_id {
747             Some(inlined) => inlined,
748             None => def_id,
749         };
750         Some(tcx.visibility(def_id))
751     }
752 }
753
754 #[derive(Clone, Debug)]
755 pub(crate) enum ItemKind {
756     ExternCrateItem {
757         /// The crate's name, *not* the name it's imported as.
758         src: Option<Symbol>,
759     },
760     ImportItem(Import),
761     StructItem(Struct),
762     UnionItem(Union),
763     EnumItem(Enum),
764     FunctionItem(Box<Function>),
765     ModuleItem(Module),
766     TypedefItem(Box<Typedef>),
767     OpaqueTyItem(OpaqueTy),
768     StaticItem(Static),
769     ConstantItem(Constant),
770     TraitItem(Box<Trait>),
771     TraitAliasItem(TraitAlias),
772     ImplItem(Box<Impl>),
773     /// A required method in a trait declaration meaning it's only a function signature.
774     TyMethodItem(Box<Function>),
775     /// A method in a trait impl or a provided method in a trait declaration.
776     ///
777     /// Compared to [TyMethodItem], it also contains a method body.
778     MethodItem(Box<Function>, Option<hir::Defaultness>),
779     StructFieldItem(Type),
780     VariantItem(Variant),
781     /// `fn`s from an extern block
782     ForeignFunctionItem(Box<Function>),
783     /// `static`s from an extern block
784     ForeignStaticItem(Static),
785     /// `type`s from an extern block
786     ForeignTypeItem,
787     MacroItem(Macro),
788     ProcMacroItem(ProcMacro),
789     PrimitiveItem(PrimitiveType),
790     /// A required associated constant in a trait declaration.
791     TyAssocConstItem(Type),
792     /// An associated associated constant in a trait impl or a provided one in a trait declaration.
793     AssocConstItem(Type, ConstantKind),
794     /// A required associated type in a trait declaration.
795     ///
796     /// The bounds may be non-empty if there is a `where` clause.
797     TyAssocTypeItem(Generics, Vec<GenericBound>),
798     /// An associated type in a trait impl or a provided one in a trait declaration.
799     AssocTypeItem(Box<Typedef>, Vec<GenericBound>),
800     /// An item that has been stripped by a rustdoc pass
801     StrippedItem(Box<ItemKind>),
802     KeywordItem,
803 }
804
805 impl ItemKind {
806     /// Some items contain others such as structs (for their fields) and Enums
807     /// (for their variants). This method returns those contained items.
808     pub(crate) fn inner_items(&self) -> impl Iterator<Item = &Item> {
809         match self {
810             StructItem(s) => s.fields.iter(),
811             UnionItem(u) => u.fields.iter(),
812             VariantItem(v) => match &v.kind {
813                 VariantKind::CLike => [].iter(),
814                 VariantKind::Tuple(t) => t.iter(),
815                 VariantKind::Struct(s) => s.fields.iter(),
816             },
817             EnumItem(e) => e.variants.iter(),
818             TraitItem(t) => t.items.iter(),
819             ImplItem(i) => i.items.iter(),
820             ModuleItem(m) => m.items.iter(),
821             ExternCrateItem { .. }
822             | ImportItem(_)
823             | FunctionItem(_)
824             | TypedefItem(_)
825             | OpaqueTyItem(_)
826             | StaticItem(_)
827             | ConstantItem(_)
828             | TraitAliasItem(_)
829             | TyMethodItem(_)
830             | MethodItem(_, _)
831             | StructFieldItem(_)
832             | ForeignFunctionItem(_)
833             | ForeignStaticItem(_)
834             | ForeignTypeItem
835             | MacroItem(_)
836             | ProcMacroItem(_)
837             | PrimitiveItem(_)
838             | TyAssocConstItem(_)
839             | AssocConstItem(_, _)
840             | TyAssocTypeItem(..)
841             | AssocTypeItem(..)
842             | StrippedItem(_)
843             | KeywordItem => [].iter(),
844         }
845     }
846
847     /// Returns `true` if this item does not appear inside an impl block.
848     pub(crate) fn is_non_assoc(&self) -> bool {
849         matches!(
850             self,
851             StructItem(_)
852                 | UnionItem(_)
853                 | EnumItem(_)
854                 | TraitItem(_)
855                 | ModuleItem(_)
856                 | ExternCrateItem { .. }
857                 | FunctionItem(_)
858                 | TypedefItem(_)
859                 | OpaqueTyItem(_)
860                 | StaticItem(_)
861                 | ConstantItem(_)
862                 | TraitAliasItem(_)
863                 | ForeignFunctionItem(_)
864                 | ForeignStaticItem(_)
865                 | ForeignTypeItem
866                 | MacroItem(_)
867                 | ProcMacroItem(_)
868                 | PrimitiveItem(_)
869         )
870     }
871 }
872
873 #[derive(Clone, Debug)]
874 pub(crate) struct Module {
875     pub(crate) items: Vec<Item>,
876     pub(crate) span: Span,
877 }
878
879 pub(crate) trait AttributesExt {
880     type AttributeIterator<'a>: Iterator<Item = ast::NestedMetaItem>
881     where
882         Self: 'a;
883
884     fn lists<'a>(&'a self, name: Symbol) -> Self::AttributeIterator<'a>;
885
886     fn span(&self) -> Option<rustc_span::Span>;
887
888     fn inner_docs(&self) -> bool;
889
890     fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>>;
891 }
892
893 impl AttributesExt for [ast::Attribute] {
894     type AttributeIterator<'a> = impl Iterator<Item = ast::NestedMetaItem> + 'a;
895
896     fn lists<'a>(&'a self, name: Symbol) -> Self::AttributeIterator<'a> {
897         self.iter()
898             .filter(move |attr| attr.has_name(name))
899             .filter_map(ast::Attribute::meta_item_list)
900             .flatten()
901     }
902
903     /// Return the span of the first doc-comment, if it exists.
904     fn span(&self) -> Option<rustc_span::Span> {
905         self.iter().find(|attr| attr.doc_str().is_some()).map(|attr| attr.span)
906     }
907
908     /// Returns whether the first doc-comment is an inner attribute.
909     ///
910     //// If there are no doc-comments, return true.
911     /// FIXME(#78591): Support both inner and outer attributes on the same item.
912     fn inner_docs(&self) -> bool {
913         self.iter().find(|a| a.doc_str().is_some()).map_or(true, |a| a.style == AttrStyle::Inner)
914     }
915
916     fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>> {
917         let sess = tcx.sess;
918         let doc_cfg_active = tcx.features().doc_cfg;
919         let doc_auto_cfg_active = tcx.features().doc_auto_cfg;
920
921         fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
922             let mut iter = it.into_iter();
923             let item = iter.next()?;
924             if iter.next().is_some() {
925                 return None;
926             }
927             Some(item)
928         }
929
930         let mut cfg = if doc_cfg_active || doc_auto_cfg_active {
931             let mut doc_cfg = self
932                 .iter()
933                 .filter(|attr| attr.has_name(sym::doc))
934                 .flat_map(|attr| attr.meta_item_list().unwrap_or_default())
935                 .filter(|attr| attr.has_name(sym::cfg))
936                 .peekable();
937             if doc_cfg.peek().is_some() && doc_cfg_active {
938                 doc_cfg
939                     .filter_map(|attr| Cfg::parse(attr.meta_item()?).ok())
940                     .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
941             } else if doc_auto_cfg_active {
942                 self.iter()
943                     .filter(|attr| attr.has_name(sym::cfg))
944                     .filter_map(|attr| single(attr.meta_item_list()?))
945                     .filter_map(|attr| {
946                         Cfg::parse_without(attr.meta_item()?, hidden_cfg).ok().flatten()
947                     })
948                     .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
949             } else {
950                 Cfg::True
951             }
952         } else {
953             Cfg::True
954         };
955
956         for attr in self.iter() {
957             // #[doc]
958             if attr.doc_str().is_none() && attr.has_name(sym::doc) {
959                 // #[doc(...)]
960                 if let Some(list) = attr.meta().as_ref().and_then(|mi| mi.meta_item_list()) {
961                     for item in list {
962                         // #[doc(hidden)]
963                         if !item.has_name(sym::cfg) {
964                             continue;
965                         }
966                         // #[doc(cfg(...))]
967                         if let Some(cfg_mi) = item
968                             .meta_item()
969                             .and_then(|item| rustc_expand::config::parse_cfg(item, sess))
970                         {
971                             match Cfg::parse(cfg_mi) {
972                                 Ok(new_cfg) => cfg &= new_cfg,
973                                 Err(e) => {
974                                     sess.span_err(e.span, e.msg);
975                                 }
976                             }
977                         }
978                     }
979                 }
980             }
981         }
982
983         // treat #[target_feature(enable = "feat")] attributes as if they were
984         // #[doc(cfg(target_feature = "feat"))] attributes as well
985         for attr in self.lists(sym::target_feature) {
986             if attr.has_name(sym::enable) {
987                 if attr.value_str().is_some() {
988                     // Clone `enable = "feat"`, change to `target_feature = "feat"`.
989                     // Unwrap is safe because `value_str` succeeded above.
990                     let mut meta = attr.meta_item().unwrap().clone();
991                     meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature));
992
993                     if let Ok(feat_cfg) = Cfg::parse(&meta) {
994                         cfg &= feat_cfg;
995                     }
996                 }
997             }
998         }
999
1000         if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) }
1001     }
1002 }
1003
1004 pub(crate) trait NestedAttributesExt {
1005     /// Returns `true` if the attribute list contains a specific `word`
1006     fn has_word(self, word: Symbol) -> bool
1007     where
1008         Self: std::marker::Sized,
1009     {
1010         <Self as NestedAttributesExt>::get_word_attr(self, word).is_some()
1011     }
1012
1013     /// Returns `Some(attr)` if the attribute list contains 'attr'
1014     /// corresponding to a specific `word`
1015     fn get_word_attr(self, word: Symbol) -> Option<ast::NestedMetaItem>;
1016 }
1017
1018 impl<I: Iterator<Item = ast::NestedMetaItem>> NestedAttributesExt for I {
1019     fn get_word_attr(mut self, word: Symbol) -> Option<ast::NestedMetaItem> {
1020         self.find(|attr| attr.is_word() && attr.has_name(word))
1021     }
1022 }
1023
1024 /// A portion of documentation, extracted from a `#[doc]` attribute.
1025 ///
1026 /// Each variant contains the line number within the complete doc-comment where the fragment
1027 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
1028 ///
1029 /// Included files are kept separate from inline doc comments so that proper line-number
1030 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
1031 /// kept separate because of issue #42760.
1032 #[derive(Clone, PartialEq, Eq, Debug)]
1033 pub(crate) struct DocFragment {
1034     pub(crate) span: rustc_span::Span,
1035     /// The module this doc-comment came from.
1036     ///
1037     /// This allows distinguishing between the original documentation and a pub re-export.
1038     /// If it is `None`, the item was not re-exported.
1039     pub(crate) parent_module: Option<DefId>,
1040     pub(crate) doc: Symbol,
1041     pub(crate) kind: DocFragmentKind,
1042     pub(crate) indent: usize,
1043 }
1044
1045 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
1046 pub(crate) enum DocFragmentKind {
1047     /// A doc fragment created from a `///` or `//!` doc comment.
1048     SugaredDoc,
1049     /// A doc fragment created from a "raw" `#[doc=""]` attribute.
1050     RawDoc,
1051 }
1052
1053 /// The goal of this function is to apply the `DocFragment` transformation that is required when
1054 /// transforming into the final Markdown, which is applying the computed indent to each line in
1055 /// each doc fragment (a `DocFragment` can contain multiple lines in case of `#[doc = ""]`).
1056 ///
1057 /// Note: remove the trailing newline where appropriate
1058 fn add_doc_fragment(out: &mut String, frag: &DocFragment) {
1059     let s = frag.doc.as_str();
1060     let mut iter = s.lines();
1061     if s.is_empty() {
1062         out.push('\n');
1063         return;
1064     }
1065     while let Some(line) = iter.next() {
1066         if line.chars().any(|c| !c.is_whitespace()) {
1067             assert!(line.len() >= frag.indent);
1068             out.push_str(&line[frag.indent..]);
1069         } else {
1070             out.push_str(line);
1071         }
1072         out.push('\n');
1073     }
1074 }
1075
1076 /// Collapse a collection of [`DocFragment`]s into one string,
1077 /// handling indentation and newlines as needed.
1078 pub(crate) fn collapse_doc_fragments(doc_strings: &[DocFragment]) -> String {
1079     let mut acc = String::new();
1080     for frag in doc_strings {
1081         add_doc_fragment(&mut acc, frag);
1082     }
1083     acc.pop();
1084     acc
1085 }
1086
1087 /// Removes excess indentation on comments in order for the Markdown
1088 /// to be parsed correctly. This is necessary because the convention for
1089 /// writing documentation is to provide a space between the /// or //! marker
1090 /// and the doc text, but Markdown is whitespace-sensitive. For example,
1091 /// a block of text with four-space indentation is parsed as a code block,
1092 /// so if we didn't unindent comments, these list items
1093 ///
1094 /// /// A list:
1095 /// ///
1096 /// ///    - Foo
1097 /// ///    - Bar
1098 ///
1099 /// would be parsed as if they were in a code block, which is likely not what the user intended.
1100 fn unindent_doc_fragments(docs: &mut Vec<DocFragment>) {
1101     // `add` is used in case the most common sugared doc syntax is used ("/// "). The other
1102     // fragments kind's lines are never starting with a whitespace unless they are using some
1103     // markdown formatting requiring it. Therefore, if the doc block have a mix between the two,
1104     // we need to take into account the fact that the minimum indent minus one (to take this
1105     // whitespace into account).
1106     //
1107     // For example:
1108     //
1109     // /// hello!
1110     // #[doc = "another"]
1111     //
1112     // In this case, you want "hello! another" and not "hello!  another".
1113     let add = if docs.windows(2).any(|arr| arr[0].kind != arr[1].kind)
1114         && docs.iter().any(|d| d.kind == DocFragmentKind::SugaredDoc)
1115     {
1116         // In case we have a mix of sugared doc comments and "raw" ones, we want the sugared one to
1117         // "decide" how much the minimum indent will be.
1118         1
1119     } else {
1120         0
1121     };
1122
1123     // `min_indent` is used to know how much whitespaces from the start of each lines must be
1124     // removed. Example:
1125     //
1126     // ///     hello!
1127     // #[doc = "another"]
1128     //
1129     // In here, the `min_indent` is 1 (because non-sugared fragment are always counted with minimum
1130     // 1 whitespace), meaning that "hello!" will be considered a codeblock because it starts with 4
1131     // (5 - 1) whitespaces.
1132     let Some(min_indent) = docs
1133         .iter()
1134         .map(|fragment| {
1135             fragment.doc.as_str().lines().fold(usize::MAX, |min_indent, line| {
1136                 if line.chars().all(|c| c.is_whitespace()) {
1137                     min_indent
1138                 } else {
1139                     // Compare against either space or tab, ignoring whether they are
1140                     // mixed or not.
1141                     let whitespace = line.chars().take_while(|c| *c == ' ' || *c == '\t').count();
1142                     cmp::min(min_indent, whitespace)
1143                         + if fragment.kind == DocFragmentKind::SugaredDoc { 0 } else { add }
1144                 }
1145             })
1146         })
1147         .min()
1148     else {
1149         return;
1150     };
1151
1152     for fragment in docs {
1153         if fragment.doc == kw::Empty {
1154             continue;
1155         }
1156
1157         let min_indent = if fragment.kind != DocFragmentKind::SugaredDoc && min_indent > 0 {
1158             min_indent - add
1159         } else {
1160             min_indent
1161         };
1162
1163         fragment.indent = min_indent;
1164     }
1165 }
1166
1167 /// A link that has not yet been rendered.
1168 ///
1169 /// This link will be turned into a rendered link by [`Item::links`].
1170 #[derive(Clone, Debug, PartialEq, Eq)]
1171 pub(crate) struct ItemLink {
1172     /// The original link written in the markdown
1173     pub(crate) link: String,
1174     /// The link text displayed in the HTML.
1175     ///
1176     /// This may not be the same as `link` if there was a disambiguator
1177     /// in an intra-doc link (e.g. \[`fn@f`\])
1178     pub(crate) link_text: String,
1179     /// The `DefId` of the Item whose **HTML Page** contains the item being
1180     /// linked to. This will be different to `item_id` on item's that don't
1181     /// have their own page, such as struct fields and enum variants.
1182     pub(crate) page_id: DefId,
1183     /// The url fragment to append to the link
1184     pub(crate) fragment: Option<UrlFragment>,
1185 }
1186
1187 pub struct RenderedLink {
1188     /// The text the link was original written as.
1189     ///
1190     /// This could potentially include disambiguators and backticks.
1191     pub(crate) original_text: String,
1192     /// The text to display in the HTML
1193     pub(crate) new_text: String,
1194     /// The URL to put in the `href`
1195     pub(crate) href: String,
1196 }
1197
1198 /// The attributes on an [`Item`], including attributes like `#[derive(...)]` and `#[inline]`,
1199 /// as well as doc comments.
1200 #[derive(Clone, Debug, Default)]
1201 pub(crate) struct Attributes {
1202     pub(crate) doc_strings: Vec<DocFragment>,
1203     pub(crate) other_attrs: ast::AttrVec,
1204 }
1205
1206 impl Attributes {
1207     pub(crate) fn lists(&self, name: Symbol) -> impl Iterator<Item = ast::NestedMetaItem> + '_ {
1208         self.other_attrs.lists(name)
1209     }
1210
1211     pub(crate) fn has_doc_flag(&self, flag: Symbol) -> bool {
1212         for attr in &self.other_attrs {
1213             if !attr.has_name(sym::doc) {
1214                 continue;
1215             }
1216
1217             if let Some(items) = attr.meta_item_list() {
1218                 if items.iter().filter_map(|i| i.meta_item()).any(|it| it.has_name(flag)) {
1219                     return true;
1220                 }
1221             }
1222         }
1223
1224         false
1225     }
1226
1227     pub(crate) fn from_ast(attrs: &[ast::Attribute]) -> Attributes {
1228         Attributes::from_ast_iter(attrs.iter().map(|attr| (attr, None)), false)
1229     }
1230
1231     pub(crate) fn from_ast_with_additional(
1232         attrs: &[ast::Attribute],
1233         (additional_attrs, def_id): (&[ast::Attribute], DefId),
1234     ) -> Attributes {
1235         // Additional documentation should be shown before the original documentation.
1236         let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id)));
1237         let attrs2 = attrs.iter().map(|attr| (attr, None));
1238         Attributes::from_ast_iter(attrs1.chain(attrs2), false)
1239     }
1240
1241     pub(crate) fn from_ast_iter<'a>(
1242         attrs: impl Iterator<Item = (&'a ast::Attribute, Option<DefId>)>,
1243         doc_only: bool,
1244     ) -> Attributes {
1245         let mut doc_strings = Vec::new();
1246         let mut other_attrs = ast::AttrVec::new();
1247         for (attr, parent_module) in attrs {
1248             if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() {
1249                 trace!("got doc_str={doc_str:?}");
1250                 let doc = beautify_doc_string(doc_str, comment_kind);
1251                 let kind = if attr.is_doc_comment() {
1252                     DocFragmentKind::SugaredDoc
1253                 } else {
1254                     DocFragmentKind::RawDoc
1255                 };
1256                 let fragment = DocFragment { span: attr.span, doc, kind, parent_module, indent: 0 };
1257                 doc_strings.push(fragment);
1258             } else if !doc_only {
1259                 other_attrs.push(attr.clone());
1260             }
1261         }
1262
1263         unindent_doc_fragments(&mut doc_strings);
1264
1265         Attributes { doc_strings, other_attrs }
1266     }
1267
1268     /// Finds the `doc` attribute as a NameValue and returns the corresponding
1269     /// value found.
1270     pub(crate) fn doc_value(&self) -> Option<String> {
1271         let mut iter = self.doc_strings.iter();
1272
1273         let ori = iter.next()?;
1274         let mut out = String::new();
1275         add_doc_fragment(&mut out, ori);
1276         for new_frag in iter {
1277             add_doc_fragment(&mut out, new_frag);
1278         }
1279         out.pop();
1280         if out.is_empty() { None } else { Some(out) }
1281     }
1282
1283     /// Return the doc-comments on this item, grouped by the module they came from.
1284     /// The module can be different if this is a re-export with added documentation.
1285     ///
1286     /// The last newline is not trimmed so the produced strings are reusable between
1287     /// early and late doc link resolution regardless of their position.
1288     pub(crate) fn prepare_to_doc_link_resolution(&self) -> FxHashMap<Option<DefId>, String> {
1289         let mut res = FxHashMap::default();
1290         for fragment in &self.doc_strings {
1291             let out_str = res.entry(fragment.parent_module).or_default();
1292             add_doc_fragment(out_str, fragment);
1293         }
1294         res
1295     }
1296
1297     /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
1298     /// with newlines.
1299     pub(crate) fn collapsed_doc_value(&self) -> Option<String> {
1300         if self.doc_strings.is_empty() {
1301             None
1302         } else {
1303             Some(collapse_doc_fragments(&self.doc_strings))
1304         }
1305     }
1306
1307     pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> {
1308         let mut aliases = FxHashSet::default();
1309
1310         for attr in self.other_attrs.lists(sym::doc).filter(|a| a.has_name(sym::alias)) {
1311             if let Some(values) = attr.meta_item_list() {
1312                 for l in values {
1313                     match l.lit().unwrap().kind {
1314                         ast::LitKind::Str(s, _) => {
1315                             aliases.insert(s);
1316                         }
1317                         _ => unreachable!(),
1318                     }
1319                 }
1320             } else {
1321                 aliases.insert(attr.value_str().unwrap());
1322             }
1323         }
1324         aliases.into_iter().collect::<Vec<_>>().into()
1325     }
1326 }
1327
1328 impl PartialEq for Attributes {
1329     fn eq(&self, rhs: &Self) -> bool {
1330         self.doc_strings == rhs.doc_strings
1331             && self
1332                 .other_attrs
1333                 .iter()
1334                 .map(|attr| attr.id)
1335                 .eq(rhs.other_attrs.iter().map(|attr| attr.id))
1336     }
1337 }
1338
1339 impl Eq for Attributes {}
1340
1341 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1342 pub(crate) enum GenericBound {
1343     TraitBound(PolyTrait, hir::TraitBoundModifier),
1344     Outlives(Lifetime),
1345 }
1346
1347 impl GenericBound {
1348     pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1349         let did = cx.tcx.require_lang_item(LangItem::Sized, None);
1350         let empty = ty::Binder::dummy(ty::InternalSubsts::empty());
1351         let path = external_path(cx, did, false, ThinVec::new(), empty);
1352         inline::record_extern_fqn(cx, did, ItemType::Trait);
1353         GenericBound::TraitBound(
1354             PolyTrait { trait_: path, generic_params: Vec::new() },
1355             hir::TraitBoundModifier::Maybe,
1356         )
1357     }
1358
1359     pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1360         use rustc_hir::TraitBoundModifier as TBM;
1361         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
1362             if Some(trait_.def_id()) == cx.tcx.lang_items().sized_trait() {
1363                 return true;
1364             }
1365         }
1366         false
1367     }
1368
1369     pub(crate) fn get_poly_trait(&self) -> Option<PolyTrait> {
1370         if let GenericBound::TraitBound(ref p, _) = *self {
1371             return Some(p.clone());
1372         }
1373         None
1374     }
1375
1376     pub(crate) fn get_trait_path(&self) -> Option<Path> {
1377         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1378             Some(trait_.clone())
1379         } else {
1380             None
1381         }
1382     }
1383 }
1384
1385 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1386 pub(crate) struct Lifetime(pub Symbol);
1387
1388 impl Lifetime {
1389     pub(crate) fn statik() -> Lifetime {
1390         Lifetime(kw::StaticLifetime)
1391     }
1392
1393     pub(crate) fn elided() -> Lifetime {
1394         Lifetime(kw::UnderscoreLifetime)
1395     }
1396 }
1397
1398 #[derive(Clone, Debug)]
1399 pub(crate) enum WherePredicate {
1400     BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<Lifetime> },
1401     RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1402     EqPredicate { lhs: Box<Type>, rhs: Box<Term>, bound_params: Vec<Lifetime> },
1403 }
1404
1405 impl WherePredicate {
1406     pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1407         match *self {
1408             WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
1409             WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
1410             _ => None,
1411         }
1412     }
1413
1414     pub(crate) fn get_bound_params(&self) -> Option<&[Lifetime]> {
1415         match self {
1416             Self::BoundPredicate { bound_params, .. } | Self::EqPredicate { bound_params, .. } => {
1417                 Some(bound_params)
1418             }
1419             _ => None,
1420         }
1421     }
1422 }
1423
1424 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1425 pub(crate) enum GenericParamDefKind {
1426     Lifetime { outlives: Vec<Lifetime> },
1427     Type { did: DefId, bounds: Vec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
1428     Const { did: DefId, ty: Box<Type>, default: Option<Box<String>> },
1429 }
1430
1431 impl GenericParamDefKind {
1432     pub(crate) fn is_type(&self) -> bool {
1433         matches!(self, GenericParamDefKind::Type { .. })
1434     }
1435 }
1436
1437 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1438 pub(crate) struct GenericParamDef {
1439     pub(crate) name: Symbol,
1440     pub(crate) kind: GenericParamDefKind,
1441 }
1442
1443 impl GenericParamDef {
1444     pub(crate) fn lifetime(name: Symbol) -> Self {
1445         Self { name, kind: GenericParamDefKind::Lifetime { outlives: Vec::new() } }
1446     }
1447
1448     pub(crate) fn is_synthetic_type_param(&self) -> bool {
1449         match self.kind {
1450             GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
1451             GenericParamDefKind::Type { synthetic, .. } => synthetic,
1452         }
1453     }
1454
1455     pub(crate) fn is_type(&self) -> bool {
1456         self.kind.is_type()
1457     }
1458
1459     pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1460         match self.kind {
1461             GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1462             _ => None,
1463         }
1464     }
1465 }
1466
1467 // maybe use a Generic enum and use Vec<Generic>?
1468 #[derive(Clone, Debug, Default)]
1469 pub(crate) struct Generics {
1470     pub(crate) params: ThinVec<GenericParamDef>,
1471     pub(crate) where_predicates: ThinVec<WherePredicate>,
1472 }
1473
1474 impl Generics {
1475     pub(crate) fn is_empty(&self) -> bool {
1476         self.params.is_empty() && self.where_predicates.is_empty()
1477     }
1478 }
1479
1480 #[derive(Clone, Debug)]
1481 pub(crate) struct Function {
1482     pub(crate) decl: FnDecl,
1483     pub(crate) generics: Generics,
1484 }
1485
1486 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1487 pub(crate) struct FnDecl {
1488     pub(crate) inputs: Arguments,
1489     pub(crate) output: FnRetTy,
1490     pub(crate) c_variadic: bool,
1491 }
1492
1493 impl FnDecl {
1494     pub(crate) fn self_type(&self) -> Option<SelfTy> {
1495         self.inputs.values.get(0).and_then(|v| v.to_self())
1496     }
1497
1498     /// Returns the sugared return type for an async function.
1499     ///
1500     /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
1501     /// will return `i32`.
1502     ///
1503     /// # Panics
1504     ///
1505     /// This function will panic if the return type does not match the expected sugaring for async
1506     /// functions.
1507     pub(crate) fn sugared_async_return_type(&self) -> FnRetTy {
1508         match &self.output {
1509             FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
1510                 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
1511                     let bindings = trait_.bindings().unwrap();
1512                     let ret_ty = bindings[0].term();
1513                     let ty = ret_ty.ty().expect("Unexpected constant return term");
1514                     FnRetTy::Return(ty.clone())
1515                 }
1516                 _ => panic!("unexpected desugaring of async function"),
1517             },
1518             _ => panic!("unexpected desugaring of async function"),
1519         }
1520     }
1521 }
1522
1523 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1524 pub(crate) struct Arguments {
1525     pub(crate) values: Vec<Argument>,
1526 }
1527
1528 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1529 pub(crate) struct Argument {
1530     pub(crate) type_: Type,
1531     pub(crate) name: Symbol,
1532     /// This field is used to represent "const" arguments from the `rustc_legacy_const_generics`
1533     /// feature. More information in <https://github.com/rust-lang/rust/issues/83167>.
1534     pub(crate) is_const: bool,
1535 }
1536
1537 #[derive(Clone, PartialEq, Debug)]
1538 pub(crate) enum SelfTy {
1539     SelfValue,
1540     SelfBorrowed(Option<Lifetime>, Mutability),
1541     SelfExplicit(Type),
1542 }
1543
1544 impl Argument {
1545     pub(crate) fn to_self(&self) -> Option<SelfTy> {
1546         if self.name != kw::SelfLower {
1547             return None;
1548         }
1549         if self.type_.is_self_type() {
1550             return Some(SelfValue);
1551         }
1552         match self.type_ {
1553             BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
1554                 Some(SelfBorrowed(lifetime.clone(), mutability))
1555             }
1556             _ => Some(SelfExplicit(self.type_.clone())),
1557         }
1558     }
1559 }
1560
1561 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1562 pub(crate) enum FnRetTy {
1563     Return(Type),
1564     DefaultReturn,
1565 }
1566
1567 impl FnRetTy {
1568     pub(crate) fn as_return(&self) -> Option<&Type> {
1569         match self {
1570             Return(ret) => Some(ret),
1571             DefaultReturn => None,
1572         }
1573     }
1574 }
1575
1576 #[derive(Clone, Debug)]
1577 pub(crate) struct Trait {
1578     pub(crate) def_id: DefId,
1579     pub(crate) items: Vec<Item>,
1580     pub(crate) generics: Generics,
1581     pub(crate) bounds: Vec<GenericBound>,
1582 }
1583
1584 impl Trait {
1585     pub(crate) fn is_auto(&self, tcx: TyCtxt<'_>) -> bool {
1586         tcx.trait_is_auto(self.def_id)
1587     }
1588     pub(crate) fn is_notable_trait(&self, tcx: TyCtxt<'_>) -> bool {
1589         tcx.is_doc_notable_trait(self.def_id)
1590     }
1591     pub(crate) fn unsafety(&self, tcx: TyCtxt<'_>) -> hir::Unsafety {
1592         tcx.trait_def(self.def_id).unsafety
1593     }
1594 }
1595
1596 #[derive(Clone, Debug)]
1597 pub(crate) struct TraitAlias {
1598     pub(crate) generics: Generics,
1599     pub(crate) bounds: Vec<GenericBound>,
1600 }
1601
1602 /// A trait reference, which may have higher ranked lifetimes.
1603 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1604 pub(crate) struct PolyTrait {
1605     pub(crate) trait_: Path,
1606     pub(crate) generic_params: Vec<GenericParamDef>,
1607 }
1608
1609 /// Rustdoc's representation of types, mostly based on the [`hir::Ty`].
1610 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1611 pub(crate) enum Type {
1612     /// A named type, which could be a trait.
1613     ///
1614     /// This is mostly Rustdoc's version of [`hir::Path`].
1615     /// It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics.
1616     Path { path: Path },
1617     /// A `dyn Trait` object: `dyn for<'a> Trait<'a> + Send + 'static`
1618     DynTrait(Vec<PolyTrait>, Option<Lifetime>),
1619     /// A type parameter.
1620     Generic(Symbol),
1621     /// A primitive (aka, builtin) type.
1622     Primitive(PrimitiveType),
1623     /// A function pointer: `extern "ABI" fn(...) -> ...`
1624     BareFunction(Box<BareFunctionDecl>),
1625     /// A tuple type: `(i32, &str)`.
1626     Tuple(Vec<Type>),
1627     /// A slice type (does *not* include the `&`): `[i32]`
1628     Slice(Box<Type>),
1629     /// An array type.
1630     ///
1631     /// The `String` field is a stringified version of the array's length parameter.
1632     Array(Box<Type>, Box<str>),
1633     /// A raw pointer type: `*const i32`, `*mut i32`
1634     RawPointer(Mutability, Box<Type>),
1635     /// A reference type: `&i32`, `&'a mut Foo`
1636     BorrowedRef { lifetime: Option<Lifetime>, mutability: Mutability, type_: Box<Type> },
1637
1638     /// A qualified path to an associated item: `<Type as Trait>::Name`
1639     QPath(Box<QPathData>),
1640
1641     /// A type that is inferred: `_`
1642     Infer,
1643
1644     /// An `impl Trait`: `impl TraitA + TraitB + ...`
1645     ImplTrait(Vec<GenericBound>),
1646 }
1647
1648 impl Type {
1649     /// When comparing types for equality, it can help to ignore `&` wrapping.
1650     pub(crate) fn without_borrowed_ref(&self) -> &Type {
1651         let mut result = self;
1652         while let Type::BorrowedRef { type_, .. } = result {
1653             result = &*type_;
1654         }
1655         result
1656     }
1657
1658     /// Check if two types are "potentially the same".
1659     /// This is different from `Eq`, because it knows that things like
1660     /// `Placeholder` are possible matches for everything.
1661     pub(crate) fn is_same(&self, other: &Self, cache: &Cache) -> bool {
1662         match (self, other) {
1663             // Recursive cases.
1664             (Type::Tuple(a), Type::Tuple(b)) => {
1665                 a.len() == b.len() && a.iter().zip(b).all(|(a, b)| a.is_same(b, cache))
1666             }
1667             (Type::Slice(a), Type::Slice(b)) => a.is_same(b, cache),
1668             (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_same(b, cache),
1669             (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
1670                 mutability == b_mutability && type_.is_same(b_type_, cache)
1671             }
1672             (
1673                 Type::BorrowedRef { mutability, type_, .. },
1674                 Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
1675             ) => mutability == b_mutability && type_.is_same(b_type_, cache),
1676             // Placeholders and generics are equal to all other types.
1677             (Type::Infer, _) | (_, Type::Infer) => true,
1678             (Type::Generic(_), _) | (_, Type::Generic(_)) => true,
1679             // Other cases, such as primitives, just use recursion.
1680             (a, b) => a
1681                 .def_id(cache)
1682                 .and_then(|a| Some((a, b.def_id(cache)?)))
1683                 .map(|(a, b)| a == b)
1684                 .unwrap_or(false),
1685         }
1686     }
1687
1688     pub(crate) fn primitive_type(&self) -> Option<PrimitiveType> {
1689         match *self {
1690             Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1691             Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1692             Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1693             Tuple(ref tys) => {
1694                 if tys.is_empty() {
1695                     Some(PrimitiveType::Unit)
1696                 } else {
1697                     Some(PrimitiveType::Tuple)
1698                 }
1699             }
1700             RawPointer(..) => Some(PrimitiveType::RawPointer),
1701             BareFunction(..) => Some(PrimitiveType::Fn),
1702             _ => None,
1703         }
1704     }
1705
1706     /// Checks if this is a `T::Name` path for an associated type.
1707     pub(crate) fn is_assoc_ty(&self) -> bool {
1708         match self {
1709             Type::Path { path, .. } => path.is_assoc_ty(),
1710             _ => false,
1711         }
1712     }
1713
1714     pub(crate) fn is_self_type(&self) -> bool {
1715         match *self {
1716             Generic(name) => name == kw::SelfUpper,
1717             _ => false,
1718         }
1719     }
1720
1721     pub(crate) fn generics(&self) -> Option<Vec<&Type>> {
1722         match self {
1723             Type::Path { path, .. } => path.generics(),
1724             _ => None,
1725         }
1726     }
1727
1728     pub(crate) fn is_full_generic(&self) -> bool {
1729         matches!(self, Type::Generic(_))
1730     }
1731
1732     pub(crate) fn is_impl_trait(&self) -> bool {
1733         matches!(self, Type::ImplTrait(_))
1734     }
1735
1736     pub(crate) fn projection(&self) -> Option<(&Type, DefId, PathSegment)> {
1737         if let QPath(box QPathData { self_type, trait_, assoc, .. }) = self {
1738             Some((self_type, trait_.def_id(), assoc.clone()))
1739         } else {
1740             None
1741         }
1742     }
1743
1744     fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
1745         let t: PrimitiveType = match *self {
1746             Type::Path { ref path } => return Some(path.def_id()),
1747             DynTrait(ref bounds, _) => return bounds.get(0).map(|b| b.trait_.def_id()),
1748             Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
1749             BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
1750             BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache),
1751             Tuple(ref tys) => {
1752                 if tys.is_empty() {
1753                     PrimitiveType::Unit
1754                 } else {
1755                     PrimitiveType::Tuple
1756                 }
1757             }
1758             BareFunction(..) => PrimitiveType::Fn,
1759             Slice(..) => PrimitiveType::Slice,
1760             Array(..) => PrimitiveType::Array,
1761             RawPointer(..) => PrimitiveType::RawPointer,
1762             QPath(box QPathData { ref self_type, .. }) => return self_type.inner_def_id(cache),
1763             Generic(_) | Infer | ImplTrait(_) => return None,
1764         };
1765         cache.and_then(|c| Primitive(t).def_id(c))
1766     }
1767
1768     /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s.
1769     ///
1770     /// [clean]: crate::clean
1771     pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
1772         self.inner_def_id(Some(cache))
1773     }
1774 }
1775
1776 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1777 pub(crate) struct QPathData {
1778     pub assoc: PathSegment,
1779     pub self_type: Type,
1780     /// FIXME: compute this field on demand.
1781     pub should_show_cast: bool,
1782     pub trait_: Path,
1783 }
1784
1785 /// A primitive (aka, builtin) type.
1786 ///
1787 /// This represents things like `i32`, `str`, etc.
1788 ///
1789 /// N.B. This has to be different from [`hir::PrimTy`] because it also includes types that aren't
1790 /// paths, like [`Self::Unit`].
1791 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1792 pub(crate) enum PrimitiveType {
1793     Isize,
1794     I8,
1795     I16,
1796     I32,
1797     I64,
1798     I128,
1799     Usize,
1800     U8,
1801     U16,
1802     U32,
1803     U64,
1804     U128,
1805     F32,
1806     F64,
1807     Char,
1808     Bool,
1809     Str,
1810     Slice,
1811     Array,
1812     Tuple,
1813     Unit,
1814     RawPointer,
1815     Reference,
1816     Fn,
1817     Never,
1818 }
1819
1820 type SimplifiedTypes = FxHashMap<PrimitiveType, ArrayVec<SimplifiedType, 3>>;
1821 impl PrimitiveType {
1822     pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1823         use ast::{FloatTy, IntTy, UintTy};
1824         match prim {
1825             hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1826             hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1827             hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1828             hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1829             hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1830             hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1831             hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1832             hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1833             hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1834             hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1835             hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1836             hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1837             hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1838             hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1839             hir::PrimTy::Str => PrimitiveType::Str,
1840             hir::PrimTy::Bool => PrimitiveType::Bool,
1841             hir::PrimTy::Char => PrimitiveType::Char,
1842         }
1843     }
1844
1845     pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1846         match s {
1847             sym::isize => Some(PrimitiveType::Isize),
1848             sym::i8 => Some(PrimitiveType::I8),
1849             sym::i16 => Some(PrimitiveType::I16),
1850             sym::i32 => Some(PrimitiveType::I32),
1851             sym::i64 => Some(PrimitiveType::I64),
1852             sym::i128 => Some(PrimitiveType::I128),
1853             sym::usize => Some(PrimitiveType::Usize),
1854             sym::u8 => Some(PrimitiveType::U8),
1855             sym::u16 => Some(PrimitiveType::U16),
1856             sym::u32 => Some(PrimitiveType::U32),
1857             sym::u64 => Some(PrimitiveType::U64),
1858             sym::u128 => Some(PrimitiveType::U128),
1859             sym::bool => Some(PrimitiveType::Bool),
1860             sym::char => Some(PrimitiveType::Char),
1861             sym::str => Some(PrimitiveType::Str),
1862             sym::f32 => Some(PrimitiveType::F32),
1863             sym::f64 => Some(PrimitiveType::F64),
1864             sym::array => Some(PrimitiveType::Array),
1865             sym::slice => Some(PrimitiveType::Slice),
1866             sym::tuple => Some(PrimitiveType::Tuple),
1867             sym::unit => Some(PrimitiveType::Unit),
1868             sym::pointer => Some(PrimitiveType::RawPointer),
1869             sym::reference => Some(PrimitiveType::Reference),
1870             kw::Fn => Some(PrimitiveType::Fn),
1871             sym::never => Some(PrimitiveType::Never),
1872             _ => None,
1873         }
1874     }
1875
1876     pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
1877         use ty::fast_reject::SimplifiedType::*;
1878         use ty::{FloatTy, IntTy, UintTy};
1879         use PrimitiveType::*;
1880         static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
1881
1882         let single = |x| iter::once(x).collect();
1883         CELL.get_or_init(move || {
1884             map! {
1885                 Isize => single(IntSimplifiedType(IntTy::Isize)),
1886                 I8 => single(IntSimplifiedType(IntTy::I8)),
1887                 I16 => single(IntSimplifiedType(IntTy::I16)),
1888                 I32 => single(IntSimplifiedType(IntTy::I32)),
1889                 I64 => single(IntSimplifiedType(IntTy::I64)),
1890                 I128 => single(IntSimplifiedType(IntTy::I128)),
1891                 Usize => single(UintSimplifiedType(UintTy::Usize)),
1892                 U8 => single(UintSimplifiedType(UintTy::U8)),
1893                 U16 => single(UintSimplifiedType(UintTy::U16)),
1894                 U32 => single(UintSimplifiedType(UintTy::U32)),
1895                 U64 => single(UintSimplifiedType(UintTy::U64)),
1896                 U128 => single(UintSimplifiedType(UintTy::U128)),
1897                 F32 => single(FloatSimplifiedType(FloatTy::F32)),
1898                 F64 => single(FloatSimplifiedType(FloatTy::F64)),
1899                 Str => single(StrSimplifiedType),
1900                 Bool => single(BoolSimplifiedType),
1901                 Char => single(CharSimplifiedType),
1902                 Array => single(ArraySimplifiedType),
1903                 Slice => single(SliceSimplifiedType),
1904                 // FIXME: If we ever add an inherent impl for tuples
1905                 // with different lengths, they won't show in rustdoc.
1906                 //
1907                 // Either manually update this arrayvec at this point
1908                 // or start with a more complex refactoring.
1909                 Tuple => [TupleSimplifiedType(1), TupleSimplifiedType(2), TupleSimplifiedType(3)].into(),
1910                 Unit => single(TupleSimplifiedType(0)),
1911                 RawPointer => [PtrSimplifiedType(Mutability::Not), PtrSimplifiedType(Mutability::Mut)].into_iter().collect(),
1912                 Reference => [RefSimplifiedType(Mutability::Not), RefSimplifiedType(Mutability::Mut)].into_iter().collect(),
1913                 // FIXME: This will be wrong if we ever add inherent impls
1914                 // for function pointers.
1915                 Fn => single(FunctionSimplifiedType(1)),
1916                 Never => single(NeverSimplifiedType),
1917             }
1918         })
1919     }
1920
1921     pub(crate) fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = DefId> + 'tcx {
1922         Self::simplified_types()
1923             .get(self)
1924             .into_iter()
1925             .flatten()
1926             .flat_map(move |&simp| tcx.incoherent_impls(simp))
1927             .copied()
1928     }
1929
1930     pub(crate) fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> + '_ {
1931         Self::simplified_types()
1932             .values()
1933             .flatten()
1934             .flat_map(move |&simp| tcx.incoherent_impls(simp))
1935             .copied()
1936     }
1937
1938     pub(crate) fn as_sym(&self) -> Symbol {
1939         use PrimitiveType::*;
1940         match self {
1941             Isize => sym::isize,
1942             I8 => sym::i8,
1943             I16 => sym::i16,
1944             I32 => sym::i32,
1945             I64 => sym::i64,
1946             I128 => sym::i128,
1947             Usize => sym::usize,
1948             U8 => sym::u8,
1949             U16 => sym::u16,
1950             U32 => sym::u32,
1951             U64 => sym::u64,
1952             U128 => sym::u128,
1953             F32 => sym::f32,
1954             F64 => sym::f64,
1955             Str => sym::str,
1956             Bool => sym::bool,
1957             Char => sym::char,
1958             Array => sym::array,
1959             Slice => sym::slice,
1960             Tuple => sym::tuple,
1961             Unit => sym::unit,
1962             RawPointer => sym::pointer,
1963             Reference => sym::reference,
1964             Fn => kw::Fn,
1965             Never => sym::never,
1966         }
1967     }
1968
1969     /// Returns the DefId of the module with `doc(primitive)` for this primitive type.
1970     /// Panics if there is no such module.
1971     ///
1972     /// This gives precedence to primitives defined in the current crate, and deprioritizes primitives defined in `core`,
1973     /// but otherwise, if multiple crates define the same primitive, there is no guarantee of which will be picked.
1974     /// In particular, if a crate depends on both `std` and another crate that also defines `doc(primitive)`, then
1975     /// it's entirely random whether `std` or the other crate is picked. (no_std crates are usually fine unless multiple dependencies define a primitive.)
1976     pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxHashMap<PrimitiveType, DefId> {
1977         static PRIMITIVE_LOCATIONS: OnceCell<FxHashMap<PrimitiveType, DefId>> = OnceCell::new();
1978         PRIMITIVE_LOCATIONS.get_or_init(|| {
1979             let mut primitive_locations = FxHashMap::default();
1980             // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate.
1981             // This is a degenerate case that I don't plan to support.
1982             for &crate_num in tcx.crates(()) {
1983                 let e = ExternalCrate { crate_num };
1984                 let crate_name = e.name(tcx);
1985                 debug!(?crate_num, ?crate_name);
1986                 for &(def_id, prim) in &e.primitives(tcx) {
1987                     // HACK: try to link to std instead where possible
1988                     if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1989                         continue;
1990                     }
1991                     primitive_locations.insert(prim, def_id);
1992                 }
1993             }
1994             let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1995             for (def_id, prim) in local_primitives {
1996                 primitive_locations.insert(prim, def_id);
1997             }
1998             primitive_locations
1999         })
2000     }
2001 }
2002
2003 impl From<ast::IntTy> for PrimitiveType {
2004     fn from(int_ty: ast::IntTy) -> PrimitiveType {
2005         match int_ty {
2006             ast::IntTy::Isize => PrimitiveType::Isize,
2007             ast::IntTy::I8 => PrimitiveType::I8,
2008             ast::IntTy::I16 => PrimitiveType::I16,
2009             ast::IntTy::I32 => PrimitiveType::I32,
2010             ast::IntTy::I64 => PrimitiveType::I64,
2011             ast::IntTy::I128 => PrimitiveType::I128,
2012         }
2013     }
2014 }
2015
2016 impl From<ast::UintTy> for PrimitiveType {
2017     fn from(uint_ty: ast::UintTy) -> PrimitiveType {
2018         match uint_ty {
2019             ast::UintTy::Usize => PrimitiveType::Usize,
2020             ast::UintTy::U8 => PrimitiveType::U8,
2021             ast::UintTy::U16 => PrimitiveType::U16,
2022             ast::UintTy::U32 => PrimitiveType::U32,
2023             ast::UintTy::U64 => PrimitiveType::U64,
2024             ast::UintTy::U128 => PrimitiveType::U128,
2025         }
2026     }
2027 }
2028
2029 impl From<ast::FloatTy> for PrimitiveType {
2030     fn from(float_ty: ast::FloatTy) -> PrimitiveType {
2031         match float_ty {
2032             ast::FloatTy::F32 => PrimitiveType::F32,
2033             ast::FloatTy::F64 => PrimitiveType::F64,
2034         }
2035     }
2036 }
2037
2038 impl From<ty::IntTy> for PrimitiveType {
2039     fn from(int_ty: ty::IntTy) -> PrimitiveType {
2040         match int_ty {
2041             ty::IntTy::Isize => PrimitiveType::Isize,
2042             ty::IntTy::I8 => PrimitiveType::I8,
2043             ty::IntTy::I16 => PrimitiveType::I16,
2044             ty::IntTy::I32 => PrimitiveType::I32,
2045             ty::IntTy::I64 => PrimitiveType::I64,
2046             ty::IntTy::I128 => PrimitiveType::I128,
2047         }
2048     }
2049 }
2050
2051 impl From<ty::UintTy> for PrimitiveType {
2052     fn from(uint_ty: ty::UintTy) -> PrimitiveType {
2053         match uint_ty {
2054             ty::UintTy::Usize => PrimitiveType::Usize,
2055             ty::UintTy::U8 => PrimitiveType::U8,
2056             ty::UintTy::U16 => PrimitiveType::U16,
2057             ty::UintTy::U32 => PrimitiveType::U32,
2058             ty::UintTy::U64 => PrimitiveType::U64,
2059             ty::UintTy::U128 => PrimitiveType::U128,
2060         }
2061     }
2062 }
2063
2064 impl From<ty::FloatTy> for PrimitiveType {
2065     fn from(float_ty: ty::FloatTy) -> PrimitiveType {
2066         match float_ty {
2067             ty::FloatTy::F32 => PrimitiveType::F32,
2068             ty::FloatTy::F64 => PrimitiveType::F64,
2069         }
2070     }
2071 }
2072
2073 impl From<hir::PrimTy> for PrimitiveType {
2074     fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
2075         match prim_ty {
2076             hir::PrimTy::Int(int_ty) => int_ty.into(),
2077             hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
2078             hir::PrimTy::Float(float_ty) => float_ty.into(),
2079             hir::PrimTy::Str => PrimitiveType::Str,
2080             hir::PrimTy::Bool => PrimitiveType::Bool,
2081             hir::PrimTy::Char => PrimitiveType::Char,
2082         }
2083     }
2084 }
2085
2086 #[derive(Clone, Debug)]
2087 pub(crate) struct Struct {
2088     pub(crate) ctor_kind: Option<CtorKind>,
2089     pub(crate) generics: Generics,
2090     pub(crate) fields: Vec<Item>,
2091 }
2092
2093 impl Struct {
2094     pub(crate) fn has_stripped_entries(&self) -> bool {
2095         self.fields.iter().any(|f| f.is_stripped())
2096     }
2097 }
2098
2099 #[derive(Clone, Debug)]
2100 pub(crate) struct Union {
2101     pub(crate) generics: Generics,
2102     pub(crate) fields: Vec<Item>,
2103 }
2104
2105 impl Union {
2106     pub(crate) fn has_stripped_entries(&self) -> bool {
2107         self.fields.iter().any(|f| f.is_stripped())
2108     }
2109 }
2110
2111 /// This is a more limited form of the standard Struct, different in that
2112 /// it lacks the things most items have (name, id, parameterization). Found
2113 /// only as a variant in an enum.
2114 #[derive(Clone, Debug)]
2115 pub(crate) struct VariantStruct {
2116     pub(crate) fields: Vec<Item>,
2117 }
2118
2119 impl VariantStruct {
2120     pub(crate) fn has_stripped_entries(&self) -> bool {
2121         self.fields.iter().any(|f| f.is_stripped())
2122     }
2123 }
2124
2125 #[derive(Clone, Debug)]
2126 pub(crate) struct Enum {
2127     pub(crate) variants: IndexVec<VariantIdx, Item>,
2128     pub(crate) generics: Generics,
2129 }
2130
2131 impl Enum {
2132     pub(crate) fn has_stripped_entries(&self) -> bool {
2133         self.variants.iter().any(|f| f.is_stripped())
2134     }
2135
2136     pub(crate) fn variants(&self) -> impl Iterator<Item = &Item> {
2137         self.variants.iter().filter(|v| !v.is_stripped())
2138     }
2139 }
2140
2141 #[derive(Clone, Debug)]
2142 pub(crate) struct Variant {
2143     pub kind: VariantKind,
2144     pub discriminant: Option<Discriminant>,
2145 }
2146
2147 #[derive(Clone, Debug)]
2148 pub(crate) enum VariantKind {
2149     CLike,
2150     Tuple(Vec<Item>),
2151     Struct(VariantStruct),
2152 }
2153
2154 impl Variant {
2155     pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
2156         match &self.kind {
2157             VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()),
2158             VariantKind::CLike | VariantKind::Tuple(_) => None,
2159         }
2160     }
2161 }
2162
2163 #[derive(Clone, Debug)]
2164 pub(crate) struct Discriminant {
2165     // In the case of cross crate re-exports, we don't have the nessesary information
2166     // to reconstruct the expression of the discriminant, only the value.
2167     pub(super) expr: Option<BodyId>,
2168     pub(super) value: DefId,
2169 }
2170
2171 impl Discriminant {
2172     /// Will be `None` in the case of cross-crate reexports, and may be
2173     /// simplified
2174     pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
2175         self.expr.map(|body| print_const_expr(tcx, body))
2176     }
2177     /// Will always be a machine readable number, without underscores or suffixes.
2178     pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> String {
2179         print_evaluated_const(tcx, self.value, false).unwrap()
2180     }
2181 }
2182
2183 /// Small wrapper around [`rustc_span::Span`] that adds helper methods
2184 /// and enforces calling [`rustc_span::Span::source_callsite()`].
2185 #[derive(Copy, Clone, Debug)]
2186 pub(crate) struct Span(rustc_span::Span);
2187
2188 impl Span {
2189     /// Wraps a [`rustc_span::Span`]. In case this span is the result of a macro expansion, the
2190     /// span will be updated to point to the macro invocation instead of the macro definition.
2191     ///
2192     /// (See rust-lang/rust#39726)
2193     pub(crate) fn new(sp: rustc_span::Span) -> Self {
2194         Self(sp.source_callsite())
2195     }
2196
2197     pub(crate) fn inner(&self) -> rustc_span::Span {
2198         self.0
2199     }
2200
2201     pub(crate) fn filename(&self, sess: &Session) -> FileName {
2202         sess.source_map().span_to_filename(self.0)
2203     }
2204
2205     pub(crate) fn lo(&self, sess: &Session) -> Loc {
2206         sess.source_map().lookup_char_pos(self.0.lo())
2207     }
2208
2209     pub(crate) fn hi(&self, sess: &Session) -> Loc {
2210         sess.source_map().lookup_char_pos(self.0.hi())
2211     }
2212
2213     pub(crate) fn cnum(&self, sess: &Session) -> CrateNum {
2214         // FIXME: is there a time when the lo and hi crate would be different?
2215         self.lo(sess).file.cnum
2216     }
2217 }
2218
2219 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2220 pub(crate) struct Path {
2221     pub(crate) res: Res,
2222     pub(crate) segments: ThinVec<PathSegment>,
2223 }
2224
2225 impl Path {
2226     pub(crate) fn def_id(&self) -> DefId {
2227         self.res.def_id()
2228     }
2229
2230     pub(crate) fn last_opt(&self) -> Option<Symbol> {
2231         self.segments.last().map(|s| s.name)
2232     }
2233
2234     pub(crate) fn last(&self) -> Symbol {
2235         self.last_opt().expect("segments were empty")
2236     }
2237
2238     pub(crate) fn whole_name(&self) -> String {
2239         self.segments
2240             .iter()
2241             .map(|s| if s.name == kw::PathRoot { "" } else { s.name.as_str() })
2242             .intersperse("::")
2243             .collect()
2244     }
2245
2246     /// Checks if this is a `T::Name` path for an associated type.
2247     pub(crate) fn is_assoc_ty(&self) -> bool {
2248         match self.res {
2249             Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _)
2250                 if self.segments.len() != 1 =>
2251             {
2252                 true
2253             }
2254             Res::Def(DefKind::AssocTy, _) => true,
2255             _ => false,
2256         }
2257     }
2258
2259     pub(crate) fn generics(&self) -> Option<Vec<&Type>> {
2260         self.segments.last().and_then(|seg| {
2261             if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2262                 Some(
2263                     args.iter()
2264                         .filter_map(|arg| match arg {
2265                             GenericArg::Type(ty) => Some(ty),
2266                             _ => None,
2267                         })
2268                         .collect(),
2269                 )
2270             } else {
2271                 None
2272             }
2273         })
2274     }
2275
2276     pub(crate) fn bindings(&self) -> Option<&[TypeBinding]> {
2277         self.segments.last().and_then(|seg| {
2278             if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
2279                 Some(&**bindings)
2280             } else {
2281                 None
2282             }
2283         })
2284     }
2285 }
2286
2287 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2288 pub(crate) enum GenericArg {
2289     Lifetime(Lifetime),
2290     Type(Type),
2291     Const(Box<Constant>),
2292     Infer,
2293 }
2294
2295 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2296 pub(crate) enum GenericArgs {
2297     AngleBracketed { args: Box<[GenericArg]>, bindings: ThinVec<TypeBinding> },
2298     Parenthesized { inputs: Box<[Type]>, output: Option<Box<Type>> },
2299 }
2300
2301 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2302 pub(crate) struct PathSegment {
2303     pub(crate) name: Symbol,
2304     pub(crate) args: GenericArgs,
2305 }
2306
2307 #[derive(Clone, Debug)]
2308 pub(crate) struct Typedef {
2309     pub(crate) type_: Type,
2310     pub(crate) generics: Generics,
2311     /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
2312     /// alias instead of the final type. This will always have the final type, regardless of whether
2313     /// `type_` came from HIR or from metadata.
2314     ///
2315     /// If `item_type.is_none()`, `type_` is guaranteed to come from metadata (and therefore hold the
2316     /// final type).
2317     pub(crate) item_type: Option<Type>,
2318 }
2319
2320 #[derive(Clone, Debug)]
2321 pub(crate) struct OpaqueTy {
2322     pub(crate) bounds: Vec<GenericBound>,
2323     pub(crate) generics: Generics,
2324 }
2325
2326 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2327 pub(crate) struct BareFunctionDecl {
2328     pub(crate) unsafety: hir::Unsafety,
2329     pub(crate) generic_params: Vec<GenericParamDef>,
2330     pub(crate) decl: FnDecl,
2331     pub(crate) abi: Abi,
2332 }
2333
2334 #[derive(Clone, Debug)]
2335 pub(crate) struct Static {
2336     pub(crate) type_: Type,
2337     pub(crate) mutability: Mutability,
2338     pub(crate) expr: Option<BodyId>,
2339 }
2340
2341 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2342 pub(crate) struct Constant {
2343     pub(crate) type_: Type,
2344     pub(crate) kind: ConstantKind,
2345 }
2346
2347 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2348 pub(crate) enum Term {
2349     Type(Type),
2350     Constant(Constant),
2351 }
2352
2353 impl Term {
2354     pub(crate) fn ty(&self) -> Option<&Type> {
2355         if let Term::Type(ty) = self { Some(ty) } else { None }
2356     }
2357 }
2358
2359 impl From<Type> for Term {
2360     fn from(ty: Type) -> Self {
2361         Term::Type(ty)
2362     }
2363 }
2364
2365 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
2366 pub(crate) enum ConstantKind {
2367     /// This is the wrapper around `ty::Const` for a non-local constant. Because it doesn't have a
2368     /// `BodyId`, we need to handle it on its own.
2369     ///
2370     /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified
2371     /// by a DefId. So this field must be different from `Extern`.
2372     TyConst { expr: Box<str> },
2373     /// A constant (expression) that's not an item or associated item. These are usually found
2374     /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
2375     /// used to define explicit discriminant values for enum variants.
2376     Anonymous { body: BodyId },
2377     /// A constant from a different crate.
2378     Extern { def_id: DefId },
2379     /// `const FOO: u32 = ...;`
2380     Local { def_id: DefId, body: BodyId },
2381 }
2382
2383 impl Constant {
2384     pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2385         self.kind.expr(tcx)
2386     }
2387
2388     pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2389         self.kind.value(tcx)
2390     }
2391
2392     pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2393         self.kind.is_literal(tcx)
2394     }
2395 }
2396
2397 impl ConstantKind {
2398     pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
2399         match *self {
2400             ConstantKind::TyConst { ref expr } => expr.to_string(),
2401             ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
2402             ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2403                 print_const_expr(tcx, body)
2404             }
2405         }
2406     }
2407
2408     pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
2409         match *self {
2410             ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
2411             ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2412                 print_evaluated_const(tcx, def_id, true)
2413             }
2414         }
2415     }
2416
2417     pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
2418         match *self {
2419             ConstantKind::TyConst { .. } => false,
2420             ConstantKind::Extern { def_id } => def_id.as_local().map_or(false, |def_id| {
2421                 is_literal_expr(tcx, tcx.hir().local_def_id_to_hir_id(def_id))
2422             }),
2423             ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
2424                 is_literal_expr(tcx, body.hir_id)
2425             }
2426         }
2427     }
2428 }
2429
2430 #[derive(Clone, Debug)]
2431 pub(crate) struct Impl {
2432     pub(crate) unsafety: hir::Unsafety,
2433     pub(crate) generics: Generics,
2434     pub(crate) trait_: Option<Path>,
2435     pub(crate) for_: Type,
2436     pub(crate) items: Vec<Item>,
2437     pub(crate) polarity: ty::ImplPolarity,
2438     pub(crate) kind: ImplKind,
2439 }
2440
2441 impl Impl {
2442     pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxHashSet<Symbol> {
2443         self.trait_
2444             .as_ref()
2445             .map(|t| t.def_id())
2446             .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name).collect())
2447             .unwrap_or_default()
2448     }
2449 }
2450
2451 #[derive(Clone, Debug)]
2452 pub(crate) enum ImplKind {
2453     Normal,
2454     Auto,
2455     FakeVaradic,
2456     Blanket(Box<Type>),
2457 }
2458
2459 impl ImplKind {
2460     pub(crate) fn is_auto(&self) -> bool {
2461         matches!(self, ImplKind::Auto)
2462     }
2463
2464     pub(crate) fn is_blanket(&self) -> bool {
2465         matches!(self, ImplKind::Blanket(_))
2466     }
2467
2468     pub(crate) fn is_fake_variadic(&self) -> bool {
2469         matches!(self, ImplKind::FakeVaradic)
2470     }
2471
2472     pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
2473         match self {
2474             ImplKind::Blanket(ty) => Some(ty),
2475             _ => None,
2476         }
2477     }
2478 }
2479
2480 #[derive(Clone, Debug)]
2481 pub(crate) struct Import {
2482     pub(crate) kind: ImportKind,
2483     pub(crate) source: ImportSource,
2484     pub(crate) should_be_displayed: bool,
2485 }
2486
2487 impl Import {
2488     pub(crate) fn new_simple(
2489         name: Symbol,
2490         source: ImportSource,
2491         should_be_displayed: bool,
2492     ) -> Self {
2493         Self { kind: ImportKind::Simple(name), source, should_be_displayed }
2494     }
2495
2496     pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
2497         Self { kind: ImportKind::Glob, source, should_be_displayed }
2498     }
2499
2500     pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool {
2501         match self.source.did {
2502             Some(did) => tcx
2503                 .get_attrs(did, sym::doc)
2504                 .filter_map(ast::Attribute::meta_item_list)
2505                 .flatten()
2506                 .has_word(sym::hidden),
2507             None => false,
2508         }
2509     }
2510 }
2511
2512 #[derive(Clone, Debug)]
2513 pub(crate) enum ImportKind {
2514     // use source as str;
2515     Simple(Symbol),
2516     // use source::*;
2517     Glob,
2518 }
2519
2520 #[derive(Clone, Debug)]
2521 pub(crate) struct ImportSource {
2522     pub(crate) path: Path,
2523     pub(crate) did: Option<DefId>,
2524 }
2525
2526 #[derive(Clone, Debug)]
2527 pub(crate) struct Macro {
2528     pub(crate) source: String,
2529 }
2530
2531 #[derive(Clone, Debug)]
2532 pub(crate) struct ProcMacro {
2533     pub(crate) kind: MacroKind,
2534     pub(crate) helpers: Vec<Symbol>,
2535 }
2536
2537 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
2538 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
2539 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2540 pub(crate) struct TypeBinding {
2541     pub(crate) assoc: PathSegment,
2542     pub(crate) kind: TypeBindingKind,
2543 }
2544
2545 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
2546 pub(crate) enum TypeBindingKind {
2547     Equality { term: Term },
2548     Constraint { bounds: Vec<GenericBound> },
2549 }
2550
2551 impl TypeBinding {
2552     pub(crate) fn term(&self) -> &Term {
2553         match self.kind {
2554             TypeBindingKind::Equality { ref term } => term,
2555             _ => panic!("expected equality type binding for parenthesized generic args"),
2556         }
2557     }
2558 }
2559
2560 /// The type, lifetime, or constant that a private type alias's parameter should be
2561 /// replaced with when expanding a use of that type alias.
2562 ///
2563 /// For example:
2564 ///
2565 /// ```
2566 /// type PrivAlias<T> = Vec<T>;
2567 ///
2568 /// pub fn public_fn() -> PrivAlias<i32> { vec![] }
2569 /// ```
2570 ///
2571 /// `public_fn`'s docs will show it as returning `Vec<i32>`, since `PrivAlias` is private.
2572 /// [`SubstParam`] is used to record that `T` should be mapped to `i32`.
2573 pub(crate) enum SubstParam {
2574     Type(Type),
2575     Lifetime(Lifetime),
2576     Constant(Constant),
2577 }
2578
2579 impl SubstParam {
2580     pub(crate) fn as_ty(&self) -> Option<&Type> {
2581         if let Self::Type(ty) = self { Some(ty) } else { None }
2582     }
2583
2584     pub(crate) fn as_lt(&self) -> Option<&Lifetime> {
2585         if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2586     }
2587 }
2588
2589 // Some nodes are used a lot. Make sure they don't unintentionally get bigger.
2590 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
2591 mod size_asserts {
2592     use super::*;
2593     use rustc_data_structures::static_assert_size;
2594     // tidy-alphabetical-start
2595     static_assert_size!(Crate, 64); // frequently moved by-value
2596     static_assert_size!(DocFragment, 32);
2597     static_assert_size!(GenericArg, 32);
2598     static_assert_size!(GenericArgs, 32);
2599     static_assert_size!(GenericParamDef, 56);
2600     static_assert_size!(Generics, 16);
2601     static_assert_size!(Item, 56);
2602     static_assert_size!(ItemKind, 64);
2603     static_assert_size!(PathSegment, 40);
2604     static_assert_size!(Type, 32);
2605     // tidy-alphabetical-end
2606 }