]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/clean/mod.rs
Fix impl Trait Lifetime Handling
[rust.git] / src / librustdoc / clean / mod.rs
1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! This module contains the "cleaned" pieces of the AST, and the functions
12 //! that clean them.
13
14 pub use self::Type::*;
15 pub use self::Mutability::*;
16 pub use self::ItemEnum::*;
17 pub use self::TyParamBound::*;
18 pub use self::SelfTy::*;
19 pub use self::FunctionRetTy::*;
20 pub use self::Visibility::*;
21
22 use syntax::abi::Abi;
23 use syntax::ast;
24 use syntax::attr;
25 use syntax::codemap::Spanned;
26 use syntax::ptr::P;
27 use syntax::symbol::keywords;
28 use syntax_pos::{self, DUMMY_SP, Pos};
29
30 use rustc::middle::const_val::ConstVal;
31 use rustc::middle::privacy::AccessLevels;
32 use rustc::middle::resolve_lifetime as rl;
33 use rustc::middle::lang_items;
34 use rustc::hir::def::{Def, CtorKind};
35 use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
36 use rustc::traits::Reveal;
37 use rustc::ty::subst::Substs;
38 use rustc::ty::{self, Ty, AdtKind};
39 use rustc::middle::stability;
40 use rustc::util::nodemap::{FxHashMap, FxHashSet};
41 use rustc_typeck::hir_ty_to_ty;
42
43 use rustc::hir;
44
45 use rustc_const_math::ConstInt;
46 use std::{mem, slice, vec};
47 use std::path::PathBuf;
48 use std::rc::Rc;
49 use std::sync::Arc;
50 use std::u32;
51
52 use core::DocContext;
53 use doctree;
54 use visit_ast;
55 use html::item_type::ItemType;
56
57 pub mod inline;
58 pub mod cfg;
59 mod simplify;
60
61 use self::cfg::Cfg;
62
63 // extract the stability index for a node from tcx, if possible
64 fn get_stability(cx: &DocContext, def_id: DefId) -> Option<Stability> {
65     cx.tcx.lookup_stability(def_id).clean(cx)
66 }
67
68 fn get_deprecation(cx: &DocContext, def_id: DefId) -> Option<Deprecation> {
69     cx.tcx.lookup_deprecation(def_id).clean(cx)
70 }
71
72 pub trait Clean<T> {
73     fn clean(&self, cx: &DocContext) -> T;
74 }
75
76 impl<T: Clean<U>, U> Clean<Vec<U>> for [T] {
77     fn clean(&self, cx: &DocContext) -> Vec<U> {
78         self.iter().map(|x| x.clean(cx)).collect()
79     }
80 }
81
82 impl<T: Clean<U>, U> Clean<U> for P<T> {
83     fn clean(&self, cx: &DocContext) -> U {
84         (**self).clean(cx)
85     }
86 }
87
88 impl<T: Clean<U>, U> Clean<U> for Rc<T> {
89     fn clean(&self, cx: &DocContext) -> U {
90         (**self).clean(cx)
91     }
92 }
93
94 impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
95     fn clean(&self, cx: &DocContext) -> Option<U> {
96         self.as_ref().map(|v| v.clean(cx))
97     }
98 }
99
100 impl<T, U> Clean<U> for ty::Binder<T> where T: Clean<U> {
101     fn clean(&self, cx: &DocContext) -> U {
102         self.0.clean(cx)
103     }
104 }
105
106 impl<T: Clean<U>, U> Clean<Vec<U>> for P<[T]> {
107     fn clean(&self, cx: &DocContext) -> Vec<U> {
108         self.iter().map(|x| x.clean(cx)).collect()
109     }
110 }
111
112 #[derive(Clone, Debug)]
113 pub struct Crate {
114     pub name: String,
115     pub version: Option<String>,
116     pub src: PathBuf,
117     pub module: Option<Item>,
118     pub externs: Vec<(CrateNum, ExternalCrate)>,
119     pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
120     pub access_levels: Arc<AccessLevels<DefId>>,
121     // These are later on moved into `CACHEKEY`, leaving the map empty.
122     // Only here so that they can be filtered through the rustdoc passes.
123     pub external_traits: FxHashMap<DefId, Trait>,
124     pub masked_crates: FxHashSet<CrateNum>,
125 }
126
127 impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
128     fn clean(&self, cx: &DocContext) -> Crate {
129         use ::visit_lib::LibEmbargoVisitor;
130
131         {
132             let mut r = cx.renderinfo.borrow_mut();
133             r.deref_trait_did = cx.tcx.lang_items().deref_trait();
134             r.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait();
135             r.owned_box_did = cx.tcx.lang_items().owned_box();
136         }
137
138         let mut externs = Vec::new();
139         for &cnum in cx.tcx.crates().iter() {
140             externs.push((cnum, cnum.clean(cx)));
141             // Analyze doc-reachability for extern items
142             LibEmbargoVisitor::new(cx).visit_lib(cnum);
143         }
144         externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
145
146         // Clean the crate, translating the entire libsyntax AST to one that is
147         // understood by rustdoc.
148         let mut module = self.module.clean(cx);
149         let mut masked_crates = FxHashSet();
150
151         match module.inner {
152             ModuleItem(ref module) => {
153                 for it in &module.items {
154                     if it.is_extern_crate() && it.attrs.has_doc_masked() {
155                         masked_crates.insert(it.def_id.krate);
156                     }
157                 }
158             }
159             _ => unreachable!(),
160         }
161
162         let ExternalCrate { name, src, primitives, .. } = LOCAL_CRATE.clean(cx);
163         {
164             let m = match module.inner {
165                 ModuleItem(ref mut m) => m,
166                 _ => unreachable!(),
167             };
168             m.items.extend(primitives.iter().map(|&(def_id, prim, ref attrs)| {
169                 Item {
170                     source: Span::empty(),
171                     name: Some(prim.to_url_str().to_string()),
172                     attrs: attrs.clone(),
173                     visibility: Some(Public),
174                     stability: get_stability(cx, def_id),
175                     deprecation: get_deprecation(cx, def_id),
176                     def_id,
177                     inner: PrimitiveItem(prim),
178                 }
179             }));
180         }
181
182         let mut access_levels = cx.access_levels.borrow_mut();
183         let mut external_traits = cx.external_traits.borrow_mut();
184
185         Crate {
186             name,
187             version: None,
188             src,
189             module: Some(module),
190             externs,
191             primitives,
192             access_levels: Arc::new(mem::replace(&mut access_levels, Default::default())),
193             external_traits: mem::replace(&mut external_traits, Default::default()),
194             masked_crates,
195         }
196     }
197 }
198
199 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
200 pub struct ExternalCrate {
201     pub name: String,
202     pub src: PathBuf,
203     pub attrs: Attributes,
204     pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
205 }
206
207 impl Clean<ExternalCrate> for CrateNum {
208     fn clean(&self, cx: &DocContext) -> ExternalCrate {
209         let root = DefId { krate: *self, index: CRATE_DEF_INDEX };
210         let krate_span = cx.tcx.def_span(root);
211         let krate_src = cx.sess().codemap().span_to_filename(krate_span);
212
213         // Collect all inner modules which are tagged as implementations of
214         // primitives.
215         //
216         // Note that this loop only searches the top-level items of the crate,
217         // and this is intentional. If we were to search the entire crate for an
218         // item tagged with `#[doc(primitive)]` then we would also have to
219         // search the entirety of external modules for items tagged
220         // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
221         // all that metadata unconditionally).
222         //
223         // In order to keep the metadata load under control, the
224         // `#[doc(primitive)]` feature is explicitly designed to only allow the
225         // primitive tags to show up as the top level items in a crate.
226         //
227         // Also note that this does not attempt to deal with modules tagged
228         // duplicately for the same primitive. This is handled later on when
229         // rendering by delegating everything to a hash map.
230         let as_primitive = |def: Def| {
231             if let Def::Mod(def_id) = def {
232                 let attrs = cx.tcx.get_attrs(def_id).clean(cx);
233                 let mut prim = None;
234                 for attr in attrs.lists("doc") {
235                     if let Some(v) = attr.value_str() {
236                         if attr.check_name("primitive") {
237                             prim = PrimitiveType::from_str(&v.as_str());
238                             if prim.is_some() {
239                                 break;
240                             }
241                             // FIXME: should warn on unknown primitives?
242                         }
243                     }
244                 }
245                 return prim.map(|p| (def_id, p, attrs));
246             }
247             None
248         };
249         let primitives = if root.is_local() {
250             cx.tcx.hir.krate().module.item_ids.iter().filter_map(|&id| {
251                 let item = cx.tcx.hir.expect_item(id.id);
252                 match item.node {
253                     hir::ItemMod(_) => {
254                         as_primitive(Def::Mod(cx.tcx.hir.local_def_id(id.id)))
255                     }
256                     hir::ItemUse(ref path, hir::UseKind::Single)
257                     if item.vis == hir::Visibility::Public => {
258                         as_primitive(path.def).map(|(_, prim, attrs)| {
259                             // Pretend the primitive is local.
260                             (cx.tcx.hir.local_def_id(id.id), prim, attrs)
261                         })
262                     }
263                     _ => None
264                 }
265             }).collect()
266         } else {
267             cx.tcx.item_children(root).iter().map(|item| item.def)
268               .filter_map(as_primitive).collect()
269         };
270
271         ExternalCrate {
272             name: cx.tcx.crate_name(*self).to_string(),
273             src: PathBuf::from(krate_src),
274             attrs: cx.tcx.get_attrs(root).clean(cx),
275             primitives,
276         }
277     }
278 }
279
280 /// Anything with a source location and set of attributes and, optionally, a
281 /// name. That is, anything that can be documented. This doesn't correspond
282 /// directly to the AST's concept of an item; it's a strict superset.
283 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
284 pub struct Item {
285     /// Stringified span
286     pub source: Span,
287     /// Not everything has a name. E.g., impls
288     pub name: Option<String>,
289     pub attrs: Attributes,
290     pub inner: ItemEnum,
291     pub visibility: Option<Visibility>,
292     pub def_id: DefId,
293     pub stability: Option<Stability>,
294     pub deprecation: Option<Deprecation>,
295 }
296
297 impl Item {
298     /// Finds the `doc` attribute as a NameValue and returns the corresponding
299     /// value found.
300     pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
301         self.attrs.doc_value()
302     }
303     pub fn is_crate(&self) -> bool {
304         match self.inner {
305             StrippedItem(box ModuleItem(Module { is_crate: true, ..})) |
306             ModuleItem(Module { is_crate: true, ..}) => true,
307             _ => false,
308         }
309     }
310     pub fn is_mod(&self) -> bool {
311         self.type_() == ItemType::Module
312     }
313     pub fn is_trait(&self) -> bool {
314         self.type_() == ItemType::Trait
315     }
316     pub fn is_struct(&self) -> bool {
317         self.type_() == ItemType::Struct
318     }
319     pub fn is_enum(&self) -> bool {
320         self.type_() == ItemType::Enum
321     }
322     pub fn is_fn(&self) -> bool {
323         self.type_() == ItemType::Function
324     }
325     pub fn is_associated_type(&self) -> bool {
326         self.type_() == ItemType::AssociatedType
327     }
328     pub fn is_associated_const(&self) -> bool {
329         self.type_() == ItemType::AssociatedConst
330     }
331     pub fn is_method(&self) -> bool {
332         self.type_() == ItemType::Method
333     }
334     pub fn is_ty_method(&self) -> bool {
335         self.type_() == ItemType::TyMethod
336     }
337     pub fn is_typedef(&self) -> bool {
338         self.type_() == ItemType::Typedef
339     }
340     pub fn is_primitive(&self) -> bool {
341         self.type_() == ItemType::Primitive
342     }
343     pub fn is_union(&self) -> bool {
344         self.type_() == ItemType::Union
345     }
346     pub fn is_import(&self) -> bool {
347         self.type_() == ItemType::Import
348     }
349     pub fn is_extern_crate(&self) -> bool {
350         self.type_() == ItemType::ExternCrate
351     }
352
353     pub fn is_stripped(&self) -> bool {
354         match self.inner { StrippedItem(..) => true, _ => false }
355     }
356     pub fn has_stripped_fields(&self) -> Option<bool> {
357         match self.inner {
358             StructItem(ref _struct) => Some(_struct.fields_stripped),
359             UnionItem(ref union) => Some(union.fields_stripped),
360             VariantItem(Variant { kind: VariantKind::Struct(ref vstruct)} ) => {
361                 Some(vstruct.fields_stripped)
362             },
363             _ => None,
364         }
365     }
366
367     pub fn stability_class(&self) -> Option<String> {
368         self.stability.as_ref().and_then(|ref s| {
369             let mut classes = Vec::with_capacity(2);
370
371             if s.level == stability::Unstable {
372                 classes.push("unstable");
373             }
374
375             if !s.deprecated_since.is_empty() {
376                 classes.push("deprecated");
377             }
378
379             if classes.len() != 0 {
380                 Some(classes.join(" "))
381             } else {
382                 None
383             }
384         })
385     }
386
387     pub fn stable_since(&self) -> Option<&str> {
388         self.stability.as_ref().map(|s| &s.since[..])
389     }
390
391     /// Returns a documentation-level item type from the item.
392     pub fn type_(&self) -> ItemType {
393         ItemType::from(self)
394     }
395 }
396
397 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
398 pub enum ItemEnum {
399     ExternCrateItem(String, Option<String>),
400     ImportItem(Import),
401     StructItem(Struct),
402     UnionItem(Union),
403     EnumItem(Enum),
404     FunctionItem(Function),
405     ModuleItem(Module),
406     TypedefItem(Typedef, bool /* is associated type */),
407     StaticItem(Static),
408     ConstantItem(Constant),
409     TraitItem(Trait),
410     ImplItem(Impl),
411     /// A method signature only. Used for required methods in traits (ie,
412     /// non-default-methods).
413     TyMethodItem(TyMethod),
414     /// A method with a body.
415     MethodItem(Method),
416     StructFieldItem(Type),
417     VariantItem(Variant),
418     /// `fn`s from an extern block
419     ForeignFunctionItem(Function),
420     /// `static`s from an extern block
421     ForeignStaticItem(Static),
422     /// `type`s from an extern block
423     ForeignTypeItem,
424     MacroItem(Macro),
425     PrimitiveItem(PrimitiveType),
426     AssociatedConstItem(Type, Option<String>),
427     AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
428     AutoImplItem(AutoImpl),
429     /// An item that has been stripped by a rustdoc pass
430     StrippedItem(Box<ItemEnum>),
431 }
432
433 impl ItemEnum {
434     pub fn generics(&self) -> Option<&Generics> {
435         Some(match *self {
436             ItemEnum::StructItem(ref s) => &s.generics,
437             ItemEnum::EnumItem(ref e) => &e.generics,
438             ItemEnum::FunctionItem(ref f) => &f.generics,
439             ItemEnum::TypedefItem(ref t, _) => &t.generics,
440             ItemEnum::TraitItem(ref t) => &t.generics,
441             ItemEnum::ImplItem(ref i) => &i.generics,
442             ItemEnum::TyMethodItem(ref i) => &i.generics,
443             ItemEnum::MethodItem(ref i) => &i.generics,
444             ItemEnum::ForeignFunctionItem(ref f) => &f.generics,
445             _ => return None,
446         })
447     }
448 }
449
450 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
451 pub struct Module {
452     pub items: Vec<Item>,
453     pub is_crate: bool,
454 }
455
456 impl Clean<Item> for doctree::Module {
457     fn clean(&self, cx: &DocContext) -> Item {
458         let name = if self.name.is_some() {
459             self.name.unwrap().clean(cx)
460         } else {
461             "".to_string()
462         };
463
464         let mut items: Vec<Item> = vec![];
465         items.extend(self.extern_crates.iter().map(|x| x.clean(cx)));
466         items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
467         items.extend(self.structs.iter().map(|x| x.clean(cx)));
468         items.extend(self.unions.iter().map(|x| x.clean(cx)));
469         items.extend(self.enums.iter().map(|x| x.clean(cx)));
470         items.extend(self.fns.iter().map(|x| x.clean(cx)));
471         items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx)));
472         items.extend(self.mods.iter().map(|x| x.clean(cx)));
473         items.extend(self.typedefs.iter().map(|x| x.clean(cx)));
474         items.extend(self.statics.iter().map(|x| x.clean(cx)));
475         items.extend(self.constants.iter().map(|x| x.clean(cx)));
476         items.extend(self.traits.iter().map(|x| x.clean(cx)));
477         items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
478         items.extend(self.macros.iter().map(|x| x.clean(cx)));
479         items.extend(self.def_traits.iter().map(|x| x.clean(cx)));
480
481         // determine if we should display the inner contents or
482         // the outer `mod` item for the source code.
483         let whence = {
484             let cm = cx.sess().codemap();
485             let outer = cm.lookup_char_pos(self.where_outer.lo());
486             let inner = cm.lookup_char_pos(self.where_inner.lo());
487             if outer.file.start_pos == inner.file.start_pos {
488                 // mod foo { ... }
489                 self.where_outer
490             } else {
491                 // mod foo; (and a separate FileMap for the contents)
492                 self.where_inner
493             }
494         };
495
496         Item {
497             name: Some(name),
498             attrs: self.attrs.clean(cx),
499             source: whence.clean(cx),
500             visibility: self.vis.clean(cx),
501             stability: self.stab.clean(cx),
502             deprecation: self.depr.clean(cx),
503             def_id: cx.tcx.hir.local_def_id(self.id),
504             inner: ModuleItem(Module {
505                is_crate: self.is_crate,
506                items,
507             })
508         }
509     }
510 }
511
512 pub struct ListAttributesIter<'a> {
513     attrs: slice::Iter<'a, ast::Attribute>,
514     current_list: vec::IntoIter<ast::NestedMetaItem>,
515     name: &'a str
516 }
517
518 impl<'a> Iterator for ListAttributesIter<'a> {
519     type Item = ast::NestedMetaItem;
520
521     fn next(&mut self) -> Option<Self::Item> {
522         if let Some(nested) = self.current_list.next() {
523             return Some(nested);
524         }
525
526         for attr in &mut self.attrs {
527             if let Some(list) = attr.meta_item_list() {
528                 if attr.check_name(self.name) {
529                     self.current_list = list.into_iter();
530                     if let Some(nested) = self.current_list.next() {
531                         return Some(nested);
532                     }
533                 }
534             }
535         }
536
537         None
538     }
539 }
540
541 pub trait AttributesExt {
542     /// Finds an attribute as List and returns the list of attributes nested inside.
543     fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a>;
544 }
545
546 impl AttributesExt for [ast::Attribute] {
547     fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a> {
548         ListAttributesIter {
549             attrs: self.iter(),
550             current_list: Vec::new().into_iter(),
551             name,
552         }
553     }
554 }
555
556 pub trait NestedAttributesExt {
557     /// Returns whether the attribute list contains a specific `Word`
558     fn has_word(self, word: &str) -> bool;
559 }
560
561 impl<I: IntoIterator<Item=ast::NestedMetaItem>> NestedAttributesExt for I {
562     fn has_word(self, word: &str) -> bool {
563         self.into_iter().any(|attr| attr.is_word() && attr.check_name(word))
564     }
565 }
566
567 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug, Default)]
568 pub struct Attributes {
569     pub doc_strings: Vec<String>,
570     pub other_attrs: Vec<ast::Attribute>,
571     pub cfg: Option<Rc<Cfg>>,
572     pub span: Option<syntax_pos::Span>,
573 }
574
575 impl Attributes {
576     /// Extracts the content from an attribute `#[doc(cfg(content))]`.
577     fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
578         use syntax::ast::NestedMetaItemKind::MetaItem;
579
580         if let ast::MetaItemKind::List(ref nmis) = mi.node {
581             if nmis.len() == 1 {
582                 if let MetaItem(ref cfg_mi) = nmis[0].node {
583                     if cfg_mi.check_name("cfg") {
584                         if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.node {
585                             if cfg_nmis.len() == 1 {
586                                 if let MetaItem(ref content_mi) = cfg_nmis[0].node {
587                                     return Some(content_mi);
588                                 }
589                             }
590                         }
591                     }
592                 }
593             }
594         }
595
596         None
597     }
598
599     pub fn has_doc_masked(&self) -> bool {
600         for attr in &self.other_attrs {
601             if !attr.check_name("doc") { continue; }
602
603             if let Some(items) = attr.meta_item_list() {
604                 if items.iter().filter_map(|i| i.meta_item()).any(|it| it.check_name("masked")) {
605                     return true;
606                 }
607             }
608         }
609
610         false
611     }
612
613     pub fn from_ast(diagnostic: &::errors::Handler, attrs: &[ast::Attribute]) -> Attributes {
614         let mut doc_strings = vec![];
615         let mut sp = None;
616         let mut cfg = Cfg::True;
617
618         let other_attrs = attrs.iter().filter_map(|attr| {
619             attr.with_desugared_doc(|attr| {
620                 if attr.check_name("doc") {
621                     if let Some(mi) = attr.meta() {
622                         if let Some(value) = mi.value_str() {
623                             // Extracted #[doc = "..."]
624                             doc_strings.push(value.to_string());
625                             if sp.is_none() {
626                                 sp = Some(attr.span);
627                             }
628                             return None;
629                         } else if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
630                             // Extracted #[doc(cfg(...))]
631                             match Cfg::parse(cfg_mi) {
632                                 Ok(new_cfg) => cfg &= new_cfg,
633                                 Err(e) => diagnostic.span_err(e.span, e.msg),
634                             }
635                             return None;
636                         }
637                     }
638                 }
639                 Some(attr.clone())
640             })
641         }).collect();
642         Attributes {
643             doc_strings,
644             other_attrs,
645             cfg: if cfg == Cfg::True { None } else { Some(Rc::new(cfg)) },
646             span: sp,
647         }
648     }
649
650     /// Finds the `doc` attribute as a NameValue and returns the corresponding
651     /// value found.
652     pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
653         self.doc_strings.first().map(|s| &s[..])
654     }
655 }
656
657 impl AttributesExt for Attributes {
658     fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a> {
659         self.other_attrs.lists(name)
660     }
661 }
662
663 impl Clean<Attributes> for [ast::Attribute] {
664     fn clean(&self, cx: &DocContext) -> Attributes {
665         Attributes::from_ast(cx.sess().diagnostic(), self)
666     }
667 }
668
669 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
670 pub struct TyParam {
671     pub name: String,
672     pub did: DefId,
673     pub bounds: Vec<TyParamBound>,
674     pub default: Option<Type>,
675 }
676
677 impl Clean<TyParam> for hir::TyParam {
678     fn clean(&self, cx: &DocContext) -> TyParam {
679         TyParam {
680             name: self.name.clean(cx),
681             did: cx.tcx.hir.local_def_id(self.id),
682             bounds: self.bounds.clean(cx),
683             default: self.default.clean(cx),
684         }
685     }
686 }
687
688 impl<'tcx> Clean<TyParam> for ty::TypeParameterDef {
689     fn clean(&self, cx: &DocContext) -> TyParam {
690         cx.renderinfo.borrow_mut().external_typarams.insert(self.def_id, self.name.clean(cx));
691         TyParam {
692             name: self.name.clean(cx),
693             did: self.def_id,
694             bounds: vec![], // these are filled in from the where-clauses
695             default: if self.has_default {
696                 Some(cx.tcx.type_of(self.def_id).clean(cx))
697             } else {
698                 None
699             }
700         }
701     }
702 }
703
704 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
705 pub enum TyParamBound {
706     RegionBound(Lifetime),
707     TraitBound(PolyTrait, hir::TraitBoundModifier)
708 }
709
710 impl TyParamBound {
711     fn maybe_sized(cx: &DocContext) -> TyParamBound {
712         let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem);
713         let empty = cx.tcx.intern_substs(&[]);
714         let path = external_path(cx, &cx.tcx.item_name(did),
715             Some(did), false, vec![], empty);
716         inline::record_extern_fqn(cx, did, TypeKind::Trait);
717         TraitBound(PolyTrait {
718             trait_: ResolvedPath {
719                 path,
720                 typarams: None,
721                 did,
722                 is_generic: false,
723             },
724             lifetimes: vec![]
725         }, hir::TraitBoundModifier::Maybe)
726     }
727
728     fn is_sized_bound(&self, cx: &DocContext) -> bool {
729         use rustc::hir::TraitBoundModifier as TBM;
730         if let TyParamBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
731             if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
732                 return true;
733             }
734         }
735         false
736     }
737 }
738
739 impl Clean<TyParamBound> for hir::TyParamBound {
740     fn clean(&self, cx: &DocContext) -> TyParamBound {
741         match *self {
742             hir::RegionTyParamBound(lt) => RegionBound(lt.clean(cx)),
743             hir::TraitTyParamBound(ref t, modifier) => TraitBound(t.clean(cx), modifier),
744         }
745     }
746 }
747
748 fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: bool,
749                         bindings: Vec<TypeBinding>, substs: &Substs) -> PathParameters {
750     let lifetimes = substs.regions().filter_map(|v| v.clean(cx)).collect();
751     let types = substs.types().skip(has_self as usize).collect::<Vec<_>>();
752
753     match trait_did {
754         // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
755         Some(did) if cx.tcx.lang_items().fn_trait_kind(did).is_some() => {
756             assert_eq!(types.len(), 1);
757             let inputs = match types[0].sty {
758                 ty::TyTuple(ref tys, _) => tys.iter().map(|t| t.clean(cx)).collect(),
759                 _ => {
760                     return PathParameters::AngleBracketed {
761                         lifetimes,
762                         types: types.clean(cx),
763                         bindings,
764                     }
765                 }
766             };
767             let output = None;
768             // FIXME(#20299) return type comes from a projection now
769             // match types[1].sty {
770             //     ty::TyTuple(ref v, _) if v.is_empty() => None, // -> ()
771             //     _ => Some(types[1].clean(cx))
772             // };
773             PathParameters::Parenthesized {
774                 inputs,
775                 output,
776             }
777         },
778         _ => {
779             PathParameters::AngleBracketed {
780                 lifetimes,
781                 types: types.clean(cx),
782                 bindings,
783             }
784         }
785     }
786 }
787
788 // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
789 // from Fn<(A, B,), C> to Fn(A, B) -> C
790 fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>, has_self: bool,
791                  bindings: Vec<TypeBinding>, substs: &Substs) -> Path {
792     Path {
793         global: false,
794         def: Def::Err,
795         segments: vec![PathSegment {
796             name: name.to_string(),
797             params: external_path_params(cx, trait_did, has_self, bindings, substs)
798         }],
799     }
800 }
801
802 impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
803     fn clean(&self, cx: &DocContext) -> TyParamBound {
804         inline::record_extern_fqn(cx, self.def_id, TypeKind::Trait);
805         let path = external_path(cx, &cx.tcx.item_name(self.def_id),
806                                  Some(self.def_id), true, vec![], self.substs);
807
808         debug!("ty::TraitRef\n  subst: {:?}\n", self.substs);
809
810         // collect any late bound regions
811         let mut late_bounds = vec![];
812         for ty_s in self.input_types().skip(1) {
813             if let ty::TyTuple(ts, _) = ty_s.sty {
814                 for &ty_s in ts {
815                     if let ty::TyRef(ref reg, _) = ty_s.sty {
816                         if let &ty::RegionKind::ReLateBound(..) = *reg {
817                             debug!("  hit an ReLateBound {:?}", reg);
818                             if let Some(lt) = reg.clean(cx) {
819                                 late_bounds.push(lt);
820                             }
821                         }
822                     }
823                 }
824             }
825         }
826
827         TraitBound(
828             PolyTrait {
829                 trait_: ResolvedPath {
830                     path,
831                     typarams: None,
832                     did: self.def_id,
833                     is_generic: false,
834                 },
835                 lifetimes: late_bounds,
836             },
837             hir::TraitBoundModifier::None
838         )
839     }
840 }
841
842 impl<'tcx> Clean<Option<Vec<TyParamBound>>> for Substs<'tcx> {
843     fn clean(&self, cx: &DocContext) -> Option<Vec<TyParamBound>> {
844         let mut v = Vec::new();
845         v.extend(self.regions().filter_map(|r| r.clean(cx))
846                      .map(RegionBound));
847         v.extend(self.types().map(|t| TraitBound(PolyTrait {
848             trait_: t.clean(cx),
849             lifetimes: vec![]
850         }, hir::TraitBoundModifier::None)));
851         if !v.is_empty() {Some(v)} else {None}
852     }
853 }
854
855 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
856 pub struct Lifetime(String);
857
858 impl Lifetime {
859     pub fn get_ref<'a>(&'a self) -> &'a str {
860         let Lifetime(ref s) = *self;
861         let s: &'a str = s;
862         s
863     }
864
865     pub fn statik() -> Lifetime {
866         Lifetime("'static".to_string())
867     }
868 }
869
870 impl Clean<Lifetime> for hir::Lifetime {
871     fn clean(&self, cx: &DocContext) -> Lifetime {
872         let hir_id = cx.tcx.hir.node_to_hir_id(self.id);
873         let def = cx.tcx.named_region(hir_id);
874         match def {
875             Some(rl::Region::EarlyBound(_, node_id)) |
876             Some(rl::Region::LateBound(_, node_id)) |
877             Some(rl::Region::Free(_, node_id)) => {
878                 if let Some(lt) = cx.lt_substs.borrow().get(&node_id).cloned() {
879                     return lt;
880                 }
881             }
882             _ => {}
883         }
884         Lifetime(self.name.name().to_string())
885     }
886 }
887
888 impl Clean<Lifetime> for hir::LifetimeDef {
889     fn clean(&self, _: &DocContext) -> Lifetime {
890         if self.bounds.len() > 0 {
891             let mut s = format!("{}: {}",
892                                 self.lifetime.name.name(),
893                                 self.bounds[0].name.name());
894             for bound in self.bounds.iter().skip(1) {
895                 s.push_str(&format!(" + {}", bound.name.name()));
896             }
897             Lifetime(s)
898         } else {
899             Lifetime(self.lifetime.name.name().to_string())
900         }
901     }
902 }
903
904 impl Clean<Lifetime> for ty::RegionParameterDef {
905     fn clean(&self, _: &DocContext) -> Lifetime {
906         Lifetime(self.name.to_string())
907     }
908 }
909
910 impl Clean<Option<Lifetime>> for ty::RegionKind {
911     fn clean(&self, cx: &DocContext) -> Option<Lifetime> {
912         match *self {
913             ty::ReStatic => Some(Lifetime::statik()),
914             ty::ReLateBound(_, ty::BrNamed(_, name)) => Some(Lifetime(name.to_string())),
915             ty::ReEarlyBound(ref data) => Some(Lifetime(data.name.clean(cx))),
916
917             ty::ReLateBound(..) |
918             ty::ReFree(..) |
919             ty::ReScope(..) |
920             ty::ReVar(..) |
921             ty::ReSkolemized(..) |
922             ty::ReEmpty |
923             ty::ReErased => None
924         }
925     }
926 }
927
928 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
929 pub enum WherePredicate {
930     BoundPredicate { ty: Type, bounds: Vec<TyParamBound> },
931     RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>},
932     EqPredicate { lhs: Type, rhs: Type },
933 }
934
935 impl Clean<WherePredicate> for hir::WherePredicate {
936     fn clean(&self, cx: &DocContext) -> WherePredicate {
937         match *self {
938             hir::WherePredicate::BoundPredicate(ref wbp) => {
939                 WherePredicate::BoundPredicate {
940                     ty: wbp.bounded_ty.clean(cx),
941                     bounds: wbp.bounds.clean(cx)
942                 }
943             }
944
945             hir::WherePredicate::RegionPredicate(ref wrp) => {
946                 WherePredicate::RegionPredicate {
947                     lifetime: wrp.lifetime.clean(cx),
948                     bounds: wrp.bounds.clean(cx)
949                 }
950             }
951
952             hir::WherePredicate::EqPredicate(ref wrp) => {
953                 WherePredicate::EqPredicate {
954                     lhs: wrp.lhs_ty.clean(cx),
955                     rhs: wrp.rhs_ty.clean(cx)
956                 }
957             }
958         }
959     }
960 }
961
962 impl<'a> Clean<WherePredicate> for ty::Predicate<'a> {
963     fn clean(&self, cx: &DocContext) -> WherePredicate {
964         use rustc::ty::Predicate;
965
966         match *self {
967             Predicate::Trait(ref pred) => pred.clean(cx),
968             Predicate::Equate(ref pred) => pred.clean(cx),
969             Predicate::Subtype(ref pred) => pred.clean(cx),
970             Predicate::RegionOutlives(ref pred) => pred.clean(cx),
971             Predicate::TypeOutlives(ref pred) => pred.clean(cx),
972             Predicate::Projection(ref pred) => pred.clean(cx),
973             Predicate::WellFormed(_) => panic!("not user writable"),
974             Predicate::ObjectSafe(_) => panic!("not user writable"),
975             Predicate::ClosureKind(..) => panic!("not user writable"),
976             Predicate::ConstEvaluatable(..) => panic!("not user writable"),
977         }
978     }
979 }
980
981 impl<'a> Clean<WherePredicate> for ty::TraitPredicate<'a> {
982     fn clean(&self, cx: &DocContext) -> WherePredicate {
983         WherePredicate::BoundPredicate {
984             ty: self.trait_ref.self_ty().clean(cx),
985             bounds: vec![self.trait_ref.clean(cx)]
986         }
987     }
988 }
989
990 impl<'tcx> Clean<WherePredicate> for ty::EquatePredicate<'tcx> {
991     fn clean(&self, cx: &DocContext) -> WherePredicate {
992         let ty::EquatePredicate(ref lhs, ref rhs) = *self;
993         WherePredicate::EqPredicate {
994             lhs: lhs.clean(cx),
995             rhs: rhs.clean(cx)
996         }
997     }
998 }
999
1000 impl<'tcx> Clean<WherePredicate> for ty::SubtypePredicate<'tcx> {
1001     fn clean(&self, _cx: &DocContext) -> WherePredicate {
1002         panic!("subtype predicates are an internal rustc artifact \
1003                 and should not be seen by rustdoc")
1004     }
1005 }
1006
1007 impl<'tcx> Clean<WherePredicate> for ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>> {
1008     fn clean(&self, cx: &DocContext) -> WherePredicate {
1009         let ty::OutlivesPredicate(ref a, ref b) = *self;
1010         WherePredicate::RegionPredicate {
1011             lifetime: a.clean(cx).unwrap(),
1012             bounds: vec![b.clean(cx).unwrap()]
1013         }
1014     }
1015 }
1016
1017 impl<'tcx> Clean<WherePredicate> for ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>> {
1018     fn clean(&self, cx: &DocContext) -> WherePredicate {
1019         let ty::OutlivesPredicate(ref ty, ref lt) = *self;
1020
1021         WherePredicate::BoundPredicate {
1022             ty: ty.clean(cx),
1023             bounds: vec![TyParamBound::RegionBound(lt.clean(cx).unwrap())]
1024         }
1025     }
1026 }
1027
1028 impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
1029     fn clean(&self, cx: &DocContext) -> WherePredicate {
1030         WherePredicate::EqPredicate {
1031             lhs: self.projection_ty.clean(cx),
1032             rhs: self.ty.clean(cx)
1033         }
1034     }
1035 }
1036
1037 impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
1038     fn clean(&self, cx: &DocContext) -> Type {
1039         let trait_ = match self.trait_ref(cx.tcx).clean(cx) {
1040             TyParamBound::TraitBound(t, _) => t.trait_,
1041             TyParamBound::RegionBound(_) => {
1042                 panic!("cleaning a trait got a region")
1043             }
1044         };
1045         Type::QPath {
1046             name: cx.tcx.associated_item(self.item_def_id).name.clean(cx),
1047             self_type: box self.self_ty().clean(cx),
1048             trait_: box trait_
1049         }
1050     }
1051 }
1052
1053 // maybe use a Generic enum and use Vec<Generic>?
1054 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1055 pub struct Generics {
1056     pub lifetimes: Vec<Lifetime>,
1057     pub type_params: Vec<TyParam>,
1058     pub where_predicates: Vec<WherePredicate>
1059 }
1060
1061 impl Clean<Generics> for hir::Generics {
1062     fn clean(&self, cx: &DocContext) -> Generics {
1063         Generics {
1064             lifetimes: self.lifetimes.clean(cx),
1065             type_params: self.ty_params.clean(cx),
1066             where_predicates: self.where_clause.predicates.clean(cx)
1067         }
1068     }
1069 }
1070
1071 impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
1072                                     &'a ty::GenericPredicates<'tcx>) {
1073     fn clean(&self, cx: &DocContext) -> Generics {
1074         use self::WherePredicate as WP;
1075
1076         let (gens, preds) = *self;
1077
1078         // Bounds in the type_params and lifetimes fields are repeated in the
1079         // predicates field (see rustc_typeck::collect::ty_generics), so remove
1080         // them.
1081         let stripped_typarams = gens.types.iter().filter_map(|tp| {
1082             if tp.name == keywords::SelfType.name() {
1083                 assert_eq!(tp.index, 0);
1084                 None
1085             } else {
1086                 Some(tp.clean(cx))
1087             }
1088         }).collect::<Vec<_>>();
1089
1090         let mut where_predicates = preds.predicates.to_vec().clean(cx);
1091
1092         // Type parameters and have a Sized bound by default unless removed with
1093         // ?Sized.  Scan through the predicates and mark any type parameter with
1094         // a Sized bound, removing the bounds as we find them.
1095         //
1096         // Note that associated types also have a sized bound by default, but we
1097         // don't actually know the set of associated types right here so that's
1098         // handled in cleaning associated types
1099         let mut sized_params = FxHashSet();
1100         where_predicates.retain(|pred| {
1101             match *pred {
1102                 WP::BoundPredicate { ty: Generic(ref g), ref bounds } => {
1103                     if bounds.iter().any(|b| b.is_sized_bound(cx)) {
1104                         sized_params.insert(g.clone());
1105                         false
1106                     } else {
1107                         true
1108                     }
1109                 }
1110                 _ => true,
1111             }
1112         });
1113
1114         // Run through the type parameters again and insert a ?Sized
1115         // unbound for any we didn't find to be Sized.
1116         for tp in &stripped_typarams {
1117             if !sized_params.contains(&tp.name) {
1118                 where_predicates.push(WP::BoundPredicate {
1119                     ty: Type::Generic(tp.name.clone()),
1120                     bounds: vec![TyParamBound::maybe_sized(cx)],
1121                 })
1122             }
1123         }
1124
1125         // It would be nice to collect all of the bounds on a type and recombine
1126         // them if possible, to avoid e.g. `where T: Foo, T: Bar, T: Sized, T: 'a`
1127         // and instead see `where T: Foo + Bar + Sized + 'a`
1128
1129         Generics {
1130             type_params: simplify::ty_params(stripped_typarams),
1131             lifetimes: gens.regions.clean(cx),
1132             where_predicates: simplify::where_clauses(cx, where_predicates),
1133         }
1134     }
1135 }
1136
1137 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1138 pub struct Method {
1139     pub generics: Generics,
1140     pub unsafety: hir::Unsafety,
1141     pub constness: hir::Constness,
1142     pub decl: FnDecl,
1143     pub abi: Abi,
1144 }
1145
1146 impl<'a> Clean<Method> for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId) {
1147     fn clean(&self, cx: &DocContext) -> Method {
1148         Method {
1149             generics: self.1.clean(cx),
1150             unsafety: self.0.unsafety,
1151             constness: self.0.constness,
1152             decl: (&*self.0.decl, self.2).clean(cx),
1153             abi: self.0.abi
1154         }
1155     }
1156 }
1157
1158 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1159 pub struct TyMethod {
1160     pub unsafety: hir::Unsafety,
1161     pub decl: FnDecl,
1162     pub generics: Generics,
1163     pub abi: Abi,
1164 }
1165
1166 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1167 pub struct Function {
1168     pub decl: FnDecl,
1169     pub generics: Generics,
1170     pub unsafety: hir::Unsafety,
1171     pub constness: hir::Constness,
1172     pub abi: Abi,
1173 }
1174
1175 impl Clean<Item> for doctree::Function {
1176     fn clean(&self, cx: &DocContext) -> Item {
1177         Item {
1178             name: Some(self.name.clean(cx)),
1179             attrs: self.attrs.clean(cx),
1180             source: self.whence.clean(cx),
1181             visibility: self.vis.clean(cx),
1182             stability: self.stab.clean(cx),
1183             deprecation: self.depr.clean(cx),
1184             def_id: cx.tcx.hir.local_def_id(self.id),
1185             inner: FunctionItem(Function {
1186                 decl: (&self.decl, self.body).clean(cx),
1187                 generics: self.generics.clean(cx),
1188                 unsafety: self.unsafety,
1189                 constness: self.constness,
1190                 abi: self.abi,
1191             }),
1192         }
1193     }
1194 }
1195
1196 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1197 pub struct FnDecl {
1198     pub inputs: Arguments,
1199     pub output: FunctionRetTy,
1200     pub variadic: bool,
1201     pub attrs: Attributes,
1202 }
1203
1204 impl FnDecl {
1205     pub fn has_self(&self) -> bool {
1206         self.inputs.values.len() > 0 && self.inputs.values[0].name == "self"
1207     }
1208
1209     pub fn self_type(&self) -> Option<SelfTy> {
1210         self.inputs.values.get(0).and_then(|v| v.to_self())
1211     }
1212 }
1213
1214 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1215 pub struct Arguments {
1216     pub values: Vec<Argument>,
1217 }
1218
1219 impl<'a> Clean<Arguments> for (&'a [P<hir::Ty>], &'a [Spanned<ast::Name>]) {
1220     fn clean(&self, cx: &DocContext) -> Arguments {
1221         Arguments {
1222             values: self.0.iter().enumerate().map(|(i, ty)| {
1223                 let mut name = self.1.get(i).map(|n| n.node.to_string())
1224                                             .unwrap_or(String::new());
1225                 if name.is_empty() {
1226                     name = "_".to_string();
1227                 }
1228                 Argument {
1229                     name,
1230                     type_: ty.clean(cx),
1231                 }
1232             }).collect()
1233         }
1234     }
1235 }
1236
1237 impl<'a> Clean<Arguments> for (&'a [P<hir::Ty>], hir::BodyId) {
1238     fn clean(&self, cx: &DocContext) -> Arguments {
1239         let body = cx.tcx.hir.body(self.1);
1240
1241         Arguments {
1242             values: self.0.iter().enumerate().map(|(i, ty)| {
1243                 Argument {
1244                     name: name_from_pat(&body.arguments[i].pat),
1245                     type_: ty.clean(cx),
1246                 }
1247             }).collect()
1248         }
1249     }
1250 }
1251
1252 impl<'a, A: Copy> Clean<FnDecl> for (&'a hir::FnDecl, A)
1253     where (&'a [P<hir::Ty>], A): Clean<Arguments>
1254 {
1255     fn clean(&self, cx: &DocContext) -> FnDecl {
1256         FnDecl {
1257             inputs: (&self.0.inputs[..], self.1).clean(cx),
1258             output: self.0.output.clean(cx),
1259             variadic: self.0.variadic,
1260             attrs: Attributes::default()
1261         }
1262     }
1263 }
1264
1265 impl<'a, 'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
1266     fn clean(&self, cx: &DocContext) -> FnDecl {
1267         let (did, sig) = *self;
1268         let mut names = if cx.tcx.hir.as_local_node_id(did).is_some() {
1269             vec![].into_iter()
1270         } else {
1271             cx.tcx.fn_arg_names(did).into_iter()
1272         }.peekable();
1273         FnDecl {
1274             output: Return(sig.skip_binder().output().clean(cx)),
1275             attrs: Attributes::default(),
1276             variadic: sig.skip_binder().variadic,
1277             inputs: Arguments {
1278                 values: sig.skip_binder().inputs().iter().map(|t| {
1279                     Argument {
1280                         type_: t.clean(cx),
1281                         name: names.next().map_or("".to_string(), |name| name.to_string()),
1282                     }
1283                 }).collect(),
1284             },
1285         }
1286     }
1287 }
1288
1289 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1290 pub struct Argument {
1291     pub type_: Type,
1292     pub name: String,
1293 }
1294
1295 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1296 pub enum SelfTy {
1297     SelfValue,
1298     SelfBorrowed(Option<Lifetime>, Mutability),
1299     SelfExplicit(Type),
1300 }
1301
1302 impl Argument {
1303     pub fn to_self(&self) -> Option<SelfTy> {
1304         if self.name != "self" {
1305             return None;
1306         }
1307         if self.type_.is_self_type() {
1308             return Some(SelfValue);
1309         }
1310         match self.type_ {
1311             BorrowedRef{ref lifetime, mutability, ref type_} if type_.is_self_type() => {
1312                 Some(SelfBorrowed(lifetime.clone(), mutability))
1313             }
1314             _ => Some(SelfExplicit(self.type_.clone()))
1315         }
1316     }
1317 }
1318
1319 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1320 pub enum FunctionRetTy {
1321     Return(Type),
1322     DefaultReturn,
1323 }
1324
1325 impl Clean<FunctionRetTy> for hir::FunctionRetTy {
1326     fn clean(&self, cx: &DocContext) -> FunctionRetTy {
1327         match *self {
1328             hir::Return(ref typ) => Return(typ.clean(cx)),
1329             hir::DefaultReturn(..) => DefaultReturn,
1330         }
1331     }
1332 }
1333
1334 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1335 pub struct Trait {
1336     pub unsafety: hir::Unsafety,
1337     pub items: Vec<Item>,
1338     pub generics: Generics,
1339     pub bounds: Vec<TyParamBound>,
1340 }
1341
1342 impl Clean<Item> for doctree::Trait {
1343     fn clean(&self, cx: &DocContext) -> Item {
1344         Item {
1345             name: Some(self.name.clean(cx)),
1346             attrs: self.attrs.clean(cx),
1347             source: self.whence.clean(cx),
1348             def_id: cx.tcx.hir.local_def_id(self.id),
1349             visibility: self.vis.clean(cx),
1350             stability: self.stab.clean(cx),
1351             deprecation: self.depr.clean(cx),
1352             inner: TraitItem(Trait {
1353                 unsafety: self.unsafety,
1354                 items: self.items.clean(cx),
1355                 generics: self.generics.clean(cx),
1356                 bounds: self.bounds.clean(cx),
1357             }),
1358         }
1359     }
1360 }
1361
1362 impl Clean<Type> for hir::TraitRef {
1363     fn clean(&self, cx: &DocContext) -> Type {
1364         resolve_type(cx, self.path.clean(cx), self.ref_id)
1365     }
1366 }
1367
1368 impl Clean<PolyTrait> for hir::PolyTraitRef {
1369     fn clean(&self, cx: &DocContext) -> PolyTrait {
1370         PolyTrait {
1371             trait_: self.trait_ref.clean(cx),
1372             lifetimes: self.bound_lifetimes.clean(cx)
1373         }
1374     }
1375 }
1376
1377 impl Clean<Item> for hir::TraitItem {
1378     fn clean(&self, cx: &DocContext) -> Item {
1379         let inner = match self.node {
1380             hir::TraitItemKind::Const(ref ty, default) => {
1381                 AssociatedConstItem(ty.clean(cx),
1382                                     default.map(|e| print_const_expr(cx, e)))
1383             }
1384             hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
1385                 MethodItem((sig, &self.generics, body).clean(cx))
1386             }
1387             hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => {
1388                 TyMethodItem(TyMethod {
1389                     unsafety: sig.unsafety.clone(),
1390                     decl: (&*sig.decl, &names[..]).clean(cx),
1391                     generics: self.generics.clean(cx),
1392                     abi: sig.abi
1393                 })
1394             }
1395             hir::TraitItemKind::Type(ref bounds, ref default) => {
1396                 AssociatedTypeItem(bounds.clean(cx), default.clean(cx))
1397             }
1398         };
1399         Item {
1400             name: Some(self.name.clean(cx)),
1401             attrs: self.attrs.clean(cx),
1402             source: self.span.clean(cx),
1403             def_id: cx.tcx.hir.local_def_id(self.id),
1404             visibility: None,
1405             stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)),
1406             deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)),
1407             inner,
1408         }
1409     }
1410 }
1411
1412 impl Clean<Item> for hir::ImplItem {
1413     fn clean(&self, cx: &DocContext) -> Item {
1414         let inner = match self.node {
1415             hir::ImplItemKind::Const(ref ty, expr) => {
1416                 AssociatedConstItem(ty.clean(cx),
1417                                     Some(print_const_expr(cx, expr)))
1418             }
1419             hir::ImplItemKind::Method(ref sig, body) => {
1420                 MethodItem((sig, &self.generics, body).clean(cx))
1421             }
1422             hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef {
1423                 type_: ty.clean(cx),
1424                 generics: Generics {
1425                     lifetimes: Vec::new(),
1426                     type_params: Vec::new(),
1427                     where_predicates: Vec::new()
1428                 },
1429             }, true),
1430         };
1431         Item {
1432             name: Some(self.name.clean(cx)),
1433             source: self.span.clean(cx),
1434             attrs: self.attrs.clean(cx),
1435             def_id: cx.tcx.hir.local_def_id(self.id),
1436             visibility: self.vis.clean(cx),
1437             stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)),
1438             deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)),
1439             inner,
1440         }
1441     }
1442 }
1443
1444 impl<'tcx> Clean<Item> for ty::AssociatedItem {
1445     fn clean(&self, cx: &DocContext) -> Item {
1446         let inner = match self.kind {
1447             ty::AssociatedKind::Const => {
1448                 let ty = cx.tcx.type_of(self.def_id);
1449                 AssociatedConstItem(ty.clean(cx), None)
1450             }
1451             ty::AssociatedKind::Method => {
1452                 let generics = (cx.tcx.generics_of(self.def_id),
1453                                 &cx.tcx.predicates_of(self.def_id)).clean(cx);
1454                 let sig = cx.tcx.fn_sig(self.def_id);
1455                 let mut decl = (self.def_id, sig).clean(cx);
1456
1457                 if self.method_has_self_argument {
1458                     let self_ty = match self.container {
1459                         ty::ImplContainer(def_id) => {
1460                             cx.tcx.type_of(def_id)
1461                         }
1462                         ty::TraitContainer(_) => cx.tcx.mk_self_type()
1463                     };
1464                     let self_arg_ty = *sig.input(0).skip_binder();
1465                     if self_arg_ty == self_ty {
1466                         decl.inputs.values[0].type_ = Generic(String::from("Self"));
1467                     } else if let ty::TyRef(_, mt) = self_arg_ty.sty {
1468                         if mt.ty == self_ty {
1469                             match decl.inputs.values[0].type_ {
1470                                 BorrowedRef{ref mut type_, ..} => {
1471                                     **type_ = Generic(String::from("Self"))
1472                                 }
1473                                 _ => unreachable!(),
1474                             }
1475                         }
1476                     }
1477                 }
1478
1479                 let provided = match self.container {
1480                     ty::ImplContainer(_) => false,
1481                     ty::TraitContainer(_) => self.defaultness.has_value()
1482                 };
1483                 if provided {
1484                     MethodItem(Method {
1485                         unsafety: sig.unsafety(),
1486                         generics,
1487                         decl,
1488                         abi: sig.abi(),
1489
1490                         // trait methods cannot (currently, at least) be const
1491                         constness: hir::Constness::NotConst,
1492                     })
1493                 } else {
1494                     TyMethodItem(TyMethod {
1495                         unsafety: sig.unsafety(),
1496                         generics,
1497                         decl,
1498                         abi: sig.abi(),
1499                     })
1500                 }
1501             }
1502             ty::AssociatedKind::Type => {
1503                 let my_name = self.name.clean(cx);
1504
1505                 let mut bounds = if let ty::TraitContainer(did) = self.container {
1506                     // When loading a cross-crate associated type, the bounds for this type
1507                     // are actually located on the trait/impl itself, so we need to load
1508                     // all of the generics from there and then look for bounds that are
1509                     // applied to this associated type in question.
1510                     let predicates = cx.tcx.predicates_of(did);
1511                     let generics = (cx.tcx.generics_of(did), &predicates).clean(cx);
1512                     generics.where_predicates.iter().filter_map(|pred| {
1513                         let (name, self_type, trait_, bounds) = match *pred {
1514                             WherePredicate::BoundPredicate {
1515                                 ty: QPath { ref name, ref self_type, ref trait_ },
1516                                 ref bounds
1517                             } => (name, self_type, trait_, bounds),
1518                             _ => return None,
1519                         };
1520                         if *name != my_name { return None }
1521                         match **trait_ {
1522                             ResolvedPath { did, .. } if did == self.container.id() => {}
1523                             _ => return None,
1524                         }
1525                         match **self_type {
1526                             Generic(ref s) if *s == "Self" => {}
1527                             _ => return None,
1528                         }
1529                         Some(bounds)
1530                     }).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>()
1531                 } else {
1532                     vec![]
1533                 };
1534
1535                 // Our Sized/?Sized bound didn't get handled when creating the generics
1536                 // because we didn't actually get our whole set of bounds until just now
1537                 // (some of them may have come from the trait). If we do have a sized
1538                 // bound, we remove it, and if we don't then we add the `?Sized` bound
1539                 // at the end.
1540                 match bounds.iter().position(|b| b.is_sized_bound(cx)) {
1541                     Some(i) => { bounds.remove(i); }
1542                     None => bounds.push(TyParamBound::maybe_sized(cx)),
1543                 }
1544
1545                 let ty = if self.defaultness.has_value() {
1546                     Some(cx.tcx.type_of(self.def_id))
1547                 } else {
1548                     None
1549                 };
1550
1551                 AssociatedTypeItem(bounds, ty.clean(cx))
1552             }
1553         };
1554
1555         Item {
1556             name: Some(self.name.clean(cx)),
1557             visibility: Some(Inherited),
1558             stability: get_stability(cx, self.def_id),
1559             deprecation: get_deprecation(cx, self.def_id),
1560             def_id: self.def_id,
1561             attrs: inline::load_attrs(cx, self.def_id),
1562             source: cx.tcx.def_span(self.def_id).clean(cx),
1563             inner,
1564         }
1565     }
1566 }
1567
1568 /// A trait reference, which may have higher ranked lifetimes.
1569 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1570 pub struct PolyTrait {
1571     pub trait_: Type,
1572     pub lifetimes: Vec<Lifetime>
1573 }
1574
1575 /// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
1576 /// type out of the AST/TyCtxt given one of these, if more information is needed. Most importantly
1577 /// it does not preserve mutability or boxes.
1578 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1579 pub enum Type {
1580     /// structs/enums/traits (most that'd be an hir::TyPath)
1581     ResolvedPath {
1582         path: Path,
1583         typarams: Option<Vec<TyParamBound>>,
1584         did: DefId,
1585         /// true if is a `T::Name` path for associated types
1586         is_generic: bool,
1587     },
1588     /// For parameterized types, so the consumer of the JSON don't go
1589     /// looking for types which don't exist anywhere.
1590     Generic(String),
1591     /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
1592     /// arrays, slices, and tuples.
1593     Primitive(PrimitiveType),
1594     /// extern "ABI" fn
1595     BareFunction(Box<BareFunctionDecl>),
1596     Tuple(Vec<Type>),
1597     Slice(Box<Type>),
1598     Array(Box<Type>, String),
1599     Never,
1600     Unique(Box<Type>),
1601     RawPointer(Mutability, Box<Type>),
1602     BorrowedRef {
1603         lifetime: Option<Lifetime>,
1604         mutability: Mutability,
1605         type_: Box<Type>,
1606     },
1607
1608     // <Type as Trait>::Name
1609     QPath {
1610         name: String,
1611         self_type: Box<Type>,
1612         trait_: Box<Type>
1613     },
1614
1615     // _
1616     Infer,
1617
1618     // impl TraitA+TraitB
1619     ImplTrait(Vec<TyParamBound>),
1620 }
1621
1622 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
1623 pub enum PrimitiveType {
1624     Isize, I8, I16, I32, I64, I128,
1625     Usize, U8, U16, U32, U64, U128,
1626     F32, F64,
1627     Char,
1628     Bool,
1629     Str,
1630     Slice,
1631     Array,
1632     Tuple,
1633     Unit,
1634     RawPointer,
1635     Reference,
1636     Fn,
1637 }
1638
1639 #[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
1640 pub enum TypeKind {
1641     Enum,
1642     Function,
1643     Module,
1644     Const,
1645     Static,
1646     Struct,
1647     Union,
1648     Trait,
1649     Variant,
1650     Typedef,
1651     Foreign,
1652 }
1653
1654 pub trait GetDefId {
1655     fn def_id(&self) -> Option<DefId>;
1656 }
1657
1658 impl<T: GetDefId> GetDefId for Option<T> {
1659     fn def_id(&self) -> Option<DefId> {
1660         self.as_ref().and_then(|d| d.def_id())
1661     }
1662 }
1663
1664 impl Type {
1665     pub fn primitive_type(&self) -> Option<PrimitiveType> {
1666         match *self {
1667             Primitive(p) | BorrowedRef { type_: box Primitive(p), ..} => Some(p),
1668             Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1669             Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1670             Tuple(ref tys) => if tys.is_empty() {
1671                 Some(PrimitiveType::Unit)
1672             } else {
1673                 Some(PrimitiveType::Tuple)
1674             },
1675             RawPointer(..) => Some(PrimitiveType::RawPointer),
1676             BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
1677             BareFunction(..) => Some(PrimitiveType::Fn),
1678             _ => None,
1679         }
1680     }
1681
1682     pub fn is_generic(&self) -> bool {
1683         match *self {
1684             ResolvedPath { is_generic, .. } => is_generic,
1685             _ => false,
1686         }
1687     }
1688
1689     pub fn is_self_type(&self) -> bool {
1690         match *self {
1691             Generic(ref name) => name == "Self",
1692             _ => false
1693         }
1694     }
1695
1696     pub fn generics(&self) -> Option<&[Type]> {
1697         match *self {
1698             ResolvedPath { ref path, .. } => {
1699                 path.segments.last().and_then(|seg| {
1700                     if let PathParameters::AngleBracketed { ref types, .. } = seg.params {
1701                         Some(&**types)
1702                     } else {
1703                         None
1704                     }
1705                 })
1706             }
1707             _ => None,
1708         }
1709     }
1710 }
1711
1712 impl GetDefId for Type {
1713     fn def_id(&self) -> Option<DefId> {
1714         match *self {
1715             ResolvedPath { did, .. } => Some(did),
1716             Primitive(p) => ::html::render::cache().primitive_locations.get(&p).cloned(),
1717             BorrowedRef { type_: box Generic(..), .. } =>
1718                 Primitive(PrimitiveType::Reference).def_id(),
1719             BorrowedRef { ref type_, .. } => type_.def_id(),
1720             Tuple(ref tys) => if tys.is_empty() {
1721                 Primitive(PrimitiveType::Unit).def_id()
1722             } else {
1723                 Primitive(PrimitiveType::Tuple).def_id()
1724             },
1725             BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
1726             Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
1727             Array(..) => Primitive(PrimitiveType::Array).def_id(),
1728             RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(),
1729             QPath { ref self_type, .. } => self_type.def_id(),
1730             _ => None,
1731         }
1732     }
1733 }
1734
1735 impl PrimitiveType {
1736     fn from_str(s: &str) -> Option<PrimitiveType> {
1737         match s {
1738             "isize" => Some(PrimitiveType::Isize),
1739             "i8" => Some(PrimitiveType::I8),
1740             "i16" => Some(PrimitiveType::I16),
1741             "i32" => Some(PrimitiveType::I32),
1742             "i64" => Some(PrimitiveType::I64),
1743             "i128" => Some(PrimitiveType::I128),
1744             "usize" => Some(PrimitiveType::Usize),
1745             "u8" => Some(PrimitiveType::U8),
1746             "u16" => Some(PrimitiveType::U16),
1747             "u32" => Some(PrimitiveType::U32),
1748             "u64" => Some(PrimitiveType::U64),
1749             "u128" => Some(PrimitiveType::U128),
1750             "bool" => Some(PrimitiveType::Bool),
1751             "char" => Some(PrimitiveType::Char),
1752             "str" => Some(PrimitiveType::Str),
1753             "f32" => Some(PrimitiveType::F32),
1754             "f64" => Some(PrimitiveType::F64),
1755             "array" => Some(PrimitiveType::Array),
1756             "slice" => Some(PrimitiveType::Slice),
1757             "tuple" => Some(PrimitiveType::Tuple),
1758             "unit" => Some(PrimitiveType::Unit),
1759             "pointer" => Some(PrimitiveType::RawPointer),
1760             "reference" => Some(PrimitiveType::Reference),
1761             "fn" => Some(PrimitiveType::Fn),
1762             _ => None,
1763         }
1764     }
1765
1766     pub fn as_str(&self) -> &'static str {
1767         use self::PrimitiveType::*;
1768         match *self {
1769             Isize => "isize",
1770             I8 => "i8",
1771             I16 => "i16",
1772             I32 => "i32",
1773             I64 => "i64",
1774             I128 => "i128",
1775             Usize => "usize",
1776             U8 => "u8",
1777             U16 => "u16",
1778             U32 => "u32",
1779             U64 => "u64",
1780             U128 => "u128",
1781             F32 => "f32",
1782             F64 => "f64",
1783             Str => "str",
1784             Bool => "bool",
1785             Char => "char",
1786             Array => "array",
1787             Slice => "slice",
1788             Tuple => "tuple",
1789             Unit => "unit",
1790             RawPointer => "pointer",
1791             Reference => "reference",
1792             Fn => "fn",
1793         }
1794     }
1795
1796     pub fn to_url_str(&self) -> &'static str {
1797         self.as_str()
1798     }
1799 }
1800
1801 impl From<ast::IntTy> for PrimitiveType {
1802     fn from(int_ty: ast::IntTy) -> PrimitiveType {
1803         match int_ty {
1804             ast::IntTy::Is => PrimitiveType::Isize,
1805             ast::IntTy::I8 => PrimitiveType::I8,
1806             ast::IntTy::I16 => PrimitiveType::I16,
1807             ast::IntTy::I32 => PrimitiveType::I32,
1808             ast::IntTy::I64 => PrimitiveType::I64,
1809             ast::IntTy::I128 => PrimitiveType::I128,
1810         }
1811     }
1812 }
1813
1814 impl From<ast::UintTy> for PrimitiveType {
1815     fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1816         match uint_ty {
1817             ast::UintTy::Us => PrimitiveType::Usize,
1818             ast::UintTy::U8 => PrimitiveType::U8,
1819             ast::UintTy::U16 => PrimitiveType::U16,
1820             ast::UintTy::U32 => PrimitiveType::U32,
1821             ast::UintTy::U64 => PrimitiveType::U64,
1822             ast::UintTy::U128 => PrimitiveType::U128,
1823         }
1824     }
1825 }
1826
1827 impl From<ast::FloatTy> for PrimitiveType {
1828     fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1829         match float_ty {
1830             ast::FloatTy::F32 => PrimitiveType::F32,
1831             ast::FloatTy::F64 => PrimitiveType::F64,
1832         }
1833     }
1834 }
1835
1836 impl Clean<Type> for hir::Ty {
1837     fn clean(&self, cx: &DocContext) -> Type {
1838         use rustc::hir::*;
1839         match self.node {
1840             TyNever => Never,
1841             TyPtr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
1842             TyRptr(ref l, ref m) => {
1843                 let lifetime = if l.is_elided() {
1844                     None
1845                 } else {
1846                     Some(l.clean(cx))
1847                 };
1848                 BorrowedRef {lifetime: lifetime, mutability: m.mutbl.clean(cx),
1849                              type_: box m.ty.clean(cx)}
1850             }
1851             TySlice(ref ty) => Slice(box ty.clean(cx)),
1852             TyArray(ref ty, n) => {
1853                 let def_id = cx.tcx.hir.body_owner_def_id(n);
1854                 let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
1855                 let substs = Substs::identity_for_item(cx.tcx, def_id);
1856                 let n = cx.tcx.const_eval(param_env.and((def_id, substs))).unwrap();
1857                 let n = if let ConstVal::Integral(ConstInt::Usize(n)) = n.val {
1858                     n.to_string()
1859                 } else if let ConstVal::Unevaluated(def_id, _) = n.val {
1860                     if let Some(node_id) = cx.tcx.hir.as_local_node_id(def_id) {
1861                         print_const_expr(cx, cx.tcx.hir.body_owned_by(node_id))
1862                     } else {
1863                         inline::print_inlined_const(cx, def_id)
1864                     }
1865                 } else {
1866                     format!("{:?}", n)
1867                 };
1868                 Array(box ty.clean(cx), n)
1869             },
1870             TyTup(ref tys) => Tuple(tys.clean(cx)),
1871             TyPath(hir::QPath::Resolved(None, ref path)) => {
1872                 if let Some(new_ty) = cx.ty_substs.borrow().get(&path.def).cloned() {
1873                     return new_ty;
1874                 }
1875
1876                 let mut alias = None;
1877                 if let Def::TyAlias(def_id) = path.def {
1878                     // Substitute private type aliases
1879                     if let Some(node_id) = cx.tcx.hir.as_local_node_id(def_id) {
1880                         if !cx.access_levels.borrow().is_exported(def_id) {
1881                             alias = Some(&cx.tcx.hir.expect_item(node_id).node);
1882                         }
1883                     }
1884                 };
1885
1886                 if let Some(&hir::ItemTy(ref ty, ref generics)) = alias {
1887                     let provided_params = &path.segments.last().unwrap();
1888                     let mut ty_substs = FxHashMap();
1889                     let mut lt_substs = FxHashMap();
1890                     provided_params.with_parameters(|provided_params| {
1891                         for (i, ty_param) in generics.ty_params.iter().enumerate() {
1892                             let ty_param_def = Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id));
1893                             if let Some(ty) = provided_params.types.get(i).cloned() {
1894                                 ty_substs.insert(ty_param_def, ty.unwrap().clean(cx));
1895                             } else if let Some(default) = ty_param.default.clone() {
1896                                 ty_substs.insert(ty_param_def, default.unwrap().clean(cx));
1897                             }
1898                         }
1899                         for (i, lt_param) in generics.lifetimes.iter().enumerate() {
1900                             if let Some(lt) = provided_params.lifetimes.get(i).cloned() {
1901                                 if !lt.is_elided() {
1902                                     let lt_def_id = cx.tcx.hir.local_def_id(lt_param.lifetime.id);
1903                                     lt_substs.insert(lt_def_id, lt.clean(cx));
1904                                 }
1905                             }
1906                         }
1907                     });
1908                     return cx.enter_alias(ty_substs, lt_substs, || ty.clean(cx));
1909                 }
1910                 resolve_type(cx, path.clean(cx), self.id)
1911             }
1912             TyPath(hir::QPath::Resolved(Some(ref qself), ref p)) => {
1913                 let mut segments: Vec<_> = p.segments.clone().into();
1914                 segments.pop();
1915                 let trait_path = hir::Path {
1916                     span: p.span,
1917                     def: Def::Trait(cx.tcx.associated_item(p.def.def_id()).container.id()),
1918                     segments: segments.into(),
1919                 };
1920                 Type::QPath {
1921                     name: p.segments.last().unwrap().name.clean(cx),
1922                     self_type: box qself.clean(cx),
1923                     trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
1924                 }
1925             }
1926             TyPath(hir::QPath::TypeRelative(ref qself, ref segment)) => {
1927                 let mut def = Def::Err;
1928                 let ty = hir_ty_to_ty(cx.tcx, self);
1929                 if let ty::TyProjection(proj) = ty.sty {
1930                     def = Def::Trait(proj.trait_ref(cx.tcx).def_id);
1931                 }
1932                 let trait_path = hir::Path {
1933                     span: self.span,
1934                     def,
1935                     segments: vec![].into(),
1936                 };
1937                 Type::QPath {
1938                     name: segment.name.clean(cx),
1939                     self_type: box qself.clean(cx),
1940                     trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
1941                 }
1942             }
1943             TyTraitObject(ref bounds, ref lifetime) => {
1944                 match bounds[0].clean(cx).trait_ {
1945                     ResolvedPath { path, typarams: None, did, is_generic } => {
1946                         let mut bounds: Vec<_> = bounds[1..].iter().map(|bound| {
1947                             TraitBound(bound.clean(cx), hir::TraitBoundModifier::None)
1948                         }).collect();
1949                         if !lifetime.is_elided() {
1950                             bounds.push(RegionBound(lifetime.clean(cx)));
1951                         }
1952                         ResolvedPath {
1953                             path,
1954                             typarams: Some(bounds),
1955                             did,
1956                             is_generic,
1957                         }
1958                     }
1959                     _ => Infer // shouldn't happen
1960                 }
1961             }
1962             TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
1963             TyImplTraitExistential(ref exist_ty, ref _lts) => ImplTrait(exist_ty.bounds.clean(cx)),
1964             TyImplTraitUniversal(_, ref bounds) => ImplTrait(bounds.clean(cx)),
1965             TyInfer | TyErr => Infer,
1966             TyTypeof(..) => panic!("Unimplemented type {:?}", self.node),
1967         }
1968     }
1969 }
1970
1971 impl<'tcx> Clean<Type> for Ty<'tcx> {
1972     fn clean(&self, cx: &DocContext) -> Type {
1973         match self.sty {
1974             ty::TyNever => Never,
1975             ty::TyBool => Primitive(PrimitiveType::Bool),
1976             ty::TyChar => Primitive(PrimitiveType::Char),
1977             ty::TyInt(int_ty) => Primitive(int_ty.into()),
1978             ty::TyUint(uint_ty) => Primitive(uint_ty.into()),
1979             ty::TyFloat(float_ty) => Primitive(float_ty.into()),
1980             ty::TyStr => Primitive(PrimitiveType::Str),
1981             ty::TySlice(ty) => Slice(box ty.clean(cx)),
1982             ty::TyArray(ty, n) => {
1983                 let n = if let ConstVal::Integral(ConstInt::Usize(n)) = n.val {
1984                     n.to_string()
1985                 } else if let ConstVal::Unevaluated(def_id, _) = n.val {
1986                     if let Some(node_id) = cx.tcx.hir.as_local_node_id(def_id) {
1987                         print_const_expr(cx, cx.tcx.hir.body_owned_by(node_id))
1988                     } else {
1989                         inline::print_inlined_const(cx, def_id)
1990                     }
1991                 } else {
1992                     format!("{:?}", n)
1993                 };
1994                 Array(box ty.clean(cx), n)
1995             }
1996             ty::TyRawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
1997             ty::TyRef(r, mt) => BorrowedRef {
1998                 lifetime: r.clean(cx),
1999                 mutability: mt.mutbl.clean(cx),
2000                 type_: box mt.ty.clean(cx),
2001             },
2002             ty::TyFnDef(..) |
2003             ty::TyFnPtr(_) => {
2004                 let ty = cx.tcx.lift(self).unwrap();
2005                 let sig = ty.fn_sig(cx.tcx);
2006                 BareFunction(box BareFunctionDecl {
2007                     unsafety: sig.unsafety(),
2008                     generics: Generics {
2009                         lifetimes: Vec::new(),
2010                         type_params: Vec::new(),
2011                         where_predicates: Vec::new()
2012                     },
2013                     decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx),
2014                     abi: sig.abi(),
2015                 })
2016             }
2017             ty::TyAdt(def, substs) => {
2018                 let did = def.did;
2019                 let kind = match def.adt_kind() {
2020                     AdtKind::Struct => TypeKind::Struct,
2021                     AdtKind::Union => TypeKind::Union,
2022                     AdtKind::Enum => TypeKind::Enum,
2023                 };
2024                 inline::record_extern_fqn(cx, did, kind);
2025                 let path = external_path(cx, &cx.tcx.item_name(did),
2026                                          None, false, vec![], substs);
2027                 ResolvedPath {
2028                     path,
2029                     typarams: None,
2030                     did,
2031                     is_generic: false,
2032                 }
2033             }
2034             ty::TyForeign(did) => {
2035                 inline::record_extern_fqn(cx, did, TypeKind::Foreign);
2036                 let path = external_path(cx, &cx.tcx.item_name(did),
2037                                          None, false, vec![], Substs::empty());
2038                 ResolvedPath {
2039                     path: path,
2040                     typarams: None,
2041                     did: did,
2042                     is_generic: false,
2043                 }
2044             }
2045             ty::TyDynamic(ref obj, ref reg) => {
2046                 if let Some(principal) = obj.principal() {
2047                     let did = principal.def_id();
2048                     inline::record_extern_fqn(cx, did, TypeKind::Trait);
2049
2050                     let mut typarams = vec![];
2051                     reg.clean(cx).map(|b| typarams.push(RegionBound(b)));
2052                     for did in obj.auto_traits() {
2053                         let empty = cx.tcx.intern_substs(&[]);
2054                         let path = external_path(cx, &cx.tcx.item_name(did),
2055                             Some(did), false, vec![], empty);
2056                         inline::record_extern_fqn(cx, did, TypeKind::Trait);
2057                         let bound = TraitBound(PolyTrait {
2058                             trait_: ResolvedPath {
2059                                 path,
2060                                 typarams: None,
2061                                 did,
2062                                 is_generic: false,
2063                             },
2064                             lifetimes: vec![]
2065                         }, hir::TraitBoundModifier::None);
2066                         typarams.push(bound);
2067                     }
2068
2069                     let mut bindings = vec![];
2070                     for ty::Binder(ref pb) in obj.projection_bounds() {
2071                         bindings.push(TypeBinding {
2072                             name: cx.tcx.associated_item(pb.item_def_id).name.clean(cx),
2073                             ty: pb.ty.clean(cx)
2074                         });
2075                     }
2076
2077                     let path = external_path(cx, &cx.tcx.item_name(did), Some(did),
2078                         false, bindings, principal.0.substs);
2079                     ResolvedPath {
2080                         path,
2081                         typarams: Some(typarams),
2082                         did,
2083                         is_generic: false,
2084                     }
2085                 } else {
2086                     Never
2087                 }
2088             }
2089             ty::TyTuple(ref t, _) => Tuple(t.clean(cx)),
2090
2091             ty::TyProjection(ref data) => data.clean(cx),
2092
2093             ty::TyParam(ref p) => Generic(p.name.to_string()),
2094
2095             ty::TyAnon(def_id, substs) => {
2096                 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
2097                 // by looking up the projections associated with the def_id.
2098                 let predicates_of = cx.tcx.predicates_of(def_id);
2099                 let substs = cx.tcx.lift(&substs).unwrap();
2100                 let bounds = predicates_of.instantiate(cx.tcx, substs);
2101                 ImplTrait(bounds.predicates.into_iter().filter_map(|predicate| {
2102                     predicate.to_opt_poly_trait_ref().clean(cx)
2103                 }).collect())
2104             }
2105
2106             ty::TyClosure(..) | ty::TyGenerator(..) => Tuple(vec![]), // FIXME(pcwalton)
2107
2108             ty::TyInfer(..) => panic!("TyInfer"),
2109             ty::TyError => panic!("TyError"),
2110         }
2111     }
2112 }
2113
2114 impl Clean<Item> for hir::StructField {
2115     fn clean(&self, cx: &DocContext) -> Item {
2116         Item {
2117             name: Some(self.name).clean(cx),
2118             attrs: self.attrs.clean(cx),
2119             source: self.span.clean(cx),
2120             visibility: self.vis.clean(cx),
2121             stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)),
2122             deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)),
2123             def_id: cx.tcx.hir.local_def_id(self.id),
2124             inner: StructFieldItem(self.ty.clean(cx)),
2125         }
2126     }
2127 }
2128
2129 impl<'tcx> Clean<Item> for ty::FieldDef {
2130     fn clean(&self, cx: &DocContext) -> Item {
2131         Item {
2132             name: Some(self.name).clean(cx),
2133             attrs: cx.tcx.get_attrs(self.did).clean(cx),
2134             source: cx.tcx.def_span(self.did).clean(cx),
2135             visibility: self.vis.clean(cx),
2136             stability: get_stability(cx, self.did),
2137             deprecation: get_deprecation(cx, self.did),
2138             def_id: self.did,
2139             inner: StructFieldItem(cx.tcx.type_of(self.did).clean(cx)),
2140         }
2141     }
2142 }
2143
2144 #[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug)]
2145 pub enum Visibility {
2146     Public,
2147     Inherited,
2148 }
2149
2150 impl Clean<Option<Visibility>> for hir::Visibility {
2151     fn clean(&self, _: &DocContext) -> Option<Visibility> {
2152         Some(if *self == hir::Visibility::Public { Public } else { Inherited })
2153     }
2154 }
2155
2156 impl Clean<Option<Visibility>> for ty::Visibility {
2157     fn clean(&self, _: &DocContext) -> Option<Visibility> {
2158         Some(if *self == ty::Visibility::Public { Public } else { Inherited })
2159     }
2160 }
2161
2162 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2163 pub struct Struct {
2164     pub struct_type: doctree::StructType,
2165     pub generics: Generics,
2166     pub fields: Vec<Item>,
2167     pub fields_stripped: bool,
2168 }
2169
2170 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2171 pub struct Union {
2172     pub struct_type: doctree::StructType,
2173     pub generics: Generics,
2174     pub fields: Vec<Item>,
2175     pub fields_stripped: bool,
2176 }
2177
2178 impl Clean<Item> for doctree::Struct {
2179     fn clean(&self, cx: &DocContext) -> Item {
2180         Item {
2181             name: Some(self.name.clean(cx)),
2182             attrs: self.attrs.clean(cx),
2183             source: self.whence.clean(cx),
2184             def_id: cx.tcx.hir.local_def_id(self.id),
2185             visibility: self.vis.clean(cx),
2186             stability: self.stab.clean(cx),
2187             deprecation: self.depr.clean(cx),
2188             inner: StructItem(Struct {
2189                 struct_type: self.struct_type,
2190                 generics: self.generics.clean(cx),
2191                 fields: self.fields.clean(cx),
2192                 fields_stripped: false,
2193             }),
2194         }
2195     }
2196 }
2197
2198 impl Clean<Item> for doctree::Union {
2199     fn clean(&self, cx: &DocContext) -> Item {
2200         Item {
2201             name: Some(self.name.clean(cx)),
2202             attrs: self.attrs.clean(cx),
2203             source: self.whence.clean(cx),
2204             def_id: cx.tcx.hir.local_def_id(self.id),
2205             visibility: self.vis.clean(cx),
2206             stability: self.stab.clean(cx),
2207             deprecation: self.depr.clean(cx),
2208             inner: UnionItem(Union {
2209                 struct_type: self.struct_type,
2210                 generics: self.generics.clean(cx),
2211                 fields: self.fields.clean(cx),
2212                 fields_stripped: false,
2213             }),
2214         }
2215     }
2216 }
2217
2218 /// This is a more limited form of the standard Struct, different in that
2219 /// it lacks the things most items have (name, id, parameterization). Found
2220 /// only as a variant in an enum.
2221 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2222 pub struct VariantStruct {
2223     pub struct_type: doctree::StructType,
2224     pub fields: Vec<Item>,
2225     pub fields_stripped: bool,
2226 }
2227
2228 impl Clean<VariantStruct> for ::rustc::hir::VariantData {
2229     fn clean(&self, cx: &DocContext) -> VariantStruct {
2230         VariantStruct {
2231             struct_type: doctree::struct_type_from_def(self),
2232             fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
2233             fields_stripped: false,
2234         }
2235     }
2236 }
2237
2238 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2239 pub struct Enum {
2240     pub variants: Vec<Item>,
2241     pub generics: Generics,
2242     pub variants_stripped: bool,
2243 }
2244
2245 impl Clean<Item> for doctree::Enum {
2246     fn clean(&self, cx: &DocContext) -> Item {
2247         Item {
2248             name: Some(self.name.clean(cx)),
2249             attrs: self.attrs.clean(cx),
2250             source: self.whence.clean(cx),
2251             def_id: cx.tcx.hir.local_def_id(self.id),
2252             visibility: self.vis.clean(cx),
2253             stability: self.stab.clean(cx),
2254             deprecation: self.depr.clean(cx),
2255             inner: EnumItem(Enum {
2256                 variants: self.variants.clean(cx),
2257                 generics: self.generics.clean(cx),
2258                 variants_stripped: false,
2259             }),
2260         }
2261     }
2262 }
2263
2264 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2265 pub struct Variant {
2266     pub kind: VariantKind,
2267 }
2268
2269 impl Clean<Item> for doctree::Variant {
2270     fn clean(&self, cx: &DocContext) -> Item {
2271         Item {
2272             name: Some(self.name.clean(cx)),
2273             attrs: self.attrs.clean(cx),
2274             source: self.whence.clean(cx),
2275             visibility: None,
2276             stability: self.stab.clean(cx),
2277             deprecation: self.depr.clean(cx),
2278             def_id: cx.tcx.hir.local_def_id(self.def.id()),
2279             inner: VariantItem(Variant {
2280                 kind: self.def.clean(cx),
2281             }),
2282         }
2283     }
2284 }
2285
2286 impl<'tcx> Clean<Item> for ty::VariantDef {
2287     fn clean(&self, cx: &DocContext) -> Item {
2288         let kind = match self.ctor_kind {
2289             CtorKind::Const => VariantKind::CLike,
2290             CtorKind::Fn => {
2291                 VariantKind::Tuple(
2292                     self.fields.iter().map(|f| cx.tcx.type_of(f.did).clean(cx)).collect()
2293                 )
2294             }
2295             CtorKind::Fictive => {
2296                 VariantKind::Struct(VariantStruct {
2297                     struct_type: doctree::Plain,
2298                     fields_stripped: false,
2299                     fields: self.fields.iter().map(|field| {
2300                         Item {
2301                             source: cx.tcx.def_span(field.did).clean(cx),
2302                             name: Some(field.name.clean(cx)),
2303                             attrs: cx.tcx.get_attrs(field.did).clean(cx),
2304                             visibility: field.vis.clean(cx),
2305                             def_id: field.did,
2306                             stability: get_stability(cx, field.did),
2307                             deprecation: get_deprecation(cx, field.did),
2308                             inner: StructFieldItem(cx.tcx.type_of(field.did).clean(cx))
2309                         }
2310                     }).collect()
2311                 })
2312             }
2313         };
2314         Item {
2315             name: Some(self.name.clean(cx)),
2316             attrs: inline::load_attrs(cx, self.did),
2317             source: cx.tcx.def_span(self.did).clean(cx),
2318             visibility: Some(Inherited),
2319             def_id: self.did,
2320             inner: VariantItem(Variant { kind: kind }),
2321             stability: get_stability(cx, self.did),
2322             deprecation: get_deprecation(cx, self.did),
2323         }
2324     }
2325 }
2326
2327 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2328 pub enum VariantKind {
2329     CLike,
2330     Tuple(Vec<Type>),
2331     Struct(VariantStruct),
2332 }
2333
2334 impl Clean<VariantKind> for hir::VariantData {
2335     fn clean(&self, cx: &DocContext) -> VariantKind {
2336         if self.is_struct() {
2337             VariantKind::Struct(self.clean(cx))
2338         } else if self.is_unit() {
2339             VariantKind::CLike
2340         } else {
2341             VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect())
2342         }
2343     }
2344 }
2345
2346 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2347 pub struct Span {
2348     pub filename: String,
2349     pub loline: usize,
2350     pub locol: usize,
2351     pub hiline: usize,
2352     pub hicol: usize,
2353 }
2354
2355 impl Span {
2356     fn empty() -> Span {
2357         Span {
2358             filename: "".to_string(),
2359             loline: 0, locol: 0,
2360             hiline: 0, hicol: 0,
2361         }
2362     }
2363 }
2364
2365 impl Clean<Span> for syntax_pos::Span {
2366     fn clean(&self, cx: &DocContext) -> Span {
2367         if *self == DUMMY_SP {
2368             return Span::empty();
2369         }
2370
2371         let cm = cx.sess().codemap();
2372         let filename = cm.span_to_filename(*self);
2373         let lo = cm.lookup_char_pos(self.lo());
2374         let hi = cm.lookup_char_pos(self.hi());
2375         Span {
2376             filename: filename.to_string(),
2377             loline: lo.line,
2378             locol: lo.col.to_usize(),
2379             hiline: hi.line,
2380             hicol: hi.col.to_usize(),
2381         }
2382     }
2383 }
2384
2385 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2386 pub struct Path {
2387     pub global: bool,
2388     pub def: Def,
2389     pub segments: Vec<PathSegment>,
2390 }
2391
2392 impl Path {
2393     pub fn singleton(name: String) -> Path {
2394         Path {
2395             global: false,
2396             def: Def::Err,
2397             segments: vec![PathSegment {
2398                 name,
2399                 params: PathParameters::AngleBracketed {
2400                     lifetimes: Vec::new(),
2401                     types: Vec::new(),
2402                     bindings: Vec::new()
2403                 }
2404             }]
2405         }
2406     }
2407
2408     pub fn last_name(&self) -> &str {
2409         self.segments.last().unwrap().name.as_str()
2410     }
2411 }
2412
2413 impl Clean<Path> for hir::Path {
2414     fn clean(&self, cx: &DocContext) -> Path {
2415         Path {
2416             global: self.is_global(),
2417             def: self.def,
2418             segments: if self.is_global() { &self.segments[1..] } else { &self.segments }.clean(cx),
2419         }
2420     }
2421 }
2422
2423 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2424 pub enum PathParameters {
2425     AngleBracketed {
2426         lifetimes: Vec<Lifetime>,
2427         types: Vec<Type>,
2428         bindings: Vec<TypeBinding>,
2429     },
2430     Parenthesized {
2431         inputs: Vec<Type>,
2432         output: Option<Type>,
2433     }
2434 }
2435
2436 impl Clean<PathParameters> for hir::PathParameters {
2437     fn clean(&self, cx: &DocContext) -> PathParameters {
2438         if self.parenthesized {
2439             let output = self.bindings[0].ty.clean(cx);
2440             PathParameters::Parenthesized {
2441                 inputs: self.inputs().clean(cx),
2442                 output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
2443             }
2444         } else {
2445             PathParameters::AngleBracketed {
2446                 lifetimes: if self.lifetimes.iter().all(|lt| lt.is_elided()) {
2447                     vec![]
2448                 } else {
2449                     self.lifetimes.clean(cx)
2450                 },
2451                 types: self.types.clean(cx),
2452                 bindings: self.bindings.clean(cx),
2453             }
2454         }
2455     }
2456 }
2457
2458 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2459 pub struct PathSegment {
2460     pub name: String,
2461     pub params: PathParameters,
2462 }
2463
2464 impl Clean<PathSegment> for hir::PathSegment {
2465     fn clean(&self, cx: &DocContext) -> PathSegment {
2466         PathSegment {
2467             name: self.name.clean(cx),
2468             params: self.with_parameters(|parameters| parameters.clean(cx))
2469         }
2470     }
2471 }
2472
2473 fn qpath_to_string(p: &hir::QPath) -> String {
2474     let segments = match *p {
2475         hir::QPath::Resolved(_, ref path) => &path.segments,
2476         hir::QPath::TypeRelative(_, ref segment) => return segment.name.to_string(),
2477     };
2478
2479     let mut s = String::new();
2480     for (i, seg) in segments.iter().enumerate() {
2481         if i > 0 {
2482             s.push_str("::");
2483         }
2484         if seg.name != keywords::CrateRoot.name() {
2485             s.push_str(&*seg.name.as_str());
2486         }
2487     }
2488     s
2489 }
2490
2491 impl Clean<String> for ast::Name {
2492     fn clean(&self, _: &DocContext) -> String {
2493         self.to_string()
2494     }
2495 }
2496
2497 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2498 pub struct Typedef {
2499     pub type_: Type,
2500     pub generics: Generics,
2501 }
2502
2503 impl Clean<Item> for doctree::Typedef {
2504     fn clean(&self, cx: &DocContext) -> Item {
2505         Item {
2506             name: Some(self.name.clean(cx)),
2507             attrs: self.attrs.clean(cx),
2508             source: self.whence.clean(cx),
2509             def_id: cx.tcx.hir.local_def_id(self.id.clone()),
2510             visibility: self.vis.clean(cx),
2511             stability: self.stab.clean(cx),
2512             deprecation: self.depr.clean(cx),
2513             inner: TypedefItem(Typedef {
2514                 type_: self.ty.clean(cx),
2515                 generics: self.gen.clean(cx),
2516             }, false),
2517         }
2518     }
2519 }
2520
2521 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2522 pub struct BareFunctionDecl {
2523     pub unsafety: hir::Unsafety,
2524     pub generics: Generics,
2525     pub decl: FnDecl,
2526     pub abi: Abi,
2527 }
2528
2529 impl Clean<BareFunctionDecl> for hir::BareFnTy {
2530     fn clean(&self, cx: &DocContext) -> BareFunctionDecl {
2531         BareFunctionDecl {
2532             unsafety: self.unsafety,
2533             generics: Generics {
2534                 lifetimes: self.lifetimes.clean(cx),
2535                 type_params: Vec::new(),
2536                 where_predicates: Vec::new()
2537             },
2538             decl: (&*self.decl, &self.arg_names[..]).clean(cx),
2539             abi: self.abi,
2540         }
2541     }
2542 }
2543
2544 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2545 pub struct Static {
2546     pub type_: Type,
2547     pub mutability: Mutability,
2548     /// It's useful to have the value of a static documented, but I have no
2549     /// desire to represent expressions (that'd basically be all of the AST,
2550     /// which is huge!). So, have a string.
2551     pub expr: String,
2552 }
2553
2554 impl Clean<Item> for doctree::Static {
2555     fn clean(&self, cx: &DocContext) -> Item {
2556         debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
2557         Item {
2558             name: Some(self.name.clean(cx)),
2559             attrs: self.attrs.clean(cx),
2560             source: self.whence.clean(cx),
2561             def_id: cx.tcx.hir.local_def_id(self.id),
2562             visibility: self.vis.clean(cx),
2563             stability: self.stab.clean(cx),
2564             deprecation: self.depr.clean(cx),
2565             inner: StaticItem(Static {
2566                 type_: self.type_.clean(cx),
2567                 mutability: self.mutability.clean(cx),
2568                 expr: print_const_expr(cx, self.expr),
2569             }),
2570         }
2571     }
2572 }
2573
2574 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2575 pub struct Constant {
2576     pub type_: Type,
2577     pub expr: String,
2578 }
2579
2580 impl Clean<Item> for doctree::Constant {
2581     fn clean(&self, cx: &DocContext) -> Item {
2582         Item {
2583             name: Some(self.name.clean(cx)),
2584             attrs: self.attrs.clean(cx),
2585             source: self.whence.clean(cx),
2586             def_id: cx.tcx.hir.local_def_id(self.id),
2587             visibility: self.vis.clean(cx),
2588             stability: self.stab.clean(cx),
2589             deprecation: self.depr.clean(cx),
2590             inner: ConstantItem(Constant {
2591                 type_: self.type_.clean(cx),
2592                 expr: print_const_expr(cx, self.expr),
2593             }),
2594         }
2595     }
2596 }
2597
2598 #[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Copy)]
2599 pub enum Mutability {
2600     Mutable,
2601     Immutable,
2602 }
2603
2604 impl Clean<Mutability> for hir::Mutability {
2605     fn clean(&self, _: &DocContext) -> Mutability {
2606         match self {
2607             &hir::MutMutable => Mutable,
2608             &hir::MutImmutable => Immutable,
2609         }
2610     }
2611 }
2612
2613 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Copy, Debug)]
2614 pub enum ImplPolarity {
2615     Positive,
2616     Negative,
2617 }
2618
2619 impl Clean<ImplPolarity> for hir::ImplPolarity {
2620     fn clean(&self, _: &DocContext) -> ImplPolarity {
2621         match self {
2622             &hir::ImplPolarity::Positive => ImplPolarity::Positive,
2623             &hir::ImplPolarity::Negative => ImplPolarity::Negative,
2624         }
2625     }
2626 }
2627
2628 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2629 pub struct Impl {
2630     pub unsafety: hir::Unsafety,
2631     pub generics: Generics,
2632     pub provided_trait_methods: FxHashSet<String>,
2633     pub trait_: Option<Type>,
2634     pub for_: Type,
2635     pub items: Vec<Item>,
2636     pub polarity: Option<ImplPolarity>,
2637 }
2638
2639 impl Clean<Vec<Item>> for doctree::Impl {
2640     fn clean(&self, cx: &DocContext) -> Vec<Item> {
2641         let mut ret = Vec::new();
2642         let trait_ = self.trait_.clean(cx);
2643         let items = self.items.clean(cx);
2644
2645         // If this impl block is an implementation of the Deref trait, then we
2646         // need to try inlining the target's inherent impl blocks as well.
2647         if trait_.def_id() == cx.tcx.lang_items().deref_trait() {
2648             build_deref_target_impls(cx, &items, &mut ret);
2649         }
2650
2651         let provided = trait_.def_id().map(|did| {
2652             cx.tcx.provided_trait_methods(did)
2653                   .into_iter()
2654                   .map(|meth| meth.name.to_string())
2655                   .collect()
2656         }).unwrap_or(FxHashSet());
2657
2658         ret.push(Item {
2659             name: None,
2660             attrs: self.attrs.clean(cx),
2661             source: self.whence.clean(cx),
2662             def_id: cx.tcx.hir.local_def_id(self.id),
2663             visibility: self.vis.clean(cx),
2664             stability: self.stab.clean(cx),
2665             deprecation: self.depr.clean(cx),
2666             inner: ImplItem(Impl {
2667                 unsafety: self.unsafety,
2668                 generics: self.generics.clean(cx),
2669                 provided_trait_methods: provided,
2670                 trait_,
2671                 for_: self.for_.clean(cx),
2672                 items,
2673                 polarity: Some(self.polarity.clean(cx)),
2674             }),
2675         });
2676         ret
2677     }
2678 }
2679
2680 fn build_deref_target_impls(cx: &DocContext,
2681                             items: &[Item],
2682                             ret: &mut Vec<Item>) {
2683     use self::PrimitiveType::*;
2684     let tcx = cx.tcx;
2685
2686     for item in items {
2687         let target = match item.inner {
2688             TypedefItem(ref t, true) => &t.type_,
2689             _ => continue,
2690         };
2691         let primitive = match *target {
2692             ResolvedPath { did, .. } if did.is_local() => continue,
2693             ResolvedPath { did, .. } => {
2694                 ret.extend(inline::build_impls(cx, did));
2695                 continue
2696             }
2697             _ => match target.primitive_type() {
2698                 Some(prim) => prim,
2699                 None => continue,
2700             }
2701         };
2702         let did = match primitive {
2703             Isize => tcx.lang_items().isize_impl(),
2704             I8 => tcx.lang_items().i8_impl(),
2705             I16 => tcx.lang_items().i16_impl(),
2706             I32 => tcx.lang_items().i32_impl(),
2707             I64 => tcx.lang_items().i64_impl(),
2708             I128 => tcx.lang_items().i128_impl(),
2709             Usize => tcx.lang_items().usize_impl(),
2710             U8 => tcx.lang_items().u8_impl(),
2711             U16 => tcx.lang_items().u16_impl(),
2712             U32 => tcx.lang_items().u32_impl(),
2713             U64 => tcx.lang_items().u64_impl(),
2714             U128 => tcx.lang_items().u128_impl(),
2715             F32 => tcx.lang_items().f32_impl(),
2716             F64 => tcx.lang_items().f64_impl(),
2717             Char => tcx.lang_items().char_impl(),
2718             Bool => None,
2719             Str => tcx.lang_items().str_impl(),
2720             Slice => tcx.lang_items().slice_impl(),
2721             Array => tcx.lang_items().slice_impl(),
2722             Tuple => None,
2723             Unit => None,
2724             RawPointer => tcx.lang_items().const_ptr_impl(),
2725             Reference => None,
2726             Fn => None,
2727         };
2728         if let Some(did) = did {
2729             if !did.is_local() {
2730                 inline::build_impl(cx, did, ret);
2731             }
2732         }
2733     }
2734 }
2735
2736 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2737 pub struct AutoImpl {
2738     pub unsafety: hir::Unsafety,
2739     pub trait_: Type,
2740 }
2741
2742 impl Clean<Item> for doctree::AutoImpl {
2743     fn clean(&self, cx: &DocContext) -> Item {
2744         Item {
2745             name: None,
2746             attrs: self.attrs.clean(cx),
2747             source: self.whence.clean(cx),
2748             def_id: cx.tcx.hir.local_def_id(self.id),
2749             visibility: Some(Public),
2750             stability: None,
2751             deprecation: None,
2752             inner: AutoImplItem(AutoImpl {
2753                 unsafety: self.unsafety,
2754                 trait_: self.trait_.clean(cx),
2755             }),
2756         }
2757     }
2758 }
2759
2760 impl Clean<Item> for doctree::ExternCrate {
2761     fn clean(&self, cx: &DocContext) -> Item {
2762         Item {
2763             name: None,
2764             attrs: self.attrs.clean(cx),
2765             source: self.whence.clean(cx),
2766             def_id: DefId { krate: self.cnum, index: CRATE_DEF_INDEX },
2767             visibility: self.vis.clean(cx),
2768             stability: None,
2769             deprecation: None,
2770             inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
2771         }
2772     }
2773 }
2774
2775 impl Clean<Vec<Item>> for doctree::Import {
2776     fn clean(&self, cx: &DocContext) -> Vec<Item> {
2777         // We consider inlining the documentation of `pub use` statements, but we
2778         // forcefully don't inline if this is not public or if the
2779         // #[doc(no_inline)] attribute is present.
2780         // Don't inline doc(hidden) imports so they can be stripped at a later stage.
2781         let denied = self.vis != hir::Public || self.attrs.iter().any(|a| {
2782             a.name().unwrap() == "doc" && match a.meta_item_list() {
2783                 Some(l) => attr::list_contains_name(&l, "no_inline") ||
2784                            attr::list_contains_name(&l, "hidden"),
2785                 None => false,
2786             }
2787         });
2788         let path = self.path.clean(cx);
2789         let inner = if self.glob {
2790             Import::Glob(resolve_use_source(cx, path))
2791         } else {
2792             let name = self.name;
2793             if !denied {
2794                 if let Some(items) = inline::try_inline(cx, path.def, name) {
2795                     return items;
2796                 }
2797             }
2798             Import::Simple(name.clean(cx), resolve_use_source(cx, path))
2799         };
2800         vec![Item {
2801             name: None,
2802             attrs: self.attrs.clean(cx),
2803             source: self.whence.clean(cx),
2804             def_id: cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID),
2805             visibility: self.vis.clean(cx),
2806             stability: None,
2807             deprecation: None,
2808             inner: ImportItem(inner)
2809         }]
2810     }
2811 }
2812
2813 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2814 pub enum Import {
2815     // use source as str;
2816     Simple(String, ImportSource),
2817     // use source::*;
2818     Glob(ImportSource)
2819 }
2820
2821 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2822 pub struct ImportSource {
2823     pub path: Path,
2824     pub did: Option<DefId>,
2825 }
2826
2827 impl Clean<Vec<Item>> for hir::ForeignMod {
2828     fn clean(&self, cx: &DocContext) -> Vec<Item> {
2829         let mut items = self.items.clean(cx);
2830         for item in &mut items {
2831             if let ForeignFunctionItem(ref mut f) = item.inner {
2832                 f.abi = self.abi;
2833             }
2834         }
2835         items
2836     }
2837 }
2838
2839 impl Clean<Item> for hir::ForeignItem {
2840     fn clean(&self, cx: &DocContext) -> Item {
2841         let inner = match self.node {
2842             hir::ForeignItemFn(ref decl, ref names, ref generics) => {
2843                 ForeignFunctionItem(Function {
2844                     decl: (&**decl, &names[..]).clean(cx),
2845                     generics: generics.clean(cx),
2846                     unsafety: hir::Unsafety::Unsafe,
2847                     abi: Abi::Rust,
2848                     constness: hir::Constness::NotConst,
2849                 })
2850             }
2851             hir::ForeignItemStatic(ref ty, mutbl) => {
2852                 ForeignStaticItem(Static {
2853                     type_: ty.clean(cx),
2854                     mutability: if mutbl {Mutable} else {Immutable},
2855                     expr: "".to_string(),
2856                 })
2857             }
2858             hir::ForeignItemType => {
2859                 ForeignTypeItem
2860             }
2861         };
2862         Item {
2863             name: Some(self.name.clean(cx)),
2864             attrs: self.attrs.clean(cx),
2865             source: self.span.clean(cx),
2866             def_id: cx.tcx.hir.local_def_id(self.id),
2867             visibility: self.vis.clean(cx),
2868             stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)),
2869             deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)),
2870             inner,
2871         }
2872     }
2873 }
2874
2875 // Utilities
2876
2877 trait ToSource {
2878     fn to_src(&self, cx: &DocContext) -> String;
2879 }
2880
2881 impl ToSource for syntax_pos::Span {
2882     fn to_src(&self, cx: &DocContext) -> String {
2883         debug!("converting span {:?} to snippet", self.clean(cx));
2884         let sn = match cx.sess().codemap().span_to_snippet(*self) {
2885             Ok(x) => x.to_string(),
2886             Err(_) => "".to_string()
2887         };
2888         debug!("got snippet {}", sn);
2889         sn
2890     }
2891 }
2892
2893 fn name_from_pat(p: &hir::Pat) -> String {
2894     use rustc::hir::*;
2895     debug!("Trying to get a name from pattern: {:?}", p);
2896
2897     match p.node {
2898         PatKind::Wild => "_".to_string(),
2899         PatKind::Binding(_, _, ref p, _) => p.node.to_string(),
2900         PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
2901         PatKind::Struct(ref name, ref fields, etc) => {
2902             format!("{} {{ {}{} }}", qpath_to_string(name),
2903                 fields.iter().map(|&Spanned { node: ref fp, .. }|
2904                                   format!("{}: {}", fp.name, name_from_pat(&*fp.pat)))
2905                              .collect::<Vec<String>>().join(", "),
2906                 if etc { ", ..." } else { "" }
2907             )
2908         }
2909         PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
2910                                             .collect::<Vec<String>>().join(", ")),
2911         PatKind::Box(ref p) => name_from_pat(&**p),
2912         PatKind::Ref(ref p, _) => name_from_pat(&**p),
2913         PatKind::Lit(..) => {
2914             warn!("tried to get argument name from PatKind::Lit, \
2915                   which is silly in function arguments");
2916             "()".to_string()
2917         },
2918         PatKind::Range(..) => panic!("tried to get argument name from PatKind::Range, \
2919                               which is not allowed in function arguments"),
2920         PatKind::Slice(ref begin, ref mid, ref end) => {
2921             let begin = begin.iter().map(|p| name_from_pat(&**p));
2922             let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter();
2923             let end = end.iter().map(|p| name_from_pat(&**p));
2924             format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
2925         },
2926     }
2927 }
2928
2929 fn print_const_expr(cx: &DocContext, body: hir::BodyId) -> String {
2930     cx.tcx.hir.node_to_pretty_string(body.node_id)
2931 }
2932
2933 /// Given a type Path, resolve it to a Type using the TyCtxt
2934 fn resolve_type(cx: &DocContext,
2935                 path: Path,
2936                 id: ast::NodeId) -> Type {
2937     debug!("resolve_type({:?},{:?})", path, id);
2938
2939     let is_generic = match path.def {
2940         Def::PrimTy(p) => match p {
2941             hir::TyStr => return Primitive(PrimitiveType::Str),
2942             hir::TyBool => return Primitive(PrimitiveType::Bool),
2943             hir::TyChar => return Primitive(PrimitiveType::Char),
2944             hir::TyInt(int_ty) => return Primitive(int_ty.into()),
2945             hir::TyUint(uint_ty) => return Primitive(uint_ty.into()),
2946             hir::TyFloat(float_ty) => return Primitive(float_ty.into()),
2947         },
2948         Def::SelfTy(..) if path.segments.len() == 1 => {
2949             return Generic(keywords::SelfType.name().to_string());
2950         }
2951         Def::TyParam(..) if path.segments.len() == 1 => {
2952             return Generic(format!("{:#}", path));
2953         }
2954         Def::SelfTy(..) | Def::TyParam(..) | Def::AssociatedTy(..) => true,
2955         _ => false,
2956     };
2957     let did = register_def(&*cx, path.def);
2958     ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
2959 }
2960
2961 fn register_def(cx: &DocContext, def: Def) -> DefId {
2962     debug!("register_def({:?})", def);
2963
2964     let (did, kind) = match def {
2965         Def::Fn(i) => (i, TypeKind::Function),
2966         Def::TyAlias(i) => (i, TypeKind::Typedef),
2967         Def::Enum(i) => (i, TypeKind::Enum),
2968         Def::Trait(i) => (i, TypeKind::Trait),
2969         Def::Struct(i) => (i, TypeKind::Struct),
2970         Def::Union(i) => (i, TypeKind::Union),
2971         Def::Mod(i) => (i, TypeKind::Module),
2972         Def::Static(i, _) => (i, TypeKind::Static),
2973         Def::Variant(i) => (cx.tcx.parent_def_id(i).unwrap(), TypeKind::Enum),
2974         Def::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
2975         Def::SelfTy(_, Some(impl_def_id)) => {
2976             return impl_def_id
2977         }
2978         _ => return def.def_id()
2979     };
2980     if did.is_local() { return did }
2981     inline::record_extern_fqn(cx, did, kind);
2982     if let TypeKind::Trait = kind {
2983         let t = inline::build_external_trait(cx, did);
2984         cx.external_traits.borrow_mut().insert(did, t);
2985     }
2986     did
2987 }
2988
2989 fn resolve_use_source(cx: &DocContext, path: Path) -> ImportSource {
2990     ImportSource {
2991         did: if path.def == Def::Err {
2992             None
2993         } else {
2994             Some(register_def(cx, path.def))
2995         },
2996         path,
2997     }
2998 }
2999
3000 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3001 pub struct Macro {
3002     pub source: String,
3003     pub imported_from: Option<String>,
3004 }
3005
3006 impl Clean<Item> for doctree::Macro {
3007     fn clean(&self, cx: &DocContext) -> Item {
3008         let name = self.name.clean(cx);
3009         Item {
3010             name: Some(name.clone()),
3011             attrs: self.attrs.clean(cx),
3012             source: self.whence.clean(cx),
3013             visibility: Some(Public),
3014             stability: self.stab.clean(cx),
3015             deprecation: self.depr.clean(cx),
3016             def_id: self.def_id,
3017             inner: MacroItem(Macro {
3018                 source: format!("macro_rules! {} {{\n{}}}",
3019                                 name,
3020                                 self.matchers.iter().map(|span| {
3021                                     format!("    {} => {{ ... }};\n", span.to_src(cx))
3022                                 }).collect::<String>()),
3023                 imported_from: self.imported_from.clean(cx),
3024             }),
3025         }
3026     }
3027 }
3028
3029 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3030 pub struct Stability {
3031     pub level: stability::StabilityLevel,
3032     pub feature: String,
3033     pub since: String,
3034     pub deprecated_since: String,
3035     pub deprecated_reason: String,
3036     pub unstable_reason: String,
3037     pub issue: Option<u32>
3038 }
3039
3040 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3041 pub struct Deprecation {
3042     pub since: String,
3043     pub note: String,
3044 }
3045
3046 impl Clean<Stability> for attr::Stability {
3047     fn clean(&self, _: &DocContext) -> Stability {
3048         Stability {
3049             level: stability::StabilityLevel::from_attr_level(&self.level),
3050             feature: self.feature.to_string(),
3051             since: match self.level {
3052                 attr::Stable {ref since} => since.to_string(),
3053                 _ => "".to_string(),
3054             },
3055             deprecated_since: match self.rustc_depr {
3056                 Some(attr::RustcDeprecation {ref since, ..}) => since.to_string(),
3057                 _=> "".to_string(),
3058             },
3059             deprecated_reason: match self.rustc_depr {
3060                 Some(ref depr) => depr.reason.to_string(),
3061                 _ => "".to_string(),
3062             },
3063             unstable_reason: match self.level {
3064                 attr::Unstable { reason: Some(ref reason), .. } => reason.to_string(),
3065                 _ => "".to_string(),
3066             },
3067             issue: match self.level {
3068                 attr::Unstable {issue, ..} => Some(issue),
3069                 _ => None,
3070             }
3071         }
3072     }
3073 }
3074
3075 impl<'a> Clean<Stability> for &'a attr::Stability {
3076     fn clean(&self, dc: &DocContext) -> Stability {
3077         (**self).clean(dc)
3078     }
3079 }
3080
3081 impl Clean<Deprecation> for attr::Deprecation {
3082     fn clean(&self, _: &DocContext) -> Deprecation {
3083         Deprecation {
3084             since: self.since.as_ref().map_or("".to_string(), |s| s.to_string()),
3085             note: self.note.as_ref().map_or("".to_string(), |s| s.to_string()),
3086         }
3087     }
3088 }
3089
3090 /// An equality constraint on an associated type, e.g. `A=Bar` in `Foo<A=Bar>`
3091 #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Debug)]
3092 pub struct TypeBinding {
3093     pub name: String,
3094     pub ty: Type
3095 }
3096
3097 impl Clean<TypeBinding> for hir::TypeBinding {
3098     fn clean(&self, cx: &DocContext) -> TypeBinding {
3099         TypeBinding {
3100             name: self.name.clean(cx),
3101             ty: self.ty.clean(cx)
3102         }
3103     }
3104 }