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