]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/clean/mod.rs
rustdoc: Fix issues with cross-crate inlined associated items
[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                 let default = if self.defaultness.has_value() {
1599                     Some(inline::print_inlined_const(cx, self.def_id))
1600                 } else {
1601                     None
1602                 };
1603                 AssociatedConstItem(ty.clean(cx), default)
1604             }
1605             ty::AssociatedKind::Method => {
1606                 let generics = (cx.tcx.generics_of(self.def_id),
1607                                 &cx.tcx.predicates_of(self.def_id)).clean(cx);
1608                 let sig = cx.tcx.fn_sig(self.def_id);
1609                 let mut decl = (self.def_id, sig).clean(cx);
1610
1611                 if self.method_has_self_argument {
1612                     let self_ty = match self.container {
1613                         ty::ImplContainer(def_id) => {
1614                             cx.tcx.type_of(def_id)
1615                         }
1616                         ty::TraitContainer(_) => cx.tcx.mk_self_type()
1617                     };
1618                     let self_arg_ty = *sig.input(0).skip_binder();
1619                     if self_arg_ty == self_ty {
1620                         decl.inputs.values[0].type_ = Generic(String::from("Self"));
1621                     } else if let ty::TyRef(_, mt) = self_arg_ty.sty {
1622                         if mt.ty == self_ty {
1623                             match decl.inputs.values[0].type_ {
1624                                 BorrowedRef{ref mut type_, ..} => {
1625                                     **type_ = Generic(String::from("Self"))
1626                                 }
1627                                 _ => unreachable!(),
1628                             }
1629                         }
1630                     }
1631                 }
1632
1633                 let provided = match self.container {
1634                     ty::ImplContainer(_) => true,
1635                     ty::TraitContainer(_) => self.defaultness.has_value()
1636                 };
1637                 if provided {
1638                     let constness = if cx.tcx.is_const_fn(self.def_id) {
1639                         hir::Constness::Const
1640                     } else {
1641                         hir::Constness::NotConst
1642                     };
1643                     MethodItem(Method {
1644                         unsafety: sig.unsafety(),
1645                         generics,
1646                         decl,
1647                         abi: sig.abi(),
1648                         constness,
1649                     })
1650                 } else {
1651                     TyMethodItem(TyMethod {
1652                         unsafety: sig.unsafety(),
1653                         generics,
1654                         decl,
1655                         abi: sig.abi(),
1656                     })
1657                 }
1658             }
1659             ty::AssociatedKind::Type => {
1660                 let my_name = self.name.clean(cx);
1661
1662                 if let ty::TraitContainer(did) = self.container {
1663                     // When loading a cross-crate associated type, the bounds for this type
1664                     // are actually located on the trait/impl itself, so we need to load
1665                     // all of the generics from there and then look for bounds that are
1666                     // applied to this associated type in question.
1667                     let predicates = cx.tcx.predicates_of(did);
1668                     let generics = (cx.tcx.generics_of(did), &predicates).clean(cx);
1669                     let mut bounds = generics.where_predicates.iter().filter_map(|pred| {
1670                         let (name, self_type, trait_, bounds) = match *pred {
1671                             WherePredicate::BoundPredicate {
1672                                 ty: QPath { ref name, ref self_type, ref trait_ },
1673                                 ref bounds
1674                             } => (name, self_type, trait_, bounds),
1675                             _ => return None,
1676                         };
1677                         if *name != my_name { return None }
1678                         match **trait_ {
1679                             ResolvedPath { did, .. } if did == self.container.id() => {}
1680                             _ => return None,
1681                         }
1682                         match **self_type {
1683                             Generic(ref s) if *s == "Self" => {}
1684                             _ => return None,
1685                         }
1686                         Some(bounds)
1687                     }).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>();
1688                     // Our Sized/?Sized bound didn't get handled when creating the generics
1689                     // because we didn't actually get our whole set of bounds until just now
1690                     // (some of them may have come from the trait). If we do have a sized
1691                     // bound, we remove it, and if we don't then we add the `?Sized` bound
1692                     // at the end.
1693                     match bounds.iter().position(|b| b.is_sized_bound(cx)) {
1694                         Some(i) => { bounds.remove(i); }
1695                         None => bounds.push(TyParamBound::maybe_sized(cx)),
1696                     }
1697
1698                     let ty = if self.defaultness.has_value() {
1699                         Some(cx.tcx.type_of(self.def_id))
1700                     } else {
1701                         None
1702                     };
1703
1704                     AssociatedTypeItem(bounds, ty.clean(cx))
1705                 } else {
1706                     TypedefItem(Typedef {
1707                         type_: cx.tcx.type_of(self.def_id).clean(cx),
1708                         generics: Generics {
1709                             lifetimes: Vec::new(),
1710                             type_params: Vec::new(),
1711                             where_predicates: Vec::new(),
1712                         },
1713                     }, true)
1714                 }
1715             }
1716         };
1717
1718         let visibility = match self.container {
1719             ty::ImplContainer(_) => self.vis.clean(cx),
1720             ty::TraitContainer(_) => None,
1721         };
1722
1723         Item {
1724             name: Some(self.name.clean(cx)),
1725             visibility,
1726             stability: get_stability(cx, self.def_id),
1727             deprecation: get_deprecation(cx, self.def_id),
1728             def_id: self.def_id,
1729             attrs: inline::load_attrs(cx, self.def_id),
1730             source: cx.tcx.def_span(self.def_id).clean(cx),
1731             inner,
1732         }
1733     }
1734 }
1735
1736 /// A trait reference, which may have higher ranked lifetimes.
1737 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1738 pub struct PolyTrait {
1739     pub trait_: Type,
1740     pub lifetimes: Vec<Lifetime>
1741 }
1742
1743 /// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
1744 /// type out of the AST/TyCtxt given one of these, if more information is needed. Most importantly
1745 /// it does not preserve mutability or boxes.
1746 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1747 pub enum Type {
1748     /// structs/enums/traits (most that'd be an hir::TyPath)
1749     ResolvedPath {
1750         path: Path,
1751         typarams: Option<Vec<TyParamBound>>,
1752         did: DefId,
1753         /// true if is a `T::Name` path for associated types
1754         is_generic: bool,
1755     },
1756     /// For parameterized types, so the consumer of the JSON don't go
1757     /// looking for types which don't exist anywhere.
1758     Generic(String),
1759     /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
1760     /// arrays, slices, and tuples.
1761     Primitive(PrimitiveType),
1762     /// extern "ABI" fn
1763     BareFunction(Box<BareFunctionDecl>),
1764     Tuple(Vec<Type>),
1765     Slice(Box<Type>),
1766     Array(Box<Type>, String),
1767     Never,
1768     Unique(Box<Type>),
1769     RawPointer(Mutability, Box<Type>),
1770     BorrowedRef {
1771         lifetime: Option<Lifetime>,
1772         mutability: Mutability,
1773         type_: Box<Type>,
1774     },
1775
1776     // <Type as Trait>::Name
1777     QPath {
1778         name: String,
1779         self_type: Box<Type>,
1780         trait_: Box<Type>
1781     },
1782
1783     // _
1784     Infer,
1785
1786     // impl TraitA+TraitB
1787     ImplTrait(Vec<TyParamBound>),
1788 }
1789
1790 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
1791 pub enum PrimitiveType {
1792     Isize, I8, I16, I32, I64, I128,
1793     Usize, U8, U16, U32, U64, U128,
1794     F32, F64,
1795     Char,
1796     Bool,
1797     Str,
1798     Slice,
1799     Array,
1800     Tuple,
1801     Unit,
1802     RawPointer,
1803     Reference,
1804     Fn,
1805 }
1806
1807 #[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
1808 pub enum TypeKind {
1809     Enum,
1810     Function,
1811     Module,
1812     Const,
1813     Static,
1814     Struct,
1815     Union,
1816     Trait,
1817     Variant,
1818     Typedef,
1819     Foreign,
1820 }
1821
1822 pub trait GetDefId {
1823     fn def_id(&self) -> Option<DefId>;
1824 }
1825
1826 impl<T: GetDefId> GetDefId for Option<T> {
1827     fn def_id(&self) -> Option<DefId> {
1828         self.as_ref().and_then(|d| d.def_id())
1829     }
1830 }
1831
1832 impl Type {
1833     pub fn primitive_type(&self) -> Option<PrimitiveType> {
1834         match *self {
1835             Primitive(p) | BorrowedRef { type_: box Primitive(p), ..} => Some(p),
1836             Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
1837             Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1838             Tuple(ref tys) => if tys.is_empty() {
1839                 Some(PrimitiveType::Unit)
1840             } else {
1841                 Some(PrimitiveType::Tuple)
1842             },
1843             RawPointer(..) => Some(PrimitiveType::RawPointer),
1844             BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
1845             BareFunction(..) => Some(PrimitiveType::Fn),
1846             _ => None,
1847         }
1848     }
1849
1850     pub fn is_generic(&self) -> bool {
1851         match *self {
1852             ResolvedPath { is_generic, .. } => is_generic,
1853             _ => false,
1854         }
1855     }
1856
1857     pub fn is_self_type(&self) -> bool {
1858         match *self {
1859             Generic(ref name) => name == "Self",
1860             _ => false
1861         }
1862     }
1863
1864     pub fn generics(&self) -> Option<&[Type]> {
1865         match *self {
1866             ResolvedPath { ref path, .. } => {
1867                 path.segments.last().and_then(|seg| {
1868                     if let PathParameters::AngleBracketed { ref types, .. } = seg.params {
1869                         Some(&**types)
1870                     } else {
1871                         None
1872                     }
1873                 })
1874             }
1875             _ => None,
1876         }
1877     }
1878 }
1879
1880 impl GetDefId for Type {
1881     fn def_id(&self) -> Option<DefId> {
1882         match *self {
1883             ResolvedPath { did, .. } => Some(did),
1884             Primitive(p) => ::html::render::cache().primitive_locations.get(&p).cloned(),
1885             BorrowedRef { type_: box Generic(..), .. } =>
1886                 Primitive(PrimitiveType::Reference).def_id(),
1887             BorrowedRef { ref type_, .. } => type_.def_id(),
1888             Tuple(ref tys) => if tys.is_empty() {
1889                 Primitive(PrimitiveType::Unit).def_id()
1890             } else {
1891                 Primitive(PrimitiveType::Tuple).def_id()
1892             },
1893             BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
1894             Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
1895             Array(..) => Primitive(PrimitiveType::Array).def_id(),
1896             RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(),
1897             QPath { ref self_type, .. } => self_type.def_id(),
1898             _ => None,
1899         }
1900     }
1901 }
1902
1903 impl PrimitiveType {
1904     fn from_str(s: &str) -> Option<PrimitiveType> {
1905         match s {
1906             "isize" => Some(PrimitiveType::Isize),
1907             "i8" => Some(PrimitiveType::I8),
1908             "i16" => Some(PrimitiveType::I16),
1909             "i32" => Some(PrimitiveType::I32),
1910             "i64" => Some(PrimitiveType::I64),
1911             "i128" => Some(PrimitiveType::I128),
1912             "usize" => Some(PrimitiveType::Usize),
1913             "u8" => Some(PrimitiveType::U8),
1914             "u16" => Some(PrimitiveType::U16),
1915             "u32" => Some(PrimitiveType::U32),
1916             "u64" => Some(PrimitiveType::U64),
1917             "u128" => Some(PrimitiveType::U128),
1918             "bool" => Some(PrimitiveType::Bool),
1919             "char" => Some(PrimitiveType::Char),
1920             "str" => Some(PrimitiveType::Str),
1921             "f32" => Some(PrimitiveType::F32),
1922             "f64" => Some(PrimitiveType::F64),
1923             "array" => Some(PrimitiveType::Array),
1924             "slice" => Some(PrimitiveType::Slice),
1925             "tuple" => Some(PrimitiveType::Tuple),
1926             "unit" => Some(PrimitiveType::Unit),
1927             "pointer" => Some(PrimitiveType::RawPointer),
1928             "reference" => Some(PrimitiveType::Reference),
1929             "fn" => Some(PrimitiveType::Fn),
1930             _ => None,
1931         }
1932     }
1933
1934     pub fn as_str(&self) -> &'static str {
1935         use self::PrimitiveType::*;
1936         match *self {
1937             Isize => "isize",
1938             I8 => "i8",
1939             I16 => "i16",
1940             I32 => "i32",
1941             I64 => "i64",
1942             I128 => "i128",
1943             Usize => "usize",
1944             U8 => "u8",
1945             U16 => "u16",
1946             U32 => "u32",
1947             U64 => "u64",
1948             U128 => "u128",
1949             F32 => "f32",
1950             F64 => "f64",
1951             Str => "str",
1952             Bool => "bool",
1953             Char => "char",
1954             Array => "array",
1955             Slice => "slice",
1956             Tuple => "tuple",
1957             Unit => "unit",
1958             RawPointer => "pointer",
1959             Reference => "reference",
1960             Fn => "fn",
1961         }
1962     }
1963
1964     pub fn to_url_str(&self) -> &'static str {
1965         self.as_str()
1966     }
1967 }
1968
1969 impl From<ast::IntTy> for PrimitiveType {
1970     fn from(int_ty: ast::IntTy) -> PrimitiveType {
1971         match int_ty {
1972             ast::IntTy::Is => PrimitiveType::Isize,
1973             ast::IntTy::I8 => PrimitiveType::I8,
1974             ast::IntTy::I16 => PrimitiveType::I16,
1975             ast::IntTy::I32 => PrimitiveType::I32,
1976             ast::IntTy::I64 => PrimitiveType::I64,
1977             ast::IntTy::I128 => PrimitiveType::I128,
1978         }
1979     }
1980 }
1981
1982 impl From<ast::UintTy> for PrimitiveType {
1983     fn from(uint_ty: ast::UintTy) -> PrimitiveType {
1984         match uint_ty {
1985             ast::UintTy::Us => PrimitiveType::Usize,
1986             ast::UintTy::U8 => PrimitiveType::U8,
1987             ast::UintTy::U16 => PrimitiveType::U16,
1988             ast::UintTy::U32 => PrimitiveType::U32,
1989             ast::UintTy::U64 => PrimitiveType::U64,
1990             ast::UintTy::U128 => PrimitiveType::U128,
1991         }
1992     }
1993 }
1994
1995 impl From<ast::FloatTy> for PrimitiveType {
1996     fn from(float_ty: ast::FloatTy) -> PrimitiveType {
1997         match float_ty {
1998             ast::FloatTy::F32 => PrimitiveType::F32,
1999             ast::FloatTy::F64 => PrimitiveType::F64,
2000         }
2001     }
2002 }
2003
2004 impl Clean<Type> for hir::Ty {
2005     fn clean(&self, cx: &DocContext) -> Type {
2006         use rustc::hir::*;
2007         match self.node {
2008             TyNever => Never,
2009             TyPtr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
2010             TyRptr(ref l, ref m) => {
2011                 let lifetime = if l.is_elided() {
2012                     None
2013                 } else {
2014                     Some(l.clean(cx))
2015                 };
2016                 BorrowedRef {lifetime: lifetime, mutability: m.mutbl.clean(cx),
2017                              type_: box m.ty.clean(cx)}
2018             }
2019             TySlice(ref ty) => Slice(box ty.clean(cx)),
2020             TyArray(ref ty, n) => {
2021                 let def_id = cx.tcx.hir.body_owner_def_id(n);
2022                 let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
2023                 let substs = Substs::identity_for_item(cx.tcx, def_id);
2024                 let n = cx.tcx.const_eval(param_env.and((def_id, substs))).unwrap();
2025                 let n = if let ConstVal::Integral(ConstInt::Usize(n)) = n.val {
2026                     n.to_string()
2027                 } else if let ConstVal::Unevaluated(def_id, _) = n.val {
2028                     if let Some(node_id) = cx.tcx.hir.as_local_node_id(def_id) {
2029                         print_const_expr(cx, cx.tcx.hir.body_owned_by(node_id))
2030                     } else {
2031                         inline::print_inlined_const(cx, def_id)
2032                     }
2033                 } else {
2034                     format!("{:?}", n)
2035                 };
2036                 Array(box ty.clean(cx), n)
2037             },
2038             TyTup(ref tys) => Tuple(tys.clean(cx)),
2039             TyPath(hir::QPath::Resolved(None, ref path)) => {
2040                 if let Some(new_ty) = cx.ty_substs.borrow().get(&path.def).cloned() {
2041                     return new_ty;
2042                 }
2043
2044                 let mut alias = None;
2045                 if let Def::TyAlias(def_id) = path.def {
2046                     // Substitute private type aliases
2047                     if let Some(node_id) = cx.tcx.hir.as_local_node_id(def_id) {
2048                         if !cx.access_levels.borrow().is_exported(def_id) {
2049                             alias = Some(&cx.tcx.hir.expect_item(node_id).node);
2050                         }
2051                     }
2052                 };
2053
2054                 if let Some(&hir::ItemTy(ref ty, ref generics)) = alias {
2055                     let provided_params = &path.segments.last().unwrap();
2056                     let mut ty_substs = FxHashMap();
2057                     let mut lt_substs = FxHashMap();
2058                     provided_params.with_parameters(|provided_params| {
2059                         for (i, ty_param) in generics.ty_params.iter().enumerate() {
2060                             let ty_param_def = Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id));
2061                             if let Some(ty) = provided_params.types.get(i).cloned() {
2062                                 ty_substs.insert(ty_param_def, ty.unwrap().clean(cx));
2063                             } else if let Some(default) = ty_param.default.clone() {
2064                                 ty_substs.insert(ty_param_def, default.unwrap().clean(cx));
2065                             }
2066                         }
2067                         for (i, lt_param) in generics.lifetimes.iter().enumerate() {
2068                             if let Some(lt) = provided_params.lifetimes.get(i).cloned() {
2069                                 if !lt.is_elided() {
2070                                     let lt_def_id = cx.tcx.hir.local_def_id(lt_param.lifetime.id);
2071                                     lt_substs.insert(lt_def_id, lt.clean(cx));
2072                                 }
2073                             }
2074                         }
2075                     });
2076                     return cx.enter_alias(ty_substs, lt_substs, || ty.clean(cx));
2077                 }
2078                 resolve_type(cx, path.clean(cx), self.id)
2079             }
2080             TyPath(hir::QPath::Resolved(Some(ref qself), ref p)) => {
2081                 let mut segments: Vec<_> = p.segments.clone().into();
2082                 segments.pop();
2083                 let trait_path = hir::Path {
2084                     span: p.span,
2085                     def: Def::Trait(cx.tcx.associated_item(p.def.def_id()).container.id()),
2086                     segments: segments.into(),
2087                 };
2088                 Type::QPath {
2089                     name: p.segments.last().unwrap().name.clean(cx),
2090                     self_type: box qself.clean(cx),
2091                     trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
2092                 }
2093             }
2094             TyPath(hir::QPath::TypeRelative(ref qself, ref segment)) => {
2095                 let mut def = Def::Err;
2096                 let ty = hir_ty_to_ty(cx.tcx, self);
2097                 if let ty::TyProjection(proj) = ty.sty {
2098                     def = Def::Trait(proj.trait_ref(cx.tcx).def_id);
2099                 }
2100                 let trait_path = hir::Path {
2101                     span: self.span,
2102                     def,
2103                     segments: vec![].into(),
2104                 };
2105                 Type::QPath {
2106                     name: segment.name.clean(cx),
2107                     self_type: box qself.clean(cx),
2108                     trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
2109                 }
2110             }
2111             TyTraitObject(ref bounds, ref lifetime) => {
2112                 match bounds[0].clean(cx).trait_ {
2113                     ResolvedPath { path, typarams: None, did, is_generic } => {
2114                         let mut bounds: Vec<_> = bounds[1..].iter().map(|bound| {
2115                             TraitBound(bound.clean(cx), hir::TraitBoundModifier::None)
2116                         }).collect();
2117                         if !lifetime.is_elided() {
2118                             bounds.push(RegionBound(lifetime.clean(cx)));
2119                         }
2120                         ResolvedPath {
2121                             path,
2122                             typarams: Some(bounds),
2123                             did,
2124                             is_generic,
2125                         }
2126                     }
2127                     _ => Infer // shouldn't happen
2128                 }
2129             }
2130             TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
2131             TyImplTraitExistential(ref exist_ty, ref _lts) => ImplTrait(exist_ty.bounds.clean(cx)),
2132             TyImplTraitUniversal(_, ref bounds) => ImplTrait(bounds.clean(cx)),
2133             TyInfer | TyErr => Infer,
2134             TyTypeof(..) => panic!("Unimplemented type {:?}", self.node),
2135         }
2136     }
2137 }
2138
2139 impl<'tcx> Clean<Type> for Ty<'tcx> {
2140     fn clean(&self, cx: &DocContext) -> Type {
2141         match self.sty {
2142             ty::TyNever => Never,
2143             ty::TyBool => Primitive(PrimitiveType::Bool),
2144             ty::TyChar => Primitive(PrimitiveType::Char),
2145             ty::TyInt(int_ty) => Primitive(int_ty.into()),
2146             ty::TyUint(uint_ty) => Primitive(uint_ty.into()),
2147             ty::TyFloat(float_ty) => Primitive(float_ty.into()),
2148             ty::TyStr => Primitive(PrimitiveType::Str),
2149             ty::TySlice(ty) => Slice(box ty.clean(cx)),
2150             ty::TyArray(ty, n) => {
2151                 let n = if let ConstVal::Integral(ConstInt::Usize(n)) = n.val {
2152                     n.to_string()
2153                 } else if let ConstVal::Unevaluated(def_id, _) = n.val {
2154                     if let Some(node_id) = cx.tcx.hir.as_local_node_id(def_id) {
2155                         print_const_expr(cx, cx.tcx.hir.body_owned_by(node_id))
2156                     } else {
2157                         inline::print_inlined_const(cx, def_id)
2158                     }
2159                 } else {
2160                     format!("{:?}", n)
2161                 };
2162                 Array(box ty.clean(cx), n)
2163             }
2164             ty::TyRawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
2165             ty::TyRef(r, mt) => BorrowedRef {
2166                 lifetime: r.clean(cx),
2167                 mutability: mt.mutbl.clean(cx),
2168                 type_: box mt.ty.clean(cx),
2169             },
2170             ty::TyFnDef(..) |
2171             ty::TyFnPtr(_) => {
2172                 let ty = cx.tcx.lift(self).unwrap();
2173                 let sig = ty.fn_sig(cx.tcx);
2174                 BareFunction(box BareFunctionDecl {
2175                     unsafety: sig.unsafety(),
2176                     generics: Generics {
2177                         lifetimes: Vec::new(),
2178                         type_params: Vec::new(),
2179                         where_predicates: Vec::new()
2180                     },
2181                     decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx),
2182                     abi: sig.abi(),
2183                 })
2184             }
2185             ty::TyAdt(def, substs) => {
2186                 let did = def.did;
2187                 let kind = match def.adt_kind() {
2188                     AdtKind::Struct => TypeKind::Struct,
2189                     AdtKind::Union => TypeKind::Union,
2190                     AdtKind::Enum => TypeKind::Enum,
2191                 };
2192                 inline::record_extern_fqn(cx, did, kind);
2193                 let path = external_path(cx, &cx.tcx.item_name(did),
2194                                          None, false, vec![], substs);
2195                 ResolvedPath {
2196                     path,
2197                     typarams: None,
2198                     did,
2199                     is_generic: false,
2200                 }
2201             }
2202             ty::TyForeign(did) => {
2203                 inline::record_extern_fqn(cx, did, TypeKind::Foreign);
2204                 let path = external_path(cx, &cx.tcx.item_name(did),
2205                                          None, false, vec![], Substs::empty());
2206                 ResolvedPath {
2207                     path: path,
2208                     typarams: None,
2209                     did: did,
2210                     is_generic: false,
2211                 }
2212             }
2213             ty::TyDynamic(ref obj, ref reg) => {
2214                 if let Some(principal) = obj.principal() {
2215                     let did = principal.def_id();
2216                     inline::record_extern_fqn(cx, did, TypeKind::Trait);
2217
2218                     let mut typarams = vec![];
2219                     reg.clean(cx).map(|b| typarams.push(RegionBound(b)));
2220                     for did in obj.auto_traits() {
2221                         let empty = cx.tcx.intern_substs(&[]);
2222                         let path = external_path(cx, &cx.tcx.item_name(did),
2223                             Some(did), false, vec![], empty);
2224                         inline::record_extern_fqn(cx, did, TypeKind::Trait);
2225                         let bound = TraitBound(PolyTrait {
2226                             trait_: ResolvedPath {
2227                                 path,
2228                                 typarams: None,
2229                                 did,
2230                                 is_generic: false,
2231                             },
2232                             lifetimes: vec![]
2233                         }, hir::TraitBoundModifier::None);
2234                         typarams.push(bound);
2235                     }
2236
2237                     let mut bindings = vec![];
2238                     for ty::Binder(ref pb) in obj.projection_bounds() {
2239                         bindings.push(TypeBinding {
2240                             name: cx.tcx.associated_item(pb.item_def_id).name.clean(cx),
2241                             ty: pb.ty.clean(cx)
2242                         });
2243                     }
2244
2245                     let path = external_path(cx, &cx.tcx.item_name(did), Some(did),
2246                         false, bindings, principal.0.substs);
2247                     ResolvedPath {
2248                         path,
2249                         typarams: Some(typarams),
2250                         did,
2251                         is_generic: false,
2252                     }
2253                 } else {
2254                     Never
2255                 }
2256             }
2257             ty::TyTuple(ref t, _) => Tuple(t.clean(cx)),
2258
2259             ty::TyProjection(ref data) => data.clean(cx),
2260
2261             ty::TyParam(ref p) => Generic(p.name.to_string()),
2262
2263             ty::TyAnon(def_id, substs) => {
2264                 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
2265                 // by looking up the projections associated with the def_id.
2266                 let predicates_of = cx.tcx.predicates_of(def_id);
2267                 let substs = cx.tcx.lift(&substs).unwrap();
2268                 let bounds = predicates_of.instantiate(cx.tcx, substs);
2269                 ImplTrait(bounds.predicates.into_iter().filter_map(|predicate| {
2270                     predicate.to_opt_poly_trait_ref().clean(cx)
2271                 }).collect())
2272             }
2273
2274             ty::TyClosure(..) | ty::TyGenerator(..) => Tuple(vec![]), // FIXME(pcwalton)
2275
2276             ty::TyInfer(..) => panic!("TyInfer"),
2277             ty::TyError => panic!("TyError"),
2278         }
2279     }
2280 }
2281
2282 impl Clean<Item> for hir::StructField {
2283     fn clean(&self, cx: &DocContext) -> Item {
2284         Item {
2285             name: Some(self.name).clean(cx),
2286             attrs: self.attrs.clean(cx),
2287             source: self.span.clean(cx),
2288             visibility: self.vis.clean(cx),
2289             stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)),
2290             deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)),
2291             def_id: cx.tcx.hir.local_def_id(self.id),
2292             inner: StructFieldItem(self.ty.clean(cx)),
2293         }
2294     }
2295 }
2296
2297 impl<'tcx> Clean<Item> for ty::FieldDef {
2298     fn clean(&self, cx: &DocContext) -> Item {
2299         Item {
2300             name: Some(self.name).clean(cx),
2301             attrs: cx.tcx.get_attrs(self.did).clean(cx),
2302             source: cx.tcx.def_span(self.did).clean(cx),
2303             visibility: self.vis.clean(cx),
2304             stability: get_stability(cx, self.did),
2305             deprecation: get_deprecation(cx, self.did),
2306             def_id: self.did,
2307             inner: StructFieldItem(cx.tcx.type_of(self.did).clean(cx)),
2308         }
2309     }
2310 }
2311
2312 #[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug)]
2313 pub enum Visibility {
2314     Public,
2315     Inherited,
2316 }
2317
2318 impl Clean<Option<Visibility>> for hir::Visibility {
2319     fn clean(&self, _: &DocContext) -> Option<Visibility> {
2320         Some(if *self == hir::Visibility::Public { Public } else { Inherited })
2321     }
2322 }
2323
2324 impl Clean<Option<Visibility>> for ty::Visibility {
2325     fn clean(&self, _: &DocContext) -> Option<Visibility> {
2326         Some(if *self == ty::Visibility::Public { Public } else { Inherited })
2327     }
2328 }
2329
2330 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2331 pub struct Struct {
2332     pub struct_type: doctree::StructType,
2333     pub generics: Generics,
2334     pub fields: Vec<Item>,
2335     pub fields_stripped: bool,
2336 }
2337
2338 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2339 pub struct Union {
2340     pub struct_type: doctree::StructType,
2341     pub generics: Generics,
2342     pub fields: Vec<Item>,
2343     pub fields_stripped: bool,
2344 }
2345
2346 impl Clean<Item> for doctree::Struct {
2347     fn clean(&self, cx: &DocContext) -> Item {
2348         Item {
2349             name: Some(self.name.clean(cx)),
2350             attrs: self.attrs.clean(cx),
2351             source: self.whence.clean(cx),
2352             def_id: cx.tcx.hir.local_def_id(self.id),
2353             visibility: self.vis.clean(cx),
2354             stability: self.stab.clean(cx),
2355             deprecation: self.depr.clean(cx),
2356             inner: StructItem(Struct {
2357                 struct_type: self.struct_type,
2358                 generics: self.generics.clean(cx),
2359                 fields: self.fields.clean(cx),
2360                 fields_stripped: false,
2361             }),
2362         }
2363     }
2364 }
2365
2366 impl Clean<Item> for doctree::Union {
2367     fn clean(&self, cx: &DocContext) -> Item {
2368         Item {
2369             name: Some(self.name.clean(cx)),
2370             attrs: self.attrs.clean(cx),
2371             source: self.whence.clean(cx),
2372             def_id: cx.tcx.hir.local_def_id(self.id),
2373             visibility: self.vis.clean(cx),
2374             stability: self.stab.clean(cx),
2375             deprecation: self.depr.clean(cx),
2376             inner: UnionItem(Union {
2377                 struct_type: self.struct_type,
2378                 generics: self.generics.clean(cx),
2379                 fields: self.fields.clean(cx),
2380                 fields_stripped: false,
2381             }),
2382         }
2383     }
2384 }
2385
2386 /// This is a more limited form of the standard Struct, different in that
2387 /// it lacks the things most items have (name, id, parameterization). Found
2388 /// only as a variant in an enum.
2389 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2390 pub struct VariantStruct {
2391     pub struct_type: doctree::StructType,
2392     pub fields: Vec<Item>,
2393     pub fields_stripped: bool,
2394 }
2395
2396 impl Clean<VariantStruct> for ::rustc::hir::VariantData {
2397     fn clean(&self, cx: &DocContext) -> VariantStruct {
2398         VariantStruct {
2399             struct_type: doctree::struct_type_from_def(self),
2400             fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
2401             fields_stripped: false,
2402         }
2403     }
2404 }
2405
2406 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2407 pub struct Enum {
2408     pub variants: Vec<Item>,
2409     pub generics: Generics,
2410     pub variants_stripped: bool,
2411 }
2412
2413 impl Clean<Item> for doctree::Enum {
2414     fn clean(&self, cx: &DocContext) -> Item {
2415         Item {
2416             name: Some(self.name.clean(cx)),
2417             attrs: self.attrs.clean(cx),
2418             source: self.whence.clean(cx),
2419             def_id: cx.tcx.hir.local_def_id(self.id),
2420             visibility: self.vis.clean(cx),
2421             stability: self.stab.clean(cx),
2422             deprecation: self.depr.clean(cx),
2423             inner: EnumItem(Enum {
2424                 variants: self.variants.clean(cx),
2425                 generics: self.generics.clean(cx),
2426                 variants_stripped: false,
2427             }),
2428         }
2429     }
2430 }
2431
2432 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2433 pub struct Variant {
2434     pub kind: VariantKind,
2435 }
2436
2437 impl Clean<Item> for doctree::Variant {
2438     fn clean(&self, cx: &DocContext) -> Item {
2439         Item {
2440             name: Some(self.name.clean(cx)),
2441             attrs: self.attrs.clean(cx),
2442             source: self.whence.clean(cx),
2443             visibility: None,
2444             stability: self.stab.clean(cx),
2445             deprecation: self.depr.clean(cx),
2446             def_id: cx.tcx.hir.local_def_id(self.def.id()),
2447             inner: VariantItem(Variant {
2448                 kind: self.def.clean(cx),
2449             }),
2450         }
2451     }
2452 }
2453
2454 impl<'tcx> Clean<Item> for ty::VariantDef {
2455     fn clean(&self, cx: &DocContext) -> Item {
2456         let kind = match self.ctor_kind {
2457             CtorKind::Const => VariantKind::CLike,
2458             CtorKind::Fn => {
2459                 VariantKind::Tuple(
2460                     self.fields.iter().map(|f| cx.tcx.type_of(f.did).clean(cx)).collect()
2461                 )
2462             }
2463             CtorKind::Fictive => {
2464                 VariantKind::Struct(VariantStruct {
2465                     struct_type: doctree::Plain,
2466                     fields_stripped: false,
2467                     fields: self.fields.iter().map(|field| {
2468                         Item {
2469                             source: cx.tcx.def_span(field.did).clean(cx),
2470                             name: Some(field.name.clean(cx)),
2471                             attrs: cx.tcx.get_attrs(field.did).clean(cx),
2472                             visibility: field.vis.clean(cx),
2473                             def_id: field.did,
2474                             stability: get_stability(cx, field.did),
2475                             deprecation: get_deprecation(cx, field.did),
2476                             inner: StructFieldItem(cx.tcx.type_of(field.did).clean(cx))
2477                         }
2478                     }).collect()
2479                 })
2480             }
2481         };
2482         Item {
2483             name: Some(self.name.clean(cx)),
2484             attrs: inline::load_attrs(cx, self.did),
2485             source: cx.tcx.def_span(self.did).clean(cx),
2486             visibility: Some(Inherited),
2487             def_id: self.did,
2488             inner: VariantItem(Variant { kind: kind }),
2489             stability: get_stability(cx, self.did),
2490             deprecation: get_deprecation(cx, self.did),
2491         }
2492     }
2493 }
2494
2495 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2496 pub enum VariantKind {
2497     CLike,
2498     Tuple(Vec<Type>),
2499     Struct(VariantStruct),
2500 }
2501
2502 impl Clean<VariantKind> for hir::VariantData {
2503     fn clean(&self, cx: &DocContext) -> VariantKind {
2504         if self.is_struct() {
2505             VariantKind::Struct(self.clean(cx))
2506         } else if self.is_unit() {
2507             VariantKind::CLike
2508         } else {
2509             VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect())
2510         }
2511     }
2512 }
2513
2514 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2515 pub struct Span {
2516     pub filename: String,
2517     pub loline: usize,
2518     pub locol: usize,
2519     pub hiline: usize,
2520     pub hicol: usize,
2521 }
2522
2523 impl Span {
2524     fn empty() -> Span {
2525         Span {
2526             filename: "".to_string(),
2527             loline: 0, locol: 0,
2528             hiline: 0, hicol: 0,
2529         }
2530     }
2531 }
2532
2533 impl Clean<Span> for syntax_pos::Span {
2534     fn clean(&self, cx: &DocContext) -> Span {
2535         if *self == DUMMY_SP {
2536             return Span::empty();
2537         }
2538
2539         let cm = cx.sess().codemap();
2540         let filename = cm.span_to_filename(*self);
2541         let lo = cm.lookup_char_pos(self.lo());
2542         let hi = cm.lookup_char_pos(self.hi());
2543         Span {
2544             filename: filename.to_string(),
2545             loline: lo.line,
2546             locol: lo.col.to_usize(),
2547             hiline: hi.line,
2548             hicol: hi.col.to_usize(),
2549         }
2550     }
2551 }
2552
2553 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2554 pub struct Path {
2555     pub global: bool,
2556     pub def: Def,
2557     pub segments: Vec<PathSegment>,
2558 }
2559
2560 impl Path {
2561     pub fn singleton(name: String) -> Path {
2562         Path {
2563             global: false,
2564             def: Def::Err,
2565             segments: vec![PathSegment {
2566                 name,
2567                 params: PathParameters::AngleBracketed {
2568                     lifetimes: Vec::new(),
2569                     types: Vec::new(),
2570                     bindings: Vec::new()
2571                 }
2572             }]
2573         }
2574     }
2575
2576     pub fn last_name(&self) -> &str {
2577         self.segments.last().unwrap().name.as_str()
2578     }
2579 }
2580
2581 impl Clean<Path> for hir::Path {
2582     fn clean(&self, cx: &DocContext) -> Path {
2583         Path {
2584             global: self.is_global(),
2585             def: self.def,
2586             segments: if self.is_global() { &self.segments[1..] } else { &self.segments }.clean(cx),
2587         }
2588     }
2589 }
2590
2591 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2592 pub enum PathParameters {
2593     AngleBracketed {
2594         lifetimes: Vec<Lifetime>,
2595         types: Vec<Type>,
2596         bindings: Vec<TypeBinding>,
2597     },
2598     Parenthesized {
2599         inputs: Vec<Type>,
2600         output: Option<Type>,
2601     }
2602 }
2603
2604 impl Clean<PathParameters> for hir::PathParameters {
2605     fn clean(&self, cx: &DocContext) -> PathParameters {
2606         if self.parenthesized {
2607             let output = self.bindings[0].ty.clean(cx);
2608             PathParameters::Parenthesized {
2609                 inputs: self.inputs().clean(cx),
2610                 output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
2611             }
2612         } else {
2613             PathParameters::AngleBracketed {
2614                 lifetimes: if self.lifetimes.iter().all(|lt| lt.is_elided()) {
2615                     vec![]
2616                 } else {
2617                     self.lifetimes.clean(cx)
2618                 },
2619                 types: self.types.clean(cx),
2620                 bindings: self.bindings.clean(cx),
2621             }
2622         }
2623     }
2624 }
2625
2626 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2627 pub struct PathSegment {
2628     pub name: String,
2629     pub params: PathParameters,
2630 }
2631
2632 impl Clean<PathSegment> for hir::PathSegment {
2633     fn clean(&self, cx: &DocContext) -> PathSegment {
2634         PathSegment {
2635             name: self.name.clean(cx),
2636             params: self.with_parameters(|parameters| parameters.clean(cx))
2637         }
2638     }
2639 }
2640
2641 fn qpath_to_string(p: &hir::QPath) -> String {
2642     let segments = match *p {
2643         hir::QPath::Resolved(_, ref path) => &path.segments,
2644         hir::QPath::TypeRelative(_, ref segment) => return segment.name.to_string(),
2645     };
2646
2647     let mut s = String::new();
2648     for (i, seg) in segments.iter().enumerate() {
2649         if i > 0 {
2650             s.push_str("::");
2651         }
2652         if seg.name != keywords::CrateRoot.name() {
2653             s.push_str(&*seg.name.as_str());
2654         }
2655     }
2656     s
2657 }
2658
2659 impl Clean<String> for ast::Name {
2660     fn clean(&self, _: &DocContext) -> String {
2661         self.to_string()
2662     }
2663 }
2664
2665 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2666 pub struct Typedef {
2667     pub type_: Type,
2668     pub generics: Generics,
2669 }
2670
2671 impl Clean<Item> for doctree::Typedef {
2672     fn clean(&self, cx: &DocContext) -> Item {
2673         Item {
2674             name: Some(self.name.clean(cx)),
2675             attrs: self.attrs.clean(cx),
2676             source: self.whence.clean(cx),
2677             def_id: cx.tcx.hir.local_def_id(self.id.clone()),
2678             visibility: self.vis.clean(cx),
2679             stability: self.stab.clean(cx),
2680             deprecation: self.depr.clean(cx),
2681             inner: TypedefItem(Typedef {
2682                 type_: self.ty.clean(cx),
2683                 generics: self.gen.clean(cx),
2684             }, false),
2685         }
2686     }
2687 }
2688
2689 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2690 pub struct BareFunctionDecl {
2691     pub unsafety: hir::Unsafety,
2692     pub generics: Generics,
2693     pub decl: FnDecl,
2694     pub abi: Abi,
2695 }
2696
2697 impl Clean<BareFunctionDecl> for hir::BareFnTy {
2698     fn clean(&self, cx: &DocContext) -> BareFunctionDecl {
2699         BareFunctionDecl {
2700             unsafety: self.unsafety,
2701             generics: Generics {
2702                 lifetimes: self.lifetimes.clean(cx),
2703                 type_params: Vec::new(),
2704                 where_predicates: Vec::new()
2705             },
2706             decl: (&*self.decl, &self.arg_names[..]).clean(cx),
2707             abi: self.abi,
2708         }
2709     }
2710 }
2711
2712 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2713 pub struct Static {
2714     pub type_: Type,
2715     pub mutability: Mutability,
2716     /// It's useful to have the value of a static documented, but I have no
2717     /// desire to represent expressions (that'd basically be all of the AST,
2718     /// which is huge!). So, have a string.
2719     pub expr: String,
2720 }
2721
2722 impl Clean<Item> for doctree::Static {
2723     fn clean(&self, cx: &DocContext) -> Item {
2724         debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
2725         Item {
2726             name: Some(self.name.clean(cx)),
2727             attrs: self.attrs.clean(cx),
2728             source: self.whence.clean(cx),
2729             def_id: cx.tcx.hir.local_def_id(self.id),
2730             visibility: self.vis.clean(cx),
2731             stability: self.stab.clean(cx),
2732             deprecation: self.depr.clean(cx),
2733             inner: StaticItem(Static {
2734                 type_: self.type_.clean(cx),
2735                 mutability: self.mutability.clean(cx),
2736                 expr: print_const_expr(cx, self.expr),
2737             }),
2738         }
2739     }
2740 }
2741
2742 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2743 pub struct Constant {
2744     pub type_: Type,
2745     pub expr: String,
2746 }
2747
2748 impl Clean<Item> for doctree::Constant {
2749     fn clean(&self, cx: &DocContext) -> Item {
2750         Item {
2751             name: Some(self.name.clean(cx)),
2752             attrs: self.attrs.clean(cx),
2753             source: self.whence.clean(cx),
2754             def_id: cx.tcx.hir.local_def_id(self.id),
2755             visibility: self.vis.clean(cx),
2756             stability: self.stab.clean(cx),
2757             deprecation: self.depr.clean(cx),
2758             inner: ConstantItem(Constant {
2759                 type_: self.type_.clean(cx),
2760                 expr: print_const_expr(cx, self.expr),
2761             }),
2762         }
2763     }
2764 }
2765
2766 #[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Copy)]
2767 pub enum Mutability {
2768     Mutable,
2769     Immutable,
2770 }
2771
2772 impl Clean<Mutability> for hir::Mutability {
2773     fn clean(&self, _: &DocContext) -> Mutability {
2774         match self {
2775             &hir::MutMutable => Mutable,
2776             &hir::MutImmutable => Immutable,
2777         }
2778     }
2779 }
2780
2781 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Copy, Debug)]
2782 pub enum ImplPolarity {
2783     Positive,
2784     Negative,
2785 }
2786
2787 impl Clean<ImplPolarity> for hir::ImplPolarity {
2788     fn clean(&self, _: &DocContext) -> ImplPolarity {
2789         match self {
2790             &hir::ImplPolarity::Positive => ImplPolarity::Positive,
2791             &hir::ImplPolarity::Negative => ImplPolarity::Negative,
2792         }
2793     }
2794 }
2795
2796 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2797 pub struct Impl {
2798     pub unsafety: hir::Unsafety,
2799     pub generics: Generics,
2800     pub provided_trait_methods: FxHashSet<String>,
2801     pub trait_: Option<Type>,
2802     pub for_: Type,
2803     pub items: Vec<Item>,
2804     pub polarity: Option<ImplPolarity>,
2805 }
2806
2807 impl Clean<Vec<Item>> for doctree::Impl {
2808     fn clean(&self, cx: &DocContext) -> Vec<Item> {
2809         let mut ret = Vec::new();
2810         let trait_ = self.trait_.clean(cx);
2811         let items = self.items.clean(cx);
2812
2813         // If this impl block is an implementation of the Deref trait, then we
2814         // need to try inlining the target's inherent impl blocks as well.
2815         if trait_.def_id() == cx.tcx.lang_items().deref_trait() {
2816             build_deref_target_impls(cx, &items, &mut ret);
2817         }
2818
2819         let provided = trait_.def_id().map(|did| {
2820             cx.tcx.provided_trait_methods(did)
2821                   .into_iter()
2822                   .map(|meth| meth.name.to_string())
2823                   .collect()
2824         }).unwrap_or(FxHashSet());
2825
2826         ret.push(Item {
2827             name: None,
2828             attrs: self.attrs.clean(cx),
2829             source: self.whence.clean(cx),
2830             def_id: cx.tcx.hir.local_def_id(self.id),
2831             visibility: self.vis.clean(cx),
2832             stability: self.stab.clean(cx),
2833             deprecation: self.depr.clean(cx),
2834             inner: ImplItem(Impl {
2835                 unsafety: self.unsafety,
2836                 generics: self.generics.clean(cx),
2837                 provided_trait_methods: provided,
2838                 trait_,
2839                 for_: self.for_.clean(cx),
2840                 items,
2841                 polarity: Some(self.polarity.clean(cx)),
2842             }),
2843         });
2844         ret
2845     }
2846 }
2847
2848 fn build_deref_target_impls(cx: &DocContext,
2849                             items: &[Item],
2850                             ret: &mut Vec<Item>) {
2851     use self::PrimitiveType::*;
2852     let tcx = cx.tcx;
2853
2854     for item in items {
2855         let target = match item.inner {
2856             TypedefItem(ref t, true) => &t.type_,
2857             _ => continue,
2858         };
2859         let primitive = match *target {
2860             ResolvedPath { did, .. } if did.is_local() => continue,
2861             ResolvedPath { did, .. } => {
2862                 ret.extend(inline::build_impls(cx, did));
2863                 continue
2864             }
2865             _ => match target.primitive_type() {
2866                 Some(prim) => prim,
2867                 None => continue,
2868             }
2869         };
2870         let did = match primitive {
2871             Isize => tcx.lang_items().isize_impl(),
2872             I8 => tcx.lang_items().i8_impl(),
2873             I16 => tcx.lang_items().i16_impl(),
2874             I32 => tcx.lang_items().i32_impl(),
2875             I64 => tcx.lang_items().i64_impl(),
2876             I128 => tcx.lang_items().i128_impl(),
2877             Usize => tcx.lang_items().usize_impl(),
2878             U8 => tcx.lang_items().u8_impl(),
2879             U16 => tcx.lang_items().u16_impl(),
2880             U32 => tcx.lang_items().u32_impl(),
2881             U64 => tcx.lang_items().u64_impl(),
2882             U128 => tcx.lang_items().u128_impl(),
2883             F32 => tcx.lang_items().f32_impl(),
2884             F64 => tcx.lang_items().f64_impl(),
2885             Char => tcx.lang_items().char_impl(),
2886             Bool => None,
2887             Str => tcx.lang_items().str_impl(),
2888             Slice => tcx.lang_items().slice_impl(),
2889             Array => tcx.lang_items().slice_impl(),
2890             Tuple => None,
2891             Unit => None,
2892             RawPointer => tcx.lang_items().const_ptr_impl(),
2893             Reference => None,
2894             Fn => None,
2895         };
2896         if let Some(did) = did {
2897             if !did.is_local() {
2898                 inline::build_impl(cx, did, ret);
2899             }
2900         }
2901     }
2902 }
2903
2904 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2905 pub struct AutoImpl {
2906     pub unsafety: hir::Unsafety,
2907     pub trait_: Type,
2908 }
2909
2910 impl Clean<Item> for doctree::AutoImpl {
2911     fn clean(&self, cx: &DocContext) -> Item {
2912         Item {
2913             name: None,
2914             attrs: self.attrs.clean(cx),
2915             source: self.whence.clean(cx),
2916             def_id: cx.tcx.hir.local_def_id(self.id),
2917             visibility: Some(Public),
2918             stability: None,
2919             deprecation: None,
2920             inner: AutoImplItem(AutoImpl {
2921                 unsafety: self.unsafety,
2922                 trait_: self.trait_.clean(cx),
2923             }),
2924         }
2925     }
2926 }
2927
2928 impl Clean<Item> for doctree::ExternCrate {
2929     fn clean(&self, cx: &DocContext) -> Item {
2930         Item {
2931             name: None,
2932             attrs: self.attrs.clean(cx),
2933             source: self.whence.clean(cx),
2934             def_id: DefId { krate: self.cnum, index: CRATE_DEF_INDEX },
2935             visibility: self.vis.clean(cx),
2936             stability: None,
2937             deprecation: None,
2938             inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
2939         }
2940     }
2941 }
2942
2943 impl Clean<Vec<Item>> for doctree::Import {
2944     fn clean(&self, cx: &DocContext) -> Vec<Item> {
2945         // We consider inlining the documentation of `pub use` statements, but we
2946         // forcefully don't inline if this is not public or if the
2947         // #[doc(no_inline)] attribute is present.
2948         // Don't inline doc(hidden) imports so they can be stripped at a later stage.
2949         let denied = self.vis != hir::Public || self.attrs.iter().any(|a| {
2950             a.name().unwrap() == "doc" && match a.meta_item_list() {
2951                 Some(l) => attr::list_contains_name(&l, "no_inline") ||
2952                            attr::list_contains_name(&l, "hidden"),
2953                 None => false,
2954             }
2955         });
2956         let path = self.path.clean(cx);
2957         let inner = if self.glob {
2958             Import::Glob(resolve_use_source(cx, path))
2959         } else {
2960             let name = self.name;
2961             if !denied {
2962                 if let Some(items) = inline::try_inline(cx, path.def, name) {
2963                     return items;
2964                 }
2965             }
2966             Import::Simple(name.clean(cx), resolve_use_source(cx, path))
2967         };
2968         vec![Item {
2969             name: None,
2970             attrs: self.attrs.clean(cx),
2971             source: self.whence.clean(cx),
2972             def_id: cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID),
2973             visibility: self.vis.clean(cx),
2974             stability: None,
2975             deprecation: None,
2976             inner: ImportItem(inner)
2977         }]
2978     }
2979 }
2980
2981 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2982 pub enum Import {
2983     // use source as str;
2984     Simple(String, ImportSource),
2985     // use source::*;
2986     Glob(ImportSource)
2987 }
2988
2989 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2990 pub struct ImportSource {
2991     pub path: Path,
2992     pub did: Option<DefId>,
2993 }
2994
2995 impl Clean<Vec<Item>> for hir::ForeignMod {
2996     fn clean(&self, cx: &DocContext) -> Vec<Item> {
2997         let mut items = self.items.clean(cx);
2998         for item in &mut items {
2999             if let ForeignFunctionItem(ref mut f) = item.inner {
3000                 f.abi = self.abi;
3001             }
3002         }
3003         items
3004     }
3005 }
3006
3007 impl Clean<Item> for hir::ForeignItem {
3008     fn clean(&self, cx: &DocContext) -> Item {
3009         let inner = match self.node {
3010             hir::ForeignItemFn(ref decl, ref names, ref generics) => {
3011                 ForeignFunctionItem(Function {
3012                     decl: (&**decl, &names[..]).clean(cx),
3013                     generics: generics.clean(cx),
3014                     unsafety: hir::Unsafety::Unsafe,
3015                     abi: Abi::Rust,
3016                     constness: hir::Constness::NotConst,
3017                 })
3018             }
3019             hir::ForeignItemStatic(ref ty, mutbl) => {
3020                 ForeignStaticItem(Static {
3021                     type_: ty.clean(cx),
3022                     mutability: if mutbl {Mutable} else {Immutable},
3023                     expr: "".to_string(),
3024                 })
3025             }
3026             hir::ForeignItemType => {
3027                 ForeignTypeItem
3028             }
3029         };
3030         Item {
3031             name: Some(self.name.clean(cx)),
3032             attrs: self.attrs.clean(cx),
3033             source: self.span.clean(cx),
3034             def_id: cx.tcx.hir.local_def_id(self.id),
3035             visibility: self.vis.clean(cx),
3036             stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)),
3037             deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)),
3038             inner,
3039         }
3040     }
3041 }
3042
3043 // Utilities
3044
3045 trait ToSource {
3046     fn to_src(&self, cx: &DocContext) -> String;
3047 }
3048
3049 impl ToSource for syntax_pos::Span {
3050     fn to_src(&self, cx: &DocContext) -> String {
3051         debug!("converting span {:?} to snippet", self.clean(cx));
3052         let sn = match cx.sess().codemap().span_to_snippet(*self) {
3053             Ok(x) => x.to_string(),
3054             Err(_) => "".to_string()
3055         };
3056         debug!("got snippet {}", sn);
3057         sn
3058     }
3059 }
3060
3061 fn name_from_pat(p: &hir::Pat) -> String {
3062     use rustc::hir::*;
3063     debug!("Trying to get a name from pattern: {:?}", p);
3064
3065     match p.node {
3066         PatKind::Wild => "_".to_string(),
3067         PatKind::Binding(_, _, ref p, _) => p.node.to_string(),
3068         PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
3069         PatKind::Struct(ref name, ref fields, etc) => {
3070             format!("{} {{ {}{} }}", qpath_to_string(name),
3071                 fields.iter().map(|&Spanned { node: ref fp, .. }|
3072                                   format!("{}: {}", fp.name, name_from_pat(&*fp.pat)))
3073                              .collect::<Vec<String>>().join(", "),
3074                 if etc { ", ..." } else { "" }
3075             )
3076         }
3077         PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
3078                                             .collect::<Vec<String>>().join(", ")),
3079         PatKind::Box(ref p) => name_from_pat(&**p),
3080         PatKind::Ref(ref p, _) => name_from_pat(&**p),
3081         PatKind::Lit(..) => {
3082             warn!("tried to get argument name from PatKind::Lit, \
3083                   which is silly in function arguments");
3084             "()".to_string()
3085         },
3086         PatKind::Range(..) => panic!("tried to get argument name from PatKind::Range, \
3087                               which is not allowed in function arguments"),
3088         PatKind::Slice(ref begin, ref mid, ref end) => {
3089             let begin = begin.iter().map(|p| name_from_pat(&**p));
3090             let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter();
3091             let end = end.iter().map(|p| name_from_pat(&**p));
3092             format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
3093         },
3094     }
3095 }
3096
3097 fn print_const_expr(cx: &DocContext, body: hir::BodyId) -> String {
3098     cx.tcx.hir.node_to_pretty_string(body.node_id)
3099 }
3100
3101 /// Given a type Path, resolve it to a Type using the TyCtxt
3102 fn resolve_type(cx: &DocContext,
3103                 path: Path,
3104                 id: ast::NodeId) -> Type {
3105     debug!("resolve_type({:?},{:?})", path, id);
3106
3107     let is_generic = match path.def {
3108         Def::PrimTy(p) => match p {
3109             hir::TyStr => return Primitive(PrimitiveType::Str),
3110             hir::TyBool => return Primitive(PrimitiveType::Bool),
3111             hir::TyChar => return Primitive(PrimitiveType::Char),
3112             hir::TyInt(int_ty) => return Primitive(int_ty.into()),
3113             hir::TyUint(uint_ty) => return Primitive(uint_ty.into()),
3114             hir::TyFloat(float_ty) => return Primitive(float_ty.into()),
3115         },
3116         Def::SelfTy(..) if path.segments.len() == 1 => {
3117             return Generic(keywords::SelfType.name().to_string());
3118         }
3119         Def::TyParam(..) if path.segments.len() == 1 => {
3120             return Generic(format!("{:#}", path));
3121         }
3122         Def::SelfTy(..) | Def::TyParam(..) | Def::AssociatedTy(..) => true,
3123         _ => false,
3124     };
3125     let did = register_def(&*cx, path.def);
3126     ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
3127 }
3128
3129 fn register_def(cx: &DocContext, def: Def) -> DefId {
3130     debug!("register_def({:?})", def);
3131
3132     let (did, kind) = match def {
3133         Def::Fn(i) => (i, TypeKind::Function),
3134         Def::TyAlias(i) => (i, TypeKind::Typedef),
3135         Def::Enum(i) => (i, TypeKind::Enum),
3136         Def::Trait(i) => (i, TypeKind::Trait),
3137         Def::Struct(i) => (i, TypeKind::Struct),
3138         Def::Union(i) => (i, TypeKind::Union),
3139         Def::Mod(i) => (i, TypeKind::Module),
3140         Def::TyForeign(i) => (i, TypeKind::Foreign),
3141         Def::Static(i, _) => (i, TypeKind::Static),
3142         Def::Variant(i) => (cx.tcx.parent_def_id(i).unwrap(), TypeKind::Enum),
3143         Def::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
3144         Def::SelfTy(_, Some(impl_def_id)) => {
3145             return impl_def_id
3146         }
3147         _ => return def.def_id()
3148     };
3149     if did.is_local() { return did }
3150     inline::record_extern_fqn(cx, did, kind);
3151     if let TypeKind::Trait = kind {
3152         let t = inline::build_external_trait(cx, did);
3153         cx.external_traits.borrow_mut().insert(did, t);
3154     }
3155     did
3156 }
3157
3158 fn resolve_use_source(cx: &DocContext, path: Path) -> ImportSource {
3159     ImportSource {
3160         did: if path.def == Def::Err {
3161             None
3162         } else {
3163             Some(register_def(cx, path.def))
3164         },
3165         path,
3166     }
3167 }
3168
3169 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3170 pub struct Macro {
3171     pub source: String,
3172     pub imported_from: Option<String>,
3173 }
3174
3175 impl Clean<Item> for doctree::Macro {
3176     fn clean(&self, cx: &DocContext) -> Item {
3177         let name = self.name.clean(cx);
3178         Item {
3179             name: Some(name.clone()),
3180             attrs: self.attrs.clean(cx),
3181             source: self.whence.clean(cx),
3182             visibility: Some(Public),
3183             stability: self.stab.clean(cx),
3184             deprecation: self.depr.clean(cx),
3185             def_id: self.def_id,
3186             inner: MacroItem(Macro {
3187                 source: format!("macro_rules! {} {{\n{}}}",
3188                                 name,
3189                                 self.matchers.iter().map(|span| {
3190                                     format!("    {} => {{ ... }};\n", span.to_src(cx))
3191                                 }).collect::<String>()),
3192                 imported_from: self.imported_from.clean(cx),
3193             }),
3194         }
3195     }
3196 }
3197
3198 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3199 pub struct Stability {
3200     pub level: stability::StabilityLevel,
3201     pub feature: String,
3202     pub since: String,
3203     pub deprecated_since: String,
3204     pub deprecated_reason: String,
3205     pub unstable_reason: String,
3206     pub issue: Option<u32>
3207 }
3208
3209 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3210 pub struct Deprecation {
3211     pub since: String,
3212     pub note: String,
3213 }
3214
3215 impl Clean<Stability> for attr::Stability {
3216     fn clean(&self, _: &DocContext) -> Stability {
3217         Stability {
3218             level: stability::StabilityLevel::from_attr_level(&self.level),
3219             feature: self.feature.to_string(),
3220             since: match self.level {
3221                 attr::Stable {ref since} => since.to_string(),
3222                 _ => "".to_string(),
3223             },
3224             deprecated_since: match self.rustc_depr {
3225                 Some(attr::RustcDeprecation {ref since, ..}) => since.to_string(),
3226                 _=> "".to_string(),
3227             },
3228             deprecated_reason: match self.rustc_depr {
3229                 Some(ref depr) => depr.reason.to_string(),
3230                 _ => "".to_string(),
3231             },
3232             unstable_reason: match self.level {
3233                 attr::Unstable { reason: Some(ref reason), .. } => reason.to_string(),
3234                 _ => "".to_string(),
3235             },
3236             issue: match self.level {
3237                 attr::Unstable {issue, ..} => Some(issue),
3238                 _ => None,
3239             }
3240         }
3241     }
3242 }
3243
3244 impl<'a> Clean<Stability> for &'a attr::Stability {
3245     fn clean(&self, dc: &DocContext) -> Stability {
3246         (**self).clean(dc)
3247     }
3248 }
3249
3250 impl Clean<Deprecation> for attr::Deprecation {
3251     fn clean(&self, _: &DocContext) -> Deprecation {
3252         Deprecation {
3253             since: self.since.as_ref().map_or("".to_string(), |s| s.to_string()),
3254             note: self.note.as_ref().map_or("".to_string(), |s| s.to_string()),
3255         }
3256     }
3257 }
3258
3259 /// An equality constraint on an associated type, e.g. `A=Bar` in `Foo<A=Bar>`
3260 #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Debug)]
3261 pub struct TypeBinding {
3262     pub name: String,
3263     pub ty: Type
3264 }
3265
3266 impl Clean<TypeBinding> for hir::TypeBinding {
3267     fn clean(&self, cx: &DocContext) -> TypeBinding {
3268         TypeBinding {
3269             name: self.name.clean(cx),
3270             ty: self.ty.clean(cx)
3271         }
3272     }
3273 }