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