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