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