]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/clean/mod.rs
ce7de0e3128549a09d3475fd8d3539aabe28be47
[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::SelfTy::*;
18 pub use self::FunctionRetTy::*;
19 pub use self::Visibility::{Public, Inherited};
20
21 use rustc_target::spec::abi::Abi;
22 use syntax::ast::{self, AttrStyle, Ident};
23 use syntax::attr;
24 use syntax::ext::base::MacroKind;
25 use syntax::source_map::{dummy_spanned, Spanned};
26 use syntax::ptr::P;
27 use syntax::symbol::keywords::{self, Keyword};
28 use syntax::symbol::InternedString;
29 use syntax_pos::{self, DUMMY_SP, Pos, FileName};
30
31 use rustc::mir::interpret::ConstValue;
32 use rustc::middle::resolve_lifetime as rl;
33 use rustc::ty::fold::TypeFolder;
34 use rustc::middle::lang_items;
35 use rustc::mir::interpret::GlobalId;
36 use rustc::hir::{self, GenericArg, HirVec};
37 use rustc::hir::def::{self, Def, CtorKind};
38 use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
39 use rustc::ty::subst::Substs;
40 use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind};
41 use rustc::ty::layout::VariantIdx;
42 use rustc::middle::stability;
43 use rustc::util::nodemap::{FxHashMap, FxHashSet};
44 use rustc_typeck::hir_ty_to_ty;
45 use rustc::infer::region_constraints::{RegionConstraintData, Constraint};
46 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
47
48 use std::collections::hash_map::Entry;
49 use std::fmt;
50 use std::hash::{Hash, Hasher};
51 use std::default::Default;
52 use std::{mem, slice, vec};
53 use std::iter::{FromIterator, once};
54 use rustc_data_structures::sync::Lrc;
55 use std::rc::Rc;
56 use std::str::FromStr;
57 use std::cell::RefCell;
58 use std::sync::Arc;
59 use std::u32;
60
61 use parking_lot::ReentrantMutex;
62
63 use core::{self, DocContext};
64 use doctree;
65 use visit_ast;
66 use html::render::{cache, ExternalLocation};
67 use html::item_type::ItemType;
68
69 pub mod inline;
70 pub mod cfg;
71 mod simplify;
72 mod auto_trait;
73 mod blanket_impl;
74 pub mod def_ctor;
75
76 use self::cfg::Cfg;
77 use self::auto_trait::AutoTraitFinder;
78 use self::blanket_impl::BlanketImplFinder;
79
80 thread_local!(pub static MAX_DEF_ID: RefCell<FxHashMap<CrateNum, DefId>> = Default::default());
81
82 const FN_OUTPUT_NAME: &'static str = "Output";
83
84 // extract the stability index for a node from tcx, if possible
85 fn get_stability(cx: &DocContext, def_id: DefId) -> Option<Stability> {
86     cx.tcx.lookup_stability(def_id).clean(cx)
87 }
88
89 fn get_deprecation(cx: &DocContext, def_id: DefId) -> Option<Deprecation> {
90     cx.tcx.lookup_deprecation(def_id).clean(cx)
91 }
92
93 pub trait Clean<T> {
94     fn clean(&self, cx: &DocContext) -> T;
95 }
96
97 impl<T: Clean<U>, U> Clean<Vec<U>> for [T] {
98     fn clean(&self, cx: &DocContext) -> Vec<U> {
99         self.iter().map(|x| x.clean(cx)).collect()
100     }
101 }
102
103 impl<T: Clean<U>, U, V: Idx> Clean<IndexVec<V, U>> for IndexVec<V, T> {
104     fn clean(&self, cx: &DocContext) -> IndexVec<V, U> {
105         self.iter().map(|x| x.clean(cx)).collect()
106     }
107 }
108
109 impl<T: Clean<U>, U> Clean<U> for P<T> {
110     fn clean(&self, cx: &DocContext) -> U {
111         (**self).clean(cx)
112     }
113 }
114
115 impl<T: Clean<U>, U> Clean<U> for Rc<T> {
116     fn clean(&self, cx: &DocContext) -> U {
117         (**self).clean(cx)
118     }
119 }
120
121 impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
122     fn clean(&self, cx: &DocContext) -> Option<U> {
123         self.as_ref().map(|v| v.clean(cx))
124     }
125 }
126
127 impl<T, U> Clean<U> for ty::Binder<T> where T: Clean<U> {
128     fn clean(&self, cx: &DocContext) -> U {
129         self.skip_binder().clean(cx)
130     }
131 }
132
133 impl<T: Clean<U>, U> Clean<Vec<U>> for P<[T]> {
134     fn clean(&self, cx: &DocContext) -> Vec<U> {
135         self.iter().map(|x| x.clean(cx)).collect()
136     }
137 }
138
139 #[derive(Clone, Debug)]
140 pub struct Crate {
141     pub name: String,
142     pub version: Option<String>,
143     pub src: FileName,
144     pub module: Option<Item>,
145     pub externs: Vec<(CrateNum, ExternalCrate)>,
146     pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
147     // These are later on moved into `CACHEKEY`, leaving the map empty.
148     // Only here so that they can be filtered through the rustdoc passes.
149     pub external_traits: Arc<ReentrantMutex<RefCell<FxHashMap<DefId, Trait>>>>,
150     pub masked_crates: FxHashSet<CrateNum>,
151 }
152
153 impl<'a, 'tcx, 'rcx, 'cstore> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> {
154     fn clean(&self, cx: &DocContext) -> Crate {
155         use ::visit_lib::LibEmbargoVisitor;
156
157         {
158             let mut r = cx.renderinfo.borrow_mut();
159             r.deref_trait_did = cx.tcx.lang_items().deref_trait();
160             r.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait();
161             r.owned_box_did = cx.tcx.lang_items().owned_box();
162         }
163
164         let mut externs = Vec::new();
165         for &cnum in cx.tcx.crates().iter() {
166             externs.push((cnum, cnum.clean(cx)));
167             // Analyze doc-reachability for extern items
168             LibEmbargoVisitor::new(cx).visit_lib(cnum);
169         }
170         externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
171
172         // Clean the crate, translating the entire libsyntax AST to one that is
173         // understood by rustdoc.
174         let mut module = self.module.clean(cx);
175         let mut masked_crates = FxHashSet::default();
176
177         match module.inner {
178             ModuleItem(ref module) => {
179                 for it in &module.items {
180                     if it.is_extern_crate() && it.attrs.has_doc_flag("masked") {
181                         masked_crates.insert(it.def_id.krate);
182                     }
183                 }
184             }
185             _ => unreachable!(),
186         }
187
188         let ExternalCrate { name, src, primitives, keywords, .. } = LOCAL_CRATE.clean(cx);
189         {
190             let m = match module.inner {
191                 ModuleItem(ref mut m) => m,
192                 _ => unreachable!(),
193             };
194             m.items.extend(primitives.iter().map(|&(def_id, prim, ref attrs)| {
195                 Item {
196                     source: Span::empty(),
197                     name: Some(prim.to_url_str().to_string()),
198                     attrs: attrs.clone(),
199                     visibility: Some(Public),
200                     stability: get_stability(cx, def_id),
201                     deprecation: get_deprecation(cx, def_id),
202                     def_id,
203                     inner: PrimitiveItem(prim),
204                 }
205             }));
206             m.items.extend(keywords.into_iter().map(|(def_id, kw, attrs)| {
207                 Item {
208                     source: Span::empty(),
209                     name: Some(kw.clone()),
210                     attrs: attrs,
211                     visibility: Some(Public),
212                     stability: get_stability(cx, def_id),
213                     deprecation: get_deprecation(cx, def_id),
214                     def_id,
215                     inner: KeywordItem(kw),
216                 }
217             }));
218         }
219
220         Crate {
221             name,
222             version: None,
223             src,
224             module: Some(module),
225             externs,
226             primitives,
227             external_traits: cx.external_traits.clone(),
228             masked_crates,
229         }
230     }
231 }
232
233 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
234 pub struct ExternalCrate {
235     pub name: String,
236     pub src: FileName,
237     pub attrs: Attributes,
238     pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
239     pub keywords: Vec<(DefId, String, Attributes)>,
240 }
241
242 impl Clean<ExternalCrate> for CrateNum {
243     fn clean(&self, cx: &DocContext) -> ExternalCrate {
244         let root = DefId { krate: *self, index: CRATE_DEF_INDEX };
245         let krate_span = cx.tcx.def_span(root);
246         let krate_src = cx.sess().source_map().span_to_filename(krate_span);
247
248         // Collect all inner modules which are tagged as implementations of
249         // primitives.
250         //
251         // Note that this loop only searches the top-level items of the crate,
252         // and this is intentional. If we were to search the entire crate for an
253         // item tagged with `#[doc(primitive)]` then we would also have to
254         // search the entirety of external modules for items tagged
255         // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
256         // all that metadata unconditionally).
257         //
258         // In order to keep the metadata load under control, the
259         // `#[doc(primitive)]` feature is explicitly designed to only allow the
260         // primitive tags to show up as the top level items in a crate.
261         //
262         // Also note that this does not attempt to deal with modules tagged
263         // duplicately for the same primitive. This is handled later on when
264         // rendering by delegating everything to a hash map.
265         let as_primitive = |def: Def| {
266             if let Def::Mod(def_id) = def {
267                 let attrs = cx.tcx.get_attrs(def_id).clean(cx);
268                 let mut prim = None;
269                 for attr in attrs.lists("doc") {
270                     if let Some(v) = attr.value_str() {
271                         if attr.check_name("primitive") {
272                             prim = PrimitiveType::from_str(&v.as_str());
273                             if prim.is_some() {
274                                 break;
275                             }
276                             // FIXME: should warn on unknown primitives?
277                         }
278                     }
279                 }
280                 return prim.map(|p| (def_id, p, attrs));
281             }
282             None
283         };
284         let primitives = if root.is_local() {
285             cx.tcx.hir().krate().module.item_ids.iter().filter_map(|&id| {
286                 let item = cx.tcx.hir().expect_item(id.id);
287                 match item.node {
288                     hir::ItemKind::Mod(_) => {
289                         as_primitive(Def::Mod(cx.tcx.hir().local_def_id(id.id)))
290                     }
291                     hir::ItemKind::Use(ref path, hir::UseKind::Single)
292                     if item.vis.node.is_pub() => {
293                         as_primitive(path.def).map(|(_, prim, attrs)| {
294                             // Pretend the primitive is local.
295                             (cx.tcx.hir().local_def_id(id.id), prim, attrs)
296                         })
297                     }
298                     _ => None
299                 }
300             }).collect()
301         } else {
302             cx.tcx.item_children(root).iter().map(|item| item.def)
303               .filter_map(as_primitive).collect()
304         };
305
306         let as_keyword = |def: Def| {
307             if let Def::Mod(def_id) = def {
308                 let attrs = cx.tcx.get_attrs(def_id).clean(cx);
309                 let mut keyword = None;
310                 for attr in attrs.lists("doc") {
311                     if let Some(v) = attr.value_str() {
312                         if attr.check_name("keyword") {
313                             keyword = Keyword::from_str(&v.as_str()).ok()
314                                                                     .map(|x| x.name().to_string());
315                             if keyword.is_some() {
316                                 break
317                             }
318                             // FIXME: should warn on unknown keywords?
319                         }
320                     }
321                 }
322                 return keyword.map(|p| (def_id, p, attrs));
323             }
324             None
325         };
326         let keywords = if root.is_local() {
327             cx.tcx.hir().krate().module.item_ids.iter().filter_map(|&id| {
328                 let item = cx.tcx.hir().expect_item(id.id);
329                 match item.node {
330                     hir::ItemKind::Mod(_) => {
331                         as_keyword(Def::Mod(cx.tcx.hir().local_def_id(id.id)))
332                     }
333                     hir::ItemKind::Use(ref path, hir::UseKind::Single)
334                     if item.vis.node.is_pub() => {
335                         as_keyword(path.def).map(|(_, prim, attrs)| {
336                             (cx.tcx.hir().local_def_id(id.id), prim, attrs)
337                         })
338                     }
339                     _ => None
340                 }
341             }).collect()
342         } else {
343             cx.tcx.item_children(root).iter().map(|item| item.def)
344               .filter_map(as_keyword).collect()
345         };
346
347         ExternalCrate {
348             name: cx.tcx.crate_name(*self).to_string(),
349             src: krate_src,
350             attrs: cx.tcx.get_attrs(root).clean(cx),
351             primitives,
352             keywords,
353         }
354     }
355 }
356
357 /// Anything with a source location and set of attributes and, optionally, a
358 /// name. That is, anything that can be documented. This doesn't correspond
359 /// directly to the AST's concept of an item; it's a strict superset.
360 #[derive(Clone, RustcEncodable, RustcDecodable)]
361 pub struct Item {
362     /// Stringified span
363     pub source: Span,
364     /// Not everything has a name. E.g., impls
365     pub name: Option<String>,
366     pub attrs: Attributes,
367     pub inner: ItemEnum,
368     pub visibility: Option<Visibility>,
369     pub def_id: DefId,
370     pub stability: Option<Stability>,
371     pub deprecation: Option<Deprecation>,
372 }
373
374 impl fmt::Debug for Item {
375     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
376
377         let fake = MAX_DEF_ID.with(|m| m.borrow().get(&self.def_id.krate)
378                                    .map(|id| self.def_id >= *id).unwrap_or(false));
379         let def_id: &dyn fmt::Debug = if fake { &"**FAKE**" } else { &self.def_id };
380
381         fmt.debug_struct("Item")
382             .field("source", &self.source)
383             .field("name", &self.name)
384             .field("attrs", &self.attrs)
385             .field("inner", &self.inner)
386             .field("visibility", &self.visibility)
387             .field("def_id", def_id)
388             .field("stability", &self.stability)
389             .field("deprecation", &self.deprecation)
390             .finish()
391     }
392 }
393
394 impl Item {
395     /// Finds the `doc` attribute as a NameValue and returns the corresponding
396     /// value found.
397     pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
398         self.attrs.doc_value()
399     }
400     /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
401     /// with newlines.
402     pub fn collapsed_doc_value(&self) -> Option<String> {
403         self.attrs.collapsed_doc_value()
404     }
405
406     pub fn links(&self) -> Vec<(String, String)> {
407         self.attrs.links(&self.def_id.krate)
408     }
409
410     pub fn is_crate(&self) -> bool {
411         match self.inner {
412             StrippedItem(box ModuleItem(Module { is_crate: true, ..})) |
413             ModuleItem(Module { is_crate: true, ..}) => true,
414             _ => false,
415         }
416     }
417     pub fn is_mod(&self) -> bool {
418         self.type_() == ItemType::Module
419     }
420     pub fn is_trait(&self) -> bool {
421         self.type_() == ItemType::Trait
422     }
423     pub fn is_struct(&self) -> bool {
424         self.type_() == ItemType::Struct
425     }
426     pub fn is_enum(&self) -> bool {
427         self.type_() == ItemType::Enum
428     }
429     pub fn is_associated_type(&self) -> bool {
430         self.type_() == ItemType::AssociatedType
431     }
432     pub fn is_associated_const(&self) -> bool {
433         self.type_() == ItemType::AssociatedConst
434     }
435     pub fn is_method(&self) -> bool {
436         self.type_() == ItemType::Method
437     }
438     pub fn is_ty_method(&self) -> bool {
439         self.type_() == ItemType::TyMethod
440     }
441     pub fn is_typedef(&self) -> bool {
442         self.type_() == ItemType::Typedef
443     }
444     pub fn is_primitive(&self) -> bool {
445         self.type_() == ItemType::Primitive
446     }
447     pub fn is_union(&self) -> bool {
448         self.type_() == ItemType::Union
449     }
450     pub fn is_import(&self) -> bool {
451         self.type_() == ItemType::Import
452     }
453     pub fn is_extern_crate(&self) -> bool {
454         self.type_() == ItemType::ExternCrate
455     }
456     pub fn is_keyword(&self) -> bool {
457         self.type_() == ItemType::Keyword
458     }
459
460     pub fn is_stripped(&self) -> bool {
461         match self.inner { StrippedItem(..) => true, _ => false }
462     }
463     pub fn has_stripped_fields(&self) -> Option<bool> {
464         match self.inner {
465             StructItem(ref _struct) => Some(_struct.fields_stripped),
466             UnionItem(ref union) => Some(union.fields_stripped),
467             VariantItem(Variant { kind: VariantKind::Struct(ref vstruct)} ) => {
468                 Some(vstruct.fields_stripped)
469             },
470             _ => None,
471         }
472     }
473
474     pub fn stability_class(&self) -> Option<String> {
475         self.stability.as_ref().and_then(|ref s| {
476             let mut classes = Vec::with_capacity(2);
477
478             if s.level == stability::Unstable {
479                 classes.push("unstable");
480             }
481
482             if !s.deprecated_since.is_empty() {
483                 classes.push("deprecated");
484             }
485
486             if classes.len() != 0 {
487                 Some(classes.join(" "))
488             } else {
489                 None
490             }
491         })
492     }
493
494     pub fn stable_since(&self) -> Option<&str> {
495         self.stability.as_ref().map(|s| &s.since[..])
496     }
497
498     pub fn is_non_exhaustive(&self) -> bool {
499         self.attrs.other_attrs.iter()
500             .any(|a| a.name().as_str() == "non_exhaustive")
501     }
502
503     /// Returns a documentation-level item type from the item.
504     pub fn type_(&self) -> ItemType {
505         ItemType::from(self)
506     }
507 }
508
509 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
510 pub enum ItemEnum {
511     ExternCrateItem(String, Option<String>),
512     ImportItem(Import),
513     StructItem(Struct),
514     UnionItem(Union),
515     EnumItem(Enum),
516     FunctionItem(Function),
517     ModuleItem(Module),
518     TypedefItem(Typedef, bool /* is associated type */),
519     ExistentialItem(Existential, bool /* is associated type */),
520     StaticItem(Static),
521     ConstantItem(Constant),
522     TraitItem(Trait),
523     ImplItem(Impl),
524     /// A method signature only. Used for required methods in traits (ie,
525     /// non-default-methods).
526     TyMethodItem(TyMethod),
527     /// A method with a body.
528     MethodItem(Method),
529     StructFieldItem(Type),
530     VariantItem(Variant),
531     /// `fn`s from an extern block
532     ForeignFunctionItem(Function),
533     /// `static`s from an extern block
534     ForeignStaticItem(Static),
535     /// `type`s from an extern block
536     ForeignTypeItem,
537     MacroItem(Macro),
538     ProcMacroItem(ProcMacro),
539     PrimitiveItem(PrimitiveType),
540     AssociatedConstItem(Type, Option<String>),
541     AssociatedTypeItem(Vec<GenericBound>, Option<Type>),
542     /// An item that has been stripped by a rustdoc pass
543     StrippedItem(Box<ItemEnum>),
544     KeywordItem(String),
545 }
546
547 impl ItemEnum {
548     pub fn generics(&self) -> Option<&Generics> {
549         Some(match *self {
550             ItemEnum::StructItem(ref s) => &s.generics,
551             ItemEnum::EnumItem(ref e) => &e.generics,
552             ItemEnum::FunctionItem(ref f) => &f.generics,
553             ItemEnum::TypedefItem(ref t, _) => &t.generics,
554             ItemEnum::ExistentialItem(ref t, _) => &t.generics,
555             ItemEnum::TraitItem(ref t) => &t.generics,
556             ItemEnum::ImplItem(ref i) => &i.generics,
557             ItemEnum::TyMethodItem(ref i) => &i.generics,
558             ItemEnum::MethodItem(ref i) => &i.generics,
559             ItemEnum::ForeignFunctionItem(ref f) => &f.generics,
560             _ => return None,
561         })
562     }
563
564     pub fn is_associated(&self) -> bool {
565         match *self {
566             ItemEnum::TypedefItem(_, _) |
567             ItemEnum::AssociatedTypeItem(_, _) => true,
568             _ => false,
569         }
570     }
571 }
572
573 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
574 pub struct Module {
575     pub items: Vec<Item>,
576     pub is_crate: bool,
577 }
578
579 impl Clean<Item> for doctree::Module {
580     fn clean(&self, cx: &DocContext) -> Item {
581         let name = if self.name.is_some() {
582             self.name.expect("No name provided").clean(cx)
583         } else {
584             String::new()
585         };
586
587         // maintain a stack of mod ids, for doc comment path resolution
588         // but we also need to resolve the module's own docs based on whether its docs were written
589         // inside or outside the module, so check for that
590         let attrs = self.attrs.clean(cx);
591
592         let mut items: Vec<Item> = vec![];
593         items.extend(self.extern_crates.iter().map(|x| x.clean(cx)));
594         items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
595         items.extend(self.structs.iter().map(|x| x.clean(cx)));
596         items.extend(self.unions.iter().map(|x| x.clean(cx)));
597         items.extend(self.enums.iter().map(|x| x.clean(cx)));
598         items.extend(self.fns.iter().map(|x| x.clean(cx)));
599         items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx)));
600         items.extend(self.mods.iter().map(|x| x.clean(cx)));
601         items.extend(self.typedefs.iter().map(|x| x.clean(cx)));
602         items.extend(self.existentials.iter().map(|x| x.clean(cx)));
603         items.extend(self.statics.iter().map(|x| x.clean(cx)));
604         items.extend(self.constants.iter().map(|x| x.clean(cx)));
605         items.extend(self.traits.iter().map(|x| x.clean(cx)));
606         items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
607         items.extend(self.macros.iter().map(|x| x.clean(cx)));
608         items.extend(self.proc_macros.iter().map(|x| x.clean(cx)));
609
610         // determine if we should display the inner contents or
611         // the outer `mod` item for the source code.
612         let whence = {
613             let cm = cx.sess().source_map();
614             let outer = cm.lookup_char_pos(self.where_outer.lo());
615             let inner = cm.lookup_char_pos(self.where_inner.lo());
616             if outer.file.start_pos == inner.file.start_pos {
617                 // mod foo { ... }
618                 self.where_outer
619             } else {
620                 // mod foo; (and a separate SourceFile for the contents)
621                 self.where_inner
622             }
623         };
624
625         Item {
626             name: Some(name),
627             attrs,
628             source: whence.clean(cx),
629             visibility: self.vis.clean(cx),
630             stability: self.stab.clean(cx),
631             deprecation: self.depr.clean(cx),
632             def_id: cx.tcx.hir().local_def_id(self.id),
633             inner: ModuleItem(Module {
634                is_crate: self.is_crate,
635                items,
636             })
637         }
638     }
639 }
640
641 pub struct ListAttributesIter<'a> {
642     attrs: slice::Iter<'a, ast::Attribute>,
643     current_list: vec::IntoIter<ast::NestedMetaItem>,
644     name: &'a str
645 }
646
647 impl<'a> Iterator for ListAttributesIter<'a> {
648     type Item = ast::NestedMetaItem;
649
650     fn next(&mut self) -> Option<Self::Item> {
651         if let Some(nested) = self.current_list.next() {
652             return Some(nested);
653         }
654
655         for attr in &mut self.attrs {
656             if let Some(list) = attr.meta_item_list() {
657                 if attr.check_name(self.name) {
658                     self.current_list = list.into_iter();
659                     if let Some(nested) = self.current_list.next() {
660                         return Some(nested);
661                     }
662                 }
663             }
664         }
665
666         None
667     }
668
669     fn size_hint(&self) -> (usize, Option<usize>) {
670         let lower = self.current_list.len();
671         (lower, None)
672     }
673 }
674
675 pub trait AttributesExt {
676     /// Finds an attribute as List and returns the list of attributes nested inside.
677     fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a>;
678 }
679
680 impl AttributesExt for [ast::Attribute] {
681     fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a> {
682         ListAttributesIter {
683             attrs: self.iter(),
684             current_list: Vec::new().into_iter(),
685             name,
686         }
687     }
688 }
689
690 pub trait NestedAttributesExt {
691     /// Returns whether the attribute list contains a specific `Word`
692     fn has_word(self, word: &str) -> bool;
693 }
694
695 impl<I: IntoIterator<Item=ast::NestedMetaItem>> NestedAttributesExt for I {
696     fn has_word(self, word: &str) -> bool {
697         self.into_iter().any(|attr| attr.is_word() && attr.check_name(word))
698     }
699 }
700
701 /// A portion of documentation, extracted from a `#[doc]` attribute.
702 ///
703 /// Each variant contains the line number within the complete doc-comment where the fragment
704 /// starts, as well as the Span where the corresponding doc comment or attribute is located.
705 ///
706 /// Included files are kept separate from inline doc comments so that proper line-number
707 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
708 /// kept separate because of issue #42760.
709 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
710 pub enum DocFragment {
711     // FIXME #44229 (misdreavus): sugared and raw doc comments can be brought back together once
712     // hoedown is completely removed from rustdoc.
713     /// A doc fragment created from a `///` or `//!` doc comment.
714     SugaredDoc(usize, syntax_pos::Span, String),
715     /// A doc fragment created from a "raw" `#[doc=""]` attribute.
716     RawDoc(usize, syntax_pos::Span, String),
717     /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
718     /// given filename and the file contents.
719     Include(usize, syntax_pos::Span, String, String),
720 }
721
722 impl DocFragment {
723     pub fn as_str(&self) -> &str {
724         match *self {
725             DocFragment::SugaredDoc(_, _, ref s) => &s[..],
726             DocFragment::RawDoc(_, _, ref s) => &s[..],
727             DocFragment::Include(_, _, _, ref s) => &s[..],
728         }
729     }
730
731     pub fn span(&self) -> syntax_pos::Span {
732         match *self {
733             DocFragment::SugaredDoc(_, span, _) |
734                 DocFragment::RawDoc(_, span, _) |
735                 DocFragment::Include(_, span, _, _) => span,
736         }
737     }
738 }
739
740 impl<'a> FromIterator<&'a DocFragment> for String {
741     fn from_iter<T>(iter: T) -> Self
742     where
743         T: IntoIterator<Item = &'a DocFragment>
744     {
745         iter.into_iter().fold(String::new(), |mut acc, frag| {
746             if !acc.is_empty() {
747                 acc.push('\n');
748             }
749             match *frag {
750                 DocFragment::SugaredDoc(_, _, ref docs)
751                     | DocFragment::RawDoc(_, _, ref docs)
752                     | DocFragment::Include(_, _, _, ref docs) =>
753                     acc.push_str(docs),
754             }
755
756             acc
757         })
758     }
759 }
760
761 #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)]
762 pub struct Attributes {
763     pub doc_strings: Vec<DocFragment>,
764     pub other_attrs: Vec<ast::Attribute>,
765     pub cfg: Option<Arc<Cfg>>,
766     pub span: Option<syntax_pos::Span>,
767     /// map from Rust paths to resolved defs and potential URL fragments
768     pub links: Vec<(String, Option<DefId>, Option<String>)>,
769     pub inner_docs: bool,
770 }
771
772 impl Attributes {
773     /// Extracts the content from an attribute `#[doc(cfg(content))]`.
774     fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
775         use syntax::ast::NestedMetaItemKind::MetaItem;
776
777         if let ast::MetaItemKind::List(ref nmis) = mi.node {
778             if nmis.len() == 1 {
779                 if let MetaItem(ref cfg_mi) = nmis[0].node {
780                     if cfg_mi.check_name("cfg") {
781                         if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.node {
782                             if cfg_nmis.len() == 1 {
783                                 if let MetaItem(ref content_mi) = cfg_nmis[0].node {
784                                     return Some(content_mi);
785                                 }
786                             }
787                         }
788                     }
789                 }
790             }
791         }
792
793         None
794     }
795
796     /// Reads a `MetaItem` from within an attribute, looks for whether it is a
797     /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
798     /// its expansion.
799     fn extract_include(mi: &ast::MetaItem)
800         -> Option<(String, String)>
801     {
802         mi.meta_item_list().and_then(|list| {
803             for meta in list {
804                 if meta.check_name("include") {
805                     // the actual compiled `#[doc(include="filename")]` gets expanded to
806                     // `#[doc(include(file="filename", contents="file contents")]` so we need to
807                     // look for that instead
808                     return meta.meta_item_list().and_then(|list| {
809                         let mut filename: Option<String> = None;
810                         let mut contents: Option<String> = None;
811
812                         for it in list {
813                             if it.check_name("file") {
814                                 if let Some(name) = it.value_str() {
815                                     filename = Some(name.to_string());
816                                 }
817                             } else if it.check_name("contents") {
818                                 if let Some(docs) = it.value_str() {
819                                     contents = Some(docs.to_string());
820                                 }
821                             }
822                         }
823
824                         if let (Some(filename), Some(contents)) = (filename, contents) {
825                             Some((filename, contents))
826                         } else {
827                             None
828                         }
829                     });
830                 }
831             }
832
833             None
834         })
835     }
836
837     pub fn has_doc_flag(&self, flag: &str) -> bool {
838         for attr in &self.other_attrs {
839             if !attr.check_name("doc") { continue; }
840
841             if let Some(items) = attr.meta_item_list() {
842                 if items.iter().filter_map(|i| i.meta_item()).any(|it| it.check_name(flag)) {
843                     return true;
844                 }
845             }
846         }
847
848         false
849     }
850
851     pub fn from_ast(diagnostic: &::errors::Handler,
852                     attrs: &[ast::Attribute]) -> Attributes {
853         let mut doc_strings = vec![];
854         let mut sp = None;
855         let mut cfg = Cfg::True;
856         let mut doc_line = 0;
857
858         let other_attrs = attrs.iter().filter_map(|attr| {
859             attr.with_desugared_doc(|attr| {
860                 if attr.check_name("doc") {
861                     if let Some(mi) = attr.meta() {
862                         if let Some(value) = mi.value_str() {
863                             // Extracted #[doc = "..."]
864                             let value = value.to_string();
865                             let line = doc_line;
866                             doc_line += value.lines().count();
867
868                             if attr.is_sugared_doc {
869                                 doc_strings.push(DocFragment::SugaredDoc(line, attr.span, value));
870                             } else {
871                                 doc_strings.push(DocFragment::RawDoc(line, attr.span, value));
872                             }
873
874                             if sp.is_none() {
875                                 sp = Some(attr.span);
876                             }
877                             return None;
878                         } else if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
879                             // Extracted #[doc(cfg(...))]
880                             match Cfg::parse(cfg_mi) {
881                                 Ok(new_cfg) => cfg &= new_cfg,
882                                 Err(e) => diagnostic.span_err(e.span, e.msg),
883                             }
884                             return None;
885                         } else if let Some((filename, contents)) = Attributes::extract_include(&mi)
886                         {
887                             let line = doc_line;
888                             doc_line += contents.lines().count();
889                             doc_strings.push(DocFragment::Include(line,
890                                                                   attr.span,
891                                                                   filename,
892                                                                   contents));
893                         }
894                     }
895                 }
896                 Some(attr.clone())
897             })
898         }).collect();
899
900         // treat #[target_feature(enable = "feat")] attributes as if they were
901         // #[doc(cfg(target_feature = "feat"))] attributes as well
902         for attr in attrs.lists("target_feature") {
903             if attr.check_name("enable") {
904                 if let Some(feat) = attr.value_str() {
905                     let meta = attr::mk_name_value_item_str(Ident::from_str("target_feature"),
906                                                             dummy_spanned(feat));
907                     if let Ok(feat_cfg) = Cfg::parse(&meta) {
908                         cfg &= feat_cfg;
909                     }
910                 }
911             }
912         }
913
914         let inner_docs = attrs.iter()
915                               .filter(|a| a.check_name("doc"))
916                               .next()
917                               .map_or(true, |a| a.style == AttrStyle::Inner);
918
919         Attributes {
920             doc_strings,
921             other_attrs,
922             cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) },
923             span: sp,
924             links: vec![],
925             inner_docs,
926         }
927     }
928
929     /// Finds the `doc` attribute as a NameValue and returns the corresponding
930     /// value found.
931     pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
932         self.doc_strings.first().map(|s| s.as_str())
933     }
934
935     /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
936     /// with newlines.
937     pub fn collapsed_doc_value(&self) -> Option<String> {
938         if !self.doc_strings.is_empty() {
939             Some(self.doc_strings.iter().collect())
940         } else {
941             None
942         }
943     }
944
945     /// Get links as a vector
946     ///
947     /// Cache must be populated before call
948     pub fn links(&self, krate: &CrateNum) -> Vec<(String, String)> {
949         use html::format::href;
950         self.links.iter().filter_map(|&(ref s, did, ref fragment)| {
951             match did {
952                 Some(did) => {
953                     if let Some((mut href, ..)) = href(did) {
954                         if let Some(ref fragment) = *fragment {
955                             href.push_str("#");
956                             href.push_str(fragment);
957                         }
958                         Some((s.clone(), href))
959                     } else {
960                         None
961                     }
962                 }
963                 None => {
964                     if let Some(ref fragment) = *fragment {
965                         let cache = cache();
966                         let url = match cache.extern_locations.get(krate) {
967                             Some(&(_, ref src, ExternalLocation::Local)) =>
968                                 src.to_str().expect("invalid file path"),
969                             Some(&(_, _, ExternalLocation::Remote(ref s))) => s,
970                             Some(&(_, _, ExternalLocation::Unknown)) | None =>
971                                 "https://doc.rust-lang.org/nightly",
972                         };
973                         // This is a primitive so the url is done "by hand".
974                         Some((s.clone(),
975                               format!("{}{}std/primitive.{}.html",
976                                       url,
977                                       if !url.ends_with('/') { "/" } else { "" },
978                                       fragment)))
979                     } else {
980                         panic!("This isn't a primitive?!");
981                     }
982                 }
983             }
984         }).collect()
985     }
986 }
987
988 impl PartialEq for Attributes {
989     fn eq(&self, rhs: &Self) -> bool {
990         self.doc_strings == rhs.doc_strings &&
991         self.cfg == rhs.cfg &&
992         self.span == rhs.span &&
993         self.links == rhs.links &&
994         self.other_attrs.iter().map(|attr| attr.id).eq(rhs.other_attrs.iter().map(|attr| attr.id))
995     }
996 }
997
998 impl Eq for Attributes {}
999
1000 impl Hash for Attributes {
1001     fn hash<H: Hasher>(&self, hasher: &mut H) {
1002         self.doc_strings.hash(hasher);
1003         self.cfg.hash(hasher);
1004         self.span.hash(hasher);
1005         self.links.hash(hasher);
1006         for attr in &self.other_attrs {
1007             attr.id.hash(hasher);
1008         }
1009     }
1010 }
1011
1012 impl AttributesExt for Attributes {
1013     fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a> {
1014         self.other_attrs.lists(name)
1015     }
1016 }
1017
1018 impl Clean<Attributes> for [ast::Attribute] {
1019     fn clean(&self, cx: &DocContext) -> Attributes {
1020         Attributes::from_ast(cx.sess().diagnostic(), self)
1021     }
1022 }
1023
1024 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1025 pub enum GenericBound {
1026     TraitBound(PolyTrait, hir::TraitBoundModifier),
1027     Outlives(Lifetime),
1028 }
1029
1030 impl GenericBound {
1031     fn maybe_sized(cx: &DocContext) -> GenericBound {
1032         let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem);
1033         let empty = cx.tcx.intern_substs(&[]);
1034         let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
1035             Some(did), false, vec![], empty);
1036         inline::record_extern_fqn(cx, did, TypeKind::Trait);
1037         GenericBound::TraitBound(PolyTrait {
1038             trait_: ResolvedPath {
1039                 path,
1040                 typarams: None,
1041                 did,
1042                 is_generic: false,
1043             },
1044             generic_params: Vec::new(),
1045         }, hir::TraitBoundModifier::Maybe)
1046     }
1047
1048     fn is_sized_bound(&self, cx: &DocContext) -> bool {
1049         use rustc::hir::TraitBoundModifier as TBM;
1050         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
1051             if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
1052                 return true;
1053             }
1054         }
1055         false
1056     }
1057
1058     fn get_poly_trait(&self) -> Option<PolyTrait> {
1059         if let GenericBound::TraitBound(ref p, _) = *self {
1060             return Some(p.clone())
1061         }
1062         None
1063     }
1064
1065     fn get_trait_type(&self) -> Option<Type> {
1066         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
1067             return Some(trait_.clone());
1068         }
1069         None
1070     }
1071 }
1072
1073 impl Clean<GenericBound> for hir::GenericBound {
1074     fn clean(&self, cx: &DocContext) -> GenericBound {
1075         match *self {
1076             hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)),
1077             hir::GenericBound::Trait(ref t, modifier) => {
1078                 GenericBound::TraitBound(t.clean(cx), modifier)
1079             }
1080         }
1081     }
1082 }
1083
1084 fn external_generic_args(cx: &DocContext, trait_did: Option<DefId>, has_self: bool,
1085                         bindings: Vec<TypeBinding>, substs: &Substs) -> GenericArgs {
1086     let lifetimes = substs.regions().filter_map(|v| v.clean(cx)).collect();
1087     let types = substs.types().skip(has_self as usize).collect::<Vec<_>>();
1088
1089     match trait_did {
1090         // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
1091         Some(did) if cx.tcx.lang_items().fn_trait_kind(did).is_some() => {
1092             assert_eq!(types.len(), 1);
1093             let inputs = match types[0].sty {
1094                 ty::Tuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
1095                 _ => {
1096                     return GenericArgs::AngleBracketed {
1097                         lifetimes,
1098                         types: types.clean(cx),
1099                         bindings,
1100                     }
1101                 }
1102             };
1103             let output = None;
1104             // FIXME(#20299) return type comes from a projection now
1105             // match types[1].sty {
1106             //     ty::Tuple(ref v) if v.is_empty() => None, // -> ()
1107             //     _ => Some(types[1].clean(cx))
1108             // };
1109             GenericArgs::Parenthesized {
1110                 inputs,
1111                 output,
1112             }
1113         },
1114         _ => {
1115             GenericArgs::AngleBracketed {
1116                 lifetimes,
1117                 types: types.clean(cx),
1118                 bindings,
1119             }
1120         }
1121     }
1122 }
1123
1124 // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
1125 // from Fn<(A, B,), C> to Fn(A, B) -> C
1126 fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>, has_self: bool,
1127                  bindings: Vec<TypeBinding>, substs: &Substs) -> Path {
1128     Path {
1129         global: false,
1130         def: Def::Err,
1131         segments: vec![PathSegment {
1132             name: name.to_string(),
1133             args: external_generic_args(cx, trait_did, has_self, bindings, substs)
1134         }],
1135     }
1136 }
1137
1138 impl<'a, 'tcx> Clean<GenericBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>) {
1139     fn clean(&self, cx: &DocContext) -> GenericBound {
1140         let (trait_ref, ref bounds) = *self;
1141         inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait);
1142         let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id).as_str(),
1143                                  Some(trait_ref.def_id), true, bounds.clone(), trait_ref.substs);
1144
1145         debug!("ty::TraitRef\n  subst: {:?}\n", trait_ref.substs);
1146
1147         // collect any late bound regions
1148         let mut late_bounds = vec![];
1149         for ty_s in trait_ref.input_types().skip(1) {
1150             if let ty::Tuple(ts) = ty_s.sty {
1151                 for &ty_s in ts {
1152                     if let ty::Ref(ref reg, _, _) = ty_s.sty {
1153                         if let &ty::RegionKind::ReLateBound(..) = *reg {
1154                             debug!("  hit an ReLateBound {:?}", reg);
1155                             if let Some(Lifetime(name)) = reg.clean(cx) {
1156                                 late_bounds.push(GenericParamDef {
1157                                     name,
1158                                     kind: GenericParamDefKind::Lifetime,
1159                                 });
1160                             }
1161                         }
1162                     }
1163                 }
1164             }
1165         }
1166
1167         GenericBound::TraitBound(
1168             PolyTrait {
1169                 trait_: ResolvedPath {
1170                     path,
1171                     typarams: None,
1172                     did: trait_ref.def_id,
1173                     is_generic: false,
1174                 },
1175                 generic_params: late_bounds,
1176             },
1177             hir::TraitBoundModifier::None
1178         )
1179     }
1180 }
1181
1182 impl<'tcx> Clean<GenericBound> for ty::TraitRef<'tcx> {
1183     fn clean(&self, cx: &DocContext) -> GenericBound {
1184         (self, vec![]).clean(cx)
1185     }
1186 }
1187
1188 impl<'tcx> Clean<Option<Vec<GenericBound>>> for Substs<'tcx> {
1189     fn clean(&self, cx: &DocContext) -> Option<Vec<GenericBound>> {
1190         let mut v = Vec::new();
1191         v.extend(self.regions().filter_map(|r| r.clean(cx)).map(GenericBound::Outlives));
1192         v.extend(self.types().map(|t| GenericBound::TraitBound(PolyTrait {
1193             trait_: t.clean(cx),
1194             generic_params: Vec::new(),
1195         }, hir::TraitBoundModifier::None)));
1196         if !v.is_empty() {Some(v)} else {None}
1197     }
1198 }
1199
1200 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1201 pub struct Lifetime(String);
1202
1203 impl Lifetime {
1204     pub fn get_ref<'a>(&'a self) -> &'a str {
1205         let Lifetime(ref s) = *self;
1206         let s: &'a str = s;
1207         s
1208     }
1209
1210     pub fn statik() -> Lifetime {
1211         Lifetime("'static".to_string())
1212     }
1213 }
1214
1215 impl Clean<Lifetime> for hir::Lifetime {
1216     fn clean(&self, cx: &DocContext) -> Lifetime {
1217         if self.id != ast::DUMMY_NODE_ID {
1218             let hir_id = cx.tcx.hir().node_to_hir_id(self.id);
1219             let def = cx.tcx.named_region(hir_id);
1220             match def {
1221                 Some(rl::Region::EarlyBound(_, node_id, _)) |
1222                 Some(rl::Region::LateBound(_, node_id, _)) |
1223                 Some(rl::Region::Free(_, node_id)) => {
1224                     if let Some(lt) = cx.lt_substs.borrow().get(&node_id).cloned() {
1225                         return lt;
1226                     }
1227                 }
1228                 _ => {}
1229             }
1230         }
1231         Lifetime(self.name.ident().to_string())
1232     }
1233 }
1234
1235 impl Clean<Lifetime> for hir::GenericParam {
1236     fn clean(&self, _: &DocContext) -> Lifetime {
1237         match self.kind {
1238             hir::GenericParamKind::Lifetime { .. } => {
1239                 if self.bounds.len() > 0 {
1240                     let mut bounds = self.bounds.iter().map(|bound| match bound {
1241                         hir::GenericBound::Outlives(lt) => lt,
1242                         _ => panic!(),
1243                     });
1244                     let name = bounds.next().expect("no more bounds").name.ident();
1245                     let mut s = format!("{}: {}", self.name.ident(), name);
1246                     for bound in bounds {
1247                         s.push_str(&format!(" + {}", bound.name.ident()));
1248                     }
1249                     Lifetime(s)
1250                 } else {
1251                     Lifetime(self.name.ident().to_string())
1252                 }
1253             }
1254             _ => panic!(),
1255         }
1256     }
1257 }
1258
1259 impl<'tcx> Clean<Lifetime> for ty::GenericParamDef {
1260     fn clean(&self, _cx: &DocContext) -> Lifetime {
1261         Lifetime(self.name.to_string())
1262     }
1263 }
1264
1265 impl Clean<Option<Lifetime>> for ty::RegionKind {
1266     fn clean(&self, cx: &DocContext) -> Option<Lifetime> {
1267         match *self {
1268             ty::ReStatic => Some(Lifetime::statik()),
1269             ty::ReLateBound(_, ty::BrNamed(_, name)) => Some(Lifetime(name.to_string())),
1270             ty::ReEarlyBound(ref data) => Some(Lifetime(data.name.clean(cx))),
1271
1272             ty::ReLateBound(..) |
1273             ty::ReFree(..) |
1274             ty::ReScope(..) |
1275             ty::ReVar(..) |
1276             ty::RePlaceholder(..) |
1277             ty::ReEmpty |
1278             ty::ReClosureBound(_) |
1279             ty::ReErased => None
1280         }
1281     }
1282 }
1283
1284 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1285 pub enum WherePredicate {
1286     BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
1287     RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1288     EqPredicate { lhs: Type, rhs: Type },
1289 }
1290
1291 impl Clean<WherePredicate> for hir::WherePredicate {
1292     fn clean(&self, cx: &DocContext) -> WherePredicate {
1293         match *self {
1294             hir::WherePredicate::BoundPredicate(ref wbp) => {
1295                 WherePredicate::BoundPredicate {
1296                     ty: wbp.bounded_ty.clean(cx),
1297                     bounds: wbp.bounds.clean(cx)
1298                 }
1299             }
1300
1301             hir::WherePredicate::RegionPredicate(ref wrp) => {
1302                 WherePredicate::RegionPredicate {
1303                     lifetime: wrp.lifetime.clean(cx),
1304                     bounds: wrp.bounds.clean(cx)
1305                 }
1306             }
1307
1308             hir::WherePredicate::EqPredicate(ref wrp) => {
1309                 WherePredicate::EqPredicate {
1310                     lhs: wrp.lhs_ty.clean(cx),
1311                     rhs: wrp.rhs_ty.clean(cx)
1312                 }
1313             }
1314         }
1315     }
1316 }
1317
1318 impl<'a> Clean<WherePredicate> for ty::Predicate<'a> {
1319     fn clean(&self, cx: &DocContext) -> WherePredicate {
1320         use rustc::ty::Predicate;
1321
1322         match *self {
1323             Predicate::Trait(ref pred) => pred.clean(cx),
1324             Predicate::Subtype(ref pred) => pred.clean(cx),
1325             Predicate::RegionOutlives(ref pred) => pred.clean(cx),
1326             Predicate::TypeOutlives(ref pred) => pred.clean(cx),
1327             Predicate::Projection(ref pred) => pred.clean(cx),
1328
1329             Predicate::WellFormed(..) |
1330             Predicate::ObjectSafe(..) |
1331             Predicate::ClosureKind(..) |
1332             Predicate::ConstEvaluatable(..) => panic!("not user writable"),
1333         }
1334     }
1335 }
1336
1337 impl<'a> Clean<WherePredicate> for ty::TraitPredicate<'a> {
1338     fn clean(&self, cx: &DocContext) -> WherePredicate {
1339         WherePredicate::BoundPredicate {
1340             ty: self.trait_ref.self_ty().clean(cx),
1341             bounds: vec![self.trait_ref.clean(cx)]
1342         }
1343     }
1344 }
1345
1346 impl<'tcx> Clean<WherePredicate> for ty::SubtypePredicate<'tcx> {
1347     fn clean(&self, _cx: &DocContext) -> WherePredicate {
1348         panic!("subtype predicates are an internal rustc artifact \
1349                 and should not be seen by rustdoc")
1350     }
1351 }
1352
1353 impl<'tcx> Clean<WherePredicate> for ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>> {
1354     fn clean(&self, cx: &DocContext) -> WherePredicate {
1355         let ty::OutlivesPredicate(ref a, ref b) = *self;
1356         WherePredicate::RegionPredicate {
1357             lifetime: a.clean(cx).expect("failed to clean lifetime"),
1358             bounds: vec![GenericBound::Outlives(b.clean(cx).expect("failed to clean bounds"))]
1359         }
1360     }
1361 }
1362
1363 impl<'tcx> Clean<WherePredicate> for ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>> {
1364     fn clean(&self, cx: &DocContext) -> WherePredicate {
1365         let ty::OutlivesPredicate(ref ty, ref lt) = *self;
1366
1367         WherePredicate::BoundPredicate {
1368             ty: ty.clean(cx),
1369             bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))]
1370         }
1371     }
1372 }
1373
1374 impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
1375     fn clean(&self, cx: &DocContext) -> WherePredicate {
1376         WherePredicate::EqPredicate {
1377             lhs: self.projection_ty.clean(cx),
1378             rhs: self.ty.clean(cx)
1379         }
1380     }
1381 }
1382
1383 impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
1384     fn clean(&self, cx: &DocContext) -> Type {
1385         let trait_ = match self.trait_ref(cx.tcx).clean(cx) {
1386             GenericBound::TraitBound(t, _) => t.trait_,
1387             GenericBound::Outlives(_) => panic!("cleaning a trait got a lifetime"),
1388         };
1389         Type::QPath {
1390             name: cx.tcx.associated_item(self.item_def_id).ident.name.clean(cx),
1391             self_type: box self.self_ty().clean(cx),
1392             trait_: box trait_
1393         }
1394     }
1395 }
1396
1397 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1398 pub enum GenericParamDefKind {
1399     Lifetime,
1400     Type {
1401         did: DefId,
1402         bounds: Vec<GenericBound>,
1403         default: Option<Type>,
1404         synthetic: Option<hir::SyntheticTyParamKind>,
1405     },
1406 }
1407
1408 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1409 pub struct GenericParamDef {
1410     pub name: String,
1411
1412     pub kind: GenericParamDefKind,
1413 }
1414
1415 impl GenericParamDef {
1416     pub fn is_synthetic_type_param(&self) -> bool {
1417         match self.kind {
1418             GenericParamDefKind::Lifetime => false,
1419             GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
1420         }
1421     }
1422 }
1423
1424 impl<'tcx> Clean<GenericParamDef> for ty::GenericParamDef {
1425     fn clean(&self, cx: &DocContext) -> GenericParamDef {
1426         let (name, kind) = match self.kind {
1427             ty::GenericParamDefKind::Lifetime => {
1428                 (self.name.to_string(), GenericParamDefKind::Lifetime)
1429             }
1430             ty::GenericParamDefKind::Type { has_default, .. } => {
1431                 cx.renderinfo.borrow_mut().external_typarams
1432                              .insert(self.def_id, self.name.clean(cx));
1433                 let default = if has_default {
1434                     Some(cx.tcx.type_of(self.def_id).clean(cx))
1435                 } else {
1436                     None
1437                 };
1438                 (self.name.clean(cx), GenericParamDefKind::Type {
1439                     did: self.def_id,
1440                     bounds: vec![], // These are filled in from the where-clauses.
1441                     default,
1442                     synthetic: None,
1443                 })
1444             }
1445         };
1446
1447         GenericParamDef {
1448             name,
1449             kind,
1450         }
1451     }
1452 }
1453
1454 impl Clean<GenericParamDef> for hir::GenericParam {
1455     fn clean(&self, cx: &DocContext) -> GenericParamDef {
1456         let (name, kind) = match self.kind {
1457             hir::GenericParamKind::Lifetime { .. } => {
1458                 let name = if self.bounds.len() > 0 {
1459                     let mut bounds = self.bounds.iter().map(|bound| match bound {
1460                         hir::GenericBound::Outlives(lt) => lt,
1461                         _ => panic!(),
1462                     });
1463                     let name = bounds.next().expect("no more bounds").name.ident();
1464                     let mut s = format!("{}: {}", self.name.ident(), name);
1465                     for bound in bounds {
1466                         s.push_str(&format!(" + {}", bound.name.ident()));
1467                     }
1468                     s
1469                 } else {
1470                     self.name.ident().to_string()
1471                 };
1472                 (name, GenericParamDefKind::Lifetime)
1473             }
1474             hir::GenericParamKind::Type { ref default, synthetic, .. } => {
1475                 (self.name.ident().name.clean(cx), GenericParamDefKind::Type {
1476                     did: cx.tcx.hir().local_def_id(self.id),
1477                     bounds: self.bounds.clean(cx),
1478                     default: default.clean(cx),
1479                     synthetic: synthetic,
1480                 })
1481             }
1482         };
1483
1484         GenericParamDef {
1485             name,
1486             kind,
1487         }
1488     }
1489 }
1490
1491 // maybe use a Generic enum and use Vec<Generic>?
1492 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Default, Hash)]
1493 pub struct Generics {
1494     pub params: Vec<GenericParamDef>,
1495     pub where_predicates: Vec<WherePredicate>,
1496 }
1497
1498 impl Clean<Generics> for hir::Generics {
1499     fn clean(&self, cx: &DocContext) -> Generics {
1500         // Synthetic type-parameters are inserted after normal ones.
1501         // In order for normal parameters to be able to refer to synthetic ones,
1502         // scans them first.
1503         fn is_impl_trait(param: &hir::GenericParam) -> bool {
1504             match param.kind {
1505                 hir::GenericParamKind::Type { synthetic, .. } => {
1506                     synthetic == Some(hir::SyntheticTyParamKind::ImplTrait)
1507                 }
1508                 _ => false,
1509             }
1510         }
1511         let impl_trait_params = self.params
1512             .iter()
1513             .filter(|param| is_impl_trait(param))
1514             .map(|param| {
1515                 let param: GenericParamDef = param.clean(cx);
1516                 match param.kind {
1517                     GenericParamDefKind::Lifetime => unreachable!(),
1518                     GenericParamDefKind::Type { did, ref bounds, .. } => {
1519                         cx.impl_trait_bounds.borrow_mut().insert(did, bounds.clone());
1520                     }
1521                 }
1522                 param
1523             })
1524             .collect::<Vec<_>>();
1525
1526         let mut params = Vec::with_capacity(self.params.len());
1527         for p in self.params.iter().filter(|p| !is_impl_trait(p)) {
1528             let p = p.clean(cx);
1529             params.push(p);
1530         }
1531         params.extend(impl_trait_params);
1532
1533         let mut generics = Generics {
1534             params,
1535             where_predicates: self.where_clause.predicates.clean(cx),
1536         };
1537
1538         // Some duplicates are generated for ?Sized bounds between type params and where
1539         // predicates. The point in here is to move the bounds definitions from type params
1540         // to where predicates when such cases occur.
1541         for where_pred in &mut generics.where_predicates {
1542             match *where_pred {
1543                 WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => {
1544                     if bounds.is_empty() {
1545                         for param in &mut generics.params {
1546                             match param.kind {
1547                                 GenericParamDefKind::Lifetime => {}
1548                                 GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
1549                                     if &param.name == name {
1550                                         mem::swap(bounds, ty_bounds);
1551                                         break
1552                                     }
1553                                 }
1554                             }
1555                         }
1556                     }
1557                 }
1558                 _ => continue,
1559             }
1560         }
1561         generics
1562     }
1563 }
1564
1565 impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
1566                                     &'a Lrc<ty::GenericPredicates<'tcx>>) {
1567     fn clean(&self, cx: &DocContext) -> Generics {
1568         use self::WherePredicate as WP;
1569
1570         let (gens, preds) = *self;
1571
1572         // Bounds in the type_params and lifetimes fields are repeated in the
1573         // predicates field (see rustc_typeck::collect::ty_generics), so remove
1574         // them.
1575         let stripped_typarams = gens.params.iter().filter_map(|param| match param.kind {
1576             ty::GenericParamDefKind::Lifetime => None,
1577             ty::GenericParamDefKind::Type { .. } => {
1578                 if param.name == keywords::SelfUpper.name().as_str() {
1579                     assert_eq!(param.index, 0);
1580                     return None;
1581                 }
1582                 Some(param.clean(cx))
1583             }
1584         }).collect::<Vec<GenericParamDef>>();
1585
1586         let mut where_predicates = preds.predicates.iter()
1587             .map(|(p, _)| p.clean(cx))
1588             .collect::<Vec<_>>();
1589
1590         // Type parameters and have a Sized bound by default unless removed with
1591         // ?Sized. Scan through the predicates and mark any type parameter with
1592         // a Sized bound, removing the bounds as we find them.
1593         //
1594         // Note that associated types also have a sized bound by default, but we
1595         // don't actually know the set of associated types right here so that's
1596         // handled in cleaning associated types
1597         let mut sized_params = FxHashSet::default();
1598         where_predicates.retain(|pred| {
1599             match *pred {
1600                 WP::BoundPredicate { ty: Generic(ref g), ref bounds } => {
1601                     if bounds.iter().any(|b| b.is_sized_bound(cx)) {
1602                         sized_params.insert(g.clone());
1603                         false
1604                     } else {
1605                         true
1606                     }
1607                 }
1608                 _ => true,
1609             }
1610         });
1611
1612         // Run through the type parameters again and insert a ?Sized
1613         // unbound for any we didn't find to be Sized.
1614         for tp in &stripped_typarams {
1615             if !sized_params.contains(&tp.name) {
1616                 where_predicates.push(WP::BoundPredicate {
1617                     ty: Type::Generic(tp.name.clone()),
1618                     bounds: vec![GenericBound::maybe_sized(cx)],
1619                 })
1620             }
1621         }
1622
1623         // It would be nice to collect all of the bounds on a type and recombine
1624         // them if possible, to avoid e.g. `where T: Foo, T: Bar, T: Sized, T: 'a`
1625         // and instead see `where T: Foo + Bar + Sized + 'a`
1626
1627         Generics {
1628             params: gens.params
1629                         .iter()
1630                         .flat_map(|param| match param.kind {
1631                             ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
1632                             ty::GenericParamDefKind::Type { .. } => None,
1633                         }).chain(simplify::ty_params(stripped_typarams).into_iter())
1634                         .collect(),
1635             where_predicates: simplify::where_clauses(cx, where_predicates),
1636         }
1637     }
1638 }
1639
1640 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1641 pub struct Method {
1642     pub generics: Generics,
1643     pub decl: FnDecl,
1644     pub header: hir::FnHeader,
1645 }
1646
1647 impl<'a> Clean<Method> for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId) {
1648     fn clean(&self, cx: &DocContext) -> Method {
1649         let (generics, decl) = enter_impl_trait(cx, || {
1650             (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx))
1651         });
1652         Method {
1653             decl,
1654             generics,
1655             header: self.0.header,
1656         }
1657     }
1658 }
1659
1660 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1661 pub struct TyMethod {
1662     pub header: hir::FnHeader,
1663     pub decl: FnDecl,
1664     pub generics: Generics,
1665 }
1666
1667 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1668 pub struct Function {
1669     pub decl: FnDecl,
1670     pub generics: Generics,
1671     pub header: hir::FnHeader,
1672 }
1673
1674 impl Clean<Item> for doctree::Function {
1675     fn clean(&self, cx: &DocContext) -> Item {
1676         let (generics, decl) = enter_impl_trait(cx, || {
1677             (self.generics.clean(cx), (&self.decl, self.body).clean(cx))
1678         });
1679
1680         Item {
1681             name: Some(self.name.clean(cx)),
1682             attrs: self.attrs.clean(cx),
1683             source: self.whence.clean(cx),
1684             visibility: self.vis.clean(cx),
1685             stability: self.stab.clean(cx),
1686             deprecation: self.depr.clean(cx),
1687             def_id: cx.tcx.hir().local_def_id(self.id),
1688             inner: FunctionItem(Function {
1689                 decl,
1690                 generics,
1691                 header: self.header,
1692             }),
1693         }
1694     }
1695 }
1696
1697 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1698 pub struct FnDecl {
1699     pub inputs: Arguments,
1700     pub output: FunctionRetTy,
1701     pub variadic: bool,
1702     pub attrs: Attributes,
1703 }
1704
1705 impl FnDecl {
1706     pub fn self_type(&self) -> Option<SelfTy> {
1707         self.inputs.values.get(0).and_then(|v| v.to_self())
1708     }
1709 }
1710
1711 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1712 pub struct Arguments {
1713     pub values: Vec<Argument>,
1714 }
1715
1716 impl<'a> Clean<Arguments> for (&'a [hir::Ty], &'a [ast::Ident]) {
1717     fn clean(&self, cx: &DocContext) -> Arguments {
1718         Arguments {
1719             values: self.0.iter().enumerate().map(|(i, ty)| {
1720                 let mut name = self.1.get(i).map(|ident| ident.to_string())
1721                                             .unwrap_or(String::new());
1722                 if name.is_empty() {
1723                     name = "_".to_string();
1724                 }
1725                 Argument {
1726                     name,
1727                     type_: ty.clean(cx),
1728                 }
1729             }).collect()
1730         }
1731     }
1732 }
1733
1734 impl<'a> Clean<Arguments> for (&'a [hir::Ty], hir::BodyId) {
1735     fn clean(&self, cx: &DocContext) -> Arguments {
1736         let body = cx.tcx.hir().body(self.1);
1737
1738         Arguments {
1739             values: self.0.iter().enumerate().map(|(i, ty)| {
1740                 Argument {
1741                     name: name_from_pat(&body.arguments[i].pat),
1742                     type_: ty.clean(cx),
1743                 }
1744             }).collect()
1745         }
1746     }
1747 }
1748
1749 impl<'a, A: Copy> Clean<FnDecl> for (&'a hir::FnDecl, A)
1750     where (&'a [hir::Ty], A): Clean<Arguments>
1751 {
1752     fn clean(&self, cx: &DocContext) -> FnDecl {
1753         FnDecl {
1754             inputs: (&self.0.inputs[..], self.1).clean(cx),
1755             output: self.0.output.clean(cx),
1756             variadic: self.0.variadic,
1757             attrs: Attributes::default()
1758         }
1759     }
1760 }
1761
1762 impl<'a, 'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
1763     fn clean(&self, cx: &DocContext) -> FnDecl {
1764         let (did, sig) = *self;
1765         let mut names = if cx.tcx.hir().as_local_node_id(did).is_some() {
1766             vec![].into_iter()
1767         } else {
1768             cx.tcx.fn_arg_names(did).into_iter()
1769         };
1770
1771         FnDecl {
1772             output: Return(sig.skip_binder().output().clean(cx)),
1773             attrs: Attributes::default(),
1774             variadic: sig.skip_binder().variadic,
1775             inputs: Arguments {
1776                 values: sig.skip_binder().inputs().iter().map(|t| {
1777                     Argument {
1778                         type_: t.clean(cx),
1779                         name: names.next().map_or(String::new(), |name| name.to_string()),
1780                     }
1781                 }).collect(),
1782             },
1783         }
1784     }
1785 }
1786
1787 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1788 pub struct Argument {
1789     pub type_: Type,
1790     pub name: String,
1791 }
1792
1793 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1794 pub enum SelfTy {
1795     SelfValue,
1796     SelfBorrowed(Option<Lifetime>, Mutability),
1797     SelfExplicit(Type),
1798 }
1799
1800 impl Argument {
1801     pub fn to_self(&self) -> Option<SelfTy> {
1802         if self.name != "self" {
1803             return None;
1804         }
1805         if self.type_.is_self_type() {
1806             return Some(SelfValue);
1807         }
1808         match self.type_ {
1809             BorrowedRef{ref lifetime, mutability, ref type_} if type_.is_self_type() => {
1810                 Some(SelfBorrowed(lifetime.clone(), mutability))
1811             }
1812             _ => Some(SelfExplicit(self.type_.clone()))
1813         }
1814     }
1815 }
1816
1817 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
1818 pub enum FunctionRetTy {
1819     Return(Type),
1820     DefaultReturn,
1821 }
1822
1823 impl Clean<FunctionRetTy> for hir::FunctionRetTy {
1824     fn clean(&self, cx: &DocContext) -> FunctionRetTy {
1825         match *self {
1826             hir::Return(ref typ) => Return(typ.clean(cx)),
1827             hir::DefaultReturn(..) => DefaultReturn,
1828         }
1829     }
1830 }
1831
1832 impl GetDefId for FunctionRetTy {
1833     fn def_id(&self) -> Option<DefId> {
1834         match *self {
1835             Return(ref ty) => ty.def_id(),
1836             DefaultReturn => None,
1837         }
1838     }
1839 }
1840
1841 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1842 pub struct Trait {
1843     pub auto: bool,
1844     pub unsafety: hir::Unsafety,
1845     pub items: Vec<Item>,
1846     pub generics: Generics,
1847     pub bounds: Vec<GenericBound>,
1848     pub is_spotlight: bool,
1849     pub is_auto: bool,
1850 }
1851
1852 impl Clean<Item> for doctree::Trait {
1853     fn clean(&self, cx: &DocContext) -> Item {
1854         let attrs = self.attrs.clean(cx);
1855         let is_spotlight = attrs.has_doc_flag("spotlight");
1856         Item {
1857             name: Some(self.name.clean(cx)),
1858             attrs: attrs,
1859             source: self.whence.clean(cx),
1860             def_id: cx.tcx.hir().local_def_id(self.id),
1861             visibility: self.vis.clean(cx),
1862             stability: self.stab.clean(cx),
1863             deprecation: self.depr.clean(cx),
1864             inner: TraitItem(Trait {
1865                 auto: self.is_auto.clean(cx),
1866                 unsafety: self.unsafety,
1867                 items: self.items.clean(cx),
1868                 generics: self.generics.clean(cx),
1869                 bounds: self.bounds.clean(cx),
1870                 is_spotlight: is_spotlight,
1871                 is_auto: self.is_auto.clean(cx),
1872             }),
1873         }
1874     }
1875 }
1876
1877 impl Clean<bool> for hir::IsAuto {
1878     fn clean(&self, _: &DocContext) -> bool {
1879         match *self {
1880             hir::IsAuto::Yes => true,
1881             hir::IsAuto::No => false,
1882         }
1883     }
1884 }
1885
1886 impl Clean<Type> for hir::TraitRef {
1887     fn clean(&self, cx: &DocContext) -> Type {
1888         resolve_type(cx, self.path.clean(cx), self.ref_id)
1889     }
1890 }
1891
1892 impl Clean<PolyTrait> for hir::PolyTraitRef {
1893     fn clean(&self, cx: &DocContext) -> PolyTrait {
1894         PolyTrait {
1895             trait_: self.trait_ref.clean(cx),
1896             generic_params: self.bound_generic_params.clean(cx)
1897         }
1898     }
1899 }
1900
1901 impl Clean<Item> for hir::TraitItem {
1902     fn clean(&self, cx: &DocContext) -> Item {
1903         let inner = match self.node {
1904             hir::TraitItemKind::Const(ref ty, default) => {
1905                 AssociatedConstItem(ty.clean(cx),
1906                                     default.map(|e| print_const_expr(cx, e)))
1907             }
1908             hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
1909                 MethodItem((sig, &self.generics, body).clean(cx))
1910             }
1911             hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => {
1912                 let (generics, decl) = enter_impl_trait(cx, || {
1913                     (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
1914                 });
1915                 TyMethodItem(TyMethod {
1916                     header: sig.header,
1917                     decl,
1918                     generics,
1919                 })
1920             }
1921             hir::TraitItemKind::Type(ref bounds, ref default) => {
1922                 AssociatedTypeItem(bounds.clean(cx), default.clean(cx))
1923             }
1924         };
1925         Item {
1926             name: Some(self.ident.name.clean(cx)),
1927             attrs: self.attrs.clean(cx),
1928             source: self.span.clean(cx),
1929             def_id: cx.tcx.hir().local_def_id(self.id),
1930             visibility: None,
1931             stability: get_stability(cx, cx.tcx.hir().local_def_id(self.id)),
1932             deprecation: get_deprecation(cx, cx.tcx.hir().local_def_id(self.id)),
1933             inner,
1934         }
1935     }
1936 }
1937
1938 impl Clean<Item> for hir::ImplItem {
1939     fn clean(&self, cx: &DocContext) -> Item {
1940         let inner = match self.node {
1941             hir::ImplItemKind::Const(ref ty, expr) => {
1942                 AssociatedConstItem(ty.clean(cx),
1943                                     Some(print_const_expr(cx, expr)))
1944             }
1945             hir::ImplItemKind::Method(ref sig, body) => {
1946                 MethodItem((sig, &self.generics, body).clean(cx))
1947             }
1948             hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef {
1949                 type_: ty.clean(cx),
1950                 generics: Generics::default(),
1951             }, true),
1952             hir::ImplItemKind::Existential(ref bounds) => ExistentialItem(Existential {
1953                 bounds: bounds.clean(cx),
1954                 generics: Generics::default(),
1955             }, true),
1956         };
1957         Item {
1958             name: Some(self.ident.name.clean(cx)),
1959             source: self.span.clean(cx),
1960             attrs: self.attrs.clean(cx),
1961             def_id: cx.tcx.hir().local_def_id(self.id),
1962             visibility: self.vis.clean(cx),
1963             stability: get_stability(cx, cx.tcx.hir().local_def_id(self.id)),
1964             deprecation: get_deprecation(cx, cx.tcx.hir().local_def_id(self.id)),
1965             inner,
1966         }
1967     }
1968 }
1969
1970 impl<'tcx> Clean<Item> for ty::AssociatedItem {
1971     fn clean(&self, cx: &DocContext) -> Item {
1972         let inner = match self.kind {
1973             ty::AssociatedKind::Const => {
1974                 let ty = cx.tcx.type_of(self.def_id);
1975                 let default = if self.defaultness.has_value() {
1976                     Some(inline::print_inlined_const(cx, self.def_id))
1977                 } else {
1978                     None
1979                 };
1980                 AssociatedConstItem(ty.clean(cx), default)
1981             }
1982             ty::AssociatedKind::Method => {
1983                 let generics = (cx.tcx.generics_of(self.def_id),
1984                                 &cx.tcx.predicates_of(self.def_id)).clean(cx);
1985                 let sig = cx.tcx.fn_sig(self.def_id);
1986                 let mut decl = (self.def_id, sig).clean(cx);
1987
1988                 if self.method_has_self_argument {
1989                     let self_ty = match self.container {
1990                         ty::ImplContainer(def_id) => {
1991                             cx.tcx.type_of(def_id)
1992                         }
1993                         ty::TraitContainer(_) => cx.tcx.mk_self_type()
1994                     };
1995                     let self_arg_ty = *sig.input(0).skip_binder();
1996                     if self_arg_ty == self_ty {
1997                         decl.inputs.values[0].type_ = Generic(String::from("Self"));
1998                     } else if let ty::Ref(_, ty, _) = self_arg_ty.sty {
1999                         if ty == self_ty {
2000                             match decl.inputs.values[0].type_ {
2001                                 BorrowedRef{ref mut type_, ..} => {
2002                                     **type_ = Generic(String::from("Self"))
2003                                 }
2004                                 _ => unreachable!(),
2005                             }
2006                         }
2007                     }
2008                 }
2009
2010                 let provided = match self.container {
2011                     ty::ImplContainer(_) => true,
2012                     ty::TraitContainer(_) => self.defaultness.has_value()
2013                 };
2014                 if provided {
2015                     let constness = if cx.tcx.is_const_fn(self.def_id) {
2016                         hir::Constness::Const
2017                     } else {
2018                         hir::Constness::NotConst
2019                     };
2020                     MethodItem(Method {
2021                         generics,
2022                         decl,
2023                         header: hir::FnHeader {
2024                             unsafety: sig.unsafety(),
2025                             abi: sig.abi(),
2026                             constness,
2027                             asyncness: hir::IsAsync::NotAsync,
2028                         }
2029                     })
2030                 } else {
2031                     TyMethodItem(TyMethod {
2032                         generics,
2033                         decl,
2034                         header: hir::FnHeader {
2035                             unsafety: sig.unsafety(),
2036                             abi: sig.abi(),
2037                             constness: hir::Constness::NotConst,
2038                             asyncness: hir::IsAsync::NotAsync,
2039                         }
2040                     })
2041                 }
2042             }
2043             ty::AssociatedKind::Type => {
2044                 let my_name = self.ident.name.clean(cx);
2045
2046                 if let ty::TraitContainer(did) = self.container {
2047                     // When loading a cross-crate associated type, the bounds for this type
2048                     // are actually located on the trait/impl itself, so we need to load
2049                     // all of the generics from there and then look for bounds that are
2050                     // applied to this associated type in question.
2051                     let predicates = cx.tcx.predicates_of(did);
2052                     let generics = (cx.tcx.generics_of(did), &predicates).clean(cx);
2053                     let mut bounds = generics.where_predicates.iter().filter_map(|pred| {
2054                         let (name, self_type, trait_, bounds) = match *pred {
2055                             WherePredicate::BoundPredicate {
2056                                 ty: QPath { ref name, ref self_type, ref trait_ },
2057                                 ref bounds
2058                             } => (name, self_type, trait_, bounds),
2059                             _ => return None,
2060                         };
2061                         if *name != my_name { return None }
2062                         match **trait_ {
2063                             ResolvedPath { did, .. } if did == self.container.id() => {}
2064                             _ => return None,
2065                         }
2066                         match **self_type {
2067                             Generic(ref s) if *s == "Self" => {}
2068                             _ => return None,
2069                         }
2070                         Some(bounds)
2071                     }).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>();
2072                     // Our Sized/?Sized bound didn't get handled when creating the generics
2073                     // because we didn't actually get our whole set of bounds until just now
2074                     // (some of them may have come from the trait). If we do have a sized
2075                     // bound, we remove it, and if we don't then we add the `?Sized` bound
2076                     // at the end.
2077                     match bounds.iter().position(|b| b.is_sized_bound(cx)) {
2078                         Some(i) => { bounds.remove(i); }
2079                         None => bounds.push(GenericBound::maybe_sized(cx)),
2080                     }
2081
2082                     let ty = if self.defaultness.has_value() {
2083                         Some(cx.tcx.type_of(self.def_id))
2084                     } else {
2085                         None
2086                     };
2087
2088                     AssociatedTypeItem(bounds, ty.clean(cx))
2089                 } else {
2090                     TypedefItem(Typedef {
2091                         type_: cx.tcx.type_of(self.def_id).clean(cx),
2092                         generics: Generics {
2093                             params: Vec::new(),
2094                             where_predicates: Vec::new(),
2095                         },
2096                     }, true)
2097                 }
2098             }
2099             ty::AssociatedKind::Existential => unimplemented!(),
2100         };
2101
2102         let visibility = match self.container {
2103             ty::ImplContainer(_) => self.vis.clean(cx),
2104             ty::TraitContainer(_) => None,
2105         };
2106
2107         Item {
2108             name: Some(self.ident.name.clean(cx)),
2109             visibility,
2110             stability: get_stability(cx, self.def_id),
2111             deprecation: get_deprecation(cx, self.def_id),
2112             def_id: self.def_id,
2113             attrs: inline::load_attrs(cx, self.def_id),
2114             source: cx.tcx.def_span(self.def_id).clean(cx),
2115             inner,
2116         }
2117     }
2118 }
2119
2120 /// A trait reference, which may have higher ranked lifetimes.
2121 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
2122 pub struct PolyTrait {
2123     pub trait_: Type,
2124     pub generic_params: Vec<GenericParamDef>,
2125 }
2126
2127 /// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
2128 /// type out of the AST/TyCtxt given one of these, if more information is needed. Most importantly
2129 /// it does not preserve mutability or boxes.
2130 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
2131 pub enum Type {
2132     /// structs/enums/traits (most that'd be an hir::TyKind::Path)
2133     ResolvedPath {
2134         path: Path,
2135         typarams: Option<Vec<GenericBound>>,
2136         did: DefId,
2137         /// true if is a `T::Name` path for associated types
2138         is_generic: bool,
2139     },
2140     /// For parameterized types, so the consumer of the JSON don't go
2141     /// looking for types which don't exist anywhere.
2142     Generic(String),
2143     /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
2144     /// arrays, slices, and tuples.
2145     Primitive(PrimitiveType),
2146     /// extern "ABI" fn
2147     BareFunction(Box<BareFunctionDecl>),
2148     Tuple(Vec<Type>),
2149     Slice(Box<Type>),
2150     Array(Box<Type>, String),
2151     Never,
2152     Unique(Box<Type>),
2153     RawPointer(Mutability, Box<Type>),
2154     BorrowedRef {
2155         lifetime: Option<Lifetime>,
2156         mutability: Mutability,
2157         type_: Box<Type>,
2158     },
2159
2160     // <Type as Trait>::Name
2161     QPath {
2162         name: String,
2163         self_type: Box<Type>,
2164         trait_: Box<Type>
2165     },
2166
2167     // _
2168     Infer,
2169
2170     // impl TraitA+TraitB
2171     ImplTrait(Vec<GenericBound>),
2172 }
2173
2174 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
2175 pub enum PrimitiveType {
2176     Isize, I8, I16, I32, I64, I128,
2177     Usize, U8, U16, U32, U64, U128,
2178     F32, F64,
2179     Char,
2180     Bool,
2181     Str,
2182     Slice,
2183     Array,
2184     Tuple,
2185     Unit,
2186     RawPointer,
2187     Reference,
2188     Fn,
2189     Never,
2190 }
2191
2192 #[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
2193 pub enum TypeKind {
2194     Enum,
2195     Function,
2196     Module,
2197     Const,
2198     Static,
2199     Struct,
2200     Union,
2201     Trait,
2202     Variant,
2203     Typedef,
2204     Foreign,
2205     Macro,
2206     Attr,
2207     Derive,
2208 }
2209
2210 pub trait GetDefId {
2211     fn def_id(&self) -> Option<DefId>;
2212 }
2213
2214 impl<T: GetDefId> GetDefId for Option<T> {
2215     fn def_id(&self) -> Option<DefId> {
2216         self.as_ref().and_then(|d| d.def_id())
2217     }
2218 }
2219
2220 impl Type {
2221     pub fn primitive_type(&self) -> Option<PrimitiveType> {
2222         match *self {
2223             Primitive(p) | BorrowedRef { type_: box Primitive(p), ..} => Some(p),
2224             Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
2225             Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
2226             Tuple(ref tys) => if tys.is_empty() {
2227                 Some(PrimitiveType::Unit)
2228             } else {
2229                 Some(PrimitiveType::Tuple)
2230             },
2231             RawPointer(..) => Some(PrimitiveType::RawPointer),
2232             BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
2233             BareFunction(..) => Some(PrimitiveType::Fn),
2234             Never => Some(PrimitiveType::Never),
2235             _ => None,
2236         }
2237     }
2238
2239     pub fn is_generic(&self) -> bool {
2240         match *self {
2241             ResolvedPath { is_generic, .. } => is_generic,
2242             _ => false,
2243         }
2244     }
2245
2246     pub fn is_self_type(&self) -> bool {
2247         match *self {
2248             Generic(ref name) => name == "Self",
2249             _ => false
2250         }
2251     }
2252
2253     pub fn generics(&self) -> Option<&[Type]> {
2254         match *self {
2255             ResolvedPath { ref path, .. } => {
2256                 path.segments.last().and_then(|seg| {
2257                     if let GenericArgs::AngleBracketed { ref types, .. } = seg.args {
2258                         Some(&**types)
2259                     } else {
2260                         None
2261                     }
2262                 })
2263             }
2264             _ => None,
2265         }
2266     }
2267 }
2268
2269 impl GetDefId for Type {
2270     fn def_id(&self) -> Option<DefId> {
2271         match *self {
2272             ResolvedPath { did, .. } => Some(did),
2273             Primitive(p) => ::html::render::cache().primitive_locations.get(&p).cloned(),
2274             BorrowedRef { type_: box Generic(..), .. } =>
2275                 Primitive(PrimitiveType::Reference).def_id(),
2276             BorrowedRef { ref type_, .. } => type_.def_id(),
2277             Tuple(ref tys) => if tys.is_empty() {
2278                 Primitive(PrimitiveType::Unit).def_id()
2279             } else {
2280                 Primitive(PrimitiveType::Tuple).def_id()
2281             },
2282             BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
2283             Never => Primitive(PrimitiveType::Never).def_id(),
2284             Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
2285             Array(..) => Primitive(PrimitiveType::Array).def_id(),
2286             RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(),
2287             QPath { ref self_type, .. } => self_type.def_id(),
2288             _ => None,
2289         }
2290     }
2291 }
2292
2293 impl PrimitiveType {
2294     fn from_str(s: &str) -> Option<PrimitiveType> {
2295         match s {
2296             "isize" => Some(PrimitiveType::Isize),
2297             "i8" => Some(PrimitiveType::I8),
2298             "i16" => Some(PrimitiveType::I16),
2299             "i32" => Some(PrimitiveType::I32),
2300             "i64" => Some(PrimitiveType::I64),
2301             "i128" => Some(PrimitiveType::I128),
2302             "usize" => Some(PrimitiveType::Usize),
2303             "u8" => Some(PrimitiveType::U8),
2304             "u16" => Some(PrimitiveType::U16),
2305             "u32" => Some(PrimitiveType::U32),
2306             "u64" => Some(PrimitiveType::U64),
2307             "u128" => Some(PrimitiveType::U128),
2308             "bool" => Some(PrimitiveType::Bool),
2309             "char" => Some(PrimitiveType::Char),
2310             "str" => Some(PrimitiveType::Str),
2311             "f32" => Some(PrimitiveType::F32),
2312             "f64" => Some(PrimitiveType::F64),
2313             "array" => Some(PrimitiveType::Array),
2314             "slice" => Some(PrimitiveType::Slice),
2315             "tuple" => Some(PrimitiveType::Tuple),
2316             "unit" => Some(PrimitiveType::Unit),
2317             "pointer" => Some(PrimitiveType::RawPointer),
2318             "reference" => Some(PrimitiveType::Reference),
2319             "fn" => Some(PrimitiveType::Fn),
2320             "never" => Some(PrimitiveType::Never),
2321             _ => None,
2322         }
2323     }
2324
2325     pub fn as_str(&self) -> &'static str {
2326         use self::PrimitiveType::*;
2327         match *self {
2328             Isize => "isize",
2329             I8 => "i8",
2330             I16 => "i16",
2331             I32 => "i32",
2332             I64 => "i64",
2333             I128 => "i128",
2334             Usize => "usize",
2335             U8 => "u8",
2336             U16 => "u16",
2337             U32 => "u32",
2338             U64 => "u64",
2339             U128 => "u128",
2340             F32 => "f32",
2341             F64 => "f64",
2342             Str => "str",
2343             Bool => "bool",
2344             Char => "char",
2345             Array => "array",
2346             Slice => "slice",
2347             Tuple => "tuple",
2348             Unit => "unit",
2349             RawPointer => "pointer",
2350             Reference => "reference",
2351             Fn => "fn",
2352             Never => "never",
2353         }
2354     }
2355
2356     pub fn to_url_str(&self) -> &'static str {
2357         self.as_str()
2358     }
2359 }
2360
2361 impl From<ast::IntTy> for PrimitiveType {
2362     fn from(int_ty: ast::IntTy) -> PrimitiveType {
2363         match int_ty {
2364             ast::IntTy::Isize => PrimitiveType::Isize,
2365             ast::IntTy::I8 => PrimitiveType::I8,
2366             ast::IntTy::I16 => PrimitiveType::I16,
2367             ast::IntTy::I32 => PrimitiveType::I32,
2368             ast::IntTy::I64 => PrimitiveType::I64,
2369             ast::IntTy::I128 => PrimitiveType::I128,
2370         }
2371     }
2372 }
2373
2374 impl From<ast::UintTy> for PrimitiveType {
2375     fn from(uint_ty: ast::UintTy) -> PrimitiveType {
2376         match uint_ty {
2377             ast::UintTy::Usize => PrimitiveType::Usize,
2378             ast::UintTy::U8 => PrimitiveType::U8,
2379             ast::UintTy::U16 => PrimitiveType::U16,
2380             ast::UintTy::U32 => PrimitiveType::U32,
2381             ast::UintTy::U64 => PrimitiveType::U64,
2382             ast::UintTy::U128 => PrimitiveType::U128,
2383         }
2384     }
2385 }
2386
2387 impl From<ast::FloatTy> for PrimitiveType {
2388     fn from(float_ty: ast::FloatTy) -> PrimitiveType {
2389         match float_ty {
2390             ast::FloatTy::F32 => PrimitiveType::F32,
2391             ast::FloatTy::F64 => PrimitiveType::F64,
2392         }
2393     }
2394 }
2395
2396 impl Clean<Type> for hir::Ty {
2397     fn clean(&self, cx: &DocContext) -> Type {
2398         use rustc::hir::*;
2399
2400         match self.node {
2401             TyKind::Never => Never,
2402             TyKind::Ptr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
2403             TyKind::Rptr(ref l, ref m) => {
2404                 let lifetime = if l.is_elided() {
2405                     None
2406                 } else {
2407                     Some(l.clean(cx))
2408                 };
2409                 BorrowedRef {lifetime: lifetime, mutability: m.mutbl.clean(cx),
2410                              type_: box m.ty.clean(cx)}
2411             }
2412             TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
2413             TyKind::Array(ref ty, ref length) => {
2414                 let def_id = cx.tcx.hir().local_def_id(length.id);
2415                 let param_env = cx.tcx.param_env(def_id);
2416                 let substs = Substs::identity_for_item(cx.tcx, def_id);
2417                 let cid = GlobalId {
2418                     instance: ty::Instance::new(def_id, substs),
2419                     promoted: None
2420                 };
2421                 let length = cx.tcx.const_eval(param_env.and(cid)).unwrap_or_else(|_| {
2422                     ty::Const::unevaluated(cx.tcx, def_id, substs, cx.tcx.types.usize)
2423                 });
2424                 let length = print_const(cx, length);
2425                 Array(box ty.clean(cx), length)
2426             },
2427             TyKind::Tup(ref tys) => Tuple(tys.clean(cx)),
2428             TyKind::Def(item_id, _) => {
2429                 let item = cx.tcx.hir().expect_item(item_id.id);
2430                 if let hir::ItemKind::Existential(ref ty) = item.node {
2431                     ImplTrait(ty.bounds.clean(cx))
2432                 } else {
2433                     unreachable!()
2434                 }
2435             }
2436             TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
2437                 if let Some(new_ty) = cx.ty_substs.borrow().get(&path.def).cloned() {
2438                     return new_ty;
2439                 }
2440
2441                 if let Def::TyParam(did) = path.def {
2442                     if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did) {
2443                         return ImplTrait(bounds);
2444                     }
2445                 }
2446
2447                 let mut alias = None;
2448                 if let Def::TyAlias(def_id) = path.def {
2449                     // Substitute private type aliases
2450                     if let Some(node_id) = cx.tcx.hir().as_local_node_id(def_id) {
2451                         if !cx.renderinfo.borrow().access_levels.is_exported(def_id) {
2452                             alias = Some(&cx.tcx.hir().expect_item(node_id).node);
2453                         }
2454                     }
2455                 };
2456
2457                 if let Some(&hir::ItemKind::Ty(ref ty, ref generics)) = alias {
2458                     let provided_params = &path.segments.last().expect("segments were empty");
2459                     let mut ty_substs = FxHashMap::default();
2460                     let mut lt_substs = FxHashMap::default();
2461                     provided_params.with_generic_args(|generic_args| {
2462                         let mut indices: GenericParamCount = Default::default();
2463                         for param in generics.params.iter() {
2464                             match param.kind {
2465                                 hir::GenericParamKind::Lifetime { .. } => {
2466                                     let mut j = 0;
2467                                     let lifetime = generic_args.args.iter().find_map(|arg| {
2468                                         match arg {
2469                                             GenericArg::Lifetime(lt) => {
2470                                                 if indices.lifetimes == j {
2471                                                     return Some(lt);
2472                                                 }
2473                                                 j += 1;
2474                                                 None
2475                                             }
2476                                             _ => None,
2477                                         }
2478                                     });
2479                                     if let Some(lt) = lifetime.cloned() {
2480                                         if !lt.is_elided() {
2481                                             let lt_def_id =
2482                                                 cx.tcx.hir().local_def_id(param.id);
2483                                             lt_substs.insert(lt_def_id, lt.clean(cx));
2484                                         }
2485                                     }
2486                                     indices.lifetimes += 1;
2487                                 }
2488                                 hir::GenericParamKind::Type { ref default, .. } => {
2489                                     let ty_param_def =
2490                                         Def::TyParam(cx.tcx.hir().local_def_id(param.id));
2491                                     let mut j = 0;
2492                                     let type_ = generic_args.args.iter().find_map(|arg| {
2493                                         match arg {
2494                                             GenericArg::Type(ty) => {
2495                                                 if indices.types == j {
2496                                                     return Some(ty);
2497                                                 }
2498                                                 j += 1;
2499                                                 None
2500                                             }
2501                                             _ => None,
2502                                         }
2503                                     });
2504                                     if let Some(ty) = type_.cloned() {
2505                                         ty_substs.insert(ty_param_def, ty.clean(cx));
2506                                     } else if let Some(default) = default.clone() {
2507                                         ty_substs.insert(ty_param_def,
2508                                                          default.into_inner().clean(cx));
2509                                     }
2510                                     indices.types += 1;
2511                                 }
2512                             }
2513                         }
2514                     });
2515                     return cx.enter_alias(ty_substs, lt_substs, || ty.clean(cx));
2516                 }
2517                 resolve_type(cx, path.clean(cx), self.id)
2518             }
2519             TyKind::Path(hir::QPath::Resolved(Some(ref qself), ref p)) => {
2520                 let mut segments: Vec<_> = p.segments.clone().into();
2521                 segments.pop();
2522                 let trait_path = hir::Path {
2523                     span: p.span,
2524                     def: Def::Trait(cx.tcx.associated_item(p.def.def_id()).container.id()),
2525                     segments: segments.into(),
2526                 };
2527                 Type::QPath {
2528                     name: p.segments.last().expect("segments were empty").ident.name.clean(cx),
2529                     self_type: box qself.clean(cx),
2530                     trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
2531                 }
2532             }
2533             TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
2534                 let mut def = Def::Err;
2535                 let ty = hir_ty_to_ty(cx.tcx, self);
2536                 if let ty::Projection(proj) = ty.sty {
2537                     def = Def::Trait(proj.trait_ref(cx.tcx).def_id);
2538                 }
2539                 let trait_path = hir::Path {
2540                     span: self.span,
2541                     def,
2542                     segments: vec![].into(),
2543                 };
2544                 Type::QPath {
2545                     name: segment.ident.name.clean(cx),
2546                     self_type: box qself.clean(cx),
2547                     trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
2548                 }
2549             }
2550             TyKind::TraitObject(ref bounds, ref lifetime) => {
2551                 match bounds[0].clean(cx).trait_ {
2552                     ResolvedPath { path, typarams: None, did, is_generic } => {
2553                         let mut bounds: Vec<self::GenericBound> = bounds[1..].iter().map(|bound| {
2554                             self::GenericBound::TraitBound(bound.clean(cx),
2555                                                            hir::TraitBoundModifier::None)
2556                         }).collect();
2557                         if !lifetime.is_elided() {
2558                             bounds.push(self::GenericBound::Outlives(lifetime.clean(cx)));
2559                         }
2560                         ResolvedPath { path, typarams: Some(bounds), did, is_generic, }
2561                     }
2562                     _ => Infer // shouldn't happen
2563                 }
2564             }
2565             TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
2566             TyKind::Infer | TyKind::Err => Infer,
2567             TyKind::Typeof(..) => panic!("Unimplemented type {:?}", self.node),
2568         }
2569     }
2570 }
2571
2572 impl<'tcx> Clean<Type> for Ty<'tcx> {
2573     fn clean(&self, cx: &DocContext) -> Type {
2574         match self.sty {
2575             ty::Never => Never,
2576             ty::Bool => Primitive(PrimitiveType::Bool),
2577             ty::Char => Primitive(PrimitiveType::Char),
2578             ty::Int(int_ty) => Primitive(int_ty.into()),
2579             ty::Uint(uint_ty) => Primitive(uint_ty.into()),
2580             ty::Float(float_ty) => Primitive(float_ty.into()),
2581             ty::Str => Primitive(PrimitiveType::Str),
2582             ty::Slice(ty) => Slice(box ty.clean(cx)),
2583             ty::Array(ty, n) => {
2584                 let mut n = cx.tcx.lift(&n).expect("array lift failed");
2585                 if let ConstValue::Unevaluated(def_id, substs) = n.val {
2586                     let param_env = cx.tcx.param_env(def_id);
2587                     let cid = GlobalId {
2588                         instance: ty::Instance::new(def_id, substs),
2589                         promoted: None
2590                     };
2591                     if let Ok(new_n) = cx.tcx.const_eval(param_env.and(cid)) {
2592                         n = new_n;
2593                     }
2594                 };
2595                 let n = print_const(cx, n);
2596                 Array(box ty.clean(cx), n)
2597             }
2598             ty::RawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
2599             ty::Ref(r, ty, mutbl) => BorrowedRef {
2600                 lifetime: r.clean(cx),
2601                 mutability: mutbl.clean(cx),
2602                 type_: box ty.clean(cx),
2603             },
2604             ty::FnDef(..) |
2605             ty::FnPtr(_) => {
2606                 let ty = cx.tcx.lift(self).expect("FnPtr lift failed");
2607                 let sig = ty.fn_sig(cx.tcx);
2608                 BareFunction(box BareFunctionDecl {
2609                     unsafety: sig.unsafety(),
2610                     generic_params: Vec::new(),
2611                     decl: (cx.tcx.hir().local_def_id(ast::CRATE_NODE_ID), sig).clean(cx),
2612                     abi: sig.abi(),
2613                 })
2614             }
2615             ty::Adt(def, substs) => {
2616                 let did = def.did;
2617                 let kind = match def.adt_kind() {
2618                     AdtKind::Struct => TypeKind::Struct,
2619                     AdtKind::Union => TypeKind::Union,
2620                     AdtKind::Enum => TypeKind::Enum,
2621                 };
2622                 inline::record_extern_fqn(cx, did, kind);
2623                 let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
2624                                          None, false, vec![], substs);
2625                 ResolvedPath {
2626                     path,
2627                     typarams: None,
2628                     did,
2629                     is_generic: false,
2630                 }
2631             }
2632             ty::Foreign(did) => {
2633                 inline::record_extern_fqn(cx, did, TypeKind::Foreign);
2634                 let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
2635                                          None, false, vec![], Substs::empty());
2636                 ResolvedPath {
2637                     path: path,
2638                     typarams: None,
2639                     did: did,
2640                     is_generic: false,
2641                 }
2642             }
2643             ty::Dynamic(ref obj, ref reg) => {
2644                 let principal = obj.principal();
2645                 let did = principal.def_id();
2646                 inline::record_extern_fqn(cx, did, TypeKind::Trait);
2647
2648                 let mut typarams = vec![];
2649                 reg.clean(cx).map(|b| typarams.push(GenericBound::Outlives(b)));
2650                 for did in obj.auto_traits() {
2651                     let empty = cx.tcx.intern_substs(&[]);
2652                     let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
2653                         Some(did), false, vec![], empty);
2654                     inline::record_extern_fqn(cx, did, TypeKind::Trait);
2655                     let bound = GenericBound::TraitBound(PolyTrait {
2656                         trait_: ResolvedPath {
2657                             path,
2658                             typarams: None,
2659                             did,
2660                             is_generic: false,
2661                         },
2662                         generic_params: Vec::new(),
2663                     }, hir::TraitBoundModifier::None);
2664                     typarams.push(bound);
2665                 }
2666
2667                 let mut bindings = vec![];
2668                 for pb in obj.projection_bounds() {
2669                     bindings.push(TypeBinding {
2670                         name: cx.tcx.associated_item(pb.item_def_id()).ident.name.clean(cx),
2671                         ty: pb.skip_binder().ty.clean(cx)
2672                     });
2673                 }
2674
2675                 let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did),
2676                     false, bindings, principal.skip_binder().substs);
2677                 ResolvedPath {
2678                     path,
2679                     typarams: Some(typarams),
2680                     did,
2681                     is_generic: false,
2682                 }
2683             }
2684             ty::Tuple(ref t) => Tuple(t.clean(cx)),
2685
2686             ty::Projection(ref data) => data.clean(cx),
2687
2688             ty::Param(ref p) => Generic(p.name.to_string()),
2689
2690             ty::Opaque(def_id, substs) => {
2691                 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
2692                 // by looking up the projections associated with the def_id.
2693                 let predicates_of = cx.tcx.predicates_of(def_id);
2694                 let substs = cx.tcx.lift(&substs).expect("Opaque lift failed");
2695                 let bounds = predicates_of.instantiate(cx.tcx, substs);
2696                 let mut regions = vec![];
2697                 let mut has_sized = false;
2698                 let mut bounds = bounds.predicates.iter().filter_map(|predicate| {
2699                     let trait_ref = if let Some(tr) = predicate.to_opt_poly_trait_ref() {
2700                         tr
2701                     } else if let ty::Predicate::TypeOutlives(pred) = *predicate {
2702                         // these should turn up at the end
2703                         pred.skip_binder().1.clean(cx).map(|r| {
2704                             regions.push(GenericBound::Outlives(r))
2705                         });
2706                         return None;
2707                     } else {
2708                         return None;
2709                     };
2710
2711                     if let Some(sized) = cx.tcx.lang_items().sized_trait() {
2712                         if trait_ref.def_id() == sized {
2713                             has_sized = true;
2714                             return None;
2715                         }
2716                     }
2717
2718                     let bounds = bounds.predicates.iter().filter_map(|pred|
2719                         if let ty::Predicate::Projection(proj) = *pred {
2720                             let proj = proj.skip_binder();
2721                             if proj.projection_ty.trait_ref(cx.tcx) == *trait_ref.skip_binder() {
2722                                 Some(TypeBinding {
2723                                     name: cx.tcx.associated_item(proj.projection_ty.item_def_id)
2724                                                 .ident.name.clean(cx),
2725                                     ty: proj.ty.clean(cx),
2726                                 })
2727                             } else {
2728                                 None
2729                             }
2730                         } else {
2731                             None
2732                         }
2733                     ).collect();
2734
2735                     Some((trait_ref.skip_binder(), bounds).clean(cx))
2736                 }).collect::<Vec<_>>();
2737                 bounds.extend(regions);
2738                 if !has_sized && !bounds.is_empty() {
2739                     bounds.insert(0, GenericBound::maybe_sized(cx));
2740                 }
2741                 ImplTrait(bounds)
2742             }
2743
2744             ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton)
2745
2746             ty::Bound(..) => panic!("Bound"),
2747             ty::Placeholder(..) => panic!("Placeholder"),
2748             ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"),
2749             ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
2750             ty::Infer(..) => panic!("Infer"),
2751             ty::Error => panic!("Error"),
2752         }
2753     }
2754 }
2755
2756 impl Clean<Item> for hir::StructField {
2757     fn clean(&self, cx: &DocContext) -> Item {
2758         Item {
2759             name: Some(self.ident.name).clean(cx),
2760             attrs: self.attrs.clean(cx),
2761             source: self.span.clean(cx),
2762             visibility: self.vis.clean(cx),
2763             stability: get_stability(cx, cx.tcx.hir().local_def_id(self.id)),
2764             deprecation: get_deprecation(cx, cx.tcx.hir().local_def_id(self.id)),
2765             def_id: cx.tcx.hir().local_def_id(self.id),
2766             inner: StructFieldItem(self.ty.clean(cx)),
2767         }
2768     }
2769 }
2770
2771 impl<'tcx> Clean<Item> for ty::FieldDef {
2772     fn clean(&self, cx: &DocContext) -> Item {
2773         Item {
2774             name: Some(self.ident.name).clean(cx),
2775             attrs: cx.tcx.get_attrs(self.did).clean(cx),
2776             source: cx.tcx.def_span(self.did).clean(cx),
2777             visibility: self.vis.clean(cx),
2778             stability: get_stability(cx, self.did),
2779             deprecation: get_deprecation(cx, self.did),
2780             def_id: self.did,
2781             inner: StructFieldItem(cx.tcx.type_of(self.did).clean(cx)),
2782         }
2783     }
2784 }
2785
2786 #[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug)]
2787 pub enum Visibility {
2788     Public,
2789     Inherited,
2790     Crate,
2791     Restricted(DefId, Path),
2792 }
2793
2794 impl Clean<Option<Visibility>> for hir::Visibility {
2795     fn clean(&self, cx: &DocContext) -> Option<Visibility> {
2796         Some(match self.node {
2797             hir::VisibilityKind::Public => Visibility::Public,
2798             hir::VisibilityKind::Inherited => Visibility::Inherited,
2799             hir::VisibilityKind::Crate(_) => Visibility::Crate,
2800             hir::VisibilityKind::Restricted { ref path, .. } => {
2801                 let path = path.clean(cx);
2802                 let did = register_def(cx, path.def);
2803                 Visibility::Restricted(did, path)
2804             }
2805         })
2806     }
2807 }
2808
2809 impl Clean<Option<Visibility>> for ty::Visibility {
2810     fn clean(&self, _: &DocContext) -> Option<Visibility> {
2811         Some(if *self == ty::Visibility::Public { Public } else { Inherited })
2812     }
2813 }
2814
2815 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2816 pub struct Struct {
2817     pub struct_type: doctree::StructType,
2818     pub generics: Generics,
2819     pub fields: Vec<Item>,
2820     pub fields_stripped: bool,
2821 }
2822
2823 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2824 pub struct Union {
2825     pub struct_type: doctree::StructType,
2826     pub generics: Generics,
2827     pub fields: Vec<Item>,
2828     pub fields_stripped: bool,
2829 }
2830
2831 impl Clean<Item> for doctree::Struct {
2832     fn clean(&self, cx: &DocContext) -> Item {
2833         Item {
2834             name: Some(self.name.clean(cx)),
2835             attrs: self.attrs.clean(cx),
2836             source: self.whence.clean(cx),
2837             def_id: cx.tcx.hir().local_def_id(self.id),
2838             visibility: self.vis.clean(cx),
2839             stability: self.stab.clean(cx),
2840             deprecation: self.depr.clean(cx),
2841             inner: StructItem(Struct {
2842                 struct_type: self.struct_type,
2843                 generics: self.generics.clean(cx),
2844                 fields: self.fields.clean(cx),
2845                 fields_stripped: false,
2846             }),
2847         }
2848     }
2849 }
2850
2851 impl Clean<Item> for doctree::Union {
2852     fn clean(&self, cx: &DocContext) -> Item {
2853         Item {
2854             name: Some(self.name.clean(cx)),
2855             attrs: self.attrs.clean(cx),
2856             source: self.whence.clean(cx),
2857             def_id: cx.tcx.hir().local_def_id(self.id),
2858             visibility: self.vis.clean(cx),
2859             stability: self.stab.clean(cx),
2860             deprecation: self.depr.clean(cx),
2861             inner: UnionItem(Union {
2862                 struct_type: self.struct_type,
2863                 generics: self.generics.clean(cx),
2864                 fields: self.fields.clean(cx),
2865                 fields_stripped: false,
2866             }),
2867         }
2868     }
2869 }
2870
2871 /// This is a more limited form of the standard Struct, different in that
2872 /// it lacks the things most items have (name, id, parameterization). Found
2873 /// only as a variant in an enum.
2874 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2875 pub struct VariantStruct {
2876     pub struct_type: doctree::StructType,
2877     pub fields: Vec<Item>,
2878     pub fields_stripped: bool,
2879 }
2880
2881 impl Clean<VariantStruct> for ::rustc::hir::VariantData {
2882     fn clean(&self, cx: &DocContext) -> VariantStruct {
2883         VariantStruct {
2884             struct_type: doctree::struct_type_from_def(self),
2885             fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
2886             fields_stripped: false,
2887         }
2888     }
2889 }
2890
2891 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2892 pub struct Enum {
2893     pub variants: IndexVec<VariantIdx, Item>,
2894     pub generics: Generics,
2895     pub variants_stripped: bool,
2896 }
2897
2898 impl Clean<Item> for doctree::Enum {
2899     fn clean(&self, cx: &DocContext) -> Item {
2900         Item {
2901             name: Some(self.name.clean(cx)),
2902             attrs: self.attrs.clean(cx),
2903             source: self.whence.clean(cx),
2904             def_id: cx.tcx.hir().local_def_id(self.id),
2905             visibility: self.vis.clean(cx),
2906             stability: self.stab.clean(cx),
2907             deprecation: self.depr.clean(cx),
2908             inner: EnumItem(Enum {
2909                 variants: self.variants.iter().map(|v| v.clean(cx)).collect(),
2910                 generics: self.generics.clean(cx),
2911                 variants_stripped: false,
2912             }),
2913         }
2914     }
2915 }
2916
2917 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2918 pub struct Variant {
2919     pub kind: VariantKind,
2920 }
2921
2922 impl Clean<Item> for doctree::Variant {
2923     fn clean(&self, cx: &DocContext) -> Item {
2924         Item {
2925             name: Some(self.name.clean(cx)),
2926             attrs: self.attrs.clean(cx),
2927             source: self.whence.clean(cx),
2928             visibility: None,
2929             stability: self.stab.clean(cx),
2930             deprecation: self.depr.clean(cx),
2931             def_id: cx.tcx.hir().local_def_id(self.def.id()),
2932             inner: VariantItem(Variant {
2933                 kind: self.def.clean(cx),
2934             }),
2935         }
2936     }
2937 }
2938
2939 impl<'tcx> Clean<Item> for ty::VariantDef {
2940     fn clean(&self, cx: &DocContext) -> Item {
2941         let kind = match self.ctor_kind {
2942             CtorKind::Const => VariantKind::CLike,
2943             CtorKind::Fn => {
2944                 VariantKind::Tuple(
2945                     self.fields.iter().map(|f| cx.tcx.type_of(f.did).clean(cx)).collect()
2946                 )
2947             }
2948             CtorKind::Fictive => {
2949                 VariantKind::Struct(VariantStruct {
2950                     struct_type: doctree::Plain,
2951                     fields_stripped: false,
2952                     fields: self.fields.iter().map(|field| {
2953                         Item {
2954                             source: cx.tcx.def_span(field.did).clean(cx),
2955                             name: Some(field.ident.name.clean(cx)),
2956                             attrs: cx.tcx.get_attrs(field.did).clean(cx),
2957                             visibility: field.vis.clean(cx),
2958                             def_id: field.did,
2959                             stability: get_stability(cx, field.did),
2960                             deprecation: get_deprecation(cx, field.did),
2961                             inner: StructFieldItem(cx.tcx.type_of(field.did).clean(cx))
2962                         }
2963                     }).collect()
2964                 })
2965             }
2966         };
2967         Item {
2968             name: Some(self.name.clean(cx)),
2969             attrs: inline::load_attrs(cx, self.did),
2970             source: cx.tcx.def_span(self.did).clean(cx),
2971             visibility: Some(Inherited),
2972             def_id: self.did,
2973             inner: VariantItem(Variant { kind }),
2974             stability: get_stability(cx, self.did),
2975             deprecation: get_deprecation(cx, self.did),
2976         }
2977     }
2978 }
2979
2980 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2981 pub enum VariantKind {
2982     CLike,
2983     Tuple(Vec<Type>),
2984     Struct(VariantStruct),
2985 }
2986
2987 impl Clean<VariantKind> for hir::VariantData {
2988     fn clean(&self, cx: &DocContext) -> VariantKind {
2989         if self.is_struct() {
2990             VariantKind::Struct(self.clean(cx))
2991         } else if self.is_unit() {
2992             VariantKind::CLike
2993         } else {
2994             VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect())
2995         }
2996     }
2997 }
2998
2999 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3000 pub struct Span {
3001     pub filename: FileName,
3002     pub loline: usize,
3003     pub locol: usize,
3004     pub hiline: usize,
3005     pub hicol: usize,
3006 }
3007
3008 impl Span {
3009     pub fn empty() -> Span {
3010         Span {
3011             filename: FileName::Anon(0),
3012             loline: 0, locol: 0,
3013             hiline: 0, hicol: 0,
3014         }
3015     }
3016 }
3017
3018 impl Clean<Span> for syntax_pos::Span {
3019     fn clean(&self, cx: &DocContext) -> Span {
3020         if self.is_dummy() {
3021             return Span::empty();
3022         }
3023
3024         let cm = cx.sess().source_map();
3025         let filename = cm.span_to_filename(*self);
3026         let lo = cm.lookup_char_pos(self.lo());
3027         let hi = cm.lookup_char_pos(self.hi());
3028         Span {
3029             filename,
3030             loline: lo.line,
3031             locol: lo.col.to_usize(),
3032             hiline: hi.line,
3033             hicol: hi.col.to_usize(),
3034         }
3035     }
3036 }
3037
3038 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3039 pub struct Path {
3040     pub global: bool,
3041     pub def: Def,
3042     pub segments: Vec<PathSegment>,
3043 }
3044
3045 impl Path {
3046     pub fn last_name(&self) -> &str {
3047         self.segments.last().expect("segments were empty").name.as_str()
3048     }
3049 }
3050
3051 impl Clean<Path> for hir::Path {
3052     fn clean(&self, cx: &DocContext) -> Path {
3053         Path {
3054             global: self.is_global(),
3055             def: self.def,
3056             segments: if self.is_global() { &self.segments[1..] } else { &self.segments }.clean(cx),
3057         }
3058     }
3059 }
3060
3061 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3062 pub enum GenericArgs {
3063     AngleBracketed {
3064         lifetimes: Vec<Lifetime>,
3065         types: Vec<Type>,
3066         bindings: Vec<TypeBinding>,
3067     },
3068     Parenthesized {
3069         inputs: Vec<Type>,
3070         output: Option<Type>,
3071     }
3072 }
3073
3074 impl Clean<GenericArgs> for hir::GenericArgs {
3075     fn clean(&self, cx: &DocContext) -> GenericArgs {
3076         if self.parenthesized {
3077             let output = self.bindings[0].ty.clean(cx);
3078             GenericArgs::Parenthesized {
3079                 inputs: self.inputs().clean(cx),
3080                 output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
3081             }
3082         } else {
3083             let (mut lifetimes, mut types) = (vec![], vec![]);
3084             let mut elided_lifetimes = true;
3085             for arg in &self.args {
3086                 match arg {
3087                     GenericArg::Lifetime(lt) => {
3088                         if !lt.is_elided() {
3089                             elided_lifetimes = false;
3090                         }
3091                         lifetimes.push(lt.clean(cx));
3092                     }
3093                     GenericArg::Type(ty) => {
3094                         types.push(ty.clean(cx));
3095                     }
3096                 }
3097             }
3098             GenericArgs::AngleBracketed {
3099                 lifetimes: if elided_lifetimes { vec![] } else { lifetimes },
3100                 types,
3101                 bindings: self.bindings.clean(cx),
3102             }
3103         }
3104     }
3105 }
3106
3107 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3108 pub struct PathSegment {
3109     pub name: String,
3110     pub args: GenericArgs,
3111 }
3112
3113 impl Clean<PathSegment> for hir::PathSegment {
3114     fn clean(&self, cx: &DocContext) -> PathSegment {
3115         PathSegment {
3116             name: self.ident.name.clean(cx),
3117             args: self.with_generic_args(|generic_args| generic_args.clean(cx))
3118         }
3119     }
3120 }
3121
3122 fn strip_type(ty: Type) -> Type {
3123     match ty {
3124         Type::ResolvedPath { path, typarams, did, is_generic } => {
3125             Type::ResolvedPath { path: strip_path(&path), typarams, did, is_generic }
3126         }
3127         Type::Tuple(inner_tys) => {
3128             Type::Tuple(inner_tys.iter().map(|t| strip_type(t.clone())).collect())
3129         }
3130         Type::Slice(inner_ty) => Type::Slice(Box::new(strip_type(*inner_ty))),
3131         Type::Array(inner_ty, s) => Type::Array(Box::new(strip_type(*inner_ty)), s),
3132         Type::Unique(inner_ty) => Type::Unique(Box::new(strip_type(*inner_ty))),
3133         Type::RawPointer(m, inner_ty) => Type::RawPointer(m, Box::new(strip_type(*inner_ty))),
3134         Type::BorrowedRef { lifetime, mutability, type_ } => {
3135             Type::BorrowedRef { lifetime, mutability, type_: Box::new(strip_type(*type_)) }
3136         }
3137         Type::QPath { name, self_type, trait_ } => {
3138             Type::QPath {
3139                 name,
3140                 self_type: Box::new(strip_type(*self_type)), trait_: Box::new(strip_type(*trait_))
3141             }
3142         }
3143         _ => ty
3144     }
3145 }
3146
3147 fn strip_path(path: &Path) -> Path {
3148     let segments = path.segments.iter().map(|s| {
3149         PathSegment {
3150             name: s.name.clone(),
3151             args: GenericArgs::AngleBracketed {
3152                 lifetimes: Vec::new(),
3153                 types: Vec::new(),
3154                 bindings: Vec::new(),
3155             }
3156         }
3157     }).collect();
3158
3159     Path {
3160         global: path.global,
3161         def: path.def.clone(),
3162         segments,
3163     }
3164 }
3165
3166 fn qpath_to_string(p: &hir::QPath) -> String {
3167     let segments = match *p {
3168         hir::QPath::Resolved(_, ref path) => &path.segments,
3169         hir::QPath::TypeRelative(_, ref segment) => return segment.ident.to_string(),
3170     };
3171
3172     let mut s = String::new();
3173     for (i, seg) in segments.iter().enumerate() {
3174         if i > 0 {
3175             s.push_str("::");
3176         }
3177         if seg.ident.name != keywords::PathRoot.name() {
3178             s.push_str(&*seg.ident.as_str());
3179         }
3180     }
3181     s
3182 }
3183
3184 impl Clean<String> for ast::Name {
3185     fn clean(&self, _: &DocContext) -> String {
3186         self.to_string()
3187     }
3188 }
3189
3190 impl Clean<String> for InternedString {
3191     fn clean(&self, _: &DocContext) -> String {
3192         self.to_string()
3193     }
3194 }
3195
3196 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3197 pub struct Typedef {
3198     pub type_: Type,
3199     pub generics: Generics,
3200 }
3201
3202 impl Clean<Item> for doctree::Typedef {
3203     fn clean(&self, cx: &DocContext) -> Item {
3204         Item {
3205             name: Some(self.name.clean(cx)),
3206             attrs: self.attrs.clean(cx),
3207             source: self.whence.clean(cx),
3208             def_id: cx.tcx.hir().local_def_id(self.id.clone()),
3209             visibility: self.vis.clean(cx),
3210             stability: self.stab.clean(cx),
3211             deprecation: self.depr.clean(cx),
3212             inner: TypedefItem(Typedef {
3213                 type_: self.ty.clean(cx),
3214                 generics: self.gen.clean(cx),
3215             }, false),
3216         }
3217     }
3218 }
3219
3220 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3221 pub struct Existential {
3222     pub bounds: Vec<GenericBound>,
3223     pub generics: Generics,
3224 }
3225
3226 impl Clean<Item> for doctree::Existential {
3227     fn clean(&self, cx: &DocContext) -> Item {
3228         Item {
3229             name: Some(self.name.clean(cx)),
3230             attrs: self.attrs.clean(cx),
3231             source: self.whence.clean(cx),
3232             def_id: cx.tcx.hir().local_def_id(self.id.clone()),
3233             visibility: self.vis.clean(cx),
3234             stability: self.stab.clean(cx),
3235             deprecation: self.depr.clean(cx),
3236             inner: ExistentialItem(Existential {
3237                 bounds: self.exist_ty.bounds.clean(cx),
3238                 generics: self.exist_ty.generics.clean(cx),
3239             }, false),
3240         }
3241     }
3242 }
3243
3244 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
3245 pub struct BareFunctionDecl {
3246     pub unsafety: hir::Unsafety,
3247     pub generic_params: Vec<GenericParamDef>,
3248     pub decl: FnDecl,
3249     pub abi: Abi,
3250 }
3251
3252 impl Clean<BareFunctionDecl> for hir::BareFnTy {
3253     fn clean(&self, cx: &DocContext) -> BareFunctionDecl {
3254         let (generic_params, decl) = enter_impl_trait(cx, || {
3255             (self.generic_params.clean(cx), (&*self.decl, &self.arg_names[..]).clean(cx))
3256         });
3257         BareFunctionDecl {
3258             unsafety: self.unsafety,
3259             abi: self.abi,
3260             decl,
3261             generic_params,
3262         }
3263     }
3264 }
3265
3266 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3267 pub struct Static {
3268     pub type_: Type,
3269     pub mutability: Mutability,
3270     /// It's useful to have the value of a static documented, but I have no
3271     /// desire to represent expressions (that'd basically be all of the AST,
3272     /// which is huge!). So, have a string.
3273     pub expr: String,
3274 }
3275
3276 impl Clean<Item> for doctree::Static {
3277     fn clean(&self, cx: &DocContext) -> Item {
3278         debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
3279         Item {
3280             name: Some(self.name.clean(cx)),
3281             attrs: self.attrs.clean(cx),
3282             source: self.whence.clean(cx),
3283             def_id: cx.tcx.hir().local_def_id(self.id),
3284             visibility: self.vis.clean(cx),
3285             stability: self.stab.clean(cx),
3286             deprecation: self.depr.clean(cx),
3287             inner: StaticItem(Static {
3288                 type_: self.type_.clean(cx),
3289                 mutability: self.mutability.clean(cx),
3290                 expr: print_const_expr(cx, self.expr),
3291             }),
3292         }
3293     }
3294 }
3295
3296 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3297 pub struct Constant {
3298     pub type_: Type,
3299     pub expr: String,
3300 }
3301
3302 impl Clean<Item> for doctree::Constant {
3303     fn clean(&self, cx: &DocContext) -> Item {
3304         Item {
3305             name: Some(self.name.clean(cx)),
3306             attrs: self.attrs.clean(cx),
3307             source: self.whence.clean(cx),
3308             def_id: cx.tcx.hir().local_def_id(self.id),
3309             visibility: self.vis.clean(cx),
3310             stability: self.stab.clean(cx),
3311             deprecation: self.depr.clean(cx),
3312             inner: ConstantItem(Constant {
3313                 type_: self.type_.clean(cx),
3314                 expr: print_const_expr(cx, self.expr),
3315             }),
3316         }
3317     }
3318 }
3319
3320 #[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Copy, Hash)]
3321 pub enum Mutability {
3322     Mutable,
3323     Immutable,
3324 }
3325
3326 impl Clean<Mutability> for hir::Mutability {
3327     fn clean(&self, _: &DocContext) -> Mutability {
3328         match self {
3329             &hir::MutMutable => Mutable,
3330             &hir::MutImmutable => Immutable,
3331         }
3332     }
3333 }
3334
3335 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Copy, Debug, Hash)]
3336 pub enum ImplPolarity {
3337     Positive,
3338     Negative,
3339 }
3340
3341 impl Clean<ImplPolarity> for hir::ImplPolarity {
3342     fn clean(&self, _: &DocContext) -> ImplPolarity {
3343         match self {
3344             &hir::ImplPolarity::Positive => ImplPolarity::Positive,
3345             &hir::ImplPolarity::Negative => ImplPolarity::Negative,
3346         }
3347     }
3348 }
3349
3350 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3351 pub struct Impl {
3352     pub unsafety: hir::Unsafety,
3353     pub generics: Generics,
3354     pub provided_trait_methods: FxHashSet<String>,
3355     pub trait_: Option<Type>,
3356     pub for_: Type,
3357     pub items: Vec<Item>,
3358     pub polarity: Option<ImplPolarity>,
3359     pub synthetic: bool,
3360     pub blanket_impl: Option<Type>,
3361 }
3362
3363 pub fn get_auto_traits_with_node_id(cx: &DocContext, id: ast::NodeId, name: String) -> Vec<Item> {
3364     let finder = AutoTraitFinder::new(cx);
3365     finder.get_with_node_id(id, name)
3366 }
3367
3368 pub fn get_auto_traits_with_def_id(cx: &DocContext, id: DefId) -> Vec<Item> {
3369     let finder = AutoTraitFinder::new(cx);
3370
3371     finder.get_with_def_id(id)
3372 }
3373
3374 pub fn get_blanket_impls_with_node_id(cx: &DocContext, id: ast::NodeId, name: String) -> Vec<Item> {
3375     let finder = BlanketImplFinder::new(cx);
3376     finder.get_with_node_id(id, name)
3377 }
3378
3379 pub fn get_blanket_impls_with_def_id(cx: &DocContext, id: DefId) -> Vec<Item> {
3380     let finder = BlanketImplFinder::new(cx);
3381
3382     finder.get_with_def_id(id)
3383 }
3384
3385 impl Clean<Vec<Item>> for doctree::Impl {
3386     fn clean(&self, cx: &DocContext) -> Vec<Item> {
3387         let mut ret = Vec::new();
3388         let trait_ = self.trait_.clean(cx);
3389         let items = self.items.clean(cx);
3390
3391         // If this impl block is an implementation of the Deref trait, then we
3392         // need to try inlining the target's inherent impl blocks as well.
3393         if trait_.def_id() == cx.tcx.lang_items().deref_trait() {
3394             build_deref_target_impls(cx, &items, &mut ret);
3395         }
3396
3397         let provided = trait_.def_id().map(|did| {
3398             cx.tcx.provided_trait_methods(did)
3399                   .into_iter()
3400                   .map(|meth| meth.ident.to_string())
3401                   .collect()
3402         }).unwrap_or_default();
3403
3404         ret.push(Item {
3405             name: None,
3406             attrs: self.attrs.clean(cx),
3407             source: self.whence.clean(cx),
3408             def_id: cx.tcx.hir().local_def_id(self.id),
3409             visibility: self.vis.clean(cx),
3410             stability: self.stab.clean(cx),
3411             deprecation: self.depr.clean(cx),
3412             inner: ImplItem(Impl {
3413                 unsafety: self.unsafety,
3414                 generics: self.generics.clean(cx),
3415                 provided_trait_methods: provided,
3416                 trait_,
3417                 for_: self.for_.clean(cx),
3418                 items,
3419                 polarity: Some(self.polarity.clean(cx)),
3420                 synthetic: false,
3421                 blanket_impl: None,
3422             })
3423         });
3424         ret
3425     }
3426 }
3427
3428 fn build_deref_target_impls(cx: &DocContext,
3429                             items: &[Item],
3430                             ret: &mut Vec<Item>) {
3431     use self::PrimitiveType::*;
3432     let tcx = cx.tcx;
3433
3434     for item in items {
3435         let target = match item.inner {
3436             TypedefItem(ref t, true) => &t.type_,
3437             _ => continue,
3438         };
3439         let primitive = match *target {
3440             ResolvedPath { did, .. } if did.is_local() => continue,
3441             ResolvedPath { did, .. } => {
3442                 ret.extend(inline::build_impls(cx, did));
3443                 continue
3444             }
3445             _ => match target.primitive_type() {
3446                 Some(prim) => prim,
3447                 None => continue,
3448             }
3449         };
3450         let did = match primitive {
3451             Isize => tcx.lang_items().isize_impl(),
3452             I8 => tcx.lang_items().i8_impl(),
3453             I16 => tcx.lang_items().i16_impl(),
3454             I32 => tcx.lang_items().i32_impl(),
3455             I64 => tcx.lang_items().i64_impl(),
3456             I128 => tcx.lang_items().i128_impl(),
3457             Usize => tcx.lang_items().usize_impl(),
3458             U8 => tcx.lang_items().u8_impl(),
3459             U16 => tcx.lang_items().u16_impl(),
3460             U32 => tcx.lang_items().u32_impl(),
3461             U64 => tcx.lang_items().u64_impl(),
3462             U128 => tcx.lang_items().u128_impl(),
3463             F32 => tcx.lang_items().f32_impl(),
3464             F64 => tcx.lang_items().f64_impl(),
3465             Char => tcx.lang_items().char_impl(),
3466             Bool => None,
3467             Str => tcx.lang_items().str_impl(),
3468             Slice => tcx.lang_items().slice_impl(),
3469             Array => tcx.lang_items().slice_impl(),
3470             Tuple => None,
3471             Unit => None,
3472             RawPointer => tcx.lang_items().const_ptr_impl(),
3473             Reference => None,
3474             Fn => None,
3475             Never => None,
3476         };
3477         if let Some(did) = did {
3478             if !did.is_local() {
3479                 inline::build_impl(cx, did, ret);
3480             }
3481         }
3482     }
3483 }
3484
3485 impl Clean<Item> for doctree::ExternCrate {
3486     fn clean(&self, cx: &DocContext) -> Item {
3487         Item {
3488             name: None,
3489             attrs: self.attrs.clean(cx),
3490             source: self.whence.clean(cx),
3491             def_id: DefId { krate: self.cnum, index: CRATE_DEF_INDEX },
3492             visibility: self.vis.clean(cx),
3493             stability: None,
3494             deprecation: None,
3495             inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
3496         }
3497     }
3498 }
3499
3500 impl Clean<Vec<Item>> for doctree::Import {
3501     fn clean(&self, cx: &DocContext) -> Vec<Item> {
3502         // We consider inlining the documentation of `pub use` statements, but we
3503         // forcefully don't inline if this is not public or if the
3504         // #[doc(no_inline)] attribute is present.
3505         // Don't inline doc(hidden) imports so they can be stripped at a later stage.
3506         let mut denied = !self.vis.node.is_pub() || self.attrs.iter().any(|a| {
3507             a.name() == "doc" && match a.meta_item_list() {
3508                 Some(l) => attr::list_contains_name(&l, "no_inline") ||
3509                            attr::list_contains_name(&l, "hidden"),
3510                 None => false,
3511             }
3512         });
3513         // Also check whether imports were asked to be inlined, in case we're trying to re-export a
3514         // crate in Rust 2018+
3515         let please_inline = self.attrs.lists("doc").has_word("inline");
3516         let path = self.path.clean(cx);
3517         let inner = if self.glob {
3518             if !denied {
3519                 let mut visited = FxHashSet::default();
3520                 if let Some(items) = inline::try_inline_glob(cx, path.def, &mut visited) {
3521                     return items;
3522                 }
3523             }
3524
3525             Import::Glob(resolve_use_source(cx, path))
3526         } else {
3527             let name = self.name;
3528             if !please_inline {
3529                 match path.def {
3530                     Def::Mod(did) => if !did.is_local() && did.index == CRATE_DEF_INDEX {
3531                         // if we're `pub use`ing an extern crate root, don't inline it unless we
3532                         // were specifically asked for it
3533                         denied = true;
3534                     }
3535                     _ => {}
3536                 }
3537             }
3538             if !denied {
3539                 let mut visited = FxHashSet::default();
3540                 if let Some(items) = inline::try_inline(cx, path.def, name, &mut visited) {
3541                     return items;
3542                 }
3543             }
3544             Import::Simple(name.clean(cx), resolve_use_source(cx, path))
3545         };
3546
3547         vec![Item {
3548             name: None,
3549             attrs: self.attrs.clean(cx),
3550             source: self.whence.clean(cx),
3551             def_id: cx.tcx.hir().local_def_id(ast::CRATE_NODE_ID),
3552             visibility: self.vis.clean(cx),
3553             stability: None,
3554             deprecation: None,
3555             inner: ImportItem(inner)
3556         }]
3557     }
3558 }
3559
3560 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3561 pub enum Import {
3562     // use source as str;
3563     Simple(String, ImportSource),
3564     // use source::*;
3565     Glob(ImportSource)
3566 }
3567
3568 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3569 pub struct ImportSource {
3570     pub path: Path,
3571     pub did: Option<DefId>,
3572 }
3573
3574 impl Clean<Vec<Item>> for hir::ForeignMod {
3575     fn clean(&self, cx: &DocContext) -> Vec<Item> {
3576         let mut items = self.items.clean(cx);
3577         for item in &mut items {
3578             if let ForeignFunctionItem(ref mut f) = item.inner {
3579                 f.header.abi = self.abi;
3580             }
3581         }
3582         items
3583     }
3584 }
3585
3586 impl Clean<Item> for hir::ForeignItem {
3587     fn clean(&self, cx: &DocContext) -> Item {
3588         let inner = match self.node {
3589             hir::ForeignItemKind::Fn(ref decl, ref names, ref generics) => {
3590                 let (generics, decl) = enter_impl_trait(cx, || {
3591                     (generics.clean(cx), (&**decl, &names[..]).clean(cx))
3592                 });
3593                 ForeignFunctionItem(Function {
3594                     decl,
3595                     generics,
3596                     header: hir::FnHeader {
3597                         unsafety: hir::Unsafety::Unsafe,
3598                         abi: Abi::Rust,
3599                         constness: hir::Constness::NotConst,
3600                         asyncness: hir::IsAsync::NotAsync,
3601                     },
3602                 })
3603             }
3604             hir::ForeignItemKind::Static(ref ty, mutbl) => {
3605                 ForeignStaticItem(Static {
3606                     type_: ty.clean(cx),
3607                     mutability: if mutbl {Mutable} else {Immutable},
3608                     expr: String::new(),
3609                 })
3610             }
3611             hir::ForeignItemKind::Type => {
3612                 ForeignTypeItem
3613             }
3614         };
3615
3616         Item {
3617             name: Some(self.name.clean(cx)),
3618             attrs: self.attrs.clean(cx),
3619             source: self.span.clean(cx),
3620             def_id: cx.tcx.hir().local_def_id(self.id),
3621             visibility: self.vis.clean(cx),
3622             stability: get_stability(cx, cx.tcx.hir().local_def_id(self.id)),
3623             deprecation: get_deprecation(cx, cx.tcx.hir().local_def_id(self.id)),
3624             inner,
3625         }
3626     }
3627 }
3628
3629 // Utilities
3630
3631 pub trait ToSource {
3632     fn to_src(&self, cx: &DocContext) -> String;
3633 }
3634
3635 impl ToSource for syntax_pos::Span {
3636     fn to_src(&self, cx: &DocContext) -> String {
3637         debug!("converting span {:?} to snippet", self.clean(cx));
3638         let sn = match cx.sess().source_map().span_to_snippet(*self) {
3639             Ok(x) => x,
3640             Err(_) => String::new()
3641         };
3642         debug!("got snippet {}", sn);
3643         sn
3644     }
3645 }
3646
3647 fn name_from_pat(p: &hir::Pat) -> String {
3648     use rustc::hir::*;
3649     debug!("Trying to get a name from pattern: {:?}", p);
3650
3651     match p.node {
3652         PatKind::Wild => "_".to_string(),
3653         PatKind::Binding(_, _, ident, _) => ident.to_string(),
3654         PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
3655         PatKind::Struct(ref name, ref fields, etc) => {
3656             format!("{} {{ {}{} }}", qpath_to_string(name),
3657                 fields.iter().map(|&Spanned { node: ref fp, .. }|
3658                                   format!("{}: {}", fp.ident, name_from_pat(&*fp.pat)))
3659                              .collect::<Vec<String>>().join(", "),
3660                 if etc { ", .." } else { "" }
3661             )
3662         }
3663         PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
3664                                             .collect::<Vec<String>>().join(", ")),
3665         PatKind::Box(ref p) => name_from_pat(&**p),
3666         PatKind::Ref(ref p, _) => name_from_pat(&**p),
3667         PatKind::Lit(..) => {
3668             warn!("tried to get argument name from PatKind::Lit, \
3669                   which is silly in function arguments");
3670             "()".to_string()
3671         },
3672         PatKind::Range(..) => panic!("tried to get argument name from PatKind::Range, \
3673                               which is not allowed in function arguments"),
3674         PatKind::Slice(ref begin, ref mid, ref end) => {
3675             let begin = begin.iter().map(|p| name_from_pat(&**p));
3676             let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter();
3677             let end = end.iter().map(|p| name_from_pat(&**p));
3678             format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
3679         },
3680     }
3681 }
3682
3683 fn print_const(cx: &DocContext, n: &ty::Const) -> String {
3684     match n.val {
3685         ConstValue::Unevaluated(def_id, _) => {
3686             if let Some(node_id) = cx.tcx.hir().as_local_node_id(def_id) {
3687                 print_const_expr(cx, cx.tcx.hir().body_owned_by(node_id))
3688             } else {
3689                 inline::print_inlined_const(cx, def_id)
3690             }
3691         },
3692         _ => {
3693             let mut s = String::new();
3694             ::rustc::mir::fmt_const_val(&mut s, n).expect("fmt_const_val failed");
3695             // array lengths are obviously usize
3696             if s.ends_with("usize") {
3697                 let n = s.len() - "usize".len();
3698                 s.truncate(n);
3699             }
3700             s
3701         },
3702     }
3703 }
3704
3705 fn print_const_expr(cx: &DocContext, body: hir::BodyId) -> String {
3706     cx.tcx.hir().node_to_pretty_string(body.node_id)
3707 }
3708
3709 /// Given a type Path, resolve it to a Type using the TyCtxt
3710 fn resolve_type(cx: &DocContext,
3711                 path: Path,
3712                 id: ast::NodeId) -> Type {
3713     if id == ast::DUMMY_NODE_ID {
3714         debug!("resolve_type({:?})", path);
3715     } else {
3716         debug!("resolve_type({:?},{:?})", path, id);
3717     }
3718
3719     let is_generic = match path.def {
3720         Def::PrimTy(p) => match p {
3721             hir::Str => return Primitive(PrimitiveType::Str),
3722             hir::Bool => return Primitive(PrimitiveType::Bool),
3723             hir::Char => return Primitive(PrimitiveType::Char),
3724             hir::Int(int_ty) => return Primitive(int_ty.into()),
3725             hir::Uint(uint_ty) => return Primitive(uint_ty.into()),
3726             hir::Float(float_ty) => return Primitive(float_ty.into()),
3727         },
3728         Def::SelfTy(..) if path.segments.len() == 1 => {
3729             return Generic(keywords::SelfUpper.name().to_string());
3730         }
3731         Def::TyParam(..) if path.segments.len() == 1 => {
3732             return Generic(format!("{:#}", path));
3733         }
3734         Def::SelfTy(..) | Def::TyParam(..) | Def::AssociatedTy(..) => true,
3735         _ => false,
3736     };
3737     let did = register_def(&*cx, path.def);
3738     ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
3739 }
3740
3741 pub fn register_def(cx: &DocContext, def: Def) -> DefId {
3742     debug!("register_def({:?})", def);
3743
3744     let (did, kind) = match def {
3745         Def::Fn(i) => (i, TypeKind::Function),
3746         Def::TyAlias(i) => (i, TypeKind::Typedef),
3747         Def::Enum(i) => (i, TypeKind::Enum),
3748         Def::Trait(i) => (i, TypeKind::Trait),
3749         Def::Struct(i) => (i, TypeKind::Struct),
3750         Def::Union(i) => (i, TypeKind::Union),
3751         Def::Mod(i) => (i, TypeKind::Module),
3752         Def::ForeignTy(i) => (i, TypeKind::Foreign),
3753         Def::Const(i) => (i, TypeKind::Const),
3754         Def::Static(i, _) => (i, TypeKind::Static),
3755         Def::Variant(i) => (cx.tcx.parent_def_id(i).expect("cannot get parent def id"),
3756                             TypeKind::Enum),
3757         Def::Macro(i, mac_kind) => match mac_kind {
3758             MacroKind::Bang => (i, TypeKind::Macro),
3759             MacroKind::Attr => (i, TypeKind::Attr),
3760             MacroKind::Derive => (i, TypeKind::Derive),
3761             MacroKind::ProcMacroStub => unreachable!(),
3762         },
3763         Def::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
3764         Def::SelfTy(_, Some(impl_def_id)) => {
3765             return impl_def_id
3766         }
3767         _ => return def.def_id()
3768     };
3769     if did.is_local() { return did }
3770     inline::record_extern_fqn(cx, did, kind);
3771     if let TypeKind::Trait = kind {
3772         inline::record_extern_trait(cx, did);
3773     }
3774     did
3775 }
3776
3777 fn resolve_use_source(cx: &DocContext, path: Path) -> ImportSource {
3778     ImportSource {
3779         did: if path.def == Def::Err {
3780             None
3781         } else {
3782             Some(register_def(cx, path.def))
3783         },
3784         path,
3785     }
3786 }
3787
3788 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3789 pub struct Macro {
3790     pub source: String,
3791     pub imported_from: Option<String>,
3792 }
3793
3794 impl Clean<Item> for doctree::Macro {
3795     fn clean(&self, cx: &DocContext) -> Item {
3796         let name = self.name.clean(cx);
3797         Item {
3798             name: Some(name.clone()),
3799             attrs: self.attrs.clean(cx),
3800             source: self.whence.clean(cx),
3801             visibility: Some(Public),
3802             stability: self.stab.clean(cx),
3803             deprecation: self.depr.clean(cx),
3804             def_id: self.def_id,
3805             inner: MacroItem(Macro {
3806                 source: format!("macro_rules! {} {{\n{}}}",
3807                                 name,
3808                                 self.matchers.iter().map(|span| {
3809                                     format!("    {} => {{ ... }};\n", span.to_src(cx))
3810                                 }).collect::<String>()),
3811                 imported_from: self.imported_from.clean(cx),
3812             }),
3813         }
3814     }
3815 }
3816
3817 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3818 pub struct ProcMacro {
3819     pub kind: MacroKind,
3820     pub helpers: Vec<String>,
3821 }
3822
3823 impl Clean<Item> for doctree::ProcMacro {
3824     fn clean(&self, cx: &DocContext) -> Item {
3825         Item {
3826             name: Some(self.name.clean(cx)),
3827             attrs: self.attrs.clean(cx),
3828             source: self.whence.clean(cx),
3829             visibility: Some(Public),
3830             stability: self.stab.clean(cx),
3831             deprecation: self.depr.clean(cx),
3832             def_id: cx.tcx.hir().local_def_id(self.id),
3833             inner: ProcMacroItem(ProcMacro {
3834                 kind: self.kind,
3835                 helpers: self.helpers.clean(cx),
3836             }),
3837         }
3838     }
3839 }
3840
3841 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3842 pub struct Stability {
3843     pub level: stability::StabilityLevel,
3844     pub feature: String,
3845     pub since: String,
3846     pub deprecated_since: String,
3847     pub deprecated_reason: String,
3848     pub unstable_reason: String,
3849     pub issue: Option<u32>
3850 }
3851
3852 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3853 pub struct Deprecation {
3854     pub since: String,
3855     pub note: String,
3856 }
3857
3858 impl Clean<Stability> for attr::Stability {
3859     fn clean(&self, _: &DocContext) -> Stability {
3860         Stability {
3861             level: stability::StabilityLevel::from_attr_level(&self.level),
3862             feature: self.feature.to_string(),
3863             since: match self.level {
3864                 attr::Stable {ref since} => since.to_string(),
3865                 _ => String::new(),
3866             },
3867             deprecated_since: match self.rustc_depr {
3868                 Some(attr::RustcDeprecation {ref since, ..}) => since.to_string(),
3869                 _=> String::new(),
3870             },
3871             deprecated_reason: match self.rustc_depr {
3872                 Some(ref depr) => depr.reason.to_string(),
3873                 _ => String::new(),
3874             },
3875             unstable_reason: match self.level {
3876                 attr::Unstable { reason: Some(ref reason), .. } => reason.to_string(),
3877                 _ => String::new(),
3878             },
3879             issue: match self.level {
3880                 attr::Unstable {issue, ..} => Some(issue),
3881                 _ => None,
3882             }
3883         }
3884     }
3885 }
3886
3887 impl<'a> Clean<Stability> for &'a attr::Stability {
3888     fn clean(&self, dc: &DocContext) -> Stability {
3889         (**self).clean(dc)
3890     }
3891 }
3892
3893 impl Clean<Deprecation> for attr::Deprecation {
3894     fn clean(&self, _: &DocContext) -> Deprecation {
3895         Deprecation {
3896             since: self.since.as_ref().map_or(String::new(), |s| s.to_string()),
3897             note: self.note.as_ref().map_or(String::new(), |s| s.to_string()),
3898         }
3899     }
3900 }
3901
3902 /// An equality constraint on an associated type, e.g. `A=Bar` in `Foo<A=Bar>`
3903 #[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug, Hash)]
3904 pub struct TypeBinding {
3905     pub name: String,
3906     pub ty: Type
3907 }
3908
3909 impl Clean<TypeBinding> for hir::TypeBinding {
3910     fn clean(&self, cx: &DocContext) -> TypeBinding {
3911         TypeBinding {
3912             name: self.ident.name.clean(cx),
3913             ty: self.ty.clean(cx)
3914         }
3915     }
3916 }
3917
3918 pub fn def_id_to_path(cx: &DocContext, did: DefId, name: Option<String>) -> Vec<String> {
3919     let crate_name = name.unwrap_or_else(|| cx.tcx.crate_name(did.krate).to_string());
3920     let relative = cx.tcx.def_path(did).data.into_iter().filter_map(|elem| {
3921         // extern blocks have an empty name
3922         let s = elem.data.to_string();
3923         if !s.is_empty() {
3924             Some(s)
3925         } else {
3926             None
3927         }
3928     });
3929     once(crate_name).chain(relative).collect()
3930 }
3931
3932 pub fn enter_impl_trait<F, R>(cx: &DocContext, f: F) -> R
3933 where
3934     F: FnOnce() -> R,
3935 {
3936     let old_bounds = mem::replace(&mut *cx.impl_trait_bounds.borrow_mut(), Default::default());
3937     let r = f();
3938     assert!(cx.impl_trait_bounds.borrow().is_empty());
3939     *cx.impl_trait_bounds.borrow_mut() = old_bounds;
3940     r
3941 }
3942
3943 // Start of code copied from rust-clippy
3944
3945 pub fn path_to_def_local(tcx: &TyCtxt, path: &[&str]) -> Option<DefId> {
3946     let krate = tcx.hir().krate();
3947     let mut items = krate.module.item_ids.clone();
3948     let mut path_it = path.iter().peekable();
3949
3950     loop {
3951         let segment = path_it.next()?;
3952
3953         for item_id in mem::replace(&mut items, HirVec::new()).iter() {
3954             let item = tcx.hir().expect_item(item_id.id);
3955             if item.name == *segment {
3956                 if path_it.peek().is_none() {
3957                     return Some(tcx.hir().local_def_id(item_id.id))
3958                 }
3959
3960                 items = match &item.node {
3961                     &hir::ItemKind::Mod(ref m) => m.item_ids.clone(),
3962                     _ => panic!("Unexpected item {:?} in path {:?} path")
3963                 };
3964                 break;
3965             }
3966         }
3967     }
3968 }
3969
3970 pub fn path_to_def(tcx: &TyCtxt, path: &[&str]) -> Option<DefId> {
3971     let crates = tcx.crates();
3972
3973     let krate = crates
3974         .iter()
3975         .find(|&&krate| tcx.crate_name(krate) == path[0]);
3976
3977     if let Some(krate) = krate {
3978         let krate = DefId {
3979             krate: *krate,
3980             index: CRATE_DEF_INDEX,
3981         };
3982         let mut items = tcx.item_children(krate);
3983         let mut path_it = path.iter().skip(1).peekable();
3984
3985         loop {
3986             let segment = path_it.next()?;
3987
3988             for item in mem::replace(&mut items, Lrc::new(vec![])).iter() {
3989                 if item.ident.name == *segment {
3990                     if path_it.peek().is_none() {
3991                         return match item.def {
3992                             def::Def::Trait(did) => Some(did),
3993                             _ => None,
3994                         }
3995                     }
3996
3997                     items = tcx.item_children(item.def.def_id());
3998                     break;
3999                 }
4000             }
4001         }
4002     } else {
4003         None
4004     }
4005 }
4006
4007 pub fn get_path_for_type<F>(tcx: TyCtxt, def_id: DefId, def_ctor: F) -> hir::Path
4008 where F: Fn(DefId) -> Def {
4009     #[derive(Debug)]
4010     struct AbsolutePathBuffer {
4011         names: Vec<String>,
4012     }
4013
4014     impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer {
4015         fn root_mode(&self) -> &ty::item_path::RootMode {
4016             const ABSOLUTE: &'static ty::item_path::RootMode = &ty::item_path::RootMode::Absolute;
4017             ABSOLUTE
4018         }
4019
4020         fn push(&mut self, text: &str) {
4021             self.names.push(text.to_owned());
4022         }
4023     }
4024
4025     let mut apb = AbsolutePathBuffer { names: vec![] };
4026
4027     tcx.push_item_path(&mut apb, def_id, false);
4028
4029     hir::Path {
4030         span: DUMMY_SP,
4031         def: def_ctor(def_id),
4032         segments: hir::HirVec::from_vec(apb.names.iter().map(|s| hir::PathSegment {
4033             ident: ast::Ident::from_str(&s),
4034             id: None,
4035             def: None,
4036             args: None,
4037             infer_types: false,
4038         }).collect())
4039     }
4040 }
4041
4042 // End of code copied from rust-clippy
4043
4044
4045 #[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
4046 enum RegionTarget<'tcx> {
4047     Region(Region<'tcx>),
4048     RegionVid(RegionVid)
4049 }
4050
4051 #[derive(Default, Debug, Clone)]
4052 struct RegionDeps<'tcx> {
4053     larger: FxHashSet<RegionTarget<'tcx>>,
4054     smaller: FxHashSet<RegionTarget<'tcx>>
4055 }
4056
4057 #[derive(Eq, PartialEq, Hash, Debug)]
4058 enum SimpleBound {
4059     TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier),
4060     Outlives(Lifetime),
4061 }
4062
4063 enum AutoTraitResult {
4064     ExplicitImpl,
4065     PositiveImpl(Generics),
4066     NegativeImpl,
4067 }
4068
4069 impl AutoTraitResult {
4070     fn is_auto(&self) -> bool {
4071         match *self {
4072             AutoTraitResult::PositiveImpl(_) | AutoTraitResult::NegativeImpl => true,
4073             _ => false,
4074         }
4075     }
4076 }
4077
4078 impl From<GenericBound> for SimpleBound {
4079     fn from(bound: GenericBound) -> Self {
4080         match bound.clone() {
4081             GenericBound::Outlives(l) => SimpleBound::Outlives(l),
4082             GenericBound::TraitBound(t, mod_) => match t.trait_ {
4083                 Type::ResolvedPath { path, typarams, .. } => {
4084                     SimpleBound::TraitBound(path.segments,
4085                                             typarams
4086                                                 .map_or_else(|| Vec::new(), |v| v.iter()
4087                                                         .map(|p| SimpleBound::from(p.clone()))
4088                                                         .collect()),
4089                                             t.generic_params,
4090                                             mod_)
4091                 }
4092                 _ => panic!("Unexpected bound {:?}", bound),
4093             }
4094         }
4095     }
4096 }