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