]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/clean/types.rs
Fix clean/types doc links
[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             // FIXME: remove this wildcard
1441             _ => return None,
1442         };
1443         cache.and_then(|c| Primitive(t).def_id_full(c))
1444     }
1445 }
1446
1447 impl GetDefId for Type {
1448     fn def_id(&self) -> Option<DefId> {
1449         self.inner_def_id(None)
1450     }
1451
1452     fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
1453         self.inner_def_id(Some(cache))
1454     }
1455 }
1456
1457 impl PrimitiveType {
1458     crate fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1459         match prim {
1460             hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1461             hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1462             hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1463             hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1464             hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1465             hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1466             hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1467             hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1468             hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1469             hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1470             hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1471             hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1472             hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1473             hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1474             hir::PrimTy::Str => PrimitiveType::Str,
1475             hir::PrimTy::Bool => PrimitiveType::Bool,
1476             hir::PrimTy::Char => PrimitiveType::Char,
1477         }
1478     }
1479
1480     crate fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
1481         match s {
1482             sym::isize => Some(PrimitiveType::Isize),
1483             sym::i8 => Some(PrimitiveType::I8),
1484             sym::i16 => Some(PrimitiveType::I16),
1485             sym::i32 => Some(PrimitiveType::I32),
1486             sym::i64 => Some(PrimitiveType::I64),
1487             sym::i128 => Some(PrimitiveType::I128),
1488             sym::usize => Some(PrimitiveType::Usize),
1489             sym::u8 => Some(PrimitiveType::U8),
1490             sym::u16 => Some(PrimitiveType::U16),
1491             sym::u32 => Some(PrimitiveType::U32),
1492             sym::u64 => Some(PrimitiveType::U64),
1493             sym::u128 => Some(PrimitiveType::U128),
1494             sym::bool => Some(PrimitiveType::Bool),
1495             sym::char => Some(PrimitiveType::Char),
1496             sym::str => Some(PrimitiveType::Str),
1497             sym::f32 => Some(PrimitiveType::F32),
1498             sym::f64 => Some(PrimitiveType::F64),
1499             sym::array => Some(PrimitiveType::Array),
1500             sym::slice => Some(PrimitiveType::Slice),
1501             sym::tuple => Some(PrimitiveType::Tuple),
1502             sym::unit => Some(PrimitiveType::Unit),
1503             sym::pointer => Some(PrimitiveType::RawPointer),
1504             sym::reference => Some(PrimitiveType::Reference),
1505             kw::Fn => Some(PrimitiveType::Fn),
1506             sym::never => Some(PrimitiveType::Never),
1507             _ => None,
1508         }
1509     }
1510
1511     crate fn as_str(&self) -> &'static str {
1512         use self::PrimitiveType::*;
1513         match *self {
1514             Isize => "isize",
1515             I8 => "i8",
1516             I16 => "i16",
1517             I32 => "i32",
1518             I64 => "i64",
1519             I128 => "i128",
1520             Usize => "usize",
1521             U8 => "u8",
1522             U16 => "u16",
1523             U32 => "u32",
1524             U64 => "u64",
1525             U128 => "u128",
1526             F32 => "f32",
1527             F64 => "f64",
1528             Str => "str",
1529             Bool => "bool",
1530             Char => "char",
1531             Array => "array",
1532             Slice => "slice",
1533             Tuple => "tuple",
1534             Unit => "unit",
1535             RawPointer => "pointer",
1536             Reference => "reference",
1537             Fn => "fn",
1538             Never => "never",
1539         }
1540     }
1541
1542     crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static SmallVec<[DefId; 4]> {
1543         Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
1544     }
1545
1546     crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>> {
1547         static CELL: OnceCell<FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>>> = OnceCell::new();
1548
1549         CELL.get_or_init(move || {
1550             use self::PrimitiveType::*;
1551
1552             /// A macro to create a FxHashMap.
1553             ///
1554             /// Example:
1555             ///
1556             /// ```
1557             /// let letters = map!{"a" => "b", "c" => "d"};
1558             /// ```
1559             ///
1560             /// Trailing commas are allowed.
1561             /// Commas between elements are required (even if the expression is a block).
1562             macro_rules! map {
1563                 ($( $key: expr => $val: expr ),* $(,)*) => {{
1564                     let mut map = ::rustc_data_structures::fx::FxHashMap::default();
1565                     $( map.insert($key, $val); )*
1566                     map
1567                 }}
1568             }
1569
1570             let single = |a: Option<DefId>| a.into_iter().collect();
1571             let both = |a: Option<DefId>, b: Option<DefId>| -> SmallVec<_> {
1572                 a.into_iter().chain(b).collect()
1573             };
1574
1575             let lang_items = tcx.lang_items();
1576             map! {
1577                 Isize => single(lang_items.isize_impl()),
1578                 I8 => single(lang_items.i8_impl()),
1579                 I16 => single(lang_items.i16_impl()),
1580                 I32 => single(lang_items.i32_impl()),
1581                 I64 => single(lang_items.i64_impl()),
1582                 I128 => single(lang_items.i128_impl()),
1583                 Usize => single(lang_items.usize_impl()),
1584                 U8 => single(lang_items.u8_impl()),
1585                 U16 => single(lang_items.u16_impl()),
1586                 U32 => single(lang_items.u32_impl()),
1587                 U64 => single(lang_items.u64_impl()),
1588                 U128 => single(lang_items.u128_impl()),
1589                 F32 => both(lang_items.f32_impl(), lang_items.f32_runtime_impl()),
1590                 F64 => both(lang_items.f64_impl(), lang_items.f64_runtime_impl()),
1591                 Char => single(lang_items.char_impl()),
1592                 Bool => single(lang_items.bool_impl()),
1593                 Str => both(lang_items.str_impl(), lang_items.str_alloc_impl()),
1594                 Slice => {
1595                     lang_items
1596                         .slice_impl()
1597                         .into_iter()
1598                         .chain(lang_items.slice_u8_impl())
1599                         .chain(lang_items.slice_alloc_impl())
1600                         .chain(lang_items.slice_u8_alloc_impl())
1601                         .collect()
1602                 },
1603                 Array => single(lang_items.array_impl()),
1604                 Tuple => smallvec![],
1605                 Unit => smallvec![],
1606                 RawPointer => {
1607                     lang_items
1608                         .const_ptr_impl()
1609                         .into_iter()
1610                         .chain(lang_items.mut_ptr_impl())
1611                         .chain(lang_items.const_slice_ptr_impl())
1612                         .chain(lang_items.mut_slice_ptr_impl())
1613                         .collect()
1614                 },
1615                 Reference => smallvec![],
1616                 Fn => smallvec![],
1617                 Never => smallvec![],
1618             }
1619         })
1620     }
1621
1622     crate fn to_url_str(&self) -> &'static str {
1623         self.as_str()
1624     }
1625
1626     crate fn as_sym(&self) -> Symbol {
1627         use PrimitiveType::*;
1628         match self {
1629             Isize => sym::isize,
1630             I8 => sym::i8,
1631             I16 => sym::i16,
1632             I32 => sym::i32,
1633             I64 => sym::i64,
1634             I128 => sym::i128,
1635             Usize => sym::usize,
1636             U8 => sym::u8,
1637             U16 => sym::u16,
1638             U32 => sym::u32,
1639             U64 => sym::u64,
1640             U128 => sym::u128,
1641             F32 => sym::f32,
1642             F64 => sym::f64,
1643             Str => sym::str,
1644             Bool => sym::bool,
1645             Char => sym::char,
1646             Array => sym::array,
1647             Slice => sym::slice,
1648             Tuple => sym::tuple,
1649             Unit => sym::unit,
1650             RawPointer => sym::pointer,
1651             Reference => sym::reference,
1652             Fn => kw::Fn,
1653             Never => sym::never,
1654         }
1655     }
1656 }
1657
1658 impl From<ast::IntTy> for PrimitiveType {
1659     fn from(int_ty: ast::IntTy) -> PrimitiveType {
1660         match int_ty {
1661             ast::IntTy::Isize => PrimitiveType::Isize,
1662             ast::IntTy::I8 => PrimitiveType::I8,
1663             ast::IntTy::I16 => PrimitiveType::I16,
1664             ast::IntTy::I32 => PrimitiveType::I32,
1665             ast::IntTy::I64 => PrimitiveType::I64,
1666             ast::IntTy::I128 => PrimitiveType::I128,
1667         }
1668     }
1669 }
1670
1671 impl From<ast::UintTy> for PrimitiveType {
1672     fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1673         match uint_ty {
1674             ast::UintTy::Usize => PrimitiveType::Usize,
1675             ast::UintTy::U8 => PrimitiveType::U8,
1676             ast::UintTy::U16 => PrimitiveType::U16,
1677             ast::UintTy::U32 => PrimitiveType::U32,
1678             ast::UintTy::U64 => PrimitiveType::U64,
1679             ast::UintTy::U128 => PrimitiveType::U128,
1680         }
1681     }
1682 }
1683
1684 impl From<ast::FloatTy> for PrimitiveType {
1685     fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1686         match float_ty {
1687             ast::FloatTy::F32 => PrimitiveType::F32,
1688             ast::FloatTy::F64 => PrimitiveType::F64,
1689         }
1690     }
1691 }
1692
1693 impl From<hir::PrimTy> for PrimitiveType {
1694     fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
1695         match prim_ty {
1696             hir::PrimTy::Int(int_ty) => int_ty.into(),
1697             hir::PrimTy::Uint(uint_ty) => uint_ty.into(),
1698             hir::PrimTy::Float(float_ty) => float_ty.into(),
1699             hir::PrimTy::Str => PrimitiveType::Str,
1700             hir::PrimTy::Bool => PrimitiveType::Bool,
1701             hir::PrimTy::Char => PrimitiveType::Char,
1702         }
1703     }
1704 }
1705
1706 #[derive(Copy, Clone, Debug)]
1707 crate enum Visibility {
1708     Public,
1709     Inherited,
1710     Restricted(DefId),
1711 }
1712
1713 impl Visibility {
1714     crate fn is_public(&self) -> bool {
1715         matches!(self, Visibility::Public)
1716     }
1717 }
1718
1719 #[derive(Clone, Debug)]
1720 crate struct Struct {
1721     crate struct_type: CtorKind,
1722     crate generics: Generics,
1723     crate fields: Vec<Item>,
1724     crate fields_stripped: bool,
1725 }
1726
1727 #[derive(Clone, Debug)]
1728 crate struct Union {
1729     crate generics: Generics,
1730     crate fields: Vec<Item>,
1731     crate fields_stripped: bool,
1732 }
1733
1734 /// This is a more limited form of the standard Struct, different in that
1735 /// it lacks the things most items have (name, id, parameterization). Found
1736 /// only as a variant in an enum.
1737 #[derive(Clone, Debug)]
1738 crate struct VariantStruct {
1739     crate struct_type: CtorKind,
1740     crate fields: Vec<Item>,
1741     crate fields_stripped: bool,
1742 }
1743
1744 #[derive(Clone, Debug)]
1745 crate struct Enum {
1746     crate variants: IndexVec<VariantIdx, Item>,
1747     crate generics: Generics,
1748     crate variants_stripped: bool,
1749 }
1750
1751 #[derive(Clone, Debug)]
1752 crate enum Variant {
1753     CLike,
1754     Tuple(Vec<Type>),
1755     Struct(VariantStruct),
1756 }
1757
1758 /// Small wrapper around `rustc_span::Span` that adds helper methods and enforces calling `source_callsite`.
1759 #[derive(Clone, Debug)]
1760 crate struct Span(rustc_span::Span);
1761
1762 impl Span {
1763     crate fn from_rustc_span(sp: rustc_span::Span) -> Self {
1764         // Get the macro invocation instead of the definition,
1765         // in case the span is result of a macro expansion.
1766         // (See rust-lang/rust#39726)
1767         Self(sp.source_callsite())
1768     }
1769
1770     crate fn dummy() -> Self {
1771         Self(rustc_span::DUMMY_SP)
1772     }
1773
1774     crate fn span(&self) -> rustc_span::Span {
1775         self.0
1776     }
1777
1778     crate fn filename(&self, sess: &Session) -> FileName {
1779         sess.source_map().span_to_filename(self.0)
1780     }
1781
1782     crate fn lo(&self, sess: &Session) -> Loc {
1783         sess.source_map().lookup_char_pos(self.0.lo())
1784     }
1785
1786     crate fn hi(&self, sess: &Session) -> Loc {
1787         sess.source_map().lookup_char_pos(self.0.hi())
1788     }
1789
1790     crate fn cnum(&self, sess: &Session) -> CrateNum {
1791         // FIXME: is there a time when the lo and hi crate would be different?
1792         self.lo(sess).file.cnum
1793     }
1794 }
1795
1796 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1797 crate struct Path {
1798     crate global: bool,
1799     crate res: Res,
1800     crate segments: Vec<PathSegment>,
1801 }
1802
1803 impl Path {
1804     crate fn last(&self) -> Symbol {
1805         self.segments.last().expect("segments were empty").name
1806     }
1807
1808     crate fn last_name(&self) -> SymbolStr {
1809         self.segments.last().expect("segments were empty").name.as_str()
1810     }
1811
1812     crate fn whole_name(&self) -> String {
1813         String::from(if self.global { "::" } else { "" })
1814             + &self.segments.iter().map(|s| s.name.to_string()).collect::<Vec<_>>().join("::")
1815     }
1816 }
1817
1818 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1819 crate enum GenericArg {
1820     Lifetime(Lifetime),
1821     Type(Type),
1822     Const(Constant),
1823 }
1824
1825 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1826 crate enum GenericArgs {
1827     AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
1828     Parenthesized { inputs: Vec<Type>, output: Option<Type> },
1829 }
1830
1831 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1832 crate struct PathSegment {
1833     crate name: Symbol,
1834     crate args: GenericArgs,
1835 }
1836
1837 #[derive(Clone, Debug)]
1838 crate struct Typedef {
1839     crate type_: Type,
1840     crate generics: Generics,
1841     /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
1842     /// alias instead of the final type. This will always have the final type, regardless of whether
1843     /// `type_` came from HIR or from metadata.
1844     ///
1845     /// If `item_type.is_none()`, `type_` is guarenteed to come from metadata (and therefore hold the
1846     /// final type).
1847     crate item_type: Option<Type>,
1848 }
1849
1850 impl GetDefId for Typedef {
1851     fn def_id(&self) -> Option<DefId> {
1852         self.type_.def_id()
1853     }
1854
1855     fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
1856         self.type_.def_id_full(cache)
1857     }
1858 }
1859
1860 #[derive(Clone, Debug)]
1861 crate struct OpaqueTy {
1862     crate bounds: Vec<GenericBound>,
1863     crate generics: Generics,
1864 }
1865
1866 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1867 crate struct BareFunctionDecl {
1868     crate unsafety: hir::Unsafety,
1869     crate generic_params: Vec<GenericParamDef>,
1870     crate decl: FnDecl,
1871     crate abi: Abi,
1872 }
1873
1874 #[derive(Clone, Debug)]
1875 crate struct Static {
1876     crate type_: Type,
1877     crate mutability: Mutability,
1878     /// It's useful to have the value of a static documented, but I have no
1879     /// desire to represent expressions (that'd basically be all of the AST,
1880     /// which is huge!). So, have a string.
1881     crate expr: String,
1882 }
1883
1884 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
1885 crate struct Constant {
1886     crate type_: Type,
1887     crate expr: String,
1888     crate value: Option<String>,
1889     crate is_literal: bool,
1890 }
1891
1892 #[derive(Clone, Debug)]
1893 crate struct Impl {
1894     crate unsafety: hir::Unsafety,
1895     crate generics: Generics,
1896     crate provided_trait_methods: FxHashSet<Symbol>,
1897     crate trait_: Option<Type>,
1898     crate for_: Type,
1899     crate items: Vec<Item>,
1900     crate negative_polarity: bool,
1901     crate synthetic: bool,
1902     crate blanket_impl: Option<Type>,
1903 }
1904
1905 #[derive(Clone, Debug)]
1906 crate struct Import {
1907     crate kind: ImportKind,
1908     crate source: ImportSource,
1909     crate should_be_displayed: bool,
1910 }
1911
1912 impl Import {
1913     crate fn new_simple(name: Symbol, source: ImportSource, should_be_displayed: bool) -> Self {
1914         Self { kind: ImportKind::Simple(name), source, should_be_displayed }
1915     }
1916
1917     crate fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
1918         Self { kind: ImportKind::Glob, source, should_be_displayed }
1919     }
1920 }
1921
1922 #[derive(Clone, Debug)]
1923 crate enum ImportKind {
1924     // use source as str;
1925     Simple(Symbol),
1926     // use source::*;
1927     Glob,
1928 }
1929
1930 #[derive(Clone, Debug)]
1931 crate struct ImportSource {
1932     crate path: Path,
1933     crate did: Option<DefId>,
1934 }
1935
1936 #[derive(Clone, Debug)]
1937 crate struct Macro {
1938     crate source: String,
1939     crate imported_from: Option<Symbol>,
1940 }
1941
1942 #[derive(Clone, Debug)]
1943 crate struct ProcMacro {
1944     crate kind: MacroKind,
1945     crate helpers: Vec<Symbol>,
1946 }
1947
1948 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
1949 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
1950 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1951 crate struct TypeBinding {
1952     crate name: Symbol,
1953     crate kind: TypeBindingKind,
1954 }
1955
1956 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1957 crate enum TypeBindingKind {
1958     Equality { ty: Type },
1959     Constraint { bounds: Vec<GenericBound> },
1960 }
1961
1962 impl TypeBinding {
1963     crate fn ty(&self) -> &Type {
1964         match self.kind {
1965             TypeBindingKind::Equality { ref ty } => ty,
1966             _ => panic!("expected equality type binding for parenthesized generic args"),
1967         }
1968     }
1969 }