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