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