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