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