]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/clean/mod.rs
Auto merge of #44764 - nvzqz:master, r=alexcrichton
[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     DefaultImplItem(DefaultImpl),
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             TyImplTrait(ref bounds) => ImplTrait(bounds.clean(cx)),
1964             TyInfer | TyErr => Infer,
1965             TyTypeof(..) => panic!("Unimplemented type {:?}", self.node),
1966         }
1967     }
1968 }
1969
1970 impl<'tcx> Clean<Type> for Ty<'tcx> {
1971     fn clean(&self, cx: &DocContext) -> Type {
1972         match self.sty {
1973             ty::TyNever => Never,
1974             ty::TyBool => Primitive(PrimitiveType::Bool),
1975             ty::TyChar => Primitive(PrimitiveType::Char),
1976             ty::TyInt(int_ty) => Primitive(int_ty.into()),
1977             ty::TyUint(uint_ty) => Primitive(uint_ty.into()),
1978             ty::TyFloat(float_ty) => Primitive(float_ty.into()),
1979             ty::TyStr => Primitive(PrimitiveType::Str),
1980             ty::TySlice(ty) => Slice(box ty.clean(cx)),
1981             ty::TyArray(ty, n) => {
1982                 let n = if let ConstVal::Integral(ConstInt::Usize(n)) = n.val {
1983                     n.to_string()
1984                 } else if let ConstVal::Unevaluated(def_id, _) = n.val {
1985                     if let Some(node_id) = cx.tcx.hir.as_local_node_id(def_id) {
1986                         print_const_expr(cx, cx.tcx.hir.body_owned_by(node_id))
1987                     } else {
1988                         inline::print_inlined_const(cx, def_id)
1989                     }
1990                 } else {
1991                     format!("{:?}", n)
1992                 };
1993                 Array(box ty.clean(cx), n)
1994             }
1995             ty::TyRawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
1996             ty::TyRef(r, mt) => BorrowedRef {
1997                 lifetime: r.clean(cx),
1998                 mutability: mt.mutbl.clean(cx),
1999                 type_: box mt.ty.clean(cx),
2000             },
2001             ty::TyFnDef(..) |
2002             ty::TyFnPtr(_) => {
2003                 let ty = cx.tcx.lift(self).unwrap();
2004                 let sig = ty.fn_sig(cx.tcx);
2005                 BareFunction(box BareFunctionDecl {
2006                     unsafety: sig.unsafety(),
2007                     generics: Generics {
2008                         lifetimes: Vec::new(),
2009                         type_params: Vec::new(),
2010                         where_predicates: Vec::new()
2011                     },
2012                     decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx),
2013                     abi: sig.abi(),
2014                 })
2015             }
2016             ty::TyAdt(def, substs) => {
2017                 let did = def.did;
2018                 let kind = match def.adt_kind() {
2019                     AdtKind::Struct => TypeKind::Struct,
2020                     AdtKind::Union => TypeKind::Union,
2021                     AdtKind::Enum => TypeKind::Enum,
2022                 };
2023                 inline::record_extern_fqn(cx, did, kind);
2024                 let path = external_path(cx, &cx.tcx.item_name(did),
2025                                          None, false, vec![], substs);
2026                 ResolvedPath {
2027                     path,
2028                     typarams: None,
2029                     did,
2030                     is_generic: false,
2031                 }
2032             }
2033             ty::TyForeign(did) => {
2034                 inline::record_extern_fqn(cx, did, TypeKind::Foreign);
2035                 let path = external_path(cx, &cx.tcx.item_name(did),
2036                                          None, false, vec![], Substs::empty());
2037                 ResolvedPath {
2038                     path: path,
2039                     typarams: None,
2040                     did: did,
2041                     is_generic: false,
2042                 }
2043             }
2044             ty::TyDynamic(ref obj, ref reg) => {
2045                 if let Some(principal) = obj.principal() {
2046                     let did = principal.def_id();
2047                     inline::record_extern_fqn(cx, did, TypeKind::Trait);
2048
2049                     let mut typarams = vec![];
2050                     reg.clean(cx).map(|b| typarams.push(RegionBound(b)));
2051                     for did in obj.auto_traits() {
2052                         let empty = cx.tcx.intern_substs(&[]);
2053                         let path = external_path(cx, &cx.tcx.item_name(did),
2054                             Some(did), false, vec![], empty);
2055                         inline::record_extern_fqn(cx, did, TypeKind::Trait);
2056                         let bound = TraitBound(PolyTrait {
2057                             trait_: ResolvedPath {
2058                                 path,
2059                                 typarams: None,
2060                                 did,
2061                                 is_generic: false,
2062                             },
2063                             lifetimes: vec![]
2064                         }, hir::TraitBoundModifier::None);
2065                         typarams.push(bound);
2066                     }
2067
2068                     let mut bindings = vec![];
2069                     for ty::Binder(ref pb) in obj.projection_bounds() {
2070                         bindings.push(TypeBinding {
2071                             name: cx.tcx.associated_item(pb.item_def_id).name.clean(cx),
2072                             ty: pb.ty.clean(cx)
2073                         });
2074                     }
2075
2076                     let path = external_path(cx, &cx.tcx.item_name(did), Some(did),
2077                         false, bindings, principal.0.substs);
2078                     ResolvedPath {
2079                         path,
2080                         typarams: Some(typarams),
2081                         did,
2082                         is_generic: false,
2083                     }
2084                 } else {
2085                     Never
2086                 }
2087             }
2088             ty::TyTuple(ref t, _) => Tuple(t.clean(cx)),
2089
2090             ty::TyProjection(ref data) => data.clean(cx),
2091
2092             ty::TyParam(ref p) => Generic(p.name.to_string()),
2093
2094             ty::TyAnon(def_id, substs) => {
2095                 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
2096                 // by looking up the projections associated with the def_id.
2097                 let predicates_of = cx.tcx.predicates_of(def_id);
2098                 let substs = cx.tcx.lift(&substs).unwrap();
2099                 let bounds = predicates_of.instantiate(cx.tcx, substs);
2100                 ImplTrait(bounds.predicates.into_iter().filter_map(|predicate| {
2101                     predicate.to_opt_poly_trait_ref().clean(cx)
2102                 }).collect())
2103             }
2104
2105             ty::TyClosure(..) | ty::TyGenerator(..) => Tuple(vec![]), // FIXME(pcwalton)
2106
2107             ty::TyInfer(..) => panic!("TyInfer"),
2108             ty::TyError => panic!("TyError"),
2109         }
2110     }
2111 }
2112
2113 impl Clean<Item> for hir::StructField {
2114     fn clean(&self, cx: &DocContext) -> Item {
2115         Item {
2116             name: Some(self.name).clean(cx),
2117             attrs: self.attrs.clean(cx),
2118             source: self.span.clean(cx),
2119             visibility: self.vis.clean(cx),
2120             stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)),
2121             deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)),
2122             def_id: cx.tcx.hir.local_def_id(self.id),
2123             inner: StructFieldItem(self.ty.clean(cx)),
2124         }
2125     }
2126 }
2127
2128 impl<'tcx> Clean<Item> for ty::FieldDef {
2129     fn clean(&self, cx: &DocContext) -> Item {
2130         Item {
2131             name: Some(self.name).clean(cx),
2132             attrs: cx.tcx.get_attrs(self.did).clean(cx),
2133             source: cx.tcx.def_span(self.did).clean(cx),
2134             visibility: self.vis.clean(cx),
2135             stability: get_stability(cx, self.did),
2136             deprecation: get_deprecation(cx, self.did),
2137             def_id: self.did,
2138             inner: StructFieldItem(cx.tcx.type_of(self.did).clean(cx)),
2139         }
2140     }
2141 }
2142
2143 #[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug)]
2144 pub enum Visibility {
2145     Public,
2146     Inherited,
2147 }
2148
2149 impl Clean<Option<Visibility>> for hir::Visibility {
2150     fn clean(&self, _: &DocContext) -> Option<Visibility> {
2151         Some(if *self == hir::Visibility::Public { Public } else { Inherited })
2152     }
2153 }
2154
2155 impl Clean<Option<Visibility>> for ty::Visibility {
2156     fn clean(&self, _: &DocContext) -> Option<Visibility> {
2157         Some(if *self == ty::Visibility::Public { Public } else { Inherited })
2158     }
2159 }
2160
2161 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2162 pub struct Struct {
2163     pub struct_type: doctree::StructType,
2164     pub generics: Generics,
2165     pub fields: Vec<Item>,
2166     pub fields_stripped: bool,
2167 }
2168
2169 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2170 pub struct Union {
2171     pub struct_type: doctree::StructType,
2172     pub generics: Generics,
2173     pub fields: Vec<Item>,
2174     pub fields_stripped: bool,
2175 }
2176
2177 impl Clean<Item> for doctree::Struct {
2178     fn clean(&self, cx: &DocContext) -> Item {
2179         Item {
2180             name: Some(self.name.clean(cx)),
2181             attrs: self.attrs.clean(cx),
2182             source: self.whence.clean(cx),
2183             def_id: cx.tcx.hir.local_def_id(self.id),
2184             visibility: self.vis.clean(cx),
2185             stability: self.stab.clean(cx),
2186             deprecation: self.depr.clean(cx),
2187             inner: StructItem(Struct {
2188                 struct_type: self.struct_type,
2189                 generics: self.generics.clean(cx),
2190                 fields: self.fields.clean(cx),
2191                 fields_stripped: false,
2192             }),
2193         }
2194     }
2195 }
2196
2197 impl Clean<Item> for doctree::Union {
2198     fn clean(&self, cx: &DocContext) -> Item {
2199         Item {
2200             name: Some(self.name.clean(cx)),
2201             attrs: self.attrs.clean(cx),
2202             source: self.whence.clean(cx),
2203             def_id: cx.tcx.hir.local_def_id(self.id),
2204             visibility: self.vis.clean(cx),
2205             stability: self.stab.clean(cx),
2206             deprecation: self.depr.clean(cx),
2207             inner: UnionItem(Union {
2208                 struct_type: self.struct_type,
2209                 generics: self.generics.clean(cx),
2210                 fields: self.fields.clean(cx),
2211                 fields_stripped: false,
2212             }),
2213         }
2214     }
2215 }
2216
2217 /// This is a more limited form of the standard Struct, different in that
2218 /// it lacks the things most items have (name, id, parameterization). Found
2219 /// only as a variant in an enum.
2220 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2221 pub struct VariantStruct {
2222     pub struct_type: doctree::StructType,
2223     pub fields: Vec<Item>,
2224     pub fields_stripped: bool,
2225 }
2226
2227 impl Clean<VariantStruct> for ::rustc::hir::VariantData {
2228     fn clean(&self, cx: &DocContext) -> VariantStruct {
2229         VariantStruct {
2230             struct_type: doctree::struct_type_from_def(self),
2231             fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
2232             fields_stripped: false,
2233         }
2234     }
2235 }
2236
2237 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2238 pub struct Enum {
2239     pub variants: Vec<Item>,
2240     pub generics: Generics,
2241     pub variants_stripped: bool,
2242 }
2243
2244 impl Clean<Item> for doctree::Enum {
2245     fn clean(&self, cx: &DocContext) -> Item {
2246         Item {
2247             name: Some(self.name.clean(cx)),
2248             attrs: self.attrs.clean(cx),
2249             source: self.whence.clean(cx),
2250             def_id: cx.tcx.hir.local_def_id(self.id),
2251             visibility: self.vis.clean(cx),
2252             stability: self.stab.clean(cx),
2253             deprecation: self.depr.clean(cx),
2254             inner: EnumItem(Enum {
2255                 variants: self.variants.clean(cx),
2256                 generics: self.generics.clean(cx),
2257                 variants_stripped: false,
2258             }),
2259         }
2260     }
2261 }
2262
2263 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2264 pub struct Variant {
2265     pub kind: VariantKind,
2266 }
2267
2268 impl Clean<Item> for doctree::Variant {
2269     fn clean(&self, cx: &DocContext) -> Item {
2270         Item {
2271             name: Some(self.name.clean(cx)),
2272             attrs: self.attrs.clean(cx),
2273             source: self.whence.clean(cx),
2274             visibility: None,
2275             stability: self.stab.clean(cx),
2276             deprecation: self.depr.clean(cx),
2277             def_id: cx.tcx.hir.local_def_id(self.def.id()),
2278             inner: VariantItem(Variant {
2279                 kind: self.def.clean(cx),
2280             }),
2281         }
2282     }
2283 }
2284
2285 impl<'tcx> Clean<Item> for ty::VariantDef {
2286     fn clean(&self, cx: &DocContext) -> Item {
2287         let kind = match self.ctor_kind {
2288             CtorKind::Const => VariantKind::CLike,
2289             CtorKind::Fn => {
2290                 VariantKind::Tuple(
2291                     self.fields.iter().map(|f| cx.tcx.type_of(f.did).clean(cx)).collect()
2292                 )
2293             }
2294             CtorKind::Fictive => {
2295                 VariantKind::Struct(VariantStruct {
2296                     struct_type: doctree::Plain,
2297                     fields_stripped: false,
2298                     fields: self.fields.iter().map(|field| {
2299                         Item {
2300                             source: cx.tcx.def_span(field.did).clean(cx),
2301                             name: Some(field.name.clean(cx)),
2302                             attrs: cx.tcx.get_attrs(field.did).clean(cx),
2303                             visibility: field.vis.clean(cx),
2304                             def_id: field.did,
2305                             stability: get_stability(cx, field.did),
2306                             deprecation: get_deprecation(cx, field.did),
2307                             inner: StructFieldItem(cx.tcx.type_of(field.did).clean(cx))
2308                         }
2309                     }).collect()
2310                 })
2311             }
2312         };
2313         Item {
2314             name: Some(self.name.clean(cx)),
2315             attrs: inline::load_attrs(cx, self.did),
2316             source: cx.tcx.def_span(self.did).clean(cx),
2317             visibility: Some(Inherited),
2318             def_id: self.did,
2319             inner: VariantItem(Variant { kind: kind }),
2320             stability: get_stability(cx, self.did),
2321             deprecation: get_deprecation(cx, self.did),
2322         }
2323     }
2324 }
2325
2326 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2327 pub enum VariantKind {
2328     CLike,
2329     Tuple(Vec<Type>),
2330     Struct(VariantStruct),
2331 }
2332
2333 impl Clean<VariantKind> for hir::VariantData {
2334     fn clean(&self, cx: &DocContext) -> VariantKind {
2335         if self.is_struct() {
2336             VariantKind::Struct(self.clean(cx))
2337         } else if self.is_unit() {
2338             VariantKind::CLike
2339         } else {
2340             VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect())
2341         }
2342     }
2343 }
2344
2345 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2346 pub struct Span {
2347     pub filename: String,
2348     pub loline: usize,
2349     pub locol: usize,
2350     pub hiline: usize,
2351     pub hicol: usize,
2352 }
2353
2354 impl Span {
2355     fn empty() -> Span {
2356         Span {
2357             filename: "".to_string(),
2358             loline: 0, locol: 0,
2359             hiline: 0, hicol: 0,
2360         }
2361     }
2362 }
2363
2364 impl Clean<Span> for syntax_pos::Span {
2365     fn clean(&self, cx: &DocContext) -> Span {
2366         if *self == DUMMY_SP {
2367             return Span::empty();
2368         }
2369
2370         let cm = cx.sess().codemap();
2371         let filename = cm.span_to_filename(*self);
2372         let lo = cm.lookup_char_pos(self.lo());
2373         let hi = cm.lookup_char_pos(self.hi());
2374         Span {
2375             filename: filename.to_string(),
2376             loline: lo.line,
2377             locol: lo.col.to_usize(),
2378             hiline: hi.line,
2379             hicol: hi.col.to_usize(),
2380         }
2381     }
2382 }
2383
2384 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2385 pub struct Path {
2386     pub global: bool,
2387     pub def: Def,
2388     pub segments: Vec<PathSegment>,
2389 }
2390
2391 impl Path {
2392     pub fn singleton(name: String) -> Path {
2393         Path {
2394             global: false,
2395             def: Def::Err,
2396             segments: vec![PathSegment {
2397                 name,
2398                 params: PathParameters::AngleBracketed {
2399                     lifetimes: Vec::new(),
2400                     types: Vec::new(),
2401                     bindings: Vec::new()
2402                 }
2403             }]
2404         }
2405     }
2406
2407     pub fn last_name(&self) -> &str {
2408         self.segments.last().unwrap().name.as_str()
2409     }
2410 }
2411
2412 impl Clean<Path> for hir::Path {
2413     fn clean(&self, cx: &DocContext) -> Path {
2414         Path {
2415             global: self.is_global(),
2416             def: self.def,
2417             segments: if self.is_global() { &self.segments[1..] } else { &self.segments }.clean(cx),
2418         }
2419     }
2420 }
2421
2422 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2423 pub enum PathParameters {
2424     AngleBracketed {
2425         lifetimes: Vec<Lifetime>,
2426         types: Vec<Type>,
2427         bindings: Vec<TypeBinding>,
2428     },
2429     Parenthesized {
2430         inputs: Vec<Type>,
2431         output: Option<Type>,
2432     }
2433 }
2434
2435 impl Clean<PathParameters> for hir::PathParameters {
2436     fn clean(&self, cx: &DocContext) -> PathParameters {
2437         if self.parenthesized {
2438             let output = self.bindings[0].ty.clean(cx);
2439             PathParameters::Parenthesized {
2440                 inputs: self.inputs().clean(cx),
2441                 output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
2442             }
2443         } else {
2444             PathParameters::AngleBracketed {
2445                 lifetimes: if self.lifetimes.iter().all(|lt| lt.is_elided()) {
2446                     vec![]
2447                 } else {
2448                     self.lifetimes.clean(cx)
2449                 },
2450                 types: self.types.clean(cx),
2451                 bindings: self.bindings.clean(cx),
2452             }
2453         }
2454     }
2455 }
2456
2457 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2458 pub struct PathSegment {
2459     pub name: String,
2460     pub params: PathParameters,
2461 }
2462
2463 impl Clean<PathSegment> for hir::PathSegment {
2464     fn clean(&self, cx: &DocContext) -> PathSegment {
2465         PathSegment {
2466             name: self.name.clean(cx),
2467             params: self.with_parameters(|parameters| parameters.clean(cx))
2468         }
2469     }
2470 }
2471
2472 fn qpath_to_string(p: &hir::QPath) -> String {
2473     let segments = match *p {
2474         hir::QPath::Resolved(_, ref path) => &path.segments,
2475         hir::QPath::TypeRelative(_, ref segment) => return segment.name.to_string(),
2476     };
2477
2478     let mut s = String::new();
2479     for (i, seg) in segments.iter().enumerate() {
2480         if i > 0 {
2481             s.push_str("::");
2482         }
2483         if seg.name != keywords::CrateRoot.name() {
2484             s.push_str(&*seg.name.as_str());
2485         }
2486     }
2487     s
2488 }
2489
2490 impl Clean<String> for ast::Name {
2491     fn clean(&self, _: &DocContext) -> String {
2492         self.to_string()
2493     }
2494 }
2495
2496 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2497 pub struct Typedef {
2498     pub type_: Type,
2499     pub generics: Generics,
2500 }
2501
2502 impl Clean<Item> for doctree::Typedef {
2503     fn clean(&self, cx: &DocContext) -> Item {
2504         Item {
2505             name: Some(self.name.clean(cx)),
2506             attrs: self.attrs.clean(cx),
2507             source: self.whence.clean(cx),
2508             def_id: cx.tcx.hir.local_def_id(self.id.clone()),
2509             visibility: self.vis.clean(cx),
2510             stability: self.stab.clean(cx),
2511             deprecation: self.depr.clean(cx),
2512             inner: TypedefItem(Typedef {
2513                 type_: self.ty.clean(cx),
2514                 generics: self.gen.clean(cx),
2515             }, false),
2516         }
2517     }
2518 }
2519
2520 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2521 pub struct BareFunctionDecl {
2522     pub unsafety: hir::Unsafety,
2523     pub generics: Generics,
2524     pub decl: FnDecl,
2525     pub abi: Abi,
2526 }
2527
2528 impl Clean<BareFunctionDecl> for hir::BareFnTy {
2529     fn clean(&self, cx: &DocContext) -> BareFunctionDecl {
2530         BareFunctionDecl {
2531             unsafety: self.unsafety,
2532             generics: Generics {
2533                 lifetimes: self.lifetimes.clean(cx),
2534                 type_params: Vec::new(),
2535                 where_predicates: Vec::new()
2536             },
2537             decl: (&*self.decl, &self.arg_names[..]).clean(cx),
2538             abi: self.abi,
2539         }
2540     }
2541 }
2542
2543 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2544 pub struct Static {
2545     pub type_: Type,
2546     pub mutability: Mutability,
2547     /// It's useful to have the value of a static documented, but I have no
2548     /// desire to represent expressions (that'd basically be all of the AST,
2549     /// which is huge!). So, have a string.
2550     pub expr: String,
2551 }
2552
2553 impl Clean<Item> for doctree::Static {
2554     fn clean(&self, cx: &DocContext) -> Item {
2555         debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
2556         Item {
2557             name: Some(self.name.clean(cx)),
2558             attrs: self.attrs.clean(cx),
2559             source: self.whence.clean(cx),
2560             def_id: cx.tcx.hir.local_def_id(self.id),
2561             visibility: self.vis.clean(cx),
2562             stability: self.stab.clean(cx),
2563             deprecation: self.depr.clean(cx),
2564             inner: StaticItem(Static {
2565                 type_: self.type_.clean(cx),
2566                 mutability: self.mutability.clean(cx),
2567                 expr: print_const_expr(cx, self.expr),
2568             }),
2569         }
2570     }
2571 }
2572
2573 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2574 pub struct Constant {
2575     pub type_: Type,
2576     pub expr: String,
2577 }
2578
2579 impl Clean<Item> for doctree::Constant {
2580     fn clean(&self, cx: &DocContext) -> Item {
2581         Item {
2582             name: Some(self.name.clean(cx)),
2583             attrs: self.attrs.clean(cx),
2584             source: self.whence.clean(cx),
2585             def_id: cx.tcx.hir.local_def_id(self.id),
2586             visibility: self.vis.clean(cx),
2587             stability: self.stab.clean(cx),
2588             deprecation: self.depr.clean(cx),
2589             inner: ConstantItem(Constant {
2590                 type_: self.type_.clean(cx),
2591                 expr: print_const_expr(cx, self.expr),
2592             }),
2593         }
2594     }
2595 }
2596
2597 #[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Copy)]
2598 pub enum Mutability {
2599     Mutable,
2600     Immutable,
2601 }
2602
2603 impl Clean<Mutability> for hir::Mutability {
2604     fn clean(&self, _: &DocContext) -> Mutability {
2605         match self {
2606             &hir::MutMutable => Mutable,
2607             &hir::MutImmutable => Immutable,
2608         }
2609     }
2610 }
2611
2612 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Copy, Debug)]
2613 pub enum ImplPolarity {
2614     Positive,
2615     Negative,
2616 }
2617
2618 impl Clean<ImplPolarity> for hir::ImplPolarity {
2619     fn clean(&self, _: &DocContext) -> ImplPolarity {
2620         match self {
2621             &hir::ImplPolarity::Positive => ImplPolarity::Positive,
2622             &hir::ImplPolarity::Negative => ImplPolarity::Negative,
2623         }
2624     }
2625 }
2626
2627 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2628 pub struct Impl {
2629     pub unsafety: hir::Unsafety,
2630     pub generics: Generics,
2631     pub provided_trait_methods: FxHashSet<String>,
2632     pub trait_: Option<Type>,
2633     pub for_: Type,
2634     pub items: Vec<Item>,
2635     pub polarity: Option<ImplPolarity>,
2636 }
2637
2638 impl Clean<Vec<Item>> for doctree::Impl {
2639     fn clean(&self, cx: &DocContext) -> Vec<Item> {
2640         let mut ret = Vec::new();
2641         let trait_ = self.trait_.clean(cx);
2642         let items = self.items.clean(cx);
2643
2644         // If this impl block is an implementation of the Deref trait, then we
2645         // need to try inlining the target's inherent impl blocks as well.
2646         if trait_.def_id() == cx.tcx.lang_items().deref_trait() {
2647             build_deref_target_impls(cx, &items, &mut ret);
2648         }
2649
2650         let provided = trait_.def_id().map(|did| {
2651             cx.tcx.provided_trait_methods(did)
2652                   .into_iter()
2653                   .map(|meth| meth.name.to_string())
2654                   .collect()
2655         }).unwrap_or(FxHashSet());
2656
2657         ret.push(Item {
2658             name: None,
2659             attrs: self.attrs.clean(cx),
2660             source: self.whence.clean(cx),
2661             def_id: cx.tcx.hir.local_def_id(self.id),
2662             visibility: self.vis.clean(cx),
2663             stability: self.stab.clean(cx),
2664             deprecation: self.depr.clean(cx),
2665             inner: ImplItem(Impl {
2666                 unsafety: self.unsafety,
2667                 generics: self.generics.clean(cx),
2668                 provided_trait_methods: provided,
2669                 trait_,
2670                 for_: self.for_.clean(cx),
2671                 items,
2672                 polarity: Some(self.polarity.clean(cx)),
2673             }),
2674         });
2675         ret
2676     }
2677 }
2678
2679 fn build_deref_target_impls(cx: &DocContext,
2680                             items: &[Item],
2681                             ret: &mut Vec<Item>) {
2682     use self::PrimitiveType::*;
2683     let tcx = cx.tcx;
2684
2685     for item in items {
2686         let target = match item.inner {
2687             TypedefItem(ref t, true) => &t.type_,
2688             _ => continue,
2689         };
2690         let primitive = match *target {
2691             ResolvedPath { did, .. } if did.is_local() => continue,
2692             ResolvedPath { did, .. } => {
2693                 ret.extend(inline::build_impls(cx, did));
2694                 continue
2695             }
2696             _ => match target.primitive_type() {
2697                 Some(prim) => prim,
2698                 None => continue,
2699             }
2700         };
2701         let did = match primitive {
2702             Isize => tcx.lang_items().isize_impl(),
2703             I8 => tcx.lang_items().i8_impl(),
2704             I16 => tcx.lang_items().i16_impl(),
2705             I32 => tcx.lang_items().i32_impl(),
2706             I64 => tcx.lang_items().i64_impl(),
2707             I128 => tcx.lang_items().i128_impl(),
2708             Usize => tcx.lang_items().usize_impl(),
2709             U8 => tcx.lang_items().u8_impl(),
2710             U16 => tcx.lang_items().u16_impl(),
2711             U32 => tcx.lang_items().u32_impl(),
2712             U64 => tcx.lang_items().u64_impl(),
2713             U128 => tcx.lang_items().u128_impl(),
2714             F32 => tcx.lang_items().f32_impl(),
2715             F64 => tcx.lang_items().f64_impl(),
2716             Char => tcx.lang_items().char_impl(),
2717             Bool => None,
2718             Str => tcx.lang_items().str_impl(),
2719             Slice => tcx.lang_items().slice_impl(),
2720             Array => tcx.lang_items().slice_impl(),
2721             Tuple => None,
2722             Unit => None,
2723             RawPointer => tcx.lang_items().const_ptr_impl(),
2724             Reference => None,
2725             Fn => None,
2726         };
2727         if let Some(did) = did {
2728             if !did.is_local() {
2729                 inline::build_impl(cx, did, ret);
2730             }
2731         }
2732     }
2733 }
2734
2735 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2736 pub struct DefaultImpl {
2737     pub unsafety: hir::Unsafety,
2738     pub trait_: Type,
2739 }
2740
2741 impl Clean<Item> for doctree::DefaultImpl {
2742     fn clean(&self, cx: &DocContext) -> Item {
2743         Item {
2744             name: None,
2745             attrs: self.attrs.clean(cx),
2746             source: self.whence.clean(cx),
2747             def_id: cx.tcx.hir.local_def_id(self.id),
2748             visibility: Some(Public),
2749             stability: None,
2750             deprecation: None,
2751             inner: DefaultImplItem(DefaultImpl {
2752                 unsafety: self.unsafety,
2753                 trait_: self.trait_.clean(cx),
2754             }),
2755         }
2756     }
2757 }
2758
2759 impl Clean<Item> for doctree::ExternCrate {
2760     fn clean(&self, cx: &DocContext) -> Item {
2761         Item {
2762             name: None,
2763             attrs: self.attrs.clean(cx),
2764             source: self.whence.clean(cx),
2765             def_id: DefId { krate: self.cnum, index: CRATE_DEF_INDEX },
2766             visibility: self.vis.clean(cx),
2767             stability: None,
2768             deprecation: None,
2769             inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
2770         }
2771     }
2772 }
2773
2774 impl Clean<Vec<Item>> for doctree::Import {
2775     fn clean(&self, cx: &DocContext) -> Vec<Item> {
2776         // We consider inlining the documentation of `pub use` statements, but we
2777         // forcefully don't inline if this is not public or if the
2778         // #[doc(no_inline)] attribute is present.
2779         // Don't inline doc(hidden) imports so they can be stripped at a later stage.
2780         let denied = self.vis != hir::Public || self.attrs.iter().any(|a| {
2781             a.name().unwrap() == "doc" && match a.meta_item_list() {
2782                 Some(l) => attr::list_contains_name(&l, "no_inline") ||
2783                            attr::list_contains_name(&l, "hidden"),
2784                 None => false,
2785             }
2786         });
2787         let path = self.path.clean(cx);
2788         let inner = if self.glob {
2789             Import::Glob(resolve_use_source(cx, path))
2790         } else {
2791             let name = self.name;
2792             if !denied {
2793                 if let Some(items) = inline::try_inline(cx, path.def, name) {
2794                     return items;
2795                 }
2796             }
2797             Import::Simple(name.clean(cx), resolve_use_source(cx, path))
2798         };
2799         vec![Item {
2800             name: None,
2801             attrs: self.attrs.clean(cx),
2802             source: self.whence.clean(cx),
2803             def_id: cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID),
2804             visibility: self.vis.clean(cx),
2805             stability: None,
2806             deprecation: None,
2807             inner: ImportItem(inner)
2808         }]
2809     }
2810 }
2811
2812 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2813 pub enum Import {
2814     // use source as str;
2815     Simple(String, ImportSource),
2816     // use source::*;
2817     Glob(ImportSource)
2818 }
2819
2820 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2821 pub struct ImportSource {
2822     pub path: Path,
2823     pub did: Option<DefId>,
2824 }
2825
2826 impl Clean<Vec<Item>> for hir::ForeignMod {
2827     fn clean(&self, cx: &DocContext) -> Vec<Item> {
2828         let mut items = self.items.clean(cx);
2829         for item in &mut items {
2830             if let ForeignFunctionItem(ref mut f) = item.inner {
2831                 f.abi = self.abi;
2832             }
2833         }
2834         items
2835     }
2836 }
2837
2838 impl Clean<Item> for hir::ForeignItem {
2839     fn clean(&self, cx: &DocContext) -> Item {
2840         let inner = match self.node {
2841             hir::ForeignItemFn(ref decl, ref names, ref generics) => {
2842                 ForeignFunctionItem(Function {
2843                     decl: (&**decl, &names[..]).clean(cx),
2844                     generics: generics.clean(cx),
2845                     unsafety: hir::Unsafety::Unsafe,
2846                     abi: Abi::Rust,
2847                     constness: hir::Constness::NotConst,
2848                 })
2849             }
2850             hir::ForeignItemStatic(ref ty, mutbl) => {
2851                 ForeignStaticItem(Static {
2852                     type_: ty.clean(cx),
2853                     mutability: if mutbl {Mutable} else {Immutable},
2854                     expr: "".to_string(),
2855                 })
2856             }
2857             hir::ForeignItemType => {
2858                 ForeignTypeItem
2859             }
2860         };
2861         Item {
2862             name: Some(self.name.clean(cx)),
2863             attrs: self.attrs.clean(cx),
2864             source: self.span.clean(cx),
2865             def_id: cx.tcx.hir.local_def_id(self.id),
2866             visibility: self.vis.clean(cx),
2867             stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)),
2868             deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)),
2869             inner,
2870         }
2871     }
2872 }
2873
2874 // Utilities
2875
2876 trait ToSource {
2877     fn to_src(&self, cx: &DocContext) -> String;
2878 }
2879
2880 impl ToSource for syntax_pos::Span {
2881     fn to_src(&self, cx: &DocContext) -> String {
2882         debug!("converting span {:?} to snippet", self.clean(cx));
2883         let sn = match cx.sess().codemap().span_to_snippet(*self) {
2884             Ok(x) => x.to_string(),
2885             Err(_) => "".to_string()
2886         };
2887         debug!("got snippet {}", sn);
2888         sn
2889     }
2890 }
2891
2892 fn name_from_pat(p: &hir::Pat) -> String {
2893     use rustc::hir::*;
2894     debug!("Trying to get a name from pattern: {:?}", p);
2895
2896     match p.node {
2897         PatKind::Wild => "_".to_string(),
2898         PatKind::Binding(_, _, ref p, _) => p.node.to_string(),
2899         PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
2900         PatKind::Struct(ref name, ref fields, etc) => {
2901             format!("{} {{ {}{} }}", qpath_to_string(name),
2902                 fields.iter().map(|&Spanned { node: ref fp, .. }|
2903                                   format!("{}: {}", fp.name, name_from_pat(&*fp.pat)))
2904                              .collect::<Vec<String>>().join(", "),
2905                 if etc { ", ..." } else { "" }
2906             )
2907         }
2908         PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
2909                                             .collect::<Vec<String>>().join(", ")),
2910         PatKind::Box(ref p) => name_from_pat(&**p),
2911         PatKind::Ref(ref p, _) => name_from_pat(&**p),
2912         PatKind::Lit(..) => {
2913             warn!("tried to get argument name from PatKind::Lit, \
2914                   which is silly in function arguments");
2915             "()".to_string()
2916         },
2917         PatKind::Range(..) => panic!("tried to get argument name from PatKind::Range, \
2918                               which is not allowed in function arguments"),
2919         PatKind::Slice(ref begin, ref mid, ref end) => {
2920             let begin = begin.iter().map(|p| name_from_pat(&**p));
2921             let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter();
2922             let end = end.iter().map(|p| name_from_pat(&**p));
2923             format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
2924         },
2925     }
2926 }
2927
2928 fn print_const_expr(cx: &DocContext, body: hir::BodyId) -> String {
2929     cx.tcx.hir.node_to_pretty_string(body.node_id)
2930 }
2931
2932 /// Given a type Path, resolve it to a Type using the TyCtxt
2933 fn resolve_type(cx: &DocContext,
2934                 path: Path,
2935                 id: ast::NodeId) -> Type {
2936     debug!("resolve_type({:?},{:?})", path, id);
2937
2938     let is_generic = match path.def {
2939         Def::PrimTy(p) => match p {
2940             hir::TyStr => return Primitive(PrimitiveType::Str),
2941             hir::TyBool => return Primitive(PrimitiveType::Bool),
2942             hir::TyChar => return Primitive(PrimitiveType::Char),
2943             hir::TyInt(int_ty) => return Primitive(int_ty.into()),
2944             hir::TyUint(uint_ty) => return Primitive(uint_ty.into()),
2945             hir::TyFloat(float_ty) => return Primitive(float_ty.into()),
2946         },
2947         Def::SelfTy(..) if path.segments.len() == 1 => {
2948             return Generic(keywords::SelfType.name().to_string());
2949         }
2950         Def::TyParam(..) if path.segments.len() == 1 => {
2951             return Generic(format!("{:#}", path));
2952         }
2953         Def::SelfTy(..) | Def::TyParam(..) | Def::AssociatedTy(..) => true,
2954         _ => false,
2955     };
2956     let did = register_def(&*cx, path.def);
2957     ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
2958 }
2959
2960 fn register_def(cx: &DocContext, def: Def) -> DefId {
2961     debug!("register_def({:?})", def);
2962
2963     let (did, kind) = match def {
2964         Def::Fn(i) => (i, TypeKind::Function),
2965         Def::TyAlias(i) => (i, TypeKind::Typedef),
2966         Def::Enum(i) => (i, TypeKind::Enum),
2967         Def::Trait(i) => (i, TypeKind::Trait),
2968         Def::Struct(i) => (i, TypeKind::Struct),
2969         Def::Union(i) => (i, TypeKind::Union),
2970         Def::Mod(i) => (i, TypeKind::Module),
2971         Def::Static(i, _) => (i, TypeKind::Static),
2972         Def::Variant(i) => (cx.tcx.parent_def_id(i).unwrap(), TypeKind::Enum),
2973         Def::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
2974         Def::SelfTy(_, Some(impl_def_id)) => {
2975             return impl_def_id
2976         }
2977         _ => return def.def_id()
2978     };
2979     if did.is_local() { return did }
2980     inline::record_extern_fqn(cx, did, kind);
2981     if let TypeKind::Trait = kind {
2982         let t = inline::build_external_trait(cx, did);
2983         cx.external_traits.borrow_mut().insert(did, t);
2984     }
2985     did
2986 }
2987
2988 fn resolve_use_source(cx: &DocContext, path: Path) -> ImportSource {
2989     ImportSource {
2990         did: if path.def == Def::Err {
2991             None
2992         } else {
2993             Some(register_def(cx, path.def))
2994         },
2995         path,
2996     }
2997 }
2998
2999 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3000 pub struct Macro {
3001     pub source: String,
3002     pub imported_from: Option<String>,
3003 }
3004
3005 impl Clean<Item> for doctree::Macro {
3006     fn clean(&self, cx: &DocContext) -> Item {
3007         let name = self.name.clean(cx);
3008         Item {
3009             name: Some(name.clone()),
3010             attrs: self.attrs.clean(cx),
3011             source: self.whence.clean(cx),
3012             visibility: Some(Public),
3013             stability: self.stab.clean(cx),
3014             deprecation: self.depr.clean(cx),
3015             def_id: self.def_id,
3016             inner: MacroItem(Macro {
3017                 source: format!("macro_rules! {} {{\n{}}}",
3018                                 name,
3019                                 self.matchers.iter().map(|span| {
3020                                     format!("    {} => {{ ... }};\n", span.to_src(cx))
3021                                 }).collect::<String>()),
3022                 imported_from: self.imported_from.clean(cx),
3023             }),
3024         }
3025     }
3026 }
3027
3028 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3029 pub struct Stability {
3030     pub level: stability::StabilityLevel,
3031     pub feature: String,
3032     pub since: String,
3033     pub deprecated_since: String,
3034     pub deprecated_reason: String,
3035     pub unstable_reason: String,
3036     pub issue: Option<u32>
3037 }
3038
3039 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3040 pub struct Deprecation {
3041     pub since: String,
3042     pub note: String,
3043 }
3044
3045 impl Clean<Stability> for attr::Stability {
3046     fn clean(&self, _: &DocContext) -> Stability {
3047         Stability {
3048             level: stability::StabilityLevel::from_attr_level(&self.level),
3049             feature: self.feature.to_string(),
3050             since: match self.level {
3051                 attr::Stable {ref since} => since.to_string(),
3052                 _ => "".to_string(),
3053             },
3054             deprecated_since: match self.rustc_depr {
3055                 Some(attr::RustcDeprecation {ref since, ..}) => since.to_string(),
3056                 _=> "".to_string(),
3057             },
3058             deprecated_reason: match self.rustc_depr {
3059                 Some(ref depr) => depr.reason.to_string(),
3060                 _ => "".to_string(),
3061             },
3062             unstable_reason: match self.level {
3063                 attr::Unstable { reason: Some(ref reason), .. } => reason.to_string(),
3064                 _ => "".to_string(),
3065             },
3066             issue: match self.level {
3067                 attr::Unstable {issue, ..} => Some(issue),
3068                 _ => None,
3069             }
3070         }
3071     }
3072 }
3073
3074 impl<'a> Clean<Stability> for &'a attr::Stability {
3075     fn clean(&self, dc: &DocContext) -> Stability {
3076         (**self).clean(dc)
3077     }
3078 }
3079
3080 impl Clean<Deprecation> for attr::Deprecation {
3081     fn clean(&self, _: &DocContext) -> Deprecation {
3082         Deprecation {
3083             since: self.since.as_ref().map_or("".to_string(), |s| s.to_string()),
3084             note: self.note.as_ref().map_or("".to_string(), |s| s.to_string()),
3085         }
3086     }
3087 }
3088
3089 /// An equality constraint on an associated type, e.g. `A=Bar` in `Foo<A=Bar>`
3090 #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Debug)]
3091 pub struct TypeBinding {
3092     pub name: String,
3093     pub ty: Type
3094 }
3095
3096 impl Clean<TypeBinding> for hir::TypeBinding {
3097     fn clean(&self, cx: &DocContext) -> TypeBinding {
3098         TypeBinding {
3099             name: self.name.clean(cx),
3100             ty: self.ty.clean(cx)
3101         }
3102     }
3103 }