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