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