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