]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/clean/mod.rs
Remove clean::Mutability enum
[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 pub mod utils;
7 mod auto_trait;
8 mod blanket_impl;
9 mod simplify;
10 pub mod types;
11
12 use rustc_index::vec::{IndexVec, Idx};
13 use rustc_typeck::hir_ty_to_ty;
14 use rustc::infer::region_constraints::{RegionConstraintData, Constraint};
15 use rustc::middle::resolve_lifetime as rl;
16 use rustc::middle::lang_items;
17 use rustc::middle::stability;
18 use rustc::mir::interpret::GlobalId;
19 use rustc::hir;
20 use rustc::hir::def::{CtorKind, DefKind, Res};
21 use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
22 use rustc::hir::ptr::P;
23 use rustc::ty::subst::InternalSubsts;
24 use rustc::ty::{self, TyCtxt, Ty, AdtKind};
25 use rustc::ty::fold::TypeFolder;
26 use rustc::util::nodemap::{FxHashMap, FxHashSet};
27 use syntax::ast::{self, Ident};
28 use syntax::attr;
29 use syntax_pos::symbol::{kw, sym};
30 use syntax_pos::hygiene::MacroKind;
31 use syntax_pos::{self, Pos};
32
33 use std::collections::hash_map::Entry;
34 use std::hash::Hash;
35 use std::default::Default;
36 use std::{mem, vec};
37 use std::rc::Rc;
38 use std::u32;
39
40 use crate::core::{self, DocContext, ImplTraitParam};
41 use crate::doctree;
42
43 use utils::*;
44
45 pub use utils::{get_auto_trait_and_blanket_impls, krate, register_res};
46
47 pub use self::types::*;
48 pub use self::types::Type::*;
49 pub use self::types::ItemEnum::*;
50 pub use self::types::SelfTy::*;
51 pub use self::types::FunctionRetTy::*;
52 pub use self::types::Visibility::{Public, Inherited};
53
54 const FN_OUTPUT_NAME: &'static str = "Output";
55
56 pub trait Clean<T> {
57     fn clean(&self, cx: &DocContext<'_>) -> T;
58 }
59
60 impl<T: Clean<U>, U> Clean<Vec<U>> for [T] {
61     fn clean(&self, cx: &DocContext<'_>) -> Vec<U> {
62         self.iter().map(|x| x.clean(cx)).collect()
63     }
64 }
65
66 impl<T: Clean<U>, U, V: Idx> Clean<IndexVec<V, U>> for IndexVec<V, T> {
67     fn clean(&self, cx: &DocContext<'_>) -> IndexVec<V, U> {
68         self.iter().map(|x| x.clean(cx)).collect()
69     }
70 }
71
72 impl<T: Clean<U>, U> Clean<U> for P<T> {
73     fn clean(&self, cx: &DocContext<'_>) -> U {
74         (**self).clean(cx)
75     }
76 }
77
78 impl<T: Clean<U>, U> Clean<U> for Rc<T> {
79     fn clean(&self, cx: &DocContext<'_>) -> U {
80         (**self).clean(cx)
81     }
82 }
83
84 impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
85     fn clean(&self, cx: &DocContext<'_>) -> Option<U> {
86         self.as_ref().map(|v| v.clean(cx))
87     }
88 }
89
90 impl<T, U> Clean<U> for ty::Binder<T> where T: Clean<U> {
91     fn clean(&self, cx: &DocContext<'_>) -> U {
92         self.skip_binder().clean(cx)
93     }
94 }
95
96 impl<T: Clean<U>, U> Clean<Vec<U>> for P<[T]> {
97     fn clean(&self, cx: &DocContext<'_>) -> Vec<U> {
98         self.iter().map(|x| x.clean(cx)).collect()
99     }
100 }
101
102 impl Clean<ExternalCrate> for CrateNum {
103     fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate {
104         let root = DefId { krate: *self, index: CRATE_DEF_INDEX };
105         let krate_span = cx.tcx.def_span(root);
106         let krate_src = cx.sess().source_map().span_to_filename(krate_span);
107
108         // Collect all inner modules which are tagged as implementations of
109         // primitives.
110         //
111         // Note that this loop only searches the top-level items of the crate,
112         // and this is intentional. If we were to search the entire crate for an
113         // item tagged with `#[doc(primitive)]` then we would also have to
114         // search the entirety of external modules for items tagged
115         // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
116         // all that metadata unconditionally).
117         //
118         // In order to keep the metadata load under control, the
119         // `#[doc(primitive)]` feature is explicitly designed to only allow the
120         // primitive tags to show up as the top level items in a crate.
121         //
122         // Also note that this does not attempt to deal with modules tagged
123         // duplicately for the same primitive. This is handled later on when
124         // rendering by delegating everything to a hash map.
125         let as_primitive = |res: Res| {
126             if let Res::Def(DefKind::Mod, def_id) = res {
127                 let attrs = cx.tcx.get_attrs(def_id).clean(cx);
128                 let mut prim = None;
129                 for attr in attrs.lists(sym::doc) {
130                     if let Some(v) = attr.value_str() {
131                         if attr.check_name(sym::primitive) {
132                             prim = PrimitiveType::from_str(&v.as_str());
133                             if prim.is_some() {
134                                 break;
135                             }
136                             // FIXME: should warn on unknown primitives?
137                         }
138                     }
139                 }
140                 return prim.map(|p| (def_id, p, attrs));
141             }
142             None
143         };
144         let primitives = if root.is_local() {
145             cx.tcx.hir().krate().module.item_ids.iter().filter_map(|&id| {
146                 let item = cx.tcx.hir().expect_item(id.id);
147                 match item.kind {
148                     hir::ItemKind::Mod(_) => {
149                         as_primitive(Res::Def(
150                             DefKind::Mod,
151                             cx.tcx.hir().local_def_id(id.id),
152                         ))
153                     }
154                     hir::ItemKind::Use(ref path, hir::UseKind::Single)
155                     if item.vis.node.is_pub() => {
156                         as_primitive(path.res).map(|(_, prim, attrs)| {
157                             // Pretend the primitive is local.
158                             (cx.tcx.hir().local_def_id(id.id), prim, attrs)
159                         })
160                     }
161                     _ => None
162                 }
163             }).collect()
164         } else {
165             cx.tcx.item_children(root).iter().map(|item| item.res)
166               .filter_map(as_primitive).collect()
167         };
168
169         let as_keyword = |res: Res| {
170             if let Res::Def(DefKind::Mod, def_id) = res {
171                 let attrs = cx.tcx.get_attrs(def_id).clean(cx);
172                 let mut keyword = None;
173                 for attr in attrs.lists(sym::doc) {
174                     if let Some(v) = attr.value_str() {
175                         if attr.check_name(sym::keyword) {
176                             if v.is_doc_keyword() {
177                                 keyword = Some(v.to_string());
178                                 break;
179                             }
180                             // FIXME: should warn on unknown keywords?
181                         }
182                     }
183                 }
184                 return keyword.map(|p| (def_id, p, attrs));
185             }
186             None
187         };
188         let keywords = if root.is_local() {
189             cx.tcx.hir().krate().module.item_ids.iter().filter_map(|&id| {
190                 let item = cx.tcx.hir().expect_item(id.id);
191                 match item.kind {
192                     hir::ItemKind::Mod(_) => {
193                         as_keyword(Res::Def(
194                             DefKind::Mod,
195                             cx.tcx.hir().local_def_id(id.id),
196                         ))
197                     }
198                     hir::ItemKind::Use(ref path, hir::UseKind::Single)
199                     if item.vis.node.is_pub() => {
200                         as_keyword(path.res).map(|(_, prim, attrs)| {
201                             (cx.tcx.hir().local_def_id(id.id), prim, attrs)
202                         })
203                     }
204                     _ => None
205                 }
206             }).collect()
207         } else {
208             cx.tcx.item_children(root).iter().map(|item| item.res)
209               .filter_map(as_keyword).collect()
210         };
211
212         ExternalCrate {
213             name: cx.tcx.crate_name(*self).to_string(),
214             src: krate_src,
215             attrs: cx.tcx.get_attrs(root).clean(cx),
216             primitives,
217             keywords,
218         }
219     }
220 }
221
222 impl Clean<Item> for doctree::Module<'_> {
223     fn clean(&self, cx: &DocContext<'_>) -> Item {
224         let name = if self.name.is_some() {
225             self.name.expect("No name provided").clean(cx)
226         } else {
227             String::new()
228         };
229
230         // maintain a stack of mod ids, for doc comment path resolution
231         // but we also need to resolve the module's own docs based on whether its docs were written
232         // inside or outside the module, so check for that
233         let attrs = self.attrs.clean(cx);
234
235         let mut items: Vec<Item> = vec![];
236         items.extend(self.extern_crates.iter().flat_map(|x| x.clean(cx)));
237         items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
238         items.extend(self.structs.iter().map(|x| x.clean(cx)));
239         items.extend(self.unions.iter().map(|x| x.clean(cx)));
240         items.extend(self.enums.iter().map(|x| x.clean(cx)));
241         items.extend(self.fns.iter().map(|x| x.clean(cx)));
242         items.extend(self.foreigns.iter().map(|x| x.clean(cx)));
243         items.extend(self.mods.iter().map(|x| x.clean(cx)));
244         items.extend(self.typedefs.iter().map(|x| x.clean(cx)));
245         items.extend(self.opaque_tys.iter().map(|x| x.clean(cx)));
246         items.extend(self.statics.iter().map(|x| x.clean(cx)));
247         items.extend(self.constants.iter().map(|x| x.clean(cx)));
248         items.extend(self.traits.iter().map(|x| x.clean(cx)));
249         items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
250         items.extend(self.macros.iter().map(|x| x.clean(cx)));
251         items.extend(self.proc_macros.iter().map(|x| x.clean(cx)));
252         items.extend(self.trait_aliases.iter().map(|x| x.clean(cx)));
253
254         // determine if we should display the inner contents or
255         // the outer `mod` item for the source code.
256         let whence = {
257             let cm = cx.sess().source_map();
258             let outer = cm.lookup_char_pos(self.where_outer.lo());
259             let inner = cm.lookup_char_pos(self.where_inner.lo());
260             if outer.file.start_pos == inner.file.start_pos {
261                 // mod foo { ... }
262                 self.where_outer
263             } else {
264                 // mod foo; (and a separate SourceFile for the contents)
265                 self.where_inner
266             }
267         };
268
269         Item {
270             name: Some(name),
271             attrs,
272             source: whence.clean(cx),
273             visibility: self.vis.clean(cx),
274             stability: cx.stability(self.id).clean(cx),
275             deprecation: cx.deprecation(self.id).clean(cx),
276             def_id: cx.tcx.hir().local_def_id(self.id),
277             inner: ModuleItem(Module {
278                is_crate: self.is_crate,
279                items,
280             })
281         }
282     }
283 }
284
285 impl Clean<Attributes> for [ast::Attribute] {
286     fn clean(&self, cx: &DocContext<'_>) -> Attributes {
287         Attributes::from_ast(cx.sess().diagnostic(), self)
288     }
289 }
290
291 impl Clean<GenericBound> for hir::GenericBound {
292     fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
293         match *self {
294             hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)),
295             hir::GenericBound::Trait(ref t, modifier) => {
296                 GenericBound::TraitBound(t.clean(cx), modifier)
297             }
298         }
299     }
300 }
301
302 impl<'a, 'tcx> Clean<GenericBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>) {
303     fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
304         let (trait_ref, ref bounds) = *self;
305         inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait);
306         let path = external_path(cx, cx.tcx.item_name(trait_ref.def_id),
307                                  Some(trait_ref.def_id), true, bounds.clone(), trait_ref.substs);
308
309         debug!("ty::TraitRef\n  subst: {:?}\n", trait_ref.substs);
310
311         // collect any late bound regions
312         let mut late_bounds = vec![];
313         for ty_s in trait_ref.input_types().skip(1) {
314             if let ty::Tuple(ts) = ty_s.kind {
315                 for &ty_s in ts {
316                     if let ty::Ref(ref reg, _, _) = ty_s.expect_ty().kind {
317                         if let &ty::RegionKind::ReLateBound(..) = *reg {
318                             debug!("  hit an ReLateBound {:?}", reg);
319                             if let Some(Lifetime(name)) = reg.clean(cx) {
320                                 late_bounds.push(GenericParamDef {
321                                     name,
322                                     kind: GenericParamDefKind::Lifetime,
323                                 });
324                             }
325                         }
326                     }
327                 }
328             }
329         }
330
331         GenericBound::TraitBound(
332             PolyTrait {
333                 trait_: ResolvedPath {
334                     path,
335                     param_names: None,
336                     did: trait_ref.def_id,
337                     is_generic: false,
338                 },
339                 generic_params: late_bounds,
340             },
341             hir::TraitBoundModifier::None
342         )
343     }
344 }
345
346 impl<'tcx> Clean<GenericBound> for ty::TraitRef<'tcx> {
347     fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
348         (self, vec![]).clean(cx)
349     }
350 }
351
352 impl<'tcx> Clean<Option<Vec<GenericBound>>> for InternalSubsts<'tcx> {
353     fn clean(&self, cx: &DocContext<'_>) -> Option<Vec<GenericBound>> {
354         let mut v = Vec::new();
355         v.extend(self.regions().filter_map(|r| r.clean(cx)).map(GenericBound::Outlives));
356         v.extend(self.types().map(|t| GenericBound::TraitBound(PolyTrait {
357             trait_: t.clean(cx),
358             generic_params: Vec::new(),
359         }, hir::TraitBoundModifier::None)));
360         if !v.is_empty() {Some(v)} else {None}
361     }
362 }
363
364 impl Clean<Lifetime> for hir::Lifetime {
365     fn clean(&self, cx: &DocContext<'_>) -> Lifetime {
366         if self.hir_id != hir::DUMMY_HIR_ID {
367             let def = cx.tcx.named_region(self.hir_id);
368             match def {
369                 Some(rl::Region::EarlyBound(_, node_id, _)) |
370                 Some(rl::Region::LateBound(_, node_id, _)) |
371                 Some(rl::Region::Free(_, node_id)) => {
372                     if let Some(lt) = cx.lt_substs.borrow().get(&node_id).cloned() {
373                         return lt;
374                     }
375                 }
376                 _ => {}
377             }
378         }
379         Lifetime(self.name.ident().to_string())
380     }
381 }
382
383 impl Clean<Lifetime> for hir::GenericParam {
384     fn clean(&self, _: &DocContext<'_>) -> Lifetime {
385         match self.kind {
386             hir::GenericParamKind::Lifetime { .. } => {
387                 if self.bounds.len() > 0 {
388                     let mut bounds = self.bounds.iter().map(|bound| match bound {
389                         hir::GenericBound::Outlives(lt) => lt,
390                         _ => panic!(),
391                     });
392                     let name = bounds.next().expect("no more bounds").name.ident();
393                     let mut s = format!("{}: {}", self.name.ident(), name);
394                     for bound in bounds {
395                         s.push_str(&format!(" + {}", bound.name.ident()));
396                     }
397                     Lifetime(s)
398                 } else {
399                     Lifetime(self.name.ident().to_string())
400                 }
401             }
402             _ => panic!(),
403         }
404     }
405 }
406
407 impl Clean<Constant> for hir::ConstArg {
408     fn clean(&self, cx: &DocContext<'_>) -> Constant {
409         Constant {
410             type_: cx.tcx.type_of(cx.tcx.hir().body_owner_def_id(self.value.body)).clean(cx),
411             expr: print_const_expr(cx, self.value.body),
412         }
413     }
414 }
415
416 impl Clean<Lifetime> for ty::GenericParamDef {
417     fn clean(&self, _cx: &DocContext<'_>) -> Lifetime {
418         Lifetime(self.name.to_string())
419     }
420 }
421
422 impl Clean<Option<Lifetime>> for ty::RegionKind {
423     fn clean(&self, cx: &DocContext<'_>) -> Option<Lifetime> {
424         match *self {
425             ty::ReStatic => Some(Lifetime::statik()),
426             ty::ReLateBound(_, ty::BrNamed(_, name)) => Some(Lifetime(name.to_string())),
427             ty::ReEarlyBound(ref data) => Some(Lifetime(data.name.clean(cx))),
428
429             ty::ReLateBound(..) |
430             ty::ReFree(..) |
431             ty::ReScope(..) |
432             ty::ReVar(..) |
433             ty::RePlaceholder(..) |
434             ty::ReEmpty |
435             ty::ReClosureBound(_) |
436             ty::ReErased => {
437                 debug!("cannot clean region {:?}", self);
438                 None
439             }
440         }
441     }
442 }
443
444 impl Clean<WherePredicate> for hir::WherePredicate {
445     fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
446         match *self {
447             hir::WherePredicate::BoundPredicate(ref wbp) => {
448                 WherePredicate::BoundPredicate {
449                     ty: wbp.bounded_ty.clean(cx),
450                     bounds: wbp.bounds.clean(cx)
451                 }
452             }
453
454             hir::WherePredicate::RegionPredicate(ref wrp) => {
455                 WherePredicate::RegionPredicate {
456                     lifetime: wrp.lifetime.clean(cx),
457                     bounds: wrp.bounds.clean(cx)
458                 }
459             }
460
461             hir::WherePredicate::EqPredicate(ref wrp) => {
462                 WherePredicate::EqPredicate {
463                     lhs: wrp.lhs_ty.clean(cx),
464                     rhs: wrp.rhs_ty.clean(cx)
465                 }
466             }
467         }
468     }
469 }
470
471 impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
472     fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
473         use rustc::ty::Predicate;
474
475         match *self {
476             Predicate::Trait(ref pred) => Some(pred.clean(cx)),
477             Predicate::Subtype(ref pred) => Some(pred.clean(cx)),
478             Predicate::RegionOutlives(ref pred) => pred.clean(cx),
479             Predicate::TypeOutlives(ref pred) => pred.clean(cx),
480             Predicate::Projection(ref pred) => Some(pred.clean(cx)),
481
482             Predicate::WellFormed(..) |
483             Predicate::ObjectSafe(..) |
484             Predicate::ClosureKind(..) |
485             Predicate::ConstEvaluatable(..) => panic!("not user writable"),
486         }
487     }
488 }
489
490 impl<'a> Clean<WherePredicate> for ty::TraitPredicate<'a> {
491     fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
492         WherePredicate::BoundPredicate {
493             ty: self.trait_ref.self_ty().clean(cx),
494             bounds: vec![self.trait_ref.clean(cx)]
495         }
496     }
497 }
498
499 impl<'tcx> Clean<WherePredicate> for ty::SubtypePredicate<'tcx> {
500     fn clean(&self, _cx: &DocContext<'_>) -> WherePredicate {
501         panic!("subtype predicates are an internal rustc artifact \
502                 and should not be seen by rustdoc")
503     }
504 }
505
506 impl<'tcx> Clean<Option<WherePredicate>> for
507     ty::OutlivesPredicate<ty::Region<'tcx>,ty::Region<'tcx>> {
508
509     fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
510         let ty::OutlivesPredicate(ref a, ref b) = *self;
511
512         match (a, b) {
513             (ty::ReEmpty, ty::ReEmpty) => {
514                 return None;
515             },
516             _ => {}
517         }
518
519         Some(WherePredicate::RegionPredicate {
520             lifetime: a.clean(cx).expect("failed to clean lifetime"),
521             bounds: vec![GenericBound::Outlives(b.clean(cx).expect("failed to clean bounds"))]
522         })
523     }
524 }
525
526 impl<'tcx> Clean<Option<WherePredicate>> for ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>> {
527     fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
528         let ty::OutlivesPredicate(ref ty, ref lt) = *self;
529
530         match lt {
531             ty::ReEmpty => return None,
532             _ => {}
533         }
534
535         Some(WherePredicate::BoundPredicate {
536             ty: ty.clean(cx),
537             bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))]
538         })
539     }
540 }
541
542 impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
543     fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
544         WherePredicate::EqPredicate {
545             lhs: self.projection_ty.clean(cx),
546             rhs: self.ty.clean(cx)
547         }
548     }
549 }
550
551 impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
552     fn clean(&self, cx: &DocContext<'_>) -> Type {
553         let trait_ = match self.trait_ref(cx.tcx).clean(cx) {
554             GenericBound::TraitBound(t, _) => t.trait_,
555             GenericBound::Outlives(_) => panic!("cleaning a trait got a lifetime"),
556         };
557         Type::QPath {
558             name: cx.tcx.associated_item(self.item_def_id).ident.name.clean(cx),
559             self_type: box self.self_ty().clean(cx),
560             trait_: box trait_
561         }
562     }
563 }
564
565 impl Clean<GenericParamDef> for ty::GenericParamDef {
566     fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
567         let (name, kind) = match self.kind {
568             ty::GenericParamDefKind::Lifetime => {
569                 (self.name.to_string(), GenericParamDefKind::Lifetime)
570             }
571             ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
572                 let default = if has_default {
573                     Some(cx.tcx.type_of(self.def_id).clean(cx))
574                 } else {
575                     None
576                 };
577                 (self.name.clean(cx), GenericParamDefKind::Type {
578                     did: self.def_id,
579                     bounds: vec![], // These are filled in from the where-clauses.
580                     default,
581                     synthetic,
582                 })
583             }
584             ty::GenericParamDefKind::Const { .. } => {
585                 (self.name.clean(cx), GenericParamDefKind::Const {
586                     did: self.def_id,
587                     ty: cx.tcx.type_of(self.def_id).clean(cx),
588                 })
589             }
590         };
591
592         GenericParamDef {
593             name,
594             kind,
595         }
596     }
597 }
598
599 impl Clean<GenericParamDef> for hir::GenericParam {
600     fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
601         let (name, kind) = match self.kind {
602             hir::GenericParamKind::Lifetime { .. } => {
603                 let name = if self.bounds.len() > 0 {
604                     let mut bounds = self.bounds.iter().map(|bound| match bound {
605                         hir::GenericBound::Outlives(lt) => lt,
606                         _ => panic!(),
607                     });
608                     let name = bounds.next().expect("no more bounds").name.ident();
609                     let mut s = format!("{}: {}", self.name.ident(), name);
610                     for bound in bounds {
611                         s.push_str(&format!(" + {}", bound.name.ident()));
612                     }
613                     s
614                 } else {
615                     self.name.ident().to_string()
616                 };
617                 (name, GenericParamDefKind::Lifetime)
618             }
619             hir::GenericParamKind::Type { ref default, synthetic } => {
620                 (self.name.ident().name.clean(cx), GenericParamDefKind::Type {
621                     did: cx.tcx.hir().local_def_id(self.hir_id),
622                     bounds: self.bounds.clean(cx),
623                     default: default.clean(cx),
624                     synthetic,
625                 })
626             }
627             hir::GenericParamKind::Const { ref ty } => {
628                 (self.name.ident().name.clean(cx), GenericParamDefKind::Const {
629                     did: cx.tcx.hir().local_def_id(self.hir_id),
630                     ty: ty.clean(cx),
631                 })
632             }
633         };
634
635         GenericParamDef {
636             name,
637             kind,
638         }
639     }
640 }
641
642 impl Clean<Generics> for hir::Generics {
643     fn clean(&self, cx: &DocContext<'_>) -> Generics {
644         // Synthetic type-parameters are inserted after normal ones.
645         // In order for normal parameters to be able to refer to synthetic ones,
646         // scans them first.
647         fn is_impl_trait(param: &hir::GenericParam) -> bool {
648             match param.kind {
649                 hir::GenericParamKind::Type { synthetic, .. } => {
650                     synthetic == Some(hir::SyntheticTyParamKind::ImplTrait)
651                 }
652                 _ => false,
653             }
654         }
655         let impl_trait_params = self.params
656             .iter()
657             .filter(|param| is_impl_trait(param))
658             .map(|param| {
659                 let param: GenericParamDef = param.clean(cx);
660                 match param.kind {
661                     GenericParamDefKind::Lifetime => unreachable!(),
662                     GenericParamDefKind::Type { did, ref bounds, .. } => {
663                         cx.impl_trait_bounds.borrow_mut().insert(did.into(), bounds.clone());
664                     }
665                     GenericParamDefKind::Const { .. } => unreachable!(),
666                 }
667                 param
668             })
669             .collect::<Vec<_>>();
670
671         let mut params = Vec::with_capacity(self.params.len());
672         for p in self.params.iter().filter(|p| !is_impl_trait(p)) {
673             let p = p.clean(cx);
674             params.push(p);
675         }
676         params.extend(impl_trait_params);
677
678         let mut generics = Generics {
679             params,
680             where_predicates: self.where_clause.predicates.clean(cx),
681         };
682
683         // Some duplicates are generated for ?Sized bounds between type params and where
684         // predicates. The point in here is to move the bounds definitions from type params
685         // to where predicates when such cases occur.
686         for where_pred in &mut generics.where_predicates {
687             match *where_pred {
688                 WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => {
689                     if bounds.is_empty() {
690                         for param in &mut generics.params {
691                             match param.kind {
692                                 GenericParamDefKind::Lifetime => {}
693                                 GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
694                                     if &param.name == name {
695                                         mem::swap(bounds, ty_bounds);
696                                         break
697                                     }
698                                 }
699                                 GenericParamDefKind::Const { .. } => {}
700                             }
701                         }
702                     }
703                 }
704                 _ => continue,
705             }
706         }
707         generics
708     }
709 }
710
711 impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx>) {
712     fn clean(&self, cx: &DocContext<'_>) -> Generics {
713         use self::WherePredicate as WP;
714         use std::collections::BTreeMap;
715
716         let (gens, preds) = *self;
717
718         // Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
719         // since `Clean for ty::Predicate` would consume them.
720         let mut impl_trait = BTreeMap::<ImplTraitParam, Vec<GenericBound>>::default();
721
722         // Bounds in the type_params and lifetimes fields are repeated in the
723         // predicates field (see rustc_typeck::collect::ty_generics), so remove
724         // them.
725         let stripped_typarams = gens.params.iter()
726             .filter_map(|param| match param.kind {
727                 ty::GenericParamDefKind::Lifetime => None,
728                 ty::GenericParamDefKind::Type { synthetic, .. } => {
729                     if param.name == kw::SelfUpper {
730                         assert_eq!(param.index, 0);
731                         return None;
732                     }
733                     if synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) {
734                         impl_trait.insert(param.index.into(), vec![]);
735                         return None;
736                     }
737                     Some(param.clean(cx))
738                 }
739                 ty::GenericParamDefKind::Const { .. } => None,
740             }).collect::<Vec<GenericParamDef>>();
741
742         // param index -> [(DefId of trait, associated type name, type)]
743         let mut impl_trait_proj =
744             FxHashMap::<u32, Vec<(DefId, String, Ty<'tcx>)>>::default();
745
746         let where_predicates = preds.predicates.iter()
747             .flat_map(|(p, _)| {
748                 let mut projection = None;
749                 let param_idx = (|| {
750                     if let Some(trait_ref) = p.to_opt_poly_trait_ref() {
751                         if let ty::Param(param) = trait_ref.self_ty().kind {
752                             return Some(param.index);
753                         }
754                     } else if let Some(outlives) = p.to_opt_type_outlives() {
755                         if let ty::Param(param) = outlives.skip_binder().0.kind {
756                             return Some(param.index);
757                         }
758                     } else if let ty::Predicate::Projection(p) = p {
759                         if let ty::Param(param) = p.skip_binder().projection_ty.self_ty().kind {
760                             projection = Some(p);
761                             return Some(param.index);
762                         }
763                     }
764
765                     None
766                 })();
767
768                 if let Some(param_idx) = param_idx {
769                     if let Some(b) = impl_trait.get_mut(&param_idx.into()) {
770                         let p = p.clean(cx)?;
771
772                         b.extend(
773                             p.get_bounds()
774                                 .into_iter()
775                                 .flatten()
776                                 .cloned()
777                                 .filter(|b| !b.is_sized_bound(cx))
778                         );
779
780                         let proj = projection
781                             .map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().ty));
782                         if let Some(((_, trait_did, name), rhs)) =
783                             proj.as_ref().and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs)))
784                         {
785                             impl_trait_proj
786                                 .entry(param_idx)
787                                 .or_default()
788                                 .push((trait_did, name.to_string(), rhs));
789                         }
790
791                         return None;
792                     }
793                 }
794
795                 Some(p)
796             })
797             .collect::<Vec<_>>();
798
799         for (param, mut bounds) in impl_trait {
800             // Move trait bounds to the front.
801             bounds.sort_by_key(|b| if let GenericBound::TraitBound(..) = b {
802                 false
803             } else {
804                 true
805             });
806
807             if let crate::core::ImplTraitParam::ParamIndex(idx) = param {
808                 if let Some(proj) = impl_trait_proj.remove(&idx) {
809                     for (trait_did, name, rhs) in proj {
810                         simplify::merge_bounds(
811                             cx,
812                             &mut bounds,
813                             trait_did,
814                             &name,
815                             &rhs.clean(cx),
816                         );
817                     }
818                 }
819             } else {
820                 unreachable!();
821             }
822
823             cx.impl_trait_bounds.borrow_mut().insert(param, bounds);
824         }
825
826         // Now that `cx.impl_trait_bounds` is populated, we can process
827         // remaining predicates which could contain `impl Trait`.
828         let mut where_predicates = where_predicates
829             .into_iter()
830             .flat_map(|p| p.clean(cx))
831             .collect::<Vec<_>>();
832
833         // Type parameters and have a Sized bound by default unless removed with
834         // ?Sized. Scan through the predicates and mark any type parameter with
835         // a Sized bound, removing the bounds as we find them.
836         //
837         // Note that associated types also have a sized bound by default, but we
838         // don't actually know the set of associated types right here so that's
839         // handled in cleaning associated types
840         let mut sized_params = FxHashSet::default();
841         where_predicates.retain(|pred| {
842             match *pred {
843                 WP::BoundPredicate { ty: Generic(ref g), ref bounds } => {
844                     if bounds.iter().any(|b| b.is_sized_bound(cx)) {
845                         sized_params.insert(g.clone());
846                         false
847                     } else {
848                         true
849                     }
850                 }
851                 _ => true,
852             }
853         });
854
855         // Run through the type parameters again and insert a ?Sized
856         // unbound for any we didn't find to be Sized.
857         for tp in &stripped_typarams {
858             if !sized_params.contains(&tp.name) {
859                 where_predicates.push(WP::BoundPredicate {
860                     ty: Type::Generic(tp.name.clone()),
861                     bounds: vec![GenericBound::maybe_sized(cx)],
862                 })
863             }
864         }
865
866         // It would be nice to collect all of the bounds on a type and recombine
867         // them if possible, to avoid e.g., `where T: Foo, T: Bar, T: Sized, T: 'a`
868         // and instead see `where T: Foo + Bar + Sized + 'a`
869
870         Generics {
871             params: gens.params
872                         .iter()
873                         .flat_map(|param| match param.kind {
874                             ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
875                             ty::GenericParamDefKind::Type { .. } => None,
876                             ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)),
877                         }).chain(simplify::ty_params(stripped_typarams).into_iter())
878                         .collect(),
879             where_predicates: simplify::where_clauses(cx, where_predicates),
880         }
881     }
882 }
883
884 impl<'a> Clean<Method> for (&'a hir::FnSig, &'a hir::Generics, hir::BodyId,
885                             Option<hir::Defaultness>) {
886     fn clean(&self, cx: &DocContext<'_>) -> Method {
887         let (generics, decl) = enter_impl_trait(cx, || {
888             (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx))
889         });
890         let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
891         Method {
892             decl,
893             generics,
894             header: self.0.header,
895             defaultness: self.3,
896             all_types,
897             ret_types,
898         }
899     }
900 }
901
902 impl Clean<Item> for doctree::Function<'_> {
903     fn clean(&self, cx: &DocContext<'_>) -> Item {
904         let (generics, decl) = enter_impl_trait(cx, || {
905             (self.generics.clean(cx), (self.decl, self.body).clean(cx))
906         });
907
908         let did = cx.tcx.hir().local_def_id(self.id);
909         let constness = if cx.tcx.is_min_const_fn(did) {
910             hir::Constness::Const
911         } else {
912             hir::Constness::NotConst
913         };
914         let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
915         Item {
916             name: Some(self.name.clean(cx)),
917             attrs: self.attrs.clean(cx),
918             source: self.whence.clean(cx),
919             visibility: self.vis.clean(cx),
920             stability: cx.stability(self.id).clean(cx),
921             deprecation: cx.deprecation(self.id).clean(cx),
922             def_id: did,
923             inner: FunctionItem(Function {
924                 decl,
925                 generics,
926                 header: hir::FnHeader { constness, ..self.header },
927                 all_types,
928                 ret_types,
929             }),
930         }
931     }
932 }
933
934 impl<'a> Clean<Arguments> for (&'a [hir::Ty], &'a [ast::Ident]) {
935     fn clean(&self, cx: &DocContext<'_>) -> Arguments {
936         Arguments {
937             values: self.0.iter().enumerate().map(|(i, ty)| {
938                 let mut name = self.1.get(i).map(|ident| ident.to_string())
939                                             .unwrap_or(String::new());
940                 if name.is_empty() {
941                     name = "_".to_string();
942                 }
943                 Argument {
944                     name,
945                     type_: ty.clean(cx),
946                 }
947             }).collect()
948         }
949     }
950 }
951
952 impl<'a> Clean<Arguments> for (&'a [hir::Ty], hir::BodyId) {
953     fn clean(&self, cx: &DocContext<'_>) -> Arguments {
954         let body = cx.tcx.hir().body(self.1);
955
956         Arguments {
957             values: self.0.iter().enumerate().map(|(i, ty)| {
958                 Argument {
959                     name: name_from_pat(&body.params[i].pat),
960                     type_: ty.clean(cx),
961                 }
962             }).collect()
963         }
964     }
965 }
966
967 impl<'a, A: Copy> Clean<FnDecl> for (&'a hir::FnDecl, A)
968     where (&'a [hir::Ty], A): Clean<Arguments>
969 {
970     fn clean(&self, cx: &DocContext<'_>) -> FnDecl {
971         FnDecl {
972             inputs: (&self.0.inputs[..], self.1).clean(cx),
973             output: self.0.output.clean(cx),
974             c_variadic: self.0.c_variadic,
975             attrs: Attributes::default(),
976         }
977     }
978 }
979
980 impl<'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
981     fn clean(&self, cx: &DocContext<'_>) -> FnDecl {
982         let (did, sig) = *self;
983         let mut names = if cx.tcx.hir().as_local_hir_id(did).is_some() {
984             vec![].into_iter()
985         } else {
986             cx.tcx.fn_arg_names(did).into_iter()
987         };
988
989         FnDecl {
990             output: Return(sig.skip_binder().output().clean(cx)),
991             attrs: Attributes::default(),
992             c_variadic: sig.skip_binder().c_variadic,
993             inputs: Arguments {
994                 values: sig.skip_binder().inputs().iter().map(|t| {
995                     Argument {
996                         type_: t.clean(cx),
997                         name: names.next().map_or(String::new(), |name| name.to_string()),
998                     }
999                 }).collect(),
1000             },
1001         }
1002     }
1003 }
1004
1005 impl Clean<FunctionRetTy> for hir::FunctionRetTy {
1006     fn clean(&self, cx: &DocContext<'_>) -> FunctionRetTy {
1007         match *self {
1008             hir::Return(ref typ) => Return(typ.clean(cx)),
1009             hir::DefaultReturn(..) => DefaultReturn,
1010         }
1011     }
1012 }
1013
1014 impl Clean<Item> for doctree::Trait<'_> {
1015     fn clean(&self, cx: &DocContext<'_>) -> Item {
1016         let attrs = self.attrs.clean(cx);
1017         let is_spotlight = attrs.has_doc_flag(sym::spotlight);
1018         Item {
1019             name: Some(self.name.clean(cx)),
1020             attrs,
1021             source: self.whence.clean(cx),
1022             def_id: cx.tcx.hir().local_def_id(self.id),
1023             visibility: self.vis.clean(cx),
1024             stability: cx.stability(self.id).clean(cx),
1025             deprecation: cx.deprecation(self.id).clean(cx),
1026             inner: TraitItem(Trait {
1027                 auto: self.is_auto.clean(cx),
1028                 unsafety: self.unsafety,
1029                 items: self.items.iter().map(|ti| ti.clean(cx)).collect(),
1030                 generics: self.generics.clean(cx),
1031                 bounds: self.bounds.clean(cx),
1032                 is_spotlight,
1033                 is_auto: self.is_auto.clean(cx),
1034             }),
1035         }
1036     }
1037 }
1038
1039 impl Clean<Item> for doctree::TraitAlias<'_> {
1040     fn clean(&self, cx: &DocContext<'_>) -> Item {
1041         let attrs = self.attrs.clean(cx);
1042         Item {
1043             name: Some(self.name.clean(cx)),
1044             attrs,
1045             source: self.whence.clean(cx),
1046             def_id: cx.tcx.hir().local_def_id(self.id),
1047             visibility: self.vis.clean(cx),
1048             stability: cx.stability(self.id).clean(cx),
1049             deprecation: cx.deprecation(self.id).clean(cx),
1050             inner: TraitAliasItem(TraitAlias {
1051                 generics: self.generics.clean(cx),
1052                 bounds: self.bounds.clean(cx),
1053             }),
1054         }
1055     }
1056 }
1057
1058 impl Clean<bool> for hir::IsAuto {
1059     fn clean(&self, _: &DocContext<'_>) -> bool {
1060         match *self {
1061             hir::IsAuto::Yes => true,
1062             hir::IsAuto::No => false,
1063         }
1064     }
1065 }
1066
1067 impl Clean<Type> for hir::TraitRef {
1068     fn clean(&self, cx: &DocContext<'_>) -> Type {
1069         resolve_type(cx, self.path.clean(cx), self.hir_ref_id)
1070     }
1071 }
1072
1073 impl Clean<PolyTrait> for hir::PolyTraitRef {
1074     fn clean(&self, cx: &DocContext<'_>) -> PolyTrait {
1075         PolyTrait {
1076             trait_: self.trait_ref.clean(cx),
1077             generic_params: self.bound_generic_params.clean(cx)
1078         }
1079     }
1080 }
1081
1082 impl Clean<Item> for hir::TraitItem {
1083     fn clean(&self, cx: &DocContext<'_>) -> Item {
1084         let inner = match self.kind {
1085             hir::TraitItemKind::Const(ref ty, default) => {
1086                 AssocConstItem(ty.clean(cx),
1087                                     default.map(|e| print_const_expr(cx, e)))
1088             }
1089             hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
1090                 MethodItem((sig, &self.generics, body, None).clean(cx))
1091             }
1092             hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => {
1093                 let (generics, decl) = enter_impl_trait(cx, || {
1094                     (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
1095                 });
1096                 let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
1097                 TyMethodItem(TyMethod {
1098                     header: sig.header,
1099                     decl,
1100                     generics,
1101                     all_types,
1102                     ret_types,
1103                 })
1104             }
1105             hir::TraitItemKind::Type(ref bounds, ref default) => {
1106                 AssocTypeItem(bounds.clean(cx), default.clean(cx))
1107             }
1108         };
1109         let local_did = cx.tcx.hir().local_def_id(self.hir_id);
1110         Item {
1111             name: Some(self.ident.name.clean(cx)),
1112             attrs: self.attrs.clean(cx),
1113             source: self.span.clean(cx),
1114             def_id: local_did,
1115             visibility: Visibility::Inherited,
1116             stability: get_stability(cx, local_did),
1117             deprecation: get_deprecation(cx, local_did),
1118             inner,
1119         }
1120     }
1121 }
1122
1123 impl Clean<Item> for hir::ImplItem {
1124     fn clean(&self, cx: &DocContext<'_>) -> Item {
1125         let inner = match self.kind {
1126             hir::ImplItemKind::Const(ref ty, expr) => {
1127                 AssocConstItem(ty.clean(cx),
1128                                     Some(print_const_expr(cx, expr)))
1129             }
1130             hir::ImplItemKind::Method(ref sig, body) => {
1131                 MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx))
1132             }
1133             hir::ImplItemKind::TyAlias(ref ty) => TypedefItem(Typedef {
1134                 type_: ty.clean(cx),
1135                 generics: Generics::default(),
1136             }, true),
1137             hir::ImplItemKind::OpaqueTy(ref bounds) => OpaqueTyItem(OpaqueTy {
1138                 bounds: bounds.clean(cx),
1139                 generics: Generics::default(),
1140             }, true),
1141         };
1142         let local_did = cx.tcx.hir().local_def_id(self.hir_id);
1143         Item {
1144             name: Some(self.ident.name.clean(cx)),
1145             source: self.span.clean(cx),
1146             attrs: self.attrs.clean(cx),
1147             def_id: local_did,
1148             visibility: self.vis.clean(cx),
1149             stability: get_stability(cx, local_did),
1150             deprecation: get_deprecation(cx, local_did),
1151             inner,
1152         }
1153     }
1154 }
1155
1156 impl Clean<Item> for ty::AssocItem {
1157     fn clean(&self, cx: &DocContext<'_>) -> Item {
1158         let inner = match self.kind {
1159             ty::AssocKind::Const => {
1160                 let ty = cx.tcx.type_of(self.def_id);
1161                 let default = if self.defaultness.has_value() {
1162                     Some(inline::print_inlined_const(cx, self.def_id))
1163                 } else {
1164                     None
1165                 };
1166                 AssocConstItem(ty.clean(cx), default)
1167             }
1168             ty::AssocKind::Method => {
1169                 let generics = (cx.tcx.generics_of(self.def_id),
1170                                 cx.tcx.explicit_predicates_of(self.def_id)).clean(cx);
1171                 let sig = cx.tcx.fn_sig(self.def_id);
1172                 let mut decl = (self.def_id, sig).clean(cx);
1173
1174                 if self.method_has_self_argument {
1175                     let self_ty = match self.container {
1176                         ty::ImplContainer(def_id) => {
1177                             cx.tcx.type_of(def_id)
1178                         }
1179                         ty::TraitContainer(_) => cx.tcx.types.self_param,
1180                     };
1181                     let self_arg_ty = *sig.input(0).skip_binder();
1182                     if self_arg_ty == self_ty {
1183                         decl.inputs.values[0].type_ = Generic(String::from("Self"));
1184                     } else if let ty::Ref(_, ty, _) = self_arg_ty.kind {
1185                         if ty == self_ty {
1186                             match decl.inputs.values[0].type_ {
1187                                 BorrowedRef{ref mut type_, ..} => {
1188                                     **type_ = Generic(String::from("Self"))
1189                                 }
1190                                 _ => unreachable!(),
1191                             }
1192                         }
1193                     }
1194                 }
1195
1196                 let provided = match self.container {
1197                     ty::ImplContainer(_) => true,
1198                     ty::TraitContainer(_) => self.defaultness.has_value()
1199                 };
1200                 let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
1201                 if provided {
1202                     let constness = if cx.tcx.is_min_const_fn(self.def_id) {
1203                         hir::Constness::Const
1204                     } else {
1205                         hir::Constness::NotConst
1206                     };
1207                     let asyncness = cx.tcx.asyncness(self.def_id);
1208                     let defaultness = match self.container {
1209                         ty::ImplContainer(_) => Some(self.defaultness),
1210                         ty::TraitContainer(_) => None,
1211                     };
1212                     MethodItem(Method {
1213                         generics,
1214                         decl,
1215                         header: hir::FnHeader {
1216                             unsafety: sig.unsafety(),
1217                             abi: sig.abi(),
1218                             constness,
1219                             asyncness,
1220                         },
1221                         defaultness,
1222                         all_types,
1223                         ret_types,
1224                     })
1225                 } else {
1226                     TyMethodItem(TyMethod {
1227                         generics,
1228                         decl,
1229                         header: hir::FnHeader {
1230                             unsafety: sig.unsafety(),
1231                             abi: sig.abi(),
1232                             constness: hir::Constness::NotConst,
1233                             asyncness: hir::IsAsync::NotAsync,
1234                         },
1235                         all_types,
1236                         ret_types,
1237                     })
1238                 }
1239             }
1240             ty::AssocKind::Type => {
1241                 let my_name = self.ident.name.clean(cx);
1242
1243                 if let ty::TraitContainer(did) = self.container {
1244                     // When loading a cross-crate associated type, the bounds for this type
1245                     // are actually located on the trait/impl itself, so we need to load
1246                     // all of the generics from there and then look for bounds that are
1247                     // applied to this associated type in question.
1248                     let predicates = cx.tcx.explicit_predicates_of(did);
1249                     let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
1250                     let mut bounds = generics.where_predicates.iter().filter_map(|pred| {
1251                         let (name, self_type, trait_, bounds) = match *pred {
1252                             WherePredicate::BoundPredicate {
1253                                 ty: QPath { ref name, ref self_type, ref trait_ },
1254                                 ref bounds
1255                             } => (name, self_type, trait_, bounds),
1256                             _ => return None,
1257                         };
1258                         if *name != my_name { return None }
1259                         match **trait_ {
1260                             ResolvedPath { did, .. } if did == self.container.id() => {}
1261                             _ => return None,
1262                         }
1263                         match **self_type {
1264                             Generic(ref s) if *s == "Self" => {}
1265                             _ => return None,
1266                         }
1267                         Some(bounds)
1268                     }).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>();
1269                     // Our Sized/?Sized bound didn't get handled when creating the generics
1270                     // because we didn't actually get our whole set of bounds until just now
1271                     // (some of them may have come from the trait). If we do have a sized
1272                     // bound, we remove it, and if we don't then we add the `?Sized` bound
1273                     // at the end.
1274                     match bounds.iter().position(|b| b.is_sized_bound(cx)) {
1275                         Some(i) => { bounds.remove(i); }
1276                         None => bounds.push(GenericBound::maybe_sized(cx)),
1277                     }
1278
1279                     let ty = if self.defaultness.has_value() {
1280                         Some(cx.tcx.type_of(self.def_id))
1281                     } else {
1282                         None
1283                     };
1284
1285                     AssocTypeItem(bounds, ty.clean(cx))
1286                 } else {
1287                     TypedefItem(Typedef {
1288                         type_: cx.tcx.type_of(self.def_id).clean(cx),
1289                         generics: Generics {
1290                             params: Vec::new(),
1291                             where_predicates: Vec::new(),
1292                         },
1293                     }, true)
1294                 }
1295             }
1296             ty::AssocKind::OpaqueTy => unimplemented!(),
1297         };
1298
1299         let visibility = match self.container {
1300             ty::ImplContainer(_) => self.vis.clean(cx),
1301             ty::TraitContainer(_) => Inherited,
1302         };
1303
1304         Item {
1305             name: Some(self.ident.name.clean(cx)),
1306             visibility,
1307             stability: get_stability(cx, self.def_id),
1308             deprecation: get_deprecation(cx, self.def_id),
1309             def_id: self.def_id,
1310             attrs: inline::load_attrs(cx, self.def_id).clean(cx),
1311             source: cx.tcx.def_span(self.def_id).clean(cx),
1312             inner,
1313         }
1314     }
1315 }
1316
1317 impl Clean<Type> for hir::Ty {
1318     fn clean(&self, cx: &DocContext<'_>) -> Type {
1319         use rustc::hir::*;
1320
1321         match self.kind {
1322             TyKind::Never => Never,
1323             TyKind::Ptr(ref m) => RawPointer(m.mutbl, box m.ty.clean(cx)),
1324             TyKind::Rptr(ref l, ref m) => {
1325                 let lifetime = if l.is_elided() {
1326                     None
1327                 } else {
1328                     Some(l.clean(cx))
1329                 };
1330                 BorrowedRef {lifetime, mutability: m.mutbl, type_: box m.ty.clean(cx)}
1331             }
1332             TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
1333             TyKind::Array(ref ty, ref length) => {
1334                 let def_id = cx.tcx.hir().local_def_id(length.hir_id);
1335                 let param_env = cx.tcx.param_env(def_id);
1336                 let substs = InternalSubsts::identity_for_item(cx.tcx, def_id);
1337                 let cid = GlobalId {
1338                     instance: ty::Instance::new(def_id, substs),
1339                     promoted: None
1340                 };
1341                 let length = match cx.tcx.const_eval(param_env.and(cid)) {
1342                     Ok(length) => print_const(cx, length),
1343                     Err(_) => cx.sess()
1344                                 .source_map()
1345                                 .span_to_snippet(cx.tcx.def_span(def_id))
1346                                 .unwrap_or_else(|_| "_".to_string()),
1347                 };
1348                 Array(box ty.clean(cx), length)
1349             },
1350             TyKind::Tup(ref tys) => Tuple(tys.clean(cx)),
1351             TyKind::Def(item_id, _) => {
1352                 let item = cx.tcx.hir().expect_item(item_id.id);
1353                 if let hir::ItemKind::OpaqueTy(ref ty) = item.kind {
1354                     ImplTrait(ty.bounds.clean(cx))
1355                 } else {
1356                     unreachable!()
1357                 }
1358             }
1359             TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
1360                 if let Res::Def(DefKind::TyParam, did) = path.res {
1361                     if let Some(new_ty) = cx.ty_substs.borrow().get(&did).cloned() {
1362                         return new_ty;
1363                     }
1364                     if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did.into()) {
1365                         return ImplTrait(bounds);
1366                     }
1367                 }
1368
1369                 let mut alias = None;
1370                 if let Res::Def(DefKind::TyAlias, def_id) = path.res {
1371                     // Substitute private type aliases
1372                     if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
1373                         if !cx.renderinfo.borrow().access_levels.is_exported(def_id) {
1374                             alias = Some(&cx.tcx.hir().expect_item(hir_id).kind);
1375                         }
1376                     }
1377                 };
1378
1379                 if let Some(&hir::ItemKind::TyAlias(ref ty, ref generics)) = alias {
1380                     let provided_params = &path.segments.last().expect("segments were empty");
1381                     let mut ty_substs = FxHashMap::default();
1382                     let mut lt_substs = FxHashMap::default();
1383                     let mut ct_substs = FxHashMap::default();
1384                     let generic_args = provided_params.generic_args();
1385                     {
1386                         let mut indices: GenericParamCount = Default::default();
1387                         for param in generics.params.iter() {
1388                             match param.kind {
1389                                 hir::GenericParamKind::Lifetime { .. } => {
1390                                     let mut j = 0;
1391                                     let lifetime = generic_args.args.iter().find_map(|arg| {
1392                                         match arg {
1393                                             hir::GenericArg::Lifetime(lt) => {
1394                                                 if indices.lifetimes == j {
1395                                                     return Some(lt);
1396                                                 }
1397                                                 j += 1;
1398                                                 None
1399                                             }
1400                                             _ => None,
1401                                         }
1402                                     });
1403                                     if let Some(lt) = lifetime.cloned() {
1404                                         if !lt.is_elided() {
1405                                             let lt_def_id =
1406                                                 cx.tcx.hir().local_def_id(param.hir_id);
1407                                             lt_substs.insert(lt_def_id, lt.clean(cx));
1408                                         }
1409                                     }
1410                                     indices.lifetimes += 1;
1411                                 }
1412                                 hir::GenericParamKind::Type { ref default, .. } => {
1413                                     let ty_param_def_id =
1414                                         cx.tcx.hir().local_def_id(param.hir_id);
1415                                     let mut j = 0;
1416                                     let type_ = generic_args.args.iter().find_map(|arg| {
1417                                         match arg {
1418                                             hir::GenericArg::Type(ty) => {
1419                                                 if indices.types == j {
1420                                                     return Some(ty);
1421                                                 }
1422                                                 j += 1;
1423                                                 None
1424                                             }
1425                                             _ => None,
1426                                         }
1427                                     });
1428                                     if let Some(ty) = type_ {
1429                                         ty_substs.insert(ty_param_def_id, ty.clean(cx));
1430                                     } else if let Some(default) = default.clone() {
1431                                         ty_substs.insert(ty_param_def_id,
1432                                                          default.clean(cx));
1433                                     }
1434                                     indices.types += 1;
1435                                 }
1436                                 hir::GenericParamKind::Const { .. } => {
1437                                     let const_param_def_id =
1438                                         cx.tcx.hir().local_def_id(param.hir_id);
1439                                     let mut j = 0;
1440                                     let const_ = generic_args.args.iter().find_map(|arg| {
1441                                         match arg {
1442                                             hir::GenericArg::Const(ct) => {
1443                                                 if indices.consts == j {
1444                                                     return Some(ct);
1445                                                 }
1446                                                 j += 1;
1447                                                 None
1448                                             }
1449                                             _ => None,
1450                                         }
1451                                     });
1452                                     if let Some(ct) = const_ {
1453                                         ct_substs.insert(const_param_def_id, ct.clean(cx));
1454                                     }
1455                                     // FIXME(const_generics:defaults)
1456                                     indices.consts += 1;
1457                                 }
1458                             }
1459                         }
1460                     }
1461                     return cx.enter_alias(ty_substs, lt_substs, ct_substs, || ty.clean(cx));
1462                 }
1463                 resolve_type(cx, path.clean(cx), self.hir_id)
1464             }
1465             TyKind::Path(hir::QPath::Resolved(Some(ref qself), ref p)) => {
1466                 let segments = if p.is_global() { &p.segments[1..] } else { &p.segments };
1467                 let trait_segments = &segments[..segments.len() - 1];
1468                 let trait_path = self::Path {
1469                     global: p.is_global(),
1470                     res: Res::Def(
1471                         DefKind::Trait,
1472                         cx.tcx.associated_item(p.res.def_id()).container.id(),
1473                     ),
1474                     segments: trait_segments.clean(cx),
1475                 };
1476                 Type::QPath {
1477                     name: p.segments.last().expect("segments were empty").ident.name.clean(cx),
1478                     self_type: box qself.clean(cx),
1479                     trait_: box resolve_type(cx, trait_path, self.hir_id)
1480                 }
1481             }
1482             TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
1483                 let mut res = Res::Err;
1484                 let ty = hir_ty_to_ty(cx.tcx, self);
1485                 if let ty::Projection(proj) = ty.kind {
1486                     res = Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id);
1487                 }
1488                 let trait_path = hir::Path {
1489                     span: self.span,
1490                     res,
1491                     segments: vec![].into(),
1492                 };
1493                 Type::QPath {
1494                     name: segment.ident.name.clean(cx),
1495                     self_type: box qself.clean(cx),
1496                     trait_: box resolve_type(cx, trait_path.clean(cx), self.hir_id)
1497                 }
1498             }
1499             TyKind::TraitObject(ref bounds, ref lifetime) => {
1500                 match bounds[0].clean(cx).trait_ {
1501                     ResolvedPath { path, param_names: None, did, is_generic } => {
1502                         let mut bounds: Vec<self::GenericBound> = bounds[1..].iter().map(|bound| {
1503                             self::GenericBound::TraitBound(bound.clean(cx),
1504                                                            hir::TraitBoundModifier::None)
1505                         }).collect();
1506                         if !lifetime.is_elided() {
1507                             bounds.push(self::GenericBound::Outlives(lifetime.clean(cx)));
1508                         }
1509                         ResolvedPath { path, param_names: Some(bounds), did, is_generic, }
1510                     }
1511                     _ => Infer, // shouldn't happen
1512                 }
1513             }
1514             TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
1515             TyKind::Infer | TyKind::Err => Infer,
1516             TyKind::Typeof(..) => panic!("unimplemented type {:?}", self.kind),
1517         }
1518     }
1519 }
1520
1521 impl<'tcx> Clean<Type> for Ty<'tcx> {
1522     fn clean(&self, cx: &DocContext<'_>) -> Type {
1523         debug!("cleaning type: {:?}", self);
1524         match self.kind {
1525             ty::Never => Never,
1526             ty::Bool => Primitive(PrimitiveType::Bool),
1527             ty::Char => Primitive(PrimitiveType::Char),
1528             ty::Int(int_ty) => Primitive(int_ty.into()),
1529             ty::Uint(uint_ty) => Primitive(uint_ty.into()),
1530             ty::Float(float_ty) => Primitive(float_ty.into()),
1531             ty::Str => Primitive(PrimitiveType::Str),
1532             ty::Slice(ty) => Slice(box ty.clean(cx)),
1533             ty::Array(ty, n) => {
1534                 let mut n = cx.tcx.lift(&n).expect("array lift failed");
1535                 if let ty::ConstKind::Unevaluated(def_id, substs) = n.val {
1536                     let param_env = cx.tcx.param_env(def_id);
1537                     let cid = GlobalId {
1538                         instance: ty::Instance::new(def_id, substs),
1539                         promoted: None
1540                     };
1541                     if let Ok(new_n) = cx.tcx.const_eval(param_env.and(cid)) {
1542                         n = new_n;
1543                     }
1544                 };
1545                 let n = print_const(cx, n);
1546                 Array(box ty.clean(cx), n)
1547             }
1548             ty::RawPtr(mt) => RawPointer(mt.mutbl, box mt.ty.clean(cx)),
1549             ty::Ref(r, ty, mutbl) => BorrowedRef {
1550                 lifetime: r.clean(cx),
1551                 mutability: mutbl,
1552                 type_: box ty.clean(cx),
1553             },
1554             ty::FnDef(..) |
1555             ty::FnPtr(_) => {
1556                 let ty = cx.tcx.lift(self).expect("FnPtr lift failed");
1557                 let sig = ty.fn_sig(cx.tcx);
1558                 let local_def_id = cx.tcx.hir().local_def_id_from_node_id(ast::CRATE_NODE_ID);
1559                 BareFunction(box BareFunctionDecl {
1560                     unsafety: sig.unsafety(),
1561                     generic_params: Vec::new(),
1562                     decl: (local_def_id, sig).clean(cx),
1563                     abi: sig.abi(),
1564                 })
1565             }
1566             ty::Adt(def, substs) => {
1567                 let did = def.did;
1568                 let kind = match def.adt_kind() {
1569                     AdtKind::Struct => TypeKind::Struct,
1570                     AdtKind::Union => TypeKind::Union,
1571                     AdtKind::Enum => TypeKind::Enum,
1572                 };
1573                 inline::record_extern_fqn(cx, did, kind);
1574                 let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], substs);
1575                 ResolvedPath {
1576                     path,
1577                     param_names: None,
1578                     did,
1579                     is_generic: false,
1580                 }
1581             }
1582             ty::Foreign(did) => {
1583                 inline::record_extern_fqn(cx, did, TypeKind::Foreign);
1584                 let path = external_path(cx, cx.tcx.item_name(did),
1585                                          None, false, vec![], InternalSubsts::empty());
1586                 ResolvedPath {
1587                     path,
1588                     param_names: None,
1589                     did,
1590                     is_generic: false,
1591                 }
1592             }
1593             ty::Dynamic(ref obj, ref reg) => {
1594                 // HACK: pick the first `did` as the `did` of the trait object. Someone
1595                 // might want to implement "native" support for marker-trait-only
1596                 // trait objects.
1597                 let mut dids = obj.principal_def_id().into_iter().chain(obj.auto_traits());
1598                 let did = dids.next().unwrap_or_else(|| {
1599                     panic!("found trait object `{:?}` with no traits?", self)
1600                 });
1601                 let substs = match obj.principal() {
1602                     Some(principal) => principal.skip_binder().substs,
1603                     // marker traits have no substs.
1604                     _ => cx.tcx.intern_substs(&[])
1605                 };
1606
1607                 inline::record_extern_fqn(cx, did, TypeKind::Trait);
1608
1609                 let mut param_names = vec![];
1610                 reg.clean(cx).map(|b| param_names.push(GenericBound::Outlives(b)));
1611                 for did in dids {
1612                     let empty = cx.tcx.intern_substs(&[]);
1613                     let path = external_path(cx, cx.tcx.item_name(did),
1614                         Some(did), false, vec![], empty);
1615                     inline::record_extern_fqn(cx, did, TypeKind::Trait);
1616                     let bound = GenericBound::TraitBound(PolyTrait {
1617                         trait_: ResolvedPath {
1618                             path,
1619                             param_names: None,
1620                             did,
1621                             is_generic: false,
1622                         },
1623                         generic_params: Vec::new(),
1624                     }, hir::TraitBoundModifier::None);
1625                     param_names.push(bound);
1626                 }
1627
1628                 let mut bindings = vec![];
1629                 for pb in obj.projection_bounds() {
1630                     bindings.push(TypeBinding {
1631                         name: cx.tcx.associated_item(pb.item_def_id()).ident.name.clean(cx),
1632                         kind: TypeBindingKind::Equality {
1633                             ty: pb.skip_binder().ty.clean(cx)
1634                         },
1635                     });
1636                 }
1637
1638                 let path = external_path(cx, cx.tcx.item_name(did), Some(did),
1639                     false, bindings, substs);
1640                 ResolvedPath {
1641                     path,
1642                     param_names: Some(param_names),
1643                     did,
1644                     is_generic: false,
1645                 }
1646             }
1647             ty::Tuple(ref t) => {
1648                 Tuple(t.iter().map(|t| t.expect_ty()).collect::<Vec<_>>().clean(cx))
1649             }
1650
1651             ty::Projection(ref data) => data.clean(cx),
1652
1653             ty::Param(ref p) => {
1654                 if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&p.index.into()) {
1655                     ImplTrait(bounds)
1656                 } else {
1657                     Generic(p.name.to_string())
1658                 }
1659             }
1660
1661             ty::Opaque(def_id, substs) => {
1662                 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
1663                 // by looking up the projections associated with the def_id.
1664                 let predicates_of = cx.tcx.explicit_predicates_of(def_id);
1665                 let substs = cx.tcx.lift(&substs).expect("Opaque lift failed");
1666                 let bounds = predicates_of.instantiate(cx.tcx, substs);
1667                 let mut regions = vec![];
1668                 let mut has_sized = false;
1669                 let mut bounds = bounds.predicates.iter().filter_map(|predicate| {
1670                     let trait_ref = if let Some(tr) = predicate.to_opt_poly_trait_ref() {
1671                         tr
1672                     } else if let ty::Predicate::TypeOutlives(pred) = *predicate {
1673                         // these should turn up at the end
1674                         pred.skip_binder().1.clean(cx).map(|r| {
1675                             regions.push(GenericBound::Outlives(r))
1676                         });
1677                         return None;
1678                     } else {
1679                         return None;
1680                     };
1681
1682                     if let Some(sized) = cx.tcx.lang_items().sized_trait() {
1683                         if trait_ref.def_id() == sized {
1684                             has_sized = true;
1685                             return None;
1686                         }
1687                     }
1688
1689                     let bounds = bounds.predicates.iter().filter_map(|pred|
1690                         if let ty::Predicate::Projection(proj) = *pred {
1691                             let proj = proj.skip_binder();
1692                             if proj.projection_ty.trait_ref(cx.tcx) == *trait_ref.skip_binder() {
1693                                 Some(TypeBinding {
1694                                     name: cx.tcx.associated_item(proj.projection_ty.item_def_id)
1695                                                 .ident.name.clean(cx),
1696                                     kind: TypeBindingKind::Equality {
1697                                         ty: proj.ty.clean(cx),
1698                                     },
1699                                 })
1700                             } else {
1701                                 None
1702                             }
1703                         } else {
1704                             None
1705                         }
1706                     ).collect();
1707
1708                     Some((trait_ref.skip_binder(), bounds).clean(cx))
1709                 }).collect::<Vec<_>>();
1710                 bounds.extend(regions);
1711                 if !has_sized && !bounds.is_empty() {
1712                     bounds.insert(0, GenericBound::maybe_sized(cx));
1713                 }
1714                 ImplTrait(bounds)
1715             }
1716
1717             ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton)
1718
1719             ty::Bound(..) => panic!("Bound"),
1720             ty::Placeholder(..) => panic!("Placeholder"),
1721             ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"),
1722             ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
1723             ty::Infer(..) => panic!("Infer"),
1724             ty::Error => panic!("Error"),
1725         }
1726     }
1727 }
1728
1729 impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
1730     fn clean(&self, cx: &DocContext<'_>) -> Constant {
1731         Constant {
1732             type_: self.ty.clean(cx),
1733             expr: format!("{}", self),
1734         }
1735     }
1736 }
1737
1738 impl Clean<Item> for hir::StructField {
1739     fn clean(&self, cx: &DocContext<'_>) -> Item {
1740         let local_did = cx.tcx.hir().local_def_id(self.hir_id);
1741
1742         Item {
1743             name: Some(self.ident.name).clean(cx),
1744             attrs: self.attrs.clean(cx),
1745             source: self.span.clean(cx),
1746             visibility: self.vis.clean(cx),
1747             stability: get_stability(cx, local_did),
1748             deprecation: get_deprecation(cx, local_did),
1749             def_id: local_did,
1750             inner: StructFieldItem(self.ty.clean(cx)),
1751         }
1752     }
1753 }
1754
1755 impl Clean<Item> for ty::FieldDef {
1756     fn clean(&self, cx: &DocContext<'_>) -> Item {
1757         Item {
1758             name: Some(self.ident.name).clean(cx),
1759             attrs: cx.tcx.get_attrs(self.did).clean(cx),
1760             source: cx.tcx.def_span(self.did).clean(cx),
1761             visibility: self.vis.clean(cx),
1762             stability: get_stability(cx, self.did),
1763             deprecation: get_deprecation(cx, self.did),
1764             def_id: self.did,
1765             inner: StructFieldItem(cx.tcx.type_of(self.did).clean(cx)),
1766         }
1767     }
1768 }
1769
1770 impl Clean<Visibility> for hir::Visibility {
1771     fn clean(&self, cx: &DocContext<'_>) -> Visibility {
1772         match self.node {
1773             hir::VisibilityKind::Public => Visibility::Public,
1774             hir::VisibilityKind::Inherited => Visibility::Inherited,
1775             hir::VisibilityKind::Crate(_) => Visibility::Crate,
1776             hir::VisibilityKind::Restricted { ref path, .. } => {
1777                 let path = path.clean(cx);
1778                 let did = register_res(cx, path.res);
1779                 Visibility::Restricted(did, path)
1780             }
1781         }
1782     }
1783 }
1784
1785 impl Clean<Visibility> for ty::Visibility {
1786     fn clean(&self, _: &DocContext<'_>) -> Visibility {
1787         if *self == ty::Visibility::Public { Public } else { Inherited }
1788     }
1789 }
1790
1791 impl Clean<Item> for doctree::Struct<'_> {
1792     fn clean(&self, cx: &DocContext<'_>) -> Item {
1793         Item {
1794             name: Some(self.name.clean(cx)),
1795             attrs: self.attrs.clean(cx),
1796             source: self.whence.clean(cx),
1797             def_id: cx.tcx.hir().local_def_id(self.id),
1798             visibility: self.vis.clean(cx),
1799             stability: cx.stability(self.id).clean(cx),
1800             deprecation: cx.deprecation(self.id).clean(cx),
1801             inner: StructItem(Struct {
1802                 struct_type: self.struct_type,
1803                 generics: self.generics.clean(cx),
1804                 fields: self.fields.clean(cx),
1805                 fields_stripped: false,
1806             }),
1807         }
1808     }
1809 }
1810
1811 impl Clean<Item> for doctree::Union<'_> {
1812     fn clean(&self, cx: &DocContext<'_>) -> Item {
1813         Item {
1814             name: Some(self.name.clean(cx)),
1815             attrs: self.attrs.clean(cx),
1816             source: self.whence.clean(cx),
1817             def_id: cx.tcx.hir().local_def_id(self.id),
1818             visibility: self.vis.clean(cx),
1819             stability: cx.stability(self.id).clean(cx),
1820             deprecation: cx.deprecation(self.id).clean(cx),
1821             inner: UnionItem(Union {
1822                 struct_type: self.struct_type,
1823                 generics: self.generics.clean(cx),
1824                 fields: self.fields.clean(cx),
1825                 fields_stripped: false,
1826             }),
1827         }
1828     }
1829 }
1830
1831 impl Clean<VariantStruct> for ::rustc::hir::VariantData {
1832     fn clean(&self, cx: &DocContext<'_>) -> VariantStruct {
1833         VariantStruct {
1834             struct_type: doctree::struct_type_from_def(self),
1835             fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
1836             fields_stripped: false,
1837         }
1838     }
1839 }
1840
1841 impl Clean<Item> for doctree::Enum<'_> {
1842     fn clean(&self, cx: &DocContext<'_>) -> Item {
1843         Item {
1844             name: Some(self.name.clean(cx)),
1845             attrs: self.attrs.clean(cx),
1846             source: self.whence.clean(cx),
1847             def_id: cx.tcx.hir().local_def_id(self.id),
1848             visibility: self.vis.clean(cx),
1849             stability: cx.stability(self.id).clean(cx),
1850             deprecation: cx.deprecation(self.id).clean(cx),
1851             inner: EnumItem(Enum {
1852                 variants: self.variants.iter().map(|v| v.clean(cx)).collect(),
1853                 generics: self.generics.clean(cx),
1854                 variants_stripped: false,
1855             }),
1856         }
1857     }
1858 }
1859
1860 impl Clean<Item> for doctree::Variant<'_> {
1861     fn clean(&self, cx: &DocContext<'_>) -> Item {
1862         Item {
1863             name: Some(self.name.clean(cx)),
1864             attrs: self.attrs.clean(cx),
1865             source: self.whence.clean(cx),
1866             visibility: Inherited,
1867             stability: cx.stability(self.id).clean(cx),
1868             deprecation: cx.deprecation(self.id).clean(cx),
1869             def_id: cx.tcx.hir().local_def_id(self.id),
1870             inner: VariantItem(Variant {
1871                 kind: self.def.clean(cx),
1872             }),
1873         }
1874     }
1875 }
1876
1877 impl Clean<Item> for ty::VariantDef {
1878     fn clean(&self, cx: &DocContext<'_>) -> Item {
1879         let kind = match self.ctor_kind {
1880             CtorKind::Const => VariantKind::CLike,
1881             CtorKind::Fn => {
1882                 VariantKind::Tuple(
1883                     self.fields.iter().map(|f| cx.tcx.type_of(f.did).clean(cx)).collect()
1884                 )
1885             }
1886             CtorKind::Fictive => {
1887                 VariantKind::Struct(VariantStruct {
1888                     struct_type: doctree::Plain,
1889                     fields_stripped: false,
1890                     fields: self.fields.iter().map(|field| {
1891                         Item {
1892                             source: cx.tcx.def_span(field.did).clean(cx),
1893                             name: Some(field.ident.name.clean(cx)),
1894                             attrs: cx.tcx.get_attrs(field.did).clean(cx),
1895                             visibility: field.vis.clean(cx),
1896                             def_id: field.did,
1897                             stability: get_stability(cx, field.did),
1898                             deprecation: get_deprecation(cx, field.did),
1899                             inner: StructFieldItem(cx.tcx.type_of(field.did).clean(cx))
1900                         }
1901                     }).collect()
1902                 })
1903             }
1904         };
1905         Item {
1906             name: Some(self.ident.clean(cx)),
1907             attrs: inline::load_attrs(cx, self.def_id).clean(cx),
1908             source: cx.tcx.def_span(self.def_id).clean(cx),
1909             visibility: Inherited,
1910             def_id: self.def_id,
1911             inner: VariantItem(Variant { kind }),
1912             stability: get_stability(cx, self.def_id),
1913             deprecation: get_deprecation(cx, self.def_id),
1914         }
1915     }
1916 }
1917
1918 impl Clean<VariantKind> for hir::VariantData {
1919     fn clean(&self, cx: &DocContext<'_>) -> VariantKind {
1920         match self {
1921             hir::VariantData::Struct(..) => VariantKind::Struct(self.clean(cx)),
1922             hir::VariantData::Tuple(..) =>
1923                 VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect()),
1924             hir::VariantData::Unit(..) => VariantKind::CLike,
1925         }
1926     }
1927 }
1928
1929 impl Clean<Span> for syntax_pos::Span {
1930     fn clean(&self, cx: &DocContext<'_>) -> Span {
1931         if self.is_dummy() {
1932             return Span::empty();
1933         }
1934
1935         let cm = cx.sess().source_map();
1936         let filename = cm.span_to_filename(*self);
1937         let lo = cm.lookup_char_pos(self.lo());
1938         let hi = cm.lookup_char_pos(self.hi());
1939         Span {
1940             filename,
1941             loline: lo.line,
1942             locol: lo.col.to_usize(),
1943             hiline: hi.line,
1944             hicol: hi.col.to_usize(),
1945             original: *self,
1946         }
1947     }
1948 }
1949
1950 impl Clean<Path> for hir::Path {
1951     fn clean(&self, cx: &DocContext<'_>) -> Path {
1952         Path {
1953             global: self.is_global(),
1954             res: self.res,
1955             segments: if self.is_global() { &self.segments[1..] } else { &self.segments }.clean(cx),
1956         }
1957     }
1958 }
1959
1960 impl Clean<GenericArgs> for hir::GenericArgs {
1961     fn clean(&self, cx: &DocContext<'_>) -> GenericArgs {
1962         if self.parenthesized {
1963             let output = self.bindings[0].ty().clean(cx);
1964             GenericArgs::Parenthesized {
1965                 inputs: self.inputs().clean(cx),
1966                 output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
1967             }
1968         } else {
1969             let elide_lifetimes = self.args.iter().all(|arg| match arg {
1970                 hir::GenericArg::Lifetime(lt) => lt.is_elided(),
1971                 _ => true,
1972             });
1973             GenericArgs::AngleBracketed {
1974                 args: self.args.iter().filter_map(|arg| match arg {
1975                     hir::GenericArg::Lifetime(lt) if !elide_lifetimes => {
1976                         Some(GenericArg::Lifetime(lt.clean(cx)))
1977                     }
1978                     hir::GenericArg::Lifetime(_) => None,
1979                     hir::GenericArg::Type(ty) => Some(GenericArg::Type(ty.clean(cx))),
1980                     hir::GenericArg::Const(ct) => Some(GenericArg::Const(ct.clean(cx))),
1981                 }).collect(),
1982                 bindings: self.bindings.clean(cx),
1983             }
1984         }
1985     }
1986 }
1987
1988 impl Clean<PathSegment> for hir::PathSegment {
1989     fn clean(&self, cx: &DocContext<'_>) -> PathSegment {
1990         PathSegment {
1991             name: self.ident.name.clean(cx),
1992             args: self.generic_args().clean(cx),
1993         }
1994     }
1995 }
1996
1997 impl Clean<String> for Ident {
1998     #[inline]
1999     fn clean(&self, cx: &DocContext<'_>) -> String {
2000         self.name.clean(cx)
2001     }
2002 }
2003
2004 impl Clean<String> for ast::Name {
2005     #[inline]
2006     fn clean(&self, _: &DocContext<'_>) -> String {
2007         self.to_string()
2008     }
2009 }
2010
2011 impl Clean<Item> for doctree::Typedef<'_> {
2012     fn clean(&self, cx: &DocContext<'_>) -> Item {
2013         Item {
2014             name: Some(self.name.clean(cx)),
2015             attrs: self.attrs.clean(cx),
2016             source: self.whence.clean(cx),
2017             def_id: cx.tcx.hir().local_def_id(self.id),
2018             visibility: self.vis.clean(cx),
2019             stability: cx.stability(self.id).clean(cx),
2020             deprecation: cx.deprecation(self.id).clean(cx),
2021             inner: TypedefItem(Typedef {
2022                 type_: self.ty.clean(cx),
2023                 generics: self.gen.clean(cx),
2024             }, false),
2025         }
2026     }
2027 }
2028
2029 impl Clean<Item> for doctree::OpaqueTy<'_> {
2030     fn clean(&self, cx: &DocContext<'_>) -> Item {
2031         Item {
2032             name: Some(self.name.clean(cx)),
2033             attrs: self.attrs.clean(cx),
2034             source: self.whence.clean(cx),
2035             def_id: cx.tcx.hir().local_def_id(self.id),
2036             visibility: self.vis.clean(cx),
2037             stability: cx.stability(self.id).clean(cx),
2038             deprecation: cx.deprecation(self.id).clean(cx),
2039             inner: OpaqueTyItem(OpaqueTy {
2040                 bounds: self.opaque_ty.bounds.clean(cx),
2041                 generics: self.opaque_ty.generics.clean(cx),
2042             }, false),
2043         }
2044     }
2045 }
2046
2047 impl Clean<BareFunctionDecl> for hir::BareFnTy {
2048     fn clean(&self, cx: &DocContext<'_>) -> BareFunctionDecl {
2049         let (generic_params, decl) = enter_impl_trait(cx, || {
2050             (self.generic_params.clean(cx), (&*self.decl, &self.param_names[..]).clean(cx))
2051         });
2052         BareFunctionDecl {
2053             unsafety: self.unsafety,
2054             abi: self.abi,
2055             decl,
2056             generic_params,
2057         }
2058     }
2059 }
2060
2061 impl Clean<Item> for doctree::Static<'_> {
2062     fn clean(&self, cx: &DocContext<'_>) -> Item {
2063         debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
2064         Item {
2065             name: Some(self.name.clean(cx)),
2066             attrs: self.attrs.clean(cx),
2067             source: self.whence.clean(cx),
2068             def_id: cx.tcx.hir().local_def_id(self.id),
2069             visibility: self.vis.clean(cx),
2070             stability: cx.stability(self.id).clean(cx),
2071             deprecation: cx.deprecation(self.id).clean(cx),
2072             inner: StaticItem(Static {
2073                 type_: self.type_.clean(cx),
2074                 mutability: self.mutability,
2075                 expr: print_const_expr(cx, self.expr),
2076             }),
2077         }
2078     }
2079 }
2080
2081 impl Clean<Item> for doctree::Constant<'_> {
2082     fn clean(&self, cx: &DocContext<'_>) -> Item {
2083         Item {
2084             name: Some(self.name.clean(cx)),
2085             attrs: self.attrs.clean(cx),
2086             source: self.whence.clean(cx),
2087             def_id: cx.tcx.hir().local_def_id(self.id),
2088             visibility: self.vis.clean(cx),
2089             stability: cx.stability(self.id).clean(cx),
2090             deprecation: cx.deprecation(self.id).clean(cx),
2091             inner: ConstantItem(Constant {
2092                 type_: self.type_.clean(cx),
2093                 expr: print_const_expr(cx, self.expr),
2094             }),
2095         }
2096     }
2097 }
2098
2099 impl Clean<ImplPolarity> for ty::ImplPolarity {
2100     fn clean(&self, _: &DocContext<'_>) -> ImplPolarity {
2101         match self {
2102             &ty::ImplPolarity::Positive |
2103             // FIXME: do we want to do something else here?
2104             &ty::ImplPolarity::Reservation => ImplPolarity::Positive,
2105             &ty::ImplPolarity::Negative => ImplPolarity::Negative,
2106         }
2107     }
2108 }
2109
2110 impl Clean<Vec<Item>> for doctree::Impl<'_> {
2111     fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
2112         let mut ret = Vec::new();
2113         let trait_ = self.trait_.clean(cx);
2114         let items = self.items.iter().map(|ii| ii.clean(cx)).collect::<Vec<_>>();
2115         let def_id = cx.tcx.hir().local_def_id(self.id);
2116
2117         // If this impl block is an implementation of the Deref trait, then we
2118         // need to try inlining the target's inherent impl blocks as well.
2119         if trait_.def_id() == cx.tcx.lang_items().deref_trait() {
2120             build_deref_target_impls(cx, &items, &mut ret);
2121         }
2122
2123         let provided = trait_.def_id().map(|did| {
2124             cx.tcx.provided_trait_methods(did)
2125                   .into_iter()
2126                   .map(|meth| meth.ident.to_string())
2127                   .collect()
2128         }).unwrap_or_default();
2129
2130         ret.push(Item {
2131             name: None,
2132             attrs: self.attrs.clean(cx),
2133             source: self.whence.clean(cx),
2134             def_id,
2135             visibility: self.vis.clean(cx),
2136             stability: cx.stability(self.id).clean(cx),
2137             deprecation: cx.deprecation(self.id).clean(cx),
2138             inner: ImplItem(Impl {
2139                 unsafety: self.unsafety,
2140                 generics: self.generics.clean(cx),
2141                 provided_trait_methods: provided,
2142                 trait_,
2143                 for_: self.for_.clean(cx),
2144                 items,
2145                 polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)),
2146                 synthetic: false,
2147                 blanket_impl: None,
2148             })
2149         });
2150         ret
2151     }
2152 }
2153
2154 impl Clean<Vec<Item>> for doctree::ExternCrate<'_> {
2155     fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
2156
2157         let please_inline = self.vis.node.is_pub() && self.attrs.iter().any(|a| {
2158             a.check_name(sym::doc) && match a.meta_item_list() {
2159                 Some(l) => attr::list_contains_name(&l, sym::inline),
2160                 None => false,
2161             }
2162         });
2163
2164         if please_inline {
2165             let mut visited = FxHashSet::default();
2166
2167             let res = Res::Def(
2168                 DefKind::Mod,
2169                 DefId {
2170                     krate: self.cnum,
2171                     index: CRATE_DEF_INDEX,
2172                 },
2173             );
2174
2175             if let Some(items) = inline::try_inline(
2176                 cx, res, self.name,
2177                 Some(rustc::ty::Attributes::Borrowed(self.attrs)),
2178                 &mut visited
2179             ) {
2180                 return items;
2181             }
2182         }
2183
2184         vec![Item {
2185             name: None,
2186             attrs: self.attrs.clean(cx),
2187             source: self.whence.clean(cx),
2188             def_id: DefId { krate: self.cnum, index: CRATE_DEF_INDEX },
2189             visibility: self.vis.clean(cx),
2190             stability: None,
2191             deprecation: None,
2192             inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
2193         }]
2194     }
2195 }
2196
2197 impl Clean<Vec<Item>> for doctree::Import<'_> {
2198     fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
2199         // We consider inlining the documentation of `pub use` statements, but we
2200         // forcefully don't inline if this is not public or if the
2201         // #[doc(no_inline)] attribute is present.
2202         // Don't inline doc(hidden) imports so they can be stripped at a later stage.
2203         let mut denied = !self.vis.node.is_pub() || self.attrs.iter().any(|a| {
2204             a.check_name(sym::doc) && match a.meta_item_list() {
2205                 Some(l) => attr::list_contains_name(&l, sym::no_inline) ||
2206                            attr::list_contains_name(&l, sym::hidden),
2207                 None => false,
2208             }
2209         });
2210         // Also check whether imports were asked to be inlined, in case we're trying to re-export a
2211         // crate in Rust 2018+
2212         let please_inline = self.attrs.lists(sym::doc).has_word(sym::inline);
2213         let path = self.path.clean(cx);
2214         let inner = if self.glob {
2215             if !denied {
2216                 let mut visited = FxHashSet::default();
2217                 if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) {
2218                     return items;
2219                 }
2220             }
2221
2222             Import::Glob(resolve_use_source(cx, path))
2223         } else {
2224             let name = self.name;
2225             if !please_inline {
2226                 match path.res {
2227                     Res::Def(DefKind::Mod, did) => {
2228                         if !did.is_local() && did.index == CRATE_DEF_INDEX {
2229                             // if we're `pub use`ing an extern crate root, don't inline it unless we
2230                             // were specifically asked for it
2231                             denied = true;
2232                         }
2233                     }
2234                     _ => {}
2235                 }
2236             }
2237             if !denied {
2238                 let mut visited = FxHashSet::default();
2239                 if let Some(items) = inline::try_inline(
2240                     cx, path.res, name,
2241                     Some(rustc::ty::Attributes::Borrowed(self.attrs)),
2242                     &mut visited
2243                 ) {
2244                     return items;
2245                 }
2246             }
2247             Import::Simple(name.clean(cx), resolve_use_source(cx, path))
2248         };
2249
2250         vec![Item {
2251             name: None,
2252             attrs: self.attrs.clean(cx),
2253             source: self.whence.clean(cx),
2254             def_id: cx.tcx.hir().local_def_id_from_node_id(ast::CRATE_NODE_ID),
2255             visibility: self.vis.clean(cx),
2256             stability: None,
2257             deprecation: None,
2258             inner: ImportItem(inner)
2259         }]
2260     }
2261 }
2262
2263 impl Clean<Item> for doctree::ForeignItem<'_> {
2264     fn clean(&self, cx: &DocContext<'_>) -> Item {
2265         let inner = match self.kind {
2266             hir::ForeignItemKind::Fn(ref decl, ref names, ref generics) => {
2267                 let abi = cx.tcx.hir().get_foreign_abi(self.id);
2268                 let (generics, decl) = enter_impl_trait(cx, || {
2269                     (generics.clean(cx), (&**decl, &names[..]).clean(cx))
2270                 });
2271                 let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
2272                 ForeignFunctionItem(Function {
2273                     decl,
2274                     generics,
2275                     header: hir::FnHeader {
2276                         unsafety: hir::Unsafety::Unsafe,
2277                         abi,
2278                         constness: hir::Constness::NotConst,
2279                         asyncness: hir::IsAsync::NotAsync,
2280                     },
2281                     all_types,
2282                     ret_types,
2283                 })
2284             }
2285             hir::ForeignItemKind::Static(ref ty, mutbl) => {
2286                 ForeignStaticItem(Static {
2287                     type_: ty.clean(cx),
2288                     mutability: *mutbl,
2289                     expr: String::new(),
2290                 })
2291             }
2292             hir::ForeignItemKind::Type => {
2293                 ForeignTypeItem
2294             }
2295         };
2296
2297         Item {
2298             name: Some(self.name.clean(cx)),
2299             attrs: self.attrs.clean(cx),
2300             source: self.whence.clean(cx),
2301             def_id: cx.tcx.hir().local_def_id(self.id),
2302             visibility: self.vis.clean(cx),
2303             stability: cx.stability(self.id).clean(cx),
2304             deprecation: cx.deprecation(self.id).clean(cx),
2305             inner,
2306         }
2307     }
2308 }
2309
2310 impl Clean<Item> for doctree::Macro<'_> {
2311     fn clean(&self, cx: &DocContext<'_>) -> Item {
2312         let name = self.name.clean(cx);
2313         Item {
2314             name: Some(name.clone()),
2315             attrs: self.attrs.clean(cx),
2316             source: self.whence.clean(cx),
2317             visibility: Public,
2318             stability: cx.stability(self.hid).clean(cx),
2319             deprecation: cx.deprecation(self.hid).clean(cx),
2320             def_id: self.def_id,
2321             inner: MacroItem(Macro {
2322                 source: format!("macro_rules! {} {{\n{}}}",
2323                                 name,
2324                                 self.matchers.iter().map(|span| {
2325                                     format!("    {} => {{ ... }};\n", span.to_src(cx))
2326                                 }).collect::<String>()),
2327                 imported_from: self.imported_from.clean(cx),
2328             }),
2329         }
2330     }
2331 }
2332
2333 impl Clean<Item> for doctree::ProcMacro<'_> {
2334     fn clean(&self, cx: &DocContext<'_>) -> Item {
2335         Item {
2336             name: Some(self.name.clean(cx)),
2337             attrs: self.attrs.clean(cx),
2338             source: self.whence.clean(cx),
2339             visibility: Public,
2340             stability: cx.stability(self.id).clean(cx),
2341             deprecation: cx.deprecation(self.id).clean(cx),
2342             def_id: cx.tcx.hir().local_def_id(self.id),
2343             inner: ProcMacroItem(ProcMacro {
2344                 kind: self.kind,
2345                 helpers: self.helpers.clean(cx),
2346             }),
2347         }
2348     }
2349 }
2350
2351 impl Clean<Stability> for attr::Stability {
2352     fn clean(&self, _: &DocContext<'_>) -> Stability {
2353         Stability {
2354             level: stability::StabilityLevel::from_attr_level(&self.level),
2355             feature: Some(self.feature.to_string()).filter(|f| !f.is_empty()),
2356             since: match self.level {
2357                 attr::Stable {ref since} => since.to_string(),
2358                 _ => String::new(),
2359             },
2360             deprecation: self.rustc_depr.as_ref().map(|d| {
2361                 Deprecation {
2362                     note: Some(d.reason.to_string()).filter(|r| !r.is_empty()),
2363                     since: Some(d.since.to_string()).filter(|d| !d.is_empty()),
2364                 }
2365             }),
2366             unstable_reason: match self.level {
2367                 attr::Unstable { reason: Some(ref reason), .. } => Some(reason.to_string()),
2368                 _ => None,
2369             },
2370             issue: match self.level {
2371                 attr::Unstable {issue, ..} => issue,
2372                 _ => None,
2373             }
2374         }
2375     }
2376 }
2377
2378 impl<'a> Clean<Stability> for &'a attr::Stability {
2379     fn clean(&self, dc: &DocContext<'_>) -> Stability {
2380         (**self).clean(dc)
2381     }
2382 }
2383
2384 impl Clean<Deprecation> for attr::Deprecation {
2385     fn clean(&self, _: &DocContext<'_>) -> Deprecation {
2386         Deprecation {
2387             since: self.since.map(|s| s.to_string()).filter(|s| !s.is_empty()),
2388             note: self.note.map(|n| n.to_string()).filter(|n| !n.is_empty()),
2389         }
2390     }
2391 }
2392
2393 impl Clean<TypeBinding> for hir::TypeBinding {
2394     fn clean(&self, cx: &DocContext<'_>) -> TypeBinding {
2395         TypeBinding {
2396             name: self.ident.name.clean(cx),
2397             kind: self.kind.clean(cx),
2398         }
2399     }
2400 }
2401
2402 impl Clean<TypeBindingKind> for hir::TypeBindingKind {
2403     fn clean(&self, cx: &DocContext<'_>) -> TypeBindingKind {
2404         match *self {
2405             hir::TypeBindingKind::Equality { ref ty } =>
2406                 TypeBindingKind::Equality {
2407                     ty: ty.clean(cx),
2408                 },
2409             hir::TypeBindingKind::Constraint { ref bounds } =>
2410                 TypeBindingKind::Constraint {
2411                     bounds: bounds.into_iter().map(|b| b.clean(cx)).collect(),
2412                 },
2413         }
2414     }
2415 }
2416
2417 enum SimpleBound {
2418     TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier),
2419     Outlives(Lifetime),
2420 }
2421
2422 impl From<GenericBound> for SimpleBound {
2423     fn from(bound: GenericBound) -> Self {
2424         match bound.clone() {
2425             GenericBound::Outlives(l) => SimpleBound::Outlives(l),
2426             GenericBound::TraitBound(t, mod_) => match t.trait_ {
2427                 Type::ResolvedPath { path, param_names, .. } => {
2428                     SimpleBound::TraitBound(path.segments,
2429                                             param_names
2430                                                 .map_or_else(|| Vec::new(), |v| v.iter()
2431                                                         .map(|p| SimpleBound::from(p.clone()))
2432                                                         .collect()),
2433                                             t.generic_params,
2434                                             mod_)
2435                 }
2436                 _ => panic!("Unexpected bound {:?}", bound),
2437             }
2438         }
2439     }
2440 }