]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/clean/types.rs
Rollup merge of #68462 - matthiaskrgr:novec, r=varkor
[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_data_structures::fx::{FxHashMap, FxHashSet};
15 use rustc_hir as hir;
16 use rustc_hir::def::Res;
17 use rustc_hir::def_id::{CrateNum, DefId};
18 use rustc_hir::Mutability;
19 use rustc_index::vec::IndexVec;
20 use rustc_span::hygiene::MacroKind;
21 use rustc_span::source_map::DUMMY_SP;
22 use rustc_span::symbol::{sym, Symbol};
23 use rustc_span::{self, FileName};
24 use rustc_target::spec::abi::Abi;
25 use syntax::ast::{self, AttrStyle, Ident};
26 use syntax::attr;
27 use syntax::util::comments::strip_doc_comment_decoration;
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::FunctionRetTy::*;
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.len() != 0 { 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 syntax::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             .filter(|a| a.doc_str().is_some())
569             .next()
570             .map_or(true, |a| a.style == AttrStyle::Inner);
571
572         Attributes {
573             doc_strings,
574             other_attrs,
575             cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) },
576             span: sp,
577             links: vec![],
578             inner_docs,
579         }
580     }
581
582     /// Finds the `doc` attribute as a NameValue and returns the corresponding
583     /// value found.
584     pub fn doc_value(&self) -> Option<&str> {
585         self.doc_strings.first().map(|s| s.as_str())
586     }
587
588     /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
589     /// with newlines.
590     pub fn collapsed_doc_value(&self) -> Option<String> {
591         if !self.doc_strings.is_empty() { Some(self.doc_strings.iter().collect()) } else { None }
592     }
593
594     /// Gets links as a vector
595     ///
596     /// Cache must be populated before call
597     pub fn links(&self, krate: &CrateNum) -> Vec<(String, String)> {
598         use crate::html::format::href;
599
600         self.links
601             .iter()
602             .filter_map(|&(ref s, did, ref fragment)| {
603                 match did {
604                     Some(did) => {
605                         if let Some((mut href, ..)) = href(did) {
606                             if let Some(ref fragment) = *fragment {
607                                 href.push_str("#");
608                                 href.push_str(fragment);
609                             }
610                             Some((s.clone(), href))
611                         } else {
612                             None
613                         }
614                     }
615                     None => {
616                         if let Some(ref fragment) = *fragment {
617                             let cache = cache();
618                             let url = match cache.extern_locations.get(krate) {
619                                 Some(&(_, ref src, ExternalLocation::Local)) => {
620                                     src.to_str().expect("invalid file path")
621                                 }
622                                 Some(&(_, _, ExternalLocation::Remote(ref s))) => s,
623                                 Some(&(_, _, ExternalLocation::Unknown)) | None => {
624                                     "https://doc.rust-lang.org/nightly"
625                                 }
626                             };
627                             // This is a primitive so the url is done "by hand".
628                             let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
629                             Some((
630                                 s.clone(),
631                                 format!(
632                                     "{}{}std/primitive.{}.html{}",
633                                     url,
634                                     if !url.ends_with('/') { "/" } else { "" },
635                                     &fragment[..tail],
636                                     &fragment[tail..]
637                                 ),
638                             ))
639                         } else {
640                             panic!("This isn't a primitive?!");
641                         }
642                     }
643                 }
644             })
645             .collect()
646     }
647 }
648
649 impl PartialEq for Attributes {
650     fn eq(&self, rhs: &Self) -> bool {
651         self.doc_strings == rhs.doc_strings
652             && self.cfg == rhs.cfg
653             && self.span == rhs.span
654             && self.links == rhs.links
655             && self
656                 .other_attrs
657                 .iter()
658                 .map(|attr| attr.id)
659                 .eq(rhs.other_attrs.iter().map(|attr| attr.id))
660     }
661 }
662
663 impl Eq for Attributes {}
664
665 impl Hash for Attributes {
666     fn hash<H: Hasher>(&self, hasher: &mut H) {
667         self.doc_strings.hash(hasher);
668         self.cfg.hash(hasher);
669         self.span.hash(hasher);
670         self.links.hash(hasher);
671         for attr in &self.other_attrs {
672             attr.id.hash(hasher);
673         }
674     }
675 }
676
677 impl AttributesExt for Attributes {
678     fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
679         self.other_attrs.lists(name)
680     }
681 }
682
683 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
684 pub enum GenericBound {
685     TraitBound(PolyTrait, hir::TraitBoundModifier),
686     Outlives(Lifetime),
687 }
688
689 impl GenericBound {
690     pub fn maybe_sized(cx: &DocContext<'_>) -> GenericBound {
691         let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None);
692         let empty = cx.tcx.intern_substs(&[]);
693         let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
694         inline::record_extern_fqn(cx, did, TypeKind::Trait);
695         GenericBound::TraitBound(
696             PolyTrait {
697                 trait_: ResolvedPath { path, param_names: None, did, is_generic: false },
698                 generic_params: Vec::new(),
699             },
700             hir::TraitBoundModifier::Maybe,
701         )
702     }
703
704     pub fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
705         use rustc_hir::TraitBoundModifier as TBM;
706         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
707             if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
708                 return true;
709             }
710         }
711         false
712     }
713
714     pub fn get_poly_trait(&self) -> Option<PolyTrait> {
715         if let GenericBound::TraitBound(ref p, _) = *self {
716             return Some(p.clone());
717         }
718         None
719     }
720
721     pub fn get_trait_type(&self) -> Option<Type> {
722         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
723             Some(trait_.clone())
724         } else {
725             None
726         }
727     }
728 }
729
730 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
731 pub struct Lifetime(pub String);
732
733 impl Lifetime {
734     pub fn get_ref<'a>(&'a self) -> &'a str {
735         let Lifetime(ref s) = *self;
736         let s: &'a str = s;
737         s
738     }
739
740     pub fn statik() -> Lifetime {
741         Lifetime("'static".to_string())
742     }
743 }
744
745 #[derive(Clone, Debug)]
746 pub enum WherePredicate {
747     BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
748     RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
749     EqPredicate { lhs: Type, rhs: Type },
750 }
751
752 impl WherePredicate {
753     pub fn get_bounds(&self) -> Option<&[GenericBound]> {
754         match *self {
755             WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
756             WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
757             _ => None,
758         }
759     }
760 }
761
762 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
763 pub enum GenericParamDefKind {
764     Lifetime,
765     Type {
766         did: DefId,
767         bounds: Vec<GenericBound>,
768         default: Option<Type>,
769         synthetic: Option<hir::SyntheticTyParamKind>,
770     },
771     Const {
772         did: DefId,
773         ty: Type,
774     },
775 }
776
777 impl GenericParamDefKind {
778     pub fn is_type(&self) -> bool {
779         match *self {
780             GenericParamDefKind::Type { .. } => true,
781             _ => false,
782         }
783     }
784
785     // FIXME(eddyb) this either returns the default of a type parameter, or the
786     // type of a `const` parameter. It seems that the intention is to *visit*
787     // any embedded types, but `get_type` seems to be the wrong name for that.
788     pub fn get_type(&self) -> Option<Type> {
789         match self {
790             GenericParamDefKind::Type { default, .. } => default.clone(),
791             GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
792             GenericParamDefKind::Lifetime => None,
793         }
794     }
795 }
796
797 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
798 pub struct GenericParamDef {
799     pub name: String,
800     pub kind: GenericParamDefKind,
801 }
802
803 impl GenericParamDef {
804     pub fn is_synthetic_type_param(&self) -> bool {
805         match self.kind {
806             GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => false,
807             GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
808         }
809     }
810
811     pub fn is_type(&self) -> bool {
812         self.kind.is_type()
813     }
814
815     pub fn get_type(&self) -> Option<Type> {
816         self.kind.get_type()
817     }
818
819     pub fn get_bounds(&self) -> Option<&[GenericBound]> {
820         match self.kind {
821             GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
822             _ => None,
823         }
824     }
825 }
826
827 // maybe use a Generic enum and use Vec<Generic>?
828 #[derive(Clone, Debug, Default)]
829 pub struct Generics {
830     pub params: Vec<GenericParamDef>,
831     pub where_predicates: Vec<WherePredicate>,
832 }
833
834 #[derive(Clone, Debug)]
835 pub struct Method {
836     pub generics: Generics,
837     pub decl: FnDecl,
838     pub header: hir::FnHeader,
839     pub defaultness: Option<hir::Defaultness>,
840     pub all_types: Vec<Type>,
841     pub ret_types: Vec<Type>,
842 }
843
844 #[derive(Clone, Debug)]
845 pub struct TyMethod {
846     pub header: hir::FnHeader,
847     pub decl: FnDecl,
848     pub generics: Generics,
849     pub all_types: Vec<Type>,
850     pub ret_types: Vec<Type>,
851 }
852
853 #[derive(Clone, Debug)]
854 pub struct Function {
855     pub decl: FnDecl,
856     pub generics: Generics,
857     pub header: hir::FnHeader,
858     pub all_types: Vec<Type>,
859     pub ret_types: Vec<Type>,
860 }
861
862 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
863 pub struct FnDecl {
864     pub inputs: Arguments,
865     pub output: FunctionRetTy,
866     pub c_variadic: bool,
867     pub attrs: Attributes,
868 }
869
870 impl FnDecl {
871     pub fn self_type(&self) -> Option<SelfTy> {
872         self.inputs.values.get(0).and_then(|v| v.to_self())
873     }
874
875     /// Returns the sugared return type for an async function.
876     ///
877     /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
878     /// will return `i32`.
879     ///
880     /// # Panics
881     ///
882     /// This function will panic if the return type does not match the expected sugaring for async
883     /// functions.
884     pub fn sugared_async_return_type(&self) -> FunctionRetTy {
885         match &self.output {
886             FunctionRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] {
887                 GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
888                     let bindings = trait_.bindings().unwrap();
889                     FunctionRetTy::Return(bindings[0].ty().clone())
890                 }
891                 _ => panic!("unexpected desugaring of async function"),
892             },
893             _ => panic!("unexpected desugaring of async function"),
894         }
895     }
896 }
897
898 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
899 pub struct Arguments {
900     pub values: Vec<Argument>,
901 }
902
903 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
904 pub struct Argument {
905     pub type_: Type,
906     pub name: String,
907 }
908
909 #[derive(Clone, PartialEq, Debug)]
910 pub enum SelfTy {
911     SelfValue,
912     SelfBorrowed(Option<Lifetime>, Mutability),
913     SelfExplicit(Type),
914 }
915
916 impl Argument {
917     pub fn to_self(&self) -> Option<SelfTy> {
918         if self.name != "self" {
919             return None;
920         }
921         if self.type_.is_self_type() {
922             return Some(SelfValue);
923         }
924         match self.type_ {
925             BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
926                 Some(SelfBorrowed(lifetime.clone(), mutability))
927             }
928             _ => Some(SelfExplicit(self.type_.clone())),
929         }
930     }
931 }
932
933 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
934 pub enum FunctionRetTy {
935     Return(Type),
936     DefaultReturn,
937 }
938
939 impl GetDefId for FunctionRetTy {
940     fn def_id(&self) -> Option<DefId> {
941         match *self {
942             Return(ref ty) => ty.def_id(),
943             DefaultReturn => None,
944         }
945     }
946 }
947
948 #[derive(Clone, Debug)]
949 pub struct Trait {
950     pub auto: bool,
951     pub unsafety: hir::Unsafety,
952     pub items: Vec<Item>,
953     pub generics: Generics,
954     pub bounds: Vec<GenericBound>,
955     pub is_spotlight: bool,
956     pub is_auto: bool,
957 }
958
959 #[derive(Clone, Debug)]
960 pub struct TraitAlias {
961     pub generics: Generics,
962     pub bounds: Vec<GenericBound>,
963 }
964
965 /// A trait reference, which may have higher ranked lifetimes.
966 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
967 pub struct PolyTrait {
968     pub trait_: Type,
969     pub generic_params: Vec<GenericParamDef>,
970 }
971
972 /// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
973 /// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
974 /// importantly, it does not preserve mutability or boxes.
975 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
976 pub enum Type {
977     /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
978     ResolvedPath {
979         path: Path,
980         param_names: Option<Vec<GenericBound>>,
981         did: DefId,
982         /// `true` if is a `T::Name` path for associated types.
983         is_generic: bool,
984     },
985     /// For parameterized types, so the consumer of the JSON don't go
986     /// looking for types which don't exist anywhere.
987     Generic(String),
988     /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
989     /// arrays, slices, and tuples.
990     Primitive(PrimitiveType),
991     /// `extern "ABI" fn`
992     BareFunction(Box<BareFunctionDecl>),
993     Tuple(Vec<Type>),
994     Slice(Box<Type>),
995     Array(Box<Type>, String),
996     Never,
997     RawPointer(Mutability, Box<Type>),
998     BorrowedRef {
999         lifetime: Option<Lifetime>,
1000         mutability: Mutability,
1001         type_: Box<Type>,
1002     },
1003
1004     // `<Type as Trait>::Name`
1005     QPath {
1006         name: String,
1007         self_type: Box<Type>,
1008         trait_: Box<Type>,
1009     },
1010
1011     // `_`
1012     Infer,
1013
1014     // `impl TraitA + TraitB + ...`
1015     ImplTrait(Vec<GenericBound>),
1016 }
1017
1018 #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
1019 pub enum PrimitiveType {
1020     Isize,
1021     I8,
1022     I16,
1023     I32,
1024     I64,
1025     I128,
1026     Usize,
1027     U8,
1028     U16,
1029     U32,
1030     U64,
1031     U128,
1032     F32,
1033     F64,
1034     Char,
1035     Bool,
1036     Str,
1037     Slice,
1038     Array,
1039     Tuple,
1040     Unit,
1041     RawPointer,
1042     Reference,
1043     Fn,
1044     Never,
1045 }
1046
1047 #[derive(Clone, Copy, Debug)]
1048 pub enum TypeKind {
1049     Enum,
1050     Function,
1051     Module,
1052     Const,
1053     Static,
1054     Struct,
1055     Union,
1056     Trait,
1057     Typedef,
1058     Foreign,
1059     Macro,
1060     Attr,
1061     Derive,
1062     TraitAlias,
1063 }
1064
1065 pub trait GetDefId {
1066     fn def_id(&self) -> Option<DefId>;
1067 }
1068
1069 impl<T: GetDefId> GetDefId for Option<T> {
1070     fn def_id(&self) -> Option<DefId> {
1071         self.as_ref().and_then(|d| d.def_id())
1072     }
1073 }
1074
1075 impl Type {
1076     pub fn primitive_type(&self) -> Option<PrimitiveType> {
1077         match *self {
1078             Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
1079             Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1080             Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1081             Tuple(ref tys) => {
1082                 if tys.is_empty() {
1083                     Some(PrimitiveType::Unit)
1084                 } else {
1085                     Some(PrimitiveType::Tuple)
1086                 }
1087             }
1088             RawPointer(..) => Some(PrimitiveType::RawPointer),
1089             BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
1090             BareFunction(..) => Some(PrimitiveType::Fn),
1091             Never => Some(PrimitiveType::Never),
1092             _ => None,
1093         }
1094     }
1095
1096     pub fn is_generic(&self) -> bool {
1097         match *self {
1098             ResolvedPath { is_generic, .. } => is_generic,
1099             _ => false,
1100         }
1101     }
1102
1103     pub fn is_self_type(&self) -> bool {
1104         match *self {
1105             Generic(ref name) => name == "Self",
1106             _ => false,
1107         }
1108     }
1109
1110     pub fn generics(&self) -> Option<Vec<Type>> {
1111         match *self {
1112             ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1113                 if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
1114                     Some(
1115                         args.iter()
1116                             .filter_map(|arg| match arg {
1117                                 GenericArg::Type(ty) => Some(ty.clone()),
1118                                 _ => None,
1119                             })
1120                             .collect(),
1121                     )
1122                 } else {
1123                     None
1124                 }
1125             }),
1126             _ => None,
1127         }
1128     }
1129
1130     pub fn bindings(&self) -> Option<&[TypeBinding]> {
1131         match *self {
1132             ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
1133                 if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
1134                     Some(&**bindings)
1135                 } else {
1136                     None
1137                 }
1138             }),
1139             _ => None,
1140         }
1141     }
1142
1143     pub fn is_full_generic(&self) -> bool {
1144         match *self {
1145             Type::Generic(_) => true,
1146             _ => false,
1147         }
1148     }
1149
1150     pub fn projection(&self) -> Option<(&Type, DefId, &str)> {
1151         let (self_, trait_, name) = match self {
1152             QPath { ref self_type, ref trait_, ref name } => (self_type, trait_, name),
1153             _ => return None,
1154         };
1155         let trait_did = match **trait_ {
1156             ResolvedPath { did, .. } => did,
1157             _ => return None,
1158         };
1159         Some((&self_, trait_did, name))
1160     }
1161 }
1162
1163 impl GetDefId for Type {
1164     fn def_id(&self) -> Option<DefId> {
1165         match *self {
1166             ResolvedPath { did, .. } => Some(did),
1167             Primitive(p) => crate::html::render::cache().primitive_locations.get(&p).cloned(),
1168             BorrowedRef { type_: box Generic(..), .. } => {
1169                 Primitive(PrimitiveType::Reference).def_id()
1170             }
1171             BorrowedRef { ref type_, .. } => type_.def_id(),
1172             Tuple(ref tys) => {
1173                 if tys.is_empty() {
1174                     Primitive(PrimitiveType::Unit).def_id()
1175                 } else {
1176                     Primitive(PrimitiveType::Tuple).def_id()
1177                 }
1178             }
1179             BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
1180             Never => Primitive(PrimitiveType::Never).def_id(),
1181             Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
1182             Array(..) => Primitive(PrimitiveType::Array).def_id(),
1183             RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(),
1184             QPath { ref self_type, .. } => self_type.def_id(),
1185             _ => None,
1186         }
1187     }
1188 }
1189
1190 impl PrimitiveType {
1191     pub fn from_str(s: &str) -> Option<PrimitiveType> {
1192         match s {
1193             "isize" => Some(PrimitiveType::Isize),
1194             "i8" => Some(PrimitiveType::I8),
1195             "i16" => Some(PrimitiveType::I16),
1196             "i32" => Some(PrimitiveType::I32),
1197             "i64" => Some(PrimitiveType::I64),
1198             "i128" => Some(PrimitiveType::I128),
1199             "usize" => Some(PrimitiveType::Usize),
1200             "u8" => Some(PrimitiveType::U8),
1201             "u16" => Some(PrimitiveType::U16),
1202             "u32" => Some(PrimitiveType::U32),
1203             "u64" => Some(PrimitiveType::U64),
1204             "u128" => Some(PrimitiveType::U128),
1205             "bool" => Some(PrimitiveType::Bool),
1206             "char" => Some(PrimitiveType::Char),
1207             "str" => Some(PrimitiveType::Str),
1208             "f32" => Some(PrimitiveType::F32),
1209             "f64" => Some(PrimitiveType::F64),
1210             "array" => Some(PrimitiveType::Array),
1211             "slice" => Some(PrimitiveType::Slice),
1212             "tuple" => Some(PrimitiveType::Tuple),
1213             "unit" => Some(PrimitiveType::Unit),
1214             "pointer" => Some(PrimitiveType::RawPointer),
1215             "reference" => Some(PrimitiveType::Reference),
1216             "fn" => Some(PrimitiveType::Fn),
1217             "never" => Some(PrimitiveType::Never),
1218             _ => None,
1219         }
1220     }
1221
1222     pub fn as_str(&self) -> &'static str {
1223         use self::PrimitiveType::*;
1224         match *self {
1225             Isize => "isize",
1226             I8 => "i8",
1227             I16 => "i16",
1228             I32 => "i32",
1229             I64 => "i64",
1230             I128 => "i128",
1231             Usize => "usize",
1232             U8 => "u8",
1233             U16 => "u16",
1234             U32 => "u32",
1235             U64 => "u64",
1236             U128 => "u128",
1237             F32 => "f32",
1238             F64 => "f64",
1239             Str => "str",
1240             Bool => "bool",
1241             Char => "char",
1242             Array => "array",
1243             Slice => "slice",
1244             Tuple => "tuple",
1245             Unit => "unit",
1246             RawPointer => "pointer",
1247             Reference => "reference",
1248             Fn => "fn",
1249             Never => "never",
1250         }
1251     }
1252
1253     pub fn to_url_str(&self) -> &'static str {
1254         self.as_str()
1255     }
1256 }
1257
1258 impl From<ast::IntTy> for PrimitiveType {
1259     fn from(int_ty: ast::IntTy) -> PrimitiveType {
1260         match int_ty {
1261             ast::IntTy::Isize => PrimitiveType::Isize,
1262             ast::IntTy::I8 => PrimitiveType::I8,
1263             ast::IntTy::I16 => PrimitiveType::I16,
1264             ast::IntTy::I32 => PrimitiveType::I32,
1265             ast::IntTy::I64 => PrimitiveType::I64,
1266             ast::IntTy::I128 => PrimitiveType::I128,
1267         }
1268     }
1269 }
1270
1271 impl From<ast::UintTy> for PrimitiveType {
1272     fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1273         match uint_ty {
1274             ast::UintTy::Usize => PrimitiveType::Usize,
1275             ast::UintTy::U8 => PrimitiveType::U8,
1276             ast::UintTy::U16 => PrimitiveType::U16,
1277             ast::UintTy::U32 => PrimitiveType::U32,
1278             ast::UintTy::U64 => PrimitiveType::U64,
1279             ast::UintTy::U128 => PrimitiveType::U128,
1280         }
1281     }
1282 }
1283
1284 impl From<ast::FloatTy> for PrimitiveType {
1285     fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1286         match float_ty {
1287             ast::FloatTy::F32 => PrimitiveType::F32,
1288             ast::FloatTy::F64 => PrimitiveType::F64,
1289         }
1290     }
1291 }
1292
1293 #[derive(Clone, PartialEq, Eq, Debug)]
1294 pub enum Visibility {
1295     Public,
1296     Inherited,
1297     Crate,
1298     Restricted(DefId, Path),
1299 }
1300
1301 #[derive(Clone, Debug)]
1302 pub struct Struct {
1303     pub struct_type: doctree::StructType,
1304     pub generics: Generics,
1305     pub fields: Vec<Item>,
1306     pub fields_stripped: bool,
1307 }
1308
1309 #[derive(Clone, Debug)]
1310 pub struct Union {
1311     pub struct_type: doctree::StructType,
1312     pub generics: Generics,
1313     pub fields: Vec<Item>,
1314     pub fields_stripped: bool,
1315 }
1316
1317 /// This is a more limited form of the standard Struct, different in that
1318 /// it lacks the things most items have (name, id, parameterization). Found
1319 /// only as a variant in an enum.
1320 #[derive(Clone, Debug)]
1321 pub struct VariantStruct {
1322     pub struct_type: doctree::StructType,
1323     pub fields: Vec<Item>,
1324     pub fields_stripped: bool,
1325 }
1326
1327 #[derive(Clone, Debug)]
1328 pub struct Enum {
1329     pub variants: IndexVec<VariantIdx, Item>,
1330     pub generics: Generics,
1331     pub variants_stripped: bool,
1332 }
1333
1334 #[derive(Clone, Debug)]
1335 pub struct Variant {
1336     pub kind: VariantKind,
1337 }
1338
1339 #[derive(Clone, Debug)]
1340 pub enum VariantKind {
1341     CLike,
1342     Tuple(Vec<Type>),
1343     Struct(VariantStruct),
1344 }
1345
1346 #[derive(Clone, Debug)]
1347 pub struct Span {
1348     pub filename: FileName,
1349     pub loline: usize,
1350     pub locol: usize,
1351     pub hiline: usize,
1352     pub hicol: usize,
1353     pub original: rustc_span::Span,
1354 }
1355
1356 impl Span {
1357     pub fn empty() -> Span {
1358         Span {
1359             filename: FileName::Anon(0),
1360             loline: 0,
1361             locol: 0,
1362             hiline: 0,
1363             hicol: 0,
1364             original: rustc_span::DUMMY_SP,
1365         }
1366     }
1367
1368     pub fn span(&self) -> rustc_span::Span {
1369         self.original
1370     }
1371 }
1372
1373 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1374 pub struct Path {
1375     pub global: bool,
1376     pub res: Res,
1377     pub segments: Vec<PathSegment>,
1378 }
1379
1380 impl Path {
1381     pub fn last_name(&self) -> &str {
1382         self.segments.last().expect("segments were empty").name.as_str()
1383     }
1384 }
1385
1386 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1387 pub enum GenericArg {
1388     Lifetime(Lifetime),
1389     Type(Type),
1390     Const(Constant),
1391 }
1392
1393 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1394 pub enum GenericArgs {
1395     AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
1396     Parenthesized { inputs: Vec<Type>, output: Option<Type> },
1397 }
1398
1399 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1400 pub struct PathSegment {
1401     pub name: String,
1402     pub args: GenericArgs,
1403 }
1404
1405 #[derive(Clone, Debug)]
1406 pub struct Typedef {
1407     pub type_: Type,
1408     pub generics: Generics,
1409     // Type of target item.
1410     pub item_type: Option<Type>,
1411 }
1412
1413 impl GetDefId for Typedef {
1414     fn def_id(&self) -> Option<DefId> {
1415         self.type_.def_id()
1416     }
1417 }
1418
1419 #[derive(Clone, Debug)]
1420 pub struct OpaqueTy {
1421     pub bounds: Vec<GenericBound>,
1422     pub generics: Generics,
1423 }
1424
1425 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1426 pub struct BareFunctionDecl {
1427     pub unsafety: hir::Unsafety,
1428     pub generic_params: Vec<GenericParamDef>,
1429     pub decl: FnDecl,
1430     pub abi: Abi,
1431 }
1432
1433 #[derive(Clone, Debug)]
1434 pub struct Static {
1435     pub type_: Type,
1436     pub mutability: Mutability,
1437     /// It's useful to have the value of a static documented, but I have no
1438     /// desire to represent expressions (that'd basically be all of the AST,
1439     /// which is huge!). So, have a string.
1440     pub expr: String,
1441 }
1442
1443 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
1444 pub struct Constant {
1445     pub type_: Type,
1446     pub expr: String,
1447     pub value: Option<String>,
1448     pub is_literal: bool,
1449 }
1450
1451 #[derive(Clone, PartialEq, Debug)]
1452 pub enum ImplPolarity {
1453     Positive,
1454     Negative,
1455 }
1456
1457 #[derive(Clone, Debug)]
1458 pub struct Impl {
1459     pub unsafety: hir::Unsafety,
1460     pub generics: Generics,
1461     pub provided_trait_methods: FxHashSet<String>,
1462     pub trait_: Option<Type>,
1463     pub for_: Type,
1464     pub items: Vec<Item>,
1465     pub polarity: Option<ImplPolarity>,
1466     pub synthetic: bool,
1467     pub blanket_impl: Option<Type>,
1468 }
1469
1470 #[derive(Clone, Debug)]
1471 pub enum Import {
1472     // use source as str;
1473     Simple(String, ImportSource),
1474     // use source::*;
1475     Glob(ImportSource),
1476 }
1477
1478 #[derive(Clone, Debug)]
1479 pub struct ImportSource {
1480     pub path: Path,
1481     pub did: Option<DefId>,
1482 }
1483
1484 #[derive(Clone, Debug)]
1485 pub struct Macro {
1486     pub source: String,
1487     pub imported_from: Option<String>,
1488 }
1489
1490 #[derive(Clone, Debug)]
1491 pub struct ProcMacro {
1492     pub kind: MacroKind,
1493     pub helpers: Vec<String>,
1494 }
1495
1496 #[derive(Clone, Debug)]
1497 pub struct Stability {
1498     pub level: stability::StabilityLevel,
1499     pub feature: Option<String>,
1500     pub since: String,
1501     pub deprecation: Option<Deprecation>,
1502     pub unstable_reason: Option<String>,
1503     pub issue: Option<NonZeroU32>,
1504 }
1505
1506 #[derive(Clone, Debug)]
1507 pub struct Deprecation {
1508     pub since: Option<String>,
1509     pub note: Option<String>,
1510 }
1511
1512 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
1513 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
1514 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1515 pub struct TypeBinding {
1516     pub name: String,
1517     pub kind: TypeBindingKind,
1518 }
1519
1520 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
1521 pub enum TypeBindingKind {
1522     Equality { ty: Type },
1523     Constraint { bounds: Vec<GenericBound> },
1524 }
1525
1526 impl TypeBinding {
1527     pub fn ty(&self) -> &Type {
1528         match self.kind {
1529             TypeBindingKind::Equality { ref ty } => ty,
1530             _ => panic!("expected equality type binding for parenthesized generic args"),
1531         }
1532     }
1533 }