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