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