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