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