]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/clean/types.rs
Auto merge of #80790 - JohnTitor:rollup-js1noez, r=JohnTitor
[rust.git] / src / librustdoc / clean / types.rs
1 use std::cell::RefCell;
2 use std::default::Default;
3 use std::fmt;
4 use std::hash::{Hash, Hasher};
5 use std::iter::FromIterator;
6 use std::lazy::SyncOnceCell as OnceCell;
7 use std::rc::Rc;
8 use std::sync::Arc;
9 use std::{slice, vec};
10
11 use rustc_ast::attr;
12 use rustc_ast::util::comments::beautify_doc_string;
13 use rustc_ast::{self as ast, AttrStyle};
14 use rustc_ast::{FloatTy, IntTy, UintTy};
15 use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
16 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
17 use rustc_feature::UnstableFeatures;
18 use rustc_hir as hir;
19 use rustc_hir::def::Res;
20 use rustc_hir::def_id::{CrateNum, DefId};
21 use rustc_hir::lang_items::LangItem;
22 use rustc_hir::Mutability;
23 use rustc_index::vec::IndexVec;
24 use rustc_middle::ty::TyCtxt;
25 use rustc_session::Session;
26 use rustc_span::hygiene::MacroKind;
27 use rustc_span::source_map::DUMMY_SP;
28 use rustc_span::symbol::{kw, sym, Ident, Symbol, SymbolStr};
29 use rustc_span::{self, FileName, Loc};
30 use rustc_target::abi::VariantIdx;
31 use rustc_target::spec::abi::Abi;
32 use smallvec::{smallvec, SmallVec};
33
34 use crate::clean::cfg::Cfg;
35 use crate::clean::external_path;
36 use crate::clean::inline;
37 use crate::clean::types::Type::{QPath, ResolvedPath};
38 use crate::clean::Clean;
39 use crate::core::DocContext;
40 use crate::doctree;
41 use crate::formats::cache::cache;
42 use crate::formats::item_type::ItemType;
43 use crate::html::render::cache::ExternalLocation;
44
45 use self::FnRetTy::*;
46 use self::ItemKind::*;
47 use self::SelfTy::*;
48 use self::Type::*;
49
50 thread_local!(crate static MAX_DEF_ID: RefCell<FxHashMap<CrateNum, DefId>> = Default::default());
51
52 #[derive(Clone, Debug)]
53 crate struct Crate {
54     crate name: Symbol,
55     crate version: Option<String>,
56     crate src: FileName,
57     crate module: Option<Item>,
58     crate externs: Vec<(CrateNum, ExternalCrate)>,
59     crate primitives: Vec<(DefId, PrimitiveType)>,
60     // These are later on moved into `CACHEKEY`, leaving the map empty.
61     // Only here so that they can be filtered through the rustdoc passes.
62     crate external_traits: Rc<RefCell<FxHashMap<DefId, Trait>>>,
63     crate masked_crates: FxHashSet<CrateNum>,
64     crate collapsed: bool,
65 }
66
67 #[derive(Clone, Debug)]
68 crate struct ExternalCrate {
69     crate name: Symbol,
70     crate src: FileName,
71     crate attrs: Attributes,
72     crate primitives: Vec<(DefId, PrimitiveType)>,
73     crate keywords: Vec<(DefId, Symbol)>,
74 }
75
76 /// Anything with a source location and set of attributes and, optionally, a
77 /// name. That is, anything that can be documented. This doesn't correspond
78 /// directly to the AST's concept of an item; it's a strict superset.
79 #[derive(Clone)]
80 crate struct Item {
81     /// Stringified span
82     crate source: Span,
83     /// Not everything has a name. E.g., impls
84     crate name: Option<Symbol>,
85     crate attrs: Attributes,
86     crate visibility: Visibility,
87     crate kind: Box<ItemKind>,
88     crate def_id: DefId,
89 }
90
91 // `Item` is used a lot. Make sure it doesn't unintentionally get bigger.
92 #[cfg(target_arch = "x86_64")]
93 rustc_data_structures::static_assert_size!(Item, 136);
94
95 impl fmt::Debug for Item {
96     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
97         let def_id: &dyn fmt::Debug = if self.is_fake() { &"**FAKE**" } else { &self.def_id };
98
99         fmt.debug_struct("Item")
100             .field("source", &self.source)
101             .field("name", &self.name)
102             .field("attrs", &self.attrs)
103             .field("kind", &self.kind)
104             .field("visibility", &self.visibility)
105             .field("def_id", def_id)
106             .finish()
107     }
108 }
109
110 impl Item {
111     crate fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx Stability> {
112         if self.is_fake() { None } else { tcx.lookup_stability(self.def_id) }
113     }
114
115     crate fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ConstStability> {
116         if self.is_fake() { None } else { tcx.lookup_const_stability(self.def_id) }
117     }
118
119     crate fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
120         if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id) }
121     }
122
123     /// Finds the `doc` attribute as a NameValue and returns the corresponding
124     /// value found.
125     crate fn doc_value(&self) -> Option<String> {
126         self.attrs.doc_value()
127     }
128
129     /// Convenience wrapper around [`Self::from_def_id_and_parts`] which converts
130     /// `hir_id` to a [`DefId`]
131     pub fn from_hir_id_and_parts(
132         hir_id: hir::HirId,
133         name: Option<Symbol>,
134         kind: ItemKind,
135         cx: &DocContext<'_>,
136     ) -> Item {
137         Item::from_def_id_and_parts(cx.tcx.hir().local_def_id(hir_id).to_def_id(), name, kind, cx)
138     }
139
140     pub fn from_def_id_and_parts(
141         def_id: DefId,
142         name: Option<Symbol>,
143         kind: ItemKind,
144         cx: &DocContext<'_>,
145     ) -> Item {
146         debug!("name={:?}, def_id={:?}", name, def_id);
147
148         // `span_if_local()` lies about functions and only gives the span of the function signature
149         let source = def_id.as_local().map_or_else(
150             || cx.tcx.def_span(def_id),
151             |local| {
152                 let hir = cx.tcx.hir();
153                 hir.span_with_body(hir.local_def_id_to_hir_id(local))
154             },
155         );
156
157         Item {
158             def_id,
159             kind: box kind,
160             name,
161             source: source.clean(cx),
162             attrs: cx.tcx.get_attrs(def_id).clean(cx),
163             visibility: cx.tcx.visibility(def_id).clean(cx),
164         }
165     }
166
167     /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
168     /// with newlines.
169     crate fn collapsed_doc_value(&self) -> Option<String> {
170         self.attrs.collapsed_doc_value()
171     }
172
173     crate fn links(&self) -> Vec<RenderedLink> {
174         self.attrs.links(&self.def_id.krate)
175     }
176
177     crate fn is_crate(&self) -> bool {
178         matches!(*self.kind,
179             StrippedItem(box ModuleItem(Module { is_crate: true, .. }))
180             | ModuleItem(Module { is_crate: true, .. }))
181     }
182     crate fn is_mod(&self) -> bool {
183         self.type_() == ItemType::Module
184     }
185     crate fn is_trait(&self) -> bool {
186         self.type_() == ItemType::Trait
187     }
188     crate fn is_struct(&self) -> bool {
189         self.type_() == ItemType::Struct
190     }
191     crate fn is_enum(&self) -> bool {
192         self.type_() == ItemType::Enum
193     }
194     crate fn is_variant(&self) -> bool {
195         self.type_() == ItemType::Variant
196     }
197     crate fn is_associated_type(&self) -> bool {
198         self.type_() == ItemType::AssocType
199     }
200     crate fn is_associated_const(&self) -> bool {
201         self.type_() == ItemType::AssocConst
202     }
203     crate fn is_method(&self) -> bool {
204         self.type_() == ItemType::Method
205     }
206     crate fn is_ty_method(&self) -> bool {
207         self.type_() == ItemType::TyMethod
208     }
209     crate fn is_typedef(&self) -> bool {
210         self.type_() == ItemType::Typedef
211     }
212     crate fn is_primitive(&self) -> bool {
213         self.type_() == ItemType::Primitive
214     }
215     crate fn is_union(&self) -> bool {
216         self.type_() == ItemType::Union
217     }
218     crate fn is_import(&self) -> bool {
219         self.type_() == ItemType::Import
220     }
221     crate fn is_extern_crate(&self) -> bool {
222         self.type_() == ItemType::ExternCrate
223     }
224     crate fn is_keyword(&self) -> bool {
225         self.type_() == ItemType::Keyword
226     }
227     crate fn is_stripped(&self) -> bool {
228         match *self.kind {
229             StrippedItem(..) => true,
230             ImportItem(ref i) => !i.should_be_displayed,
231             _ => false,
232         }
233     }
234     crate fn has_stripped_fields(&self) -> Option<bool> {
235         match *self.kind {
236             StructItem(ref _struct) => Some(_struct.fields_stripped),
237             UnionItem(ref union) => Some(union.fields_stripped),
238             VariantItem(Variant { kind: VariantKind::Struct(ref vstruct) }) => {
239                 Some(vstruct.fields_stripped)
240             }
241             _ => None,
242         }
243     }
244
245     crate fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
246         self.stability(tcx).as_ref().and_then(|ref s| {
247             let mut classes = Vec::with_capacity(2);
248
249             if s.level.is_unstable() {
250                 classes.push("unstable");
251             }
252
253             // FIXME: what about non-staged API items that are deprecated?
254             if self.deprecation(tcx).is_some() {
255                 classes.push("deprecated");
256             }
257
258             if !classes.is_empty() { Some(classes.join(" ")) } else { None }
259         })
260     }
261
262     crate fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
263         match self.stability(tcx)?.level {
264             StabilityLevel::Stable { since, .. } => Some(since.as_str()),
265             StabilityLevel::Unstable { .. } => None,
266         }
267     }
268
269     crate fn const_stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
270         match self.const_stability(tcx)?.level {
271             StabilityLevel::Stable { since, .. } => Some(since.as_str()),
272             StabilityLevel::Unstable { .. } => None,
273         }
274     }
275
276     crate fn is_non_exhaustive(&self) -> bool {
277         self.attrs.other_attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
278     }
279
280     /// Returns a documentation-level item type from the item.
281     crate fn type_(&self) -> ItemType {
282         ItemType::from(self)
283     }
284
285     crate fn is_default(&self) -> bool {
286         match *self.kind {
287             ItemKind::MethodItem(_, Some(defaultness)) => {
288                 defaultness.has_value() && !defaultness.is_final()
289             }
290             _ => false,
291         }
292     }
293
294     /// See the documentation for [`next_def_id()`].
295     ///
296     /// [`next_def_id()`]: DocContext::next_def_id()
297     crate fn is_fake(&self) -> bool {
298         MAX_DEF_ID.with(|m| {
299             m.borrow().get(&self.def_id.krate).map(|id| self.def_id >= *id).unwrap_or(false)
300         })
301     }
302 }
303
304 #[derive(Clone, Debug)]
305 crate enum ItemKind {
306     ExternCrateItem(Symbol, Option<Symbol>),
307     ImportItem(Import),
308     StructItem(Struct),
309     UnionItem(Union),
310     EnumItem(Enum),
311     FunctionItem(Function),
312     ModuleItem(Module),
313     TypedefItem(Typedef, bool /* is associated type */),
314     OpaqueTyItem(OpaqueTy),
315     StaticItem(Static),
316     ConstantItem(Constant),
317     TraitItem(Trait),
318     TraitAliasItem(TraitAlias),
319     ImplItem(Impl),
320     /// A method signature only. Used for required methods in traits (ie,
321     /// non-default-methods).
322     TyMethodItem(Function),
323     /// A method with a body.
324     MethodItem(Function, Option<hir::Defaultness>),
325     StructFieldItem(Type),
326     VariantItem(Variant),
327     /// `fn`s from an extern block
328     ForeignFunctionItem(Function),
329     /// `static`s from an extern block
330     ForeignStaticItem(Static),
331     /// `type`s from an extern block
332     ForeignTypeItem,
333     MacroItem(Macro),
334     ProcMacroItem(ProcMacro),
335     PrimitiveItem(PrimitiveType),
336     AssocConstItem(Type, Option<String>),
337     /// An associated item in a trait or trait impl.
338     ///
339     /// The bounds may be non-empty if there is a `where` clause.
340     /// The `Option<Type>` is the default concrete type (e.g. `trait Trait { type Target = usize; }`)
341     AssocTypeItem(Vec<GenericBound>, Option<Type>),
342     /// An item that has been stripped by a rustdoc pass
343     StrippedItem(Box<ItemKind>),
344     KeywordItem(Symbol),
345 }
346
347 impl ItemKind {
348     /// Some items contain others such as structs (for their fields) and Enums
349     /// (for their variants). This method returns those contained items.
350     crate fn inner_items(&self) -> impl Iterator<Item = &Item> {
351         match self {
352             StructItem(s) => s.fields.iter(),
353             UnionItem(u) => u.fields.iter(),
354             VariantItem(Variant { kind: VariantKind::Struct(v) }) => v.fields.iter(),
355             EnumItem(e) => e.variants.iter(),
356             TraitItem(t) => t.items.iter(),
357             ImplItem(i) => i.items.iter(),
358             ModuleItem(m) => m.items.iter(),
359             ExternCrateItem(_, _)
360             | ImportItem(_)
361             | FunctionItem(_)
362             | TypedefItem(_, _)
363             | OpaqueTyItem(_)
364             | StaticItem(_)
365             | ConstantItem(_)
366             | TraitAliasItem(_)
367             | TyMethodItem(_)
368             | MethodItem(_, _)
369             | StructFieldItem(_)
370             | VariantItem(_)
371             | ForeignFunctionItem(_)
372             | ForeignStaticItem(_)
373             | ForeignTypeItem
374             | MacroItem(_)
375             | ProcMacroItem(_)
376             | PrimitiveItem(_)
377             | AssocConstItem(_, _)
378             | AssocTypeItem(_, _)
379             | StrippedItem(_)
380             | KeywordItem(_) => [].iter(),
381         }
382     }
383
384     crate fn is_type_alias(&self) -> bool {
385         matches!(self, ItemKind::TypedefItem(..) | ItemKind::AssocTypeItem(..))
386     }
387 }
388
389 #[derive(Clone, Debug)]
390 crate struct Module {
391     crate items: Vec<Item>,
392     crate is_crate: bool,
393 }
394
395 crate struct ListAttributesIter<'a> {
396     attrs: slice::Iter<'a, ast::Attribute>,
397     current_list: vec::IntoIter<ast::NestedMetaItem>,
398     name: Symbol,
399 }
400
401 impl<'a> Iterator for ListAttributesIter<'a> {
402     type Item = ast::NestedMetaItem;
403
404     fn next(&mut self) -> Option<Self::Item> {
405         if let Some(nested) = self.current_list.next() {
406             return Some(nested);
407         }
408
409         for attr in &mut self.attrs {
410             if let Some(list) = attr.meta_item_list() {
411                 if attr.has_name(self.name) {
412                     self.current_list = list.into_iter();
413                     if let Some(nested) = self.current_list.next() {
414                         return Some(nested);
415                     }
416                 }
417             }
418         }
419
420         None
421     }
422
423     fn size_hint(&self) -> (usize, Option<usize>) {
424         let lower = self.current_list.len();
425         (lower, None)
426     }
427 }
428
429 crate trait AttributesExt {
430     /// Finds an attribute as List and returns the list of attributes nested inside.
431     fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
432 }
433
434 impl AttributesExt for [ast::Attribute] {
435     fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
436         ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), name }
437     }
438 }
439
440 crate trait NestedAttributesExt {
441     /// Returns `true` if the attribute list contains a specific `Word`
442     fn has_word(self, word: Symbol) -> bool;
443     fn get_word_attr(self, word: Symbol) -> (Option<ast::NestedMetaItem>, bool);
444 }
445
446 impl<I: Iterator<Item = ast::NestedMetaItem> + IntoIterator<Item = ast::NestedMetaItem>>
447     NestedAttributesExt for I
448 {
449     fn has_word(self, word: Symbol) -> bool {
450         self.into_iter().any(|attr| attr.is_word() && attr.has_name(word))
451     }
452
453     fn get_word_attr(mut self, word: Symbol) -> (Option<ast::NestedMetaItem>, bool) {
454         match self.find(|attr| attr.is_word() && attr.has_name(word)) {
455             Some(a) => (Some(a), true),
456             None => (None, false),
457         }
458     }
459 }
460
461 /// A portion of documentation, extracted from a `#[doc]` attribute.
462 ///
463 /// Each variant contains the line number within the complete doc-comment where the fragment
464 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
465 ///
466 /// Included files are kept separate from inline doc comments so that proper line-number
467 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
468 /// kept separate because of issue #42760.
469 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
470 crate struct DocFragment {
471     crate line: usize,
472     crate span: rustc_span::Span,
473     /// The module this doc-comment came from.
474     ///
475     /// This allows distinguishing between the original documentation and a pub re-export.
476     /// If it is `None`, the item was not re-exported.
477     crate parent_module: Option<DefId>,
478     crate doc: Symbol,
479     crate kind: DocFragmentKind,
480     crate need_backline: bool,
481     crate indent: usize,
482 }
483
484 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
485 crate enum DocFragmentKind {
486     /// A doc fragment created from a `///` or `//!` doc comment.
487     SugaredDoc,
488     /// A doc fragment created from a "raw" `#[doc=""]` attribute.
489     RawDoc,
490     /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
491     /// given filename and the file contents.
492     Include { filename: Symbol },
493 }
494
495 // The goal of this function is to apply the `DocFragment` transformations that are required when
496 // transforming into the final markdown. So the transformations in here are:
497 //
498 // * Applying the computed indent to each lines in each doc fragment (a `DocFragment` can contain
499 //   multiple lines in case of `#[doc = ""]`).
500 // * Adding backlines between `DocFragment`s and adding an extra one if required (stored in the
501 //   `need_backline` field).
502 fn add_doc_fragment(out: &mut String, frag: &DocFragment) {
503     let s = frag.doc.as_str();
504     let mut iter = s.lines().peekable();
505     while let Some(line) = iter.next() {
506         if line.chars().any(|c| !c.is_whitespace()) {
507             assert!(line.len() >= frag.indent);
508             out.push_str(&line[frag.indent..]);
509         } else {
510             out.push_str(line);
511         }
512         if iter.peek().is_some() {
513             out.push('\n');
514         }
515     }
516     if frag.need_backline {
517         out.push('\n');
518     }
519 }
520
521 impl<'a> FromIterator<&'a DocFragment> for String {
522     fn from_iter<T>(iter: T) -> Self
523     where
524         T: IntoIterator<Item = &'a DocFragment>,
525     {
526         let mut prev_kind: Option<DocFragmentKind> = None;
527         iter.into_iter().fold(String::new(), |mut acc, frag| {
528             if !acc.is_empty()
529                 && prev_kind
530                     .take()
531                     .map(|p| matches!(p, DocFragmentKind::Include { .. }) && p != frag.kind)
532                     .unwrap_or(false)
533             {
534                 acc.push('\n');
535             }
536             add_doc_fragment(&mut acc, &frag);
537             prev_kind = Some(frag.kind);
538             acc
539         })
540     }
541 }
542
543 #[derive(Clone, Debug, Default)]
544 crate struct Attributes {
545     crate doc_strings: Vec<DocFragment>,
546     crate other_attrs: Vec<ast::Attribute>,
547     crate cfg: Option<Arc<Cfg>>,
548     crate span: Option<rustc_span::Span>,
549     /// map from Rust paths to resolved defs and potential URL fragments
550     crate links: Vec<ItemLink>,
551     crate inner_docs: bool,
552 }
553
554 #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
555 /// A link that has not yet been rendered.
556 ///
557 /// This link will be turned into a rendered link by [`Attributes::links`]
558 crate struct ItemLink {
559     /// The original link written in the markdown
560     pub(crate) link: String,
561     /// The link text displayed in the HTML.
562     ///
563     /// This may not be the same as `link` if there was a disambiguator
564     /// in an intra-doc link (e.g. \[`fn@f`\])
565     pub(crate) link_text: String,
566     pub(crate) did: Option<DefId>,
567     /// The url fragment to append to the link
568     pub(crate) fragment: Option<String>,
569 }
570
571 pub struct RenderedLink {
572     /// The text the link was original written as.
573     ///
574     /// This could potentially include disambiguators and backticks.
575     pub(crate) original_text: String,
576     /// The text to display in the HTML
577     pub(crate) new_text: String,
578     /// The URL to put in the `href`
579     pub(crate) href: String,
580 }
581
582 impl Attributes {
583     /// Extracts the content from an attribute `#[doc(cfg(content))]`.
584     crate fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
585         use rustc_ast::NestedMetaItem::MetaItem;
586
587         if let ast::MetaItemKind::List(ref nmis) = mi.kind {
588             if nmis.len() == 1 {
589                 if let MetaItem(ref cfg_mi) = nmis[0] {
590                     if cfg_mi.has_name(sym::cfg) {
591                         if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.kind {
592                             if cfg_nmis.len() == 1 {
593                                 if let MetaItem(ref content_mi) = cfg_nmis[0] {
594                                     return Some(content_mi);
595                                 }
596                             }
597                         }
598                     }
599                 }
600             }
601         }
602
603         None
604     }
605
606     /// Reads a `MetaItem` from within an attribute, looks for whether it is a
607     /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
608     /// its expansion.
609     crate fn extract_include(mi: &ast::MetaItem) -> Option<(Symbol, Symbol)> {
610         mi.meta_item_list().and_then(|list| {
611             for meta in list {
612                 if meta.has_name(sym::include) {
613                     // the actual compiled `#[doc(include="filename")]` gets expanded to
614                     // `#[doc(include(file="filename", contents="file contents")]` so we need to
615                     // look for that instead
616                     return meta.meta_item_list().and_then(|list| {
617                         let mut filename: Option<Symbol> = None;
618                         let mut contents: Option<Symbol> = None;
619
620                         for it in list {
621                             if it.has_name(sym::file) {
622                                 if let Some(name) = it.value_str() {
623                                     filename = Some(name);
624                                 }
625                             } else if it.has_name(sym::contents) {
626                                 if let Some(docs) = it.value_str() {
627                                     contents = Some(docs);
628                                 }
629                             }
630                         }
631
632                         if let (Some(filename), Some(contents)) = (filename, contents) {
633                             Some((filename, contents))
634                         } else {
635                             None
636                         }
637                     });
638                 }
639             }
640
641             None
642         })
643     }
644
645     crate fn has_doc_flag(&self, flag: Symbol) -> bool {
646         for attr in &self.other_attrs {
647             if !attr.has_name(sym::doc) {
648                 continue;
649             }
650
651             if let Some(items) = attr.meta_item_list() {
652                 if items.iter().filter_map(|i| i.meta_item()).any(|it| it.has_name(flag)) {
653                     return true;
654                 }
655             }
656         }
657
658         false
659     }
660
661     crate fn from_ast(
662         diagnostic: &::rustc_errors::Handler,
663         attrs: &[ast::Attribute],
664         additional_attrs: Option<(&[ast::Attribute], DefId)>,
665     ) -> Attributes {
666         let mut doc_strings: Vec<DocFragment> = vec![];
667         let mut sp = None;
668         let mut cfg = Cfg::True;
669         let mut doc_line = 0;
670
671         fn update_need_backline(doc_strings: &mut Vec<DocFragment>, frag: &DocFragment) {
672             if let Some(prev) = doc_strings.last_mut() {
673                 if matches!(prev.kind, DocFragmentKind::Include { .. })
674                     || prev.kind != frag.kind
675                     || prev.parent_module != frag.parent_module
676                 {
677                     // add a newline for extra padding between segments
678                     prev.need_backline = prev.kind == DocFragmentKind::SugaredDoc
679                         || prev.kind == DocFragmentKind::RawDoc
680                 } else {
681                     prev.need_backline = true;
682                 }
683             }
684         }
685
686         let clean_attr = |(attr, parent_module): (&ast::Attribute, _)| {
687             if let Some(value) = attr.doc_str() {
688                 trace!("got doc_str={:?}", value);
689                 let value = beautify_doc_string(value);
690                 let kind = if attr.is_doc_comment() {
691                     DocFragmentKind::SugaredDoc
692                 } else {
693                     DocFragmentKind::RawDoc
694                 };
695
696                 let line = doc_line;
697                 doc_line += value.as_str().lines().count();
698                 let frag = DocFragment {
699                     line,
700                     span: attr.span,
701                     doc: value,
702                     kind,
703                     parent_module,
704                     need_backline: false,
705                     indent: 0,
706                 };
707
708                 update_need_backline(&mut doc_strings, &frag);
709
710                 doc_strings.push(frag);
711
712                 if sp.is_none() {
713                     sp = Some(attr.span);
714                 }
715                 None
716             } else {
717                 if attr.has_name(sym::doc) {
718                     if let Some(mi) = attr.meta() {
719                         if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
720                             // Extracted #[doc(cfg(...))]
721                             match Cfg::parse(cfg_mi) {
722                                 Ok(new_cfg) => cfg &= new_cfg,
723                                 Err(e) => diagnostic.span_err(e.span, e.msg),
724                             }
725                         } else if let Some((filename, contents)) = Attributes::extract_include(&mi)
726                         {
727                             let line = doc_line;
728                             doc_line += contents.as_str().lines().count();
729                             let frag = DocFragment {
730                                 line,
731                                 span: attr.span,
732                                 doc: contents,
733                                 kind: DocFragmentKind::Include { filename },
734                                 parent_module,
735                                 need_backline: false,
736                                 indent: 0,
737                             };
738                             update_need_backline(&mut doc_strings, &frag);
739                             doc_strings.push(frag);
740                         }
741                     }
742                 }
743                 Some(attr.clone())
744             }
745         };
746
747         // Additional documentation should be shown before the original documentation
748         let other_attrs = additional_attrs
749             .into_iter()
750             .map(|(attrs, id)| attrs.iter().map(move |attr| (attr, Some(id))))
751             .flatten()
752             .chain(attrs.iter().map(|attr| (attr, None)))
753             .filter_map(clean_attr)
754             .collect();
755
756         // treat #[target_feature(enable = "feat")] attributes as if they were
757         // #[doc(cfg(target_feature = "feat"))] attributes as well
758         for attr in attrs.lists(sym::target_feature) {
759             if attr.has_name(sym::enable) {
760                 if let Some(feat) = attr.value_str() {
761                     let meta = attr::mk_name_value_item_str(
762                         Ident::with_dummy_span(sym::target_feature),
763                         feat,
764                         DUMMY_SP,
765                     );
766                     if let Ok(feat_cfg) = Cfg::parse(&meta) {
767                         cfg &= feat_cfg;
768                     }
769                 }
770             }
771         }
772
773         let inner_docs = attrs
774             .iter()
775             .find(|a| a.doc_str().is_some())
776             .map_or(true, |a| a.style == AttrStyle::Inner);
777
778         Attributes {
779             doc_strings,
780             other_attrs,
781             cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) },
782             span: sp,
783             links: vec![],
784             inner_docs,
785         }
786     }
787
788     /// Finds the `doc` attribute as a NameValue and returns the corresponding
789     /// value found.
790     crate fn doc_value(&self) -> Option<String> {
791         let mut iter = self.doc_strings.iter();
792
793         let ori = iter.next()?;
794         let mut out = String::new();
795         add_doc_fragment(&mut out, &ori);
796         while let Some(new_frag) = iter.next() {
797             if matches!(ori.kind, DocFragmentKind::Include { .. })
798                 || new_frag.kind != ori.kind
799                 || new_frag.parent_module != ori.parent_module
800             {
801                 break;
802             }
803             add_doc_fragment(&mut out, &new_frag);
804         }
805         if out.is_empty() { None } else { Some(out) }
806     }
807
808     /// Return the doc-comments on this item, grouped by the module they came from.
809     ///
810     /// The module can be different if this is a re-export with added documentation.
811     crate fn collapsed_doc_value_by_module_level(&self) -> FxHashMap<Option<DefId>, String> {
812         let mut ret = FxHashMap::default();
813
814         for new_frag in self.doc_strings.iter() {
815             let out = ret.entry(new_frag.parent_module).or_default();
816             add_doc_fragment(out, &new_frag);
817         }
818         ret
819     }
820
821     /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
822     /// with newlines.
823     crate fn collapsed_doc_value(&self) -> Option<String> {
824         if self.doc_strings.is_empty() { None } else { Some(self.doc_strings.iter().collect()) }
825     }
826
827     /// Gets links as a vector
828     ///
829     /// Cache must be populated before call
830     crate fn links(&self, krate: &CrateNum) -> Vec<RenderedLink> {
831         use crate::html::format::href;
832         use crate::html::render::CURRENT_DEPTH;
833
834         self.links
835             .iter()
836             .filter_map(|ItemLink { link: s, link_text, did, fragment }| {
837                 match *did {
838                     Some(did) => {
839                         if let Some((mut href, ..)) = href(did) {
840                             if let Some(ref fragment) = *fragment {
841                                 href.push('#');
842                                 href.push_str(fragment);
843                             }
844                             Some(RenderedLink {
845                                 original_text: s.clone(),
846                                 new_text: link_text.clone(),
847                                 href,
848                             })
849                         } else {
850                             None
851                         }
852                     }
853                     None => {
854                         if let Some(ref fragment) = *fragment {
855                             let cache = cache();
856                             let url = match cache.extern_locations.get(krate) {
857                                 Some(&(_, _, ExternalLocation::Local)) => {
858                                     let depth = CURRENT_DEPTH.with(|l| l.get());
859                                     "../".repeat(depth)
860                                 }
861                                 Some(&(_, _, ExternalLocation::Remote(ref s))) => s.to_string(),
862                                 Some(&(_, _, ExternalLocation::Unknown)) | None => String::from(
863                                     // NOTE: intentionally doesn't pass crate name to avoid having
864                                     // different primitive links between crates
865                                     if UnstableFeatures::from_environment(None).is_nightly_build() {
866                                         "https://doc.rust-lang.org/nightly"
867                                     } else {
868                                         "https://doc.rust-lang.org"
869                                     },
870                                 ),
871                             };
872                             // This is a primitive so the url is done "by hand".
873                             let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
874                             Some(RenderedLink {
875                                 original_text: s.clone(),
876                                 new_text: link_text.clone(),
877                                 href: format!(
878                                     "{}{}std/primitive.{}.html{}",
879                                     url,
880                                     if !url.ends_with('/') { "/" } else { "" },
881                                     &fragment[..tail],
882                                     &fragment[tail..]
883                                 ),
884                             })
885                         } else {
886                             panic!("This isn't a primitive?!");
887                         }
888                     }
889                 }
890             })
891             .collect()
892     }
893
894     crate fn get_doc_aliases(&self) -> FxHashSet<String> {
895         self.other_attrs
896             .lists(sym::doc)
897             .filter(|a| a.has_name(sym::alias))
898             .filter_map(|a| a.value_str().map(|s| s.to_string()))
899             .filter(|v| !v.is_empty())
900             .collect::<FxHashSet<_>>()
901     }
902 }
903
904 impl PartialEq for Attributes {
905     fn eq(&self, rhs: &Self) -> bool {
906         self.doc_strings == rhs.doc_strings
907             && self.cfg == rhs.cfg
908             && self.span == rhs.span
909             && self.links == rhs.links
910             && self
911                 .other_attrs
912                 .iter()
913                 .map(|attr| attr.id)
914                 .eq(rhs.other_attrs.iter().map(|attr| attr.id))
915     }
916 }
917
918 impl Eq for Attributes {}
919
920 impl Hash for Attributes {
921     fn hash<H: Hasher>(&self, hasher: &mut H) {
922         self.doc_strings.hash(hasher);
923         self.cfg.hash(hasher);
924         self.span.hash(hasher);
925         self.links.hash(hasher);
926         for attr in &self.other_attrs {
927             attr.id.hash(hasher);
928         }
929     }
930 }
931
932 impl AttributesExt for Attributes {
933     fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
934         self.other_attrs.lists(name)
935     }
936 }
937
938 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
939 crate enum GenericBound {
940     TraitBound(PolyTrait, hir::TraitBoundModifier),
941     Outlives(Lifetime),
942 }
943
944 impl GenericBound {
945     crate fn maybe_sized(cx: &DocContext<'_>) -> GenericBound {
946         let did = cx.tcx.require_lang_item(LangItem::Sized, None);
947         let empty = cx.tcx.intern_substs(&[]);
948         let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
949         inline::record_extern_fqn(cx, did, TypeKind::Trait);
950         GenericBound::TraitBound(
951             PolyTrait {
952                 trait_: ResolvedPath { path, param_names: None, did, is_generic: false },
953                 generic_params: Vec::new(),
954             },
955             hir::TraitBoundModifier::Maybe,
956         )
957     }
958
959     crate fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
960         use rustc_hir::TraitBoundModifier as TBM;
961         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
962             if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
963                 return true;
964             }
965         }
966         false
967     }
968
969     crate fn get_poly_trait(&self) -> Option<PolyTrait> {
970         if let GenericBound::TraitBound(ref p, _) = *self {
971             return Some(p.clone());
972         }
973         None
974     }
975
976     crate fn get_trait_type(&self) -> Option<Type> {
977         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
978             Some(trait_.clone())
979         } else {
980             None
981         }
982     }
983 }
984
985 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
986 crate struct Lifetime(pub Symbol);
987
988 impl Lifetime {
989     crate fn get_ref(&self) -> SymbolStr {
990         self.0.as_str()
991     }
992
993     crate fn statik() -> Lifetime {
994         Lifetime(kw::StaticLifetime)
995     }
996
997     crate fn elided() -> Lifetime {
998         Lifetime(kw::UnderscoreLifetime)
999     }
1000 }
1001
1002 #[derive(Clone, Debug)]
1003 crate enum WherePredicate {
1004     BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
1005     RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1006     EqPredicate { lhs: Type, rhs: Type },
1007 }
1008
1009 impl WherePredicate {
1010     crate fn get_bounds(&self) -> Option<&[GenericBound]> {
1011         match *self {
1012             WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
1013             WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
1014             _ => None,
1015         }
1016     }
1017 }
1018
1019 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1020 crate enum GenericParamDefKind {
1021     Lifetime,
1022     Type {
1023         did: DefId,
1024         bounds: Vec<GenericBound>,
1025         default: Option<Type>,
1026         synthetic: Option<hir::SyntheticTyParamKind>,
1027     },
1028     Const {
1029         did: DefId,
1030         ty: Type,
1031     },
1032 }
1033
1034 impl GenericParamDefKind {
1035     crate fn is_type(&self) -> bool {
1036         matches!(self, GenericParamDefKind::Type { .. })
1037     }
1038
1039     // FIXME(eddyb) this either returns the default of a type parameter, or the
1040     // type of a `const` parameter. It seems that the intention is to *visit*
1041     // any embedded types, but `get_type` seems to be the wrong name for that.
1042     crate fn get_type(&self) -> Option<Type> {
1043         match self {
1044             GenericParamDefKind::Type { default, .. } => default.clone(),
1045             GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
1046             GenericParamDefKind::Lifetime => None,
1047         }
1048     }
1049 }
1050
1051 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1052 crate struct GenericParamDef {
1053     crate name: Symbol,
1054     crate kind: GenericParamDefKind,
1055 }
1056
1057 impl GenericParamDef {
1058     crate fn is_synthetic_type_param(&self) -> bool {
1059         match self.kind {
1060             GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => false,
1061             GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
1062         }
1063     }
1064
1065     crate fn is_type(&self) -> bool {
1066         self.kind.is_type()
1067     }
1068
1069     crate fn get_type(&self) -> Option<Type> {
1070         self.kind.get_type()
1071     }
1072
1073     crate fn get_bounds(&self) -> Option<&[GenericBound]> {
1074         match self.kind {
1075             GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1076             _ => None,
1077         }
1078     }
1079 }
1080
1081 // maybe use a Generic enum and use Vec<Generic>?
1082 #[derive(Clone, Debug, Default)]
1083 crate struct Generics {
1084     crate params: Vec<GenericParamDef>,
1085     crate where_predicates: Vec<WherePredicate>,
1086 }
1087
1088 #[derive(Clone, Debug)]
1089 crate struct Function {
1090     crate decl: FnDecl,
1091     crate generics: Generics,
1092     crate header: hir::FnHeader,
1093     crate all_types: Vec<(Type, TypeKind)>,
1094     crate ret_types: Vec<(Type, TypeKind)>,
1095 }
1096
1097 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1098 crate struct FnDecl {
1099     crate inputs: Arguments,
1100     crate output: FnRetTy,
1101     crate c_variadic: bool,
1102     crate attrs: Attributes,
1103 }
1104
1105 impl FnDecl {
1106     crate fn self_type(&self) -> Option<SelfTy> {
1107         self.inputs.values.get(0).and_then(|v| v.to_self())
1108     }
1109
1110     /// Returns the sugared return type for an async function.
1111     ///
1112     /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
1113     /// will return `i32`.
1114     ///
1115     /// # Panics
1116     ///
1117     /// This function will panic if the return type does not match the expected sugaring for async
1118     /// functions.
1119     crate fn sugared_async_return_type(&self) -> FnRetTy {
1120         match &self.output {
1121             FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
1122                 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
1123                     let bindings = trait_.bindings().unwrap();
1124                     FnRetTy::Return(bindings[0].ty().clone())
1125                 }
1126                 _ => panic!("unexpected desugaring of async function"),
1127             },
1128             _ => panic!("unexpected desugaring of async function"),
1129         }
1130     }
1131 }
1132
1133 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1134 crate struct Arguments {
1135     crate values: Vec<Argument>,
1136 }
1137
1138 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1139 crate struct Argument {
1140     crate type_: Type,
1141     crate name: Symbol,
1142 }
1143
1144 #[derive(Clone, PartialEq, Debug)]
1145 crate enum SelfTy {
1146     SelfValue,
1147     SelfBorrowed(Option<Lifetime>, Mutability),
1148     SelfExplicit(Type),
1149 }
1150
1151 impl Argument {
1152     crate fn to_self(&self) -> Option<SelfTy> {
1153         if self.name != kw::SelfLower {
1154             return None;
1155         }
1156         if self.type_.is_self_type() {
1157             return Some(SelfValue);
1158         }
1159         match self.type_ {
1160             BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
1161                 Some(SelfBorrowed(lifetime.clone(), mutability))
1162             }
1163             _ => Some(SelfExplicit(self.type_.clone())),
1164         }
1165     }
1166 }
1167
1168 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1169 crate enum FnRetTy {
1170     Return(Type),
1171     DefaultReturn,
1172 }
1173
1174 impl GetDefId for FnRetTy {
1175     fn def_id(&self) -> Option<DefId> {
1176         match *self {
1177             Return(ref ty) => ty.def_id(),
1178             DefaultReturn => None,
1179         }
1180     }
1181 }
1182
1183 #[derive(Clone, Debug)]
1184 crate struct Trait {
1185     crate unsafety: hir::Unsafety,
1186     crate items: Vec<Item>,
1187     crate generics: Generics,
1188     crate bounds: Vec<GenericBound>,
1189     crate is_spotlight: bool,
1190     crate is_auto: bool,
1191 }
1192
1193 #[derive(Clone, Debug)]
1194 crate struct TraitAlias {
1195     crate generics: Generics,
1196     crate bounds: Vec<GenericBound>,
1197 }
1198
1199 /// A trait reference, which may have higher ranked lifetimes.
1200 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1201 crate struct PolyTrait {
1202     crate trait_: Type,
1203     crate generic_params: Vec<GenericParamDef>,
1204 }
1205
1206 /// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
1207 /// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
1208 /// importantly, it does not preserve mutability or boxes.
1209 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1210 crate enum Type {
1211     /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
1212     ResolvedPath {
1213         path: Path,
1214         param_names: Option<Vec<GenericBound>>,
1215         did: DefId,
1216         /// `true` if is a `T::Name` path for associated types.
1217         is_generic: bool,
1218     },
1219     /// For parameterized types, so the consumer of the JSON don't go
1220     /// looking for types which don't exist anywhere.
1221     Generic(Symbol),
1222     /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
1223     /// arrays, slices, and tuples.
1224     Primitive(PrimitiveType),
1225     /// `extern "ABI" fn`
1226     BareFunction(Box<BareFunctionDecl>),
1227     Tuple(Vec<Type>),
1228     Slice(Box<Type>),
1229     Array(Box<Type>, String),
1230     Never,
1231     RawPointer(Mutability, Box<Type>),
1232     BorrowedRef {
1233         lifetime: Option<Lifetime>,
1234         mutability: Mutability,
1235         type_: Box<Type>,
1236     },
1237
1238     // `<Type as Trait>::Name`
1239     QPath {
1240         name: Symbol,
1241         self_type: Box<Type>,
1242         trait_: Box<Type>,
1243     },
1244
1245     // `_`
1246     Infer,
1247
1248     // `impl TraitA + TraitB + ...`
1249     ImplTrait(Vec<GenericBound>),
1250 }
1251
1252 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1253 /// N.B. this has to be different from `hir::PrimTy` because it also includes types that aren't
1254 /// paths, like `Unit`.
1255 crate enum PrimitiveType {
1256     Isize,
1257     I8,
1258     I16,
1259     I32,
1260     I64,
1261     I128,
1262     Usize,
1263     U8,
1264     U16,
1265     U32,
1266     U64,
1267     U128,
1268     F32,
1269     F64,
1270     Char,
1271     Bool,
1272     Str,
1273     Slice,
1274     Array,
1275     Tuple,
1276     Unit,
1277     RawPointer,
1278     Reference,
1279     Fn,
1280     Never,
1281 }
1282
1283 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1284 crate enum TypeKind {
1285     Enum,
1286     Function,
1287     Module,
1288     Const,
1289     Static,
1290     Struct,
1291     Union,
1292     Trait,
1293     Typedef,
1294     Foreign,
1295     Macro,
1296     Attr,
1297     Derive,
1298     TraitAlias,
1299 }
1300
1301 crate trait GetDefId {
1302     fn def_id(&self) -> Option<DefId>;
1303 }
1304
1305 impl<T: GetDefId> GetDefId for Option<T> {
1306     fn def_id(&self) -> Option<DefId> {
1307         self.as_ref().and_then(|d| d.def_id())
1308     }
1309 }
1310
1311 impl Type {
1312     crate fn primitive_type(&self) -> Option<PrimitiveType> {
1313         match *self {
1314             Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1315             Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1316             Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1317             Tuple(ref tys) => {
1318                 if tys.is_empty() {
1319                     Some(PrimitiveType::Unit)
1320                 } else {
1321                     Some(PrimitiveType::Tuple)
1322                 }
1323             }
1324             RawPointer(..) => Some(PrimitiveType::RawPointer),
1325             BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
1326             BareFunction(..) => Some(PrimitiveType::Fn),
1327             Never => Some(PrimitiveType::Never),
1328             _ => None,
1329         }
1330     }
1331
1332     crate fn is_generic(&self) -> bool {
1333         match *self {
1334             ResolvedPath { is_generic, .. } => is_generic,
1335             _ => false,
1336         }
1337     }
1338
1339     crate fn is_self_type(&self) -> bool {
1340         match *self {
1341             Generic(name) => name == kw::SelfUpper,
1342             _ => false,
1343         }
1344     }
1345
1346     crate fn generics(&self) -> Option<Vec<Type>> {
1347         match *self {
1348             ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1349                 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
1350                     Some(
1351                         args.iter()
1352                             .filter_map(|arg| match arg {
1353                                 GenericArg::Type(ty) => Some(ty.clone()),
1354                                 _ => None,
1355                             })
1356                             .collect(),
1357                     )
1358                 } else {
1359                     None
1360                 }
1361             }),
1362             _ => None,
1363         }
1364     }
1365
1366     crate fn bindings(&self) -> Option<&[TypeBinding]> {
1367         match *self {
1368             ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1369                 if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
1370                     Some(&**bindings)
1371                 } else {
1372                     None
1373                 }
1374             }),
1375             _ => None,
1376         }
1377     }
1378
1379     crate fn is_full_generic(&self) -> bool {
1380         matches!(self, Type::Generic(_))
1381     }
1382
1383     crate fn projection(&self) -> Option<(&Type, DefId, Symbol)> {
1384         let (self_, trait_, name) = match self {
1385             QPath { self_type, trait_, name } => (self_type, trait_, name),
1386             _ => return None,
1387         };
1388         let trait_did = match **trait_ {
1389             ResolvedPath { did, .. } => did,
1390             _ => return None,
1391         };
1392         Some((&self_, trait_did, *name))
1393     }
1394 }
1395
1396 impl GetDefId for Type {
1397     fn def_id(&self) -> Option<DefId> {
1398         match *self {
1399             ResolvedPath { did, .. } => Some(did),
1400             Primitive(p) => cache().primitive_locations.get(&p).cloned(),
1401             BorrowedRef { type_: box Generic(..), .. } => {
1402                 Primitive(PrimitiveType::Reference).def_id()
1403             }
1404             BorrowedRef { ref type_, .. } => type_.def_id(),
1405             Tuple(ref tys) => {
1406                 if tys.is_empty() {
1407                     Primitive(PrimitiveType::Unit).def_id()
1408                 } else {
1409                     Primitive(PrimitiveType::Tuple).def_id()
1410                 }
1411             }
1412             BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
1413             Never => Primitive(PrimitiveType::Never).def_id(),
1414             Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
1415             Array(..) => Primitive(PrimitiveType::Array).def_id(),
1416             RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(),
1417             QPath { ref self_type, .. } => self_type.def_id(),
1418             _ => None,
1419         }
1420     }
1421 }
1422
1423 impl PrimitiveType {
1424     crate fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1425         match prim {
1426             hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1427             hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1428             hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1429             hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1430             hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1431             hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1432             hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1433             hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1434             hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1435             hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1436             hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1437             hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1438             hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1439             hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1440             hir::PrimTy::Str => PrimitiveType::Str,
1441             hir::PrimTy::Bool => PrimitiveType::Bool,
1442             hir::PrimTy::Char => PrimitiveType::Char,
1443         }
1444     }
1445
1446     crate fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1447         match s {
1448             sym::isize => Some(PrimitiveType::Isize),
1449             sym::i8 => Some(PrimitiveType::I8),
1450             sym::i16 => Some(PrimitiveType::I16),
1451             sym::i32 => Some(PrimitiveType::I32),
1452             sym::i64 => Some(PrimitiveType::I64),
1453             sym::i128 => Some(PrimitiveType::I128),
1454             sym::usize => Some(PrimitiveType::Usize),
1455             sym::u8 => Some(PrimitiveType::U8),
1456             sym::u16 => Some(PrimitiveType::U16),
1457             sym::u32 => Some(PrimitiveType::U32),
1458             sym::u64 => Some(PrimitiveType::U64),
1459             sym::u128 => Some(PrimitiveType::U128),
1460             sym::bool => Some(PrimitiveType::Bool),
1461             sym::char => Some(PrimitiveType::Char),
1462             sym::str => Some(PrimitiveType::Str),
1463             sym::f32 => Some(PrimitiveType::F32),
1464             sym::f64 => Some(PrimitiveType::F64),
1465             sym::array => Some(PrimitiveType::Array),
1466             sym::slice => Some(PrimitiveType::Slice),
1467             sym::tuple => Some(PrimitiveType::Tuple),
1468             sym::unit => Some(PrimitiveType::Unit),
1469             sym::pointer => Some(PrimitiveType::RawPointer),
1470             sym::reference => Some(PrimitiveType::Reference),
1471             kw::Fn => Some(PrimitiveType::Fn),
1472             sym::never => Some(PrimitiveType::Never),
1473             _ => None,
1474         }
1475     }
1476
1477     crate fn as_str(&self) -> &'static str {
1478         use self::PrimitiveType::*;
1479         match *self {
1480             Isize => "isize",
1481             I8 => "i8",
1482             I16 => "i16",
1483             I32 => "i32",
1484             I64 => "i64",
1485             I128 => "i128",
1486             Usize => "usize",
1487             U8 => "u8",
1488             U16 => "u16",
1489             U32 => "u32",
1490             U64 => "u64",
1491             U128 => "u128",
1492             F32 => "f32",
1493             F64 => "f64",
1494             Str => "str",
1495             Bool => "bool",
1496             Char => "char",
1497             Array => "array",
1498             Slice => "slice",
1499             Tuple => "tuple",
1500             Unit => "unit",
1501             RawPointer => "pointer",
1502             Reference => "reference",
1503             Fn => "fn",
1504             Never => "never",
1505         }
1506     }
1507
1508     crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static SmallVec<[DefId; 4]> {
1509         Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
1510     }
1511
1512     crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>> {
1513         static CELL: OnceCell<FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>>> = OnceCell::new();
1514
1515         CELL.get_or_init(move || {
1516             use self::PrimitiveType::*;
1517
1518             /// A macro to create a FxHashMap.
1519             ///
1520             /// Example:
1521             ///
1522             /// ```
1523             /// let letters = map!{"a" => "b", "c" => "d"};
1524             /// ```
1525             ///
1526             /// Trailing commas are allowed.
1527             /// Commas between elements are required (even if the expression is a block).
1528             macro_rules! map {
1529                 ($( $key: expr => $val: expr ),* $(,)*) => {{
1530                     let mut map = ::rustc_data_structures::fx::FxHashMap::default();
1531                     $( map.insert($key, $val); )*
1532                     map
1533                 }}
1534             }
1535
1536             let single = |a: Option<DefId>| a.into_iter().collect();
1537             let both = |a: Option<DefId>, b: Option<DefId>| -> SmallVec<_> {
1538                 a.into_iter().chain(b).collect()
1539             };
1540
1541             let lang_items = tcx.lang_items();
1542             map! {
1543                 Isize => single(lang_items.isize_impl()),
1544                 I8 => single(lang_items.i8_impl()),
1545                 I16 => single(lang_items.i16_impl()),
1546                 I32 => single(lang_items.i32_impl()),
1547                 I64 => single(lang_items.i64_impl()),
1548                 I128 => single(lang_items.i128_impl()),
1549                 Usize => single(lang_items.usize_impl()),
1550                 U8 => single(lang_items.u8_impl()),
1551                 U16 => single(lang_items.u16_impl()),
1552                 U32 => single(lang_items.u32_impl()),
1553                 U64 => single(lang_items.u64_impl()),
1554                 U128 => single(lang_items.u128_impl()),
1555                 F32 => both(lang_items.f32_impl(), lang_items.f32_runtime_impl()),
1556                 F64 => both(lang_items.f64_impl(), lang_items.f64_runtime_impl()),
1557                 Char => single(lang_items.char_impl()),
1558                 Bool => single(lang_items.bool_impl()),
1559                 Str => both(lang_items.str_impl(), lang_items.str_alloc_impl()),
1560                 Slice => {
1561                     lang_items
1562                         .slice_impl()
1563                         .into_iter()
1564                         .chain(lang_items.slice_u8_impl())
1565                         .chain(lang_items.slice_alloc_impl())
1566                         .chain(lang_items.slice_u8_alloc_impl())
1567                         .collect()
1568                 },
1569                 Array => single(lang_items.array_impl()),
1570                 Tuple => smallvec![],
1571                 Unit => smallvec![],
1572                 RawPointer => {
1573                     lang_items
1574                         .const_ptr_impl()
1575                         .into_iter()
1576                         .chain(lang_items.mut_ptr_impl())
1577                         .chain(lang_items.const_slice_ptr_impl())
1578                         .chain(lang_items.mut_slice_ptr_impl())
1579                         .collect()
1580                 },
1581                 Reference => smallvec![],
1582                 Fn => smallvec![],
1583                 Never => smallvec![],
1584             }
1585         })
1586     }
1587
1588     crate fn to_url_str(&self) -> &'static str {
1589         self.as_str()
1590     }
1591
1592     crate fn as_sym(&self) -> Symbol {
1593         use PrimitiveType::*;
1594         match self {
1595             Isize => sym::isize,
1596             I8 => sym::i8,
1597             I16 => sym::i16,
1598             I32 => sym::i32,
1599             I64 => sym::i64,
1600             I128 => sym::i128,
1601             Usize => sym::usize,
1602             U8 => sym::u8,
1603             U16 => sym::u16,
1604             U32 => sym::u32,
1605             U64 => sym::u64,
1606             U128 => sym::u128,
1607             F32 => sym::f32,
1608             F64 => sym::f64,
1609             Str => sym::str,
1610             Bool => sym::bool,
1611             Char => sym::char,
1612             Array => sym::array,
1613             Slice => sym::slice,
1614             Tuple => sym::tuple,
1615             Unit => sym::unit,
1616             RawPointer => sym::pointer,
1617             Reference => sym::reference,
1618             Fn => kw::Fn,
1619             Never => sym::never,
1620         }
1621     }
1622 }
1623
1624 impl From<ast::IntTy> for PrimitiveType {
1625     fn from(int_ty: ast::IntTy) -> PrimitiveType {
1626         match int_ty {
1627             ast::IntTy::Isize => PrimitiveType::Isize,
1628             ast::IntTy::I8 => PrimitiveType::I8,
1629             ast::IntTy::I16 => PrimitiveType::I16,
1630             ast::IntTy::I32 => PrimitiveType::I32,
1631             ast::IntTy::I64 => PrimitiveType::I64,
1632             ast::IntTy::I128 => PrimitiveType::I128,
1633         }
1634     }
1635 }
1636
1637 impl From<ast::UintTy> for PrimitiveType {
1638     fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1639         match uint_ty {
1640             ast::UintTy::Usize => PrimitiveType::Usize,
1641             ast::UintTy::U8 => PrimitiveType::U8,
1642             ast::UintTy::U16 => PrimitiveType::U16,
1643             ast::UintTy::U32 => PrimitiveType::U32,
1644             ast::UintTy::U64 => PrimitiveType::U64,
1645             ast::UintTy::U128 => PrimitiveType::U128,
1646         }
1647     }
1648 }
1649
1650 impl From<ast::FloatTy> for PrimitiveType {
1651     fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1652         match float_ty {
1653             ast::FloatTy::F32 => PrimitiveType::F32,
1654             ast::FloatTy::F64 => PrimitiveType::F64,
1655         }
1656     }
1657 }
1658
1659 impl From<hir::PrimTy> for PrimitiveType {
1660     fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1661         match prim_ty {
1662             hir::PrimTy::Int(int_ty) => int_ty.into(),
1663             hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1664             hir::PrimTy::Float(float_ty) => float_ty.into(),
1665             hir::PrimTy::Str => PrimitiveType::Str,
1666             hir::PrimTy::Bool => PrimitiveType::Bool,
1667             hir::PrimTy::Char => PrimitiveType::Char,
1668         }
1669     }
1670 }
1671
1672 #[derive(Copy, Clone, Debug)]
1673 crate enum Visibility {
1674     Public,
1675     Inherited,
1676     Restricted(DefId),
1677 }
1678
1679 impl Visibility {
1680     crate fn is_public(&self) -> bool {
1681         matches!(self, Visibility::Public)
1682     }
1683 }
1684
1685 #[derive(Clone, Debug)]
1686 crate struct Struct {
1687     crate struct_type: doctree::StructType,
1688     crate generics: Generics,
1689     crate fields: Vec<Item>,
1690     crate fields_stripped: bool,
1691 }
1692
1693 #[derive(Clone, Debug)]
1694 crate struct Union {
1695     crate struct_type: doctree::StructType,
1696     crate generics: Generics,
1697     crate fields: Vec<Item>,
1698     crate fields_stripped: bool,
1699 }
1700
1701 /// This is a more limited form of the standard Struct, different in that
1702 /// it lacks the things most items have (name, id, parameterization). Found
1703 /// only as a variant in an enum.
1704 #[derive(Clone, Debug)]
1705 crate struct VariantStruct {
1706     crate struct_type: doctree::StructType,
1707     crate fields: Vec<Item>,
1708     crate fields_stripped: bool,
1709 }
1710
1711 #[derive(Clone, Debug)]
1712 crate struct Enum {
1713     crate variants: IndexVec<VariantIdx, Item>,
1714     crate generics: Generics,
1715     crate variants_stripped: bool,
1716 }
1717
1718 #[derive(Clone, Debug)]
1719 crate struct Variant {
1720     crate kind: VariantKind,
1721 }
1722
1723 #[derive(Clone, Debug)]
1724 crate enum VariantKind {
1725     CLike,
1726     Tuple(Vec<Type>),
1727     Struct(VariantStruct),
1728 }
1729
1730 /// Small wrapper around `rustc_span::Span` that adds helper methods and enforces calling `source_callsite`.
1731 #[derive(Clone, Debug)]
1732 crate struct Span(rustc_span::Span);
1733
1734 impl Span {
1735     crate fn from_rustc_span(sp: rustc_span::Span) -> Self {
1736         // Get the macro invocation instead of the definition,
1737         // in case the span is result of a macro expansion.
1738         // (See rust-lang/rust#39726)
1739         Self(sp.source_callsite())
1740     }
1741
1742     crate fn dummy() -> Self {
1743         Self(rustc_span::DUMMY_SP)
1744     }
1745
1746     crate fn span(&self) -> rustc_span::Span {
1747         self.0
1748     }
1749
1750     crate fn filename(&self, sess: &Session) -> FileName {
1751         sess.source_map().span_to_filename(self.0)
1752     }
1753
1754     crate fn lo(&self, sess: &Session) -> Loc {
1755         sess.source_map().lookup_char_pos(self.0.lo())
1756     }
1757
1758     crate fn hi(&self, sess: &Session) -> Loc {
1759         sess.source_map().lookup_char_pos(self.0.hi())
1760     }
1761
1762     crate fn cnum(&self, sess: &Session) -> CrateNum {
1763         // FIXME: is there a time when the lo and hi crate would be different?
1764         self.lo(sess).file.cnum
1765     }
1766 }
1767
1768 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1769 crate struct Path {
1770     crate global: bool,
1771     crate res: Res,
1772     crate segments: Vec<PathSegment>,
1773 }
1774
1775 impl Path {
1776     crate fn last(&self) -> Symbol {
1777         self.segments.last().expect("segments were empty").name
1778     }
1779
1780     crate fn last_name(&self) -> SymbolStr {
1781         self.segments.last().expect("segments were empty").name.as_str()
1782     }
1783
1784     crate fn whole_name(&self) -> String {
1785         String::from(if self.global { "::" } else { "" })
1786             + &self.segments.iter().map(|s| s.name.to_string()).collect::<Vec<_>>().join("::")
1787     }
1788 }
1789
1790 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1791 crate enum GenericArg {
1792     Lifetime(Lifetime),
1793     Type(Type),
1794     Const(Constant),
1795 }
1796
1797 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1798 crate enum GenericArgs {
1799     AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
1800     Parenthesized { inputs: Vec<Type>, output: Option<Type> },
1801 }
1802
1803 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1804 crate struct PathSegment {
1805     crate name: Symbol,
1806     crate args: GenericArgs,
1807 }
1808
1809 #[derive(Clone, Debug)]
1810 crate struct Typedef {
1811     crate type_: Type,
1812     crate generics: Generics,
1813     /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
1814     /// alias instead of the final type. This will always have the final type, regardless of whether
1815     /// `type_` came from HIR or from metadata.
1816     ///
1817     /// If `item_type.is_none()`, `type_` is guarenteed to come from metadata (and therefore hold the
1818     /// final type).
1819     crate item_type: Option<Type>,
1820 }
1821
1822 impl GetDefId for Typedef {
1823     fn def_id(&self) -> Option<DefId> {
1824         self.type_.def_id()
1825     }
1826 }
1827
1828 #[derive(Clone, Debug)]
1829 crate struct OpaqueTy {
1830     crate bounds: Vec<GenericBound>,
1831     crate generics: Generics,
1832 }
1833
1834 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1835 crate struct BareFunctionDecl {
1836     crate unsafety: hir::Unsafety,
1837     crate generic_params: Vec<GenericParamDef>,
1838     crate decl: FnDecl,
1839     crate abi: Abi,
1840 }
1841
1842 #[derive(Clone, Debug)]
1843 crate struct Static {
1844     crate type_: Type,
1845     crate mutability: Mutability,
1846     /// It's useful to have the value of a static documented, but I have no
1847     /// desire to represent expressions (that'd basically be all of the AST,
1848     /// which is huge!). So, have a string.
1849     crate expr: String,
1850 }
1851
1852 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
1853 crate struct Constant {
1854     crate type_: Type,
1855     crate expr: String,
1856     crate value: Option<String>,
1857     crate is_literal: bool,
1858 }
1859
1860 #[derive(Clone, PartialEq, Debug)]
1861 crate enum ImplPolarity {
1862     Positive,
1863     Negative,
1864 }
1865
1866 #[derive(Clone, Debug)]
1867 crate struct Impl {
1868     crate unsafety: hir::Unsafety,
1869     crate generics: Generics,
1870     crate provided_trait_methods: FxHashSet<Symbol>,
1871     crate trait_: Option<Type>,
1872     crate for_: Type,
1873     crate items: Vec<Item>,
1874     crate polarity: Option<ImplPolarity>,
1875     crate synthetic: bool,
1876     crate blanket_impl: Option<Type>,
1877 }
1878
1879 #[derive(Clone, Debug)]
1880 crate struct Import {
1881     crate kind: ImportKind,
1882     crate source: ImportSource,
1883     crate should_be_displayed: bool,
1884 }
1885
1886 impl Import {
1887     crate fn new_simple(name: Symbol, source: ImportSource, should_be_displayed: bool) -> Self {
1888         Self { kind: ImportKind::Simple(name), source, should_be_displayed }
1889     }
1890
1891     crate fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
1892         Self { kind: ImportKind::Glob, source, should_be_displayed }
1893     }
1894 }
1895
1896 #[derive(Clone, Debug)]
1897 crate enum ImportKind {
1898     // use source as str;
1899     Simple(Symbol),
1900     // use source::*;
1901     Glob,
1902 }
1903
1904 #[derive(Clone, Debug)]
1905 crate struct ImportSource {
1906     crate path: Path,
1907     crate did: Option<DefId>,
1908 }
1909
1910 #[derive(Clone, Debug)]
1911 crate struct Macro {
1912     crate source: String,
1913     crate imported_from: Option<Symbol>,
1914 }
1915
1916 #[derive(Clone, Debug)]
1917 crate struct ProcMacro {
1918     crate kind: MacroKind,
1919     crate helpers: Vec<Symbol>,
1920 }
1921
1922 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
1923 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
1924 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1925 crate struct TypeBinding {
1926     crate name: Symbol,
1927     crate kind: TypeBindingKind,
1928 }
1929
1930 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1931 crate enum TypeBindingKind {
1932     Equality { ty: Type },
1933     Constraint { bounds: Vec<GenericBound> },
1934 }
1935
1936 impl TypeBinding {
1937     crate fn ty(&self) -> &Type {
1938         match self.kind {
1939             TypeBindingKind::Equality { ref ty } => ty,
1940             _ => panic!("expected equality type binding for parenthesized generic args"),
1941         }
1942     }
1943 }