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