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