]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/clean/mod.rs
Merge commit '5ff7b632a95bac6955611d85040859128902c580' into sync-rustfmt-subtree
[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 crate mod cfg;
7 crate mod inline;
8 mod render_macro_matchers;
9 mod simplify;
10 crate mod types;
11 crate mod utils;
12
13 use rustc_ast as ast;
14 use rustc_attr as attr;
15 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
16 use rustc_hir as hir;
17 use rustc_hir::def::{CtorKind, DefKind, Res};
18 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
19 use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
20 use rustc_middle::middle::resolve_lifetime as rl;
21 use rustc_middle::ty::fold::TypeFolder;
22 use rustc_middle::ty::subst::{InternalSubsts, Subst};
23 use rustc_middle::ty::{self, AdtKind, DefIdTree, Lift, Ty, TyCtxt};
24 use rustc_middle::{bug, span_bug};
25 use rustc_span::hygiene::{AstPass, MacroKind};
26 use rustc_span::symbol::{kw, sym, Ident, Symbol};
27 use rustc_span::{self, ExpnKind};
28 use rustc_typeck::hir_ty_to_ty;
29
30 use std::assert_matches::assert_matches;
31 use std::collections::hash_map::Entry;
32 use std::collections::BTreeMap;
33 use std::default::Default;
34 use std::hash::Hash;
35 use std::{mem, vec};
36
37 use crate::core::{self, DocContext, ImplTraitParam};
38 use crate::formats::item_type::ItemType;
39 use crate::visit_ast::Module as DocModule;
40
41 use utils::*;
42
43 crate use self::types::*;
44 crate use self::utils::{get_auto_trait_and_blanket_impls, krate, register_res};
45
46 crate trait Clean<T> {
47     fn clean(&self, cx: &mut DocContext<'_>) -> T;
48 }
49
50 impl Clean<Item> for DocModule<'_> {
51     fn clean(&self, cx: &mut DocContext<'_>) -> Item {
52         let mut items: Vec<Item> = vec![];
53         items.extend(
54             self.foreigns
55                 .iter()
56                 .map(|(item, renamed)| clean_maybe_renamed_foreign_item(cx, item, *renamed)),
57         );
58         items.extend(self.mods.iter().map(|x| x.clean(cx)));
59         items.extend(
60             self.items
61                 .iter()
62                 .flat_map(|(item, renamed)| clean_maybe_renamed_item(cx, item, *renamed)),
63         );
64
65         // determine if we should display the inner contents or
66         // the outer `mod` item for the source code.
67
68         let span = Span::new({
69             let where_outer = self.where_outer(cx.tcx);
70             let sm = cx.sess().source_map();
71             let outer = sm.lookup_char_pos(where_outer.lo());
72             let inner = sm.lookup_char_pos(self.where_inner.lo());
73             if outer.file.start_pos == inner.file.start_pos {
74                 // mod foo { ... }
75                 where_outer
76             } else {
77                 // mod foo; (and a separate SourceFile for the contents)
78                 self.where_inner
79             }
80         });
81
82         Item::from_hir_id_and_parts(
83             self.id,
84             Some(self.name),
85             ModuleItem(Module { items, span }),
86             cx,
87         )
88     }
89 }
90
91 impl Clean<Attributes> for [ast::Attribute] {
92     fn clean(&self, _cx: &mut DocContext<'_>) -> Attributes {
93         Attributes::from_ast(self, None)
94     }
95 }
96
97 impl Clean<Option<GenericBound>> for hir::GenericBound<'_> {
98     fn clean(&self, cx: &mut DocContext<'_>) -> Option<GenericBound> {
99         Some(match *self {
100             hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)),
101             hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
102                 let def_id = cx.tcx.require_lang_item(lang_item, Some(span));
103
104                 let trait_ref = ty::TraitRef::identity(cx.tcx, def_id).skip_binder();
105
106                 let generic_args = generic_args.clean(cx);
107                 let GenericArgs::AngleBracketed { bindings, .. } = generic_args
108                 else {
109                     bug!("clean: parenthesized `GenericBound::LangItemTrait`");
110                 };
111
112                 let trait_ = clean_trait_ref_with_bindings(cx, trait_ref, &bindings);
113                 GenericBound::TraitBound(
114                     PolyTrait { trait_, generic_params: vec![] },
115                     hir::TraitBoundModifier::None,
116                 )
117             }
118             hir::GenericBound::Trait(ref t, modifier) => {
119                 // `T: ~const Drop` is not equivalent to `T: Drop`, and we don't currently document `~const` bounds
120                 // because of its experimental status, so just don't show these.
121                 // `T: ~const Destruct` is hidden because `T: Destruct` is a no-op.
122                 if modifier == hir::TraitBoundModifier::MaybeConst
123                     && [cx.tcx.lang_items().drop_trait(), cx.tcx.lang_items().destruct_trait()]
124                         .iter()
125                         .any(|tr| *tr == Some(t.trait_ref.trait_def_id().unwrap()))
126                 {
127                     return None;
128                 }
129
130                 #[cfg(bootstrap)]
131                 {
132                     // FIXME: remove `lang_items().drop_trait()` from above logic,
133                     // as well as the comment about `~const Drop` because it was renamed to `Destruct`.
134                 }
135                 GenericBound::TraitBound(t.clean(cx), modifier)
136             }
137         })
138     }
139 }
140
141 fn clean_trait_ref_with_bindings(
142     cx: &mut DocContext<'_>,
143     trait_ref: ty::TraitRef<'_>,
144     bindings: &[TypeBinding],
145 ) -> Path {
146     let kind = cx.tcx.def_kind(trait_ref.def_id).into();
147     if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) {
148         span_bug!(cx.tcx.def_span(trait_ref.def_id), "`TraitRef` had unexpected kind {:?}", kind);
149     }
150     inline::record_extern_fqn(cx, trait_ref.def_id, kind);
151     let path = external_path(cx, trait_ref.def_id, true, bindings.to_vec(), trait_ref.substs);
152
153     debug!("ty::TraitRef\n  subst: {:?}\n", trait_ref.substs);
154
155     path
156 }
157
158 impl Clean<Path> for ty::TraitRef<'_> {
159     fn clean(&self, cx: &mut DocContext<'_>) -> Path {
160         clean_trait_ref_with_bindings(cx, *self, &[])
161     }
162 }
163
164 fn clean_poly_trait_ref_with_bindings(
165     cx: &mut DocContext<'_>,
166     poly_trait_ref: ty::PolyTraitRef<'_>,
167     bindings: &[TypeBinding],
168 ) -> GenericBound {
169     let poly_trait_ref = poly_trait_ref.lift_to_tcx(cx.tcx).unwrap();
170
171     // collect any late bound regions
172     let late_bound_regions: Vec<_> = cx
173         .tcx
174         .collect_referenced_late_bound_regions(&poly_trait_ref)
175         .into_iter()
176         .filter_map(|br| match br {
177             ty::BrNamed(_, name) => Some(GenericParamDef {
178                 name,
179                 kind: GenericParamDefKind::Lifetime { outlives: vec![] },
180             }),
181             _ => None,
182         })
183         .collect();
184
185     let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref.skip_binder(), bindings);
186     GenericBound::TraitBound(
187         PolyTrait { trait_, generic_params: late_bound_regions },
188         hir::TraitBoundModifier::None,
189     )
190 }
191
192 impl<'tcx> Clean<GenericBound> for ty::PolyTraitRef<'tcx> {
193     fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
194         clean_poly_trait_ref_with_bindings(cx, *self, &[])
195     }
196 }
197
198 impl Clean<Lifetime> for hir::Lifetime {
199     fn clean(&self, cx: &mut DocContext<'_>) -> Lifetime {
200         let def = cx.tcx.named_region(self.hir_id);
201         if let Some(
202             rl::Region::EarlyBound(_, node_id)
203             | rl::Region::LateBound(_, _, node_id)
204             | rl::Region::Free(_, node_id),
205         ) = def
206         {
207             if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() {
208                 return lt;
209             }
210         }
211         Lifetime(self.name.ident().name)
212     }
213 }
214
215 impl Clean<Constant> for hir::ConstArg {
216     fn clean(&self, cx: &mut DocContext<'_>) -> Constant {
217         Constant {
218             type_: cx
219                 .tcx
220                 .type_of(cx.tcx.hir().body_owner_def_id(self.value.body).to_def_id())
221                 .clean(cx),
222             kind: ConstantKind::Anonymous { body: self.value.body },
223         }
224     }
225 }
226
227 impl Clean<Option<Lifetime>> for ty::Region<'_> {
228     fn clean(&self, _cx: &mut DocContext<'_>) -> Option<Lifetime> {
229         match **self {
230             ty::ReStatic => Some(Lifetime::statik()),
231             ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => {
232                 Some(Lifetime(name))
233             }
234             ty::ReEarlyBound(ref data) => Some(Lifetime(data.name)),
235
236             ty::ReLateBound(..)
237             | ty::ReFree(..)
238             | ty::ReVar(..)
239             | ty::RePlaceholder(..)
240             | ty::ReEmpty(_)
241             | ty::ReErased => {
242                 debug!("cannot clean region {:?}", self);
243                 None
244             }
245         }
246     }
247 }
248
249 impl Clean<WherePredicate> for hir::WherePredicate<'_> {
250     fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate {
251         match *self {
252             hir::WherePredicate::BoundPredicate(ref wbp) => {
253                 let bound_params = wbp
254                     .bound_generic_params
255                     .into_iter()
256                     .map(|param| {
257                         // Higher-ranked params must be lifetimes.
258                         // Higher-ranked lifetimes can't have bounds.
259                         assert_matches!(
260                             param,
261                             hir::GenericParam {
262                                 kind: hir::GenericParamKind::Lifetime { .. },
263                                 bounds: [],
264                                 ..
265                             }
266                         );
267                         Lifetime(param.name.ident().name)
268                     })
269                     .collect();
270                 WherePredicate::BoundPredicate {
271                     ty: wbp.bounded_ty.clean(cx),
272                     bounds: wbp.bounds.iter().filter_map(|x| x.clean(cx)).collect(),
273                     bound_params,
274                 }
275             }
276
277             hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
278                 lifetime: wrp.lifetime.clean(cx),
279                 bounds: wrp.bounds.iter().filter_map(|x| x.clean(cx)).collect(),
280             },
281
282             hir::WherePredicate::EqPredicate(ref wrp) => WherePredicate::EqPredicate {
283                 lhs: wrp.lhs_ty.clean(cx),
284                 rhs: wrp.rhs_ty.clean(cx).into(),
285             },
286         }
287     }
288 }
289
290 impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
291     fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> {
292         let bound_predicate = self.kind();
293         match bound_predicate.skip_binder() {
294             ty::PredicateKind::Trait(pred) => bound_predicate.rebind(pred).clean(cx),
295             ty::PredicateKind::RegionOutlives(pred) => pred.clean(cx),
296             ty::PredicateKind::TypeOutlives(pred) => pred.clean(cx),
297             ty::PredicateKind::Projection(pred) => Some(pred.clean(cx)),
298             ty::PredicateKind::ConstEvaluatable(..) => None,
299
300             ty::PredicateKind::Subtype(..)
301             | ty::PredicateKind::Coerce(..)
302             | ty::PredicateKind::WellFormed(..)
303             | ty::PredicateKind::ObjectSafe(..)
304             | ty::PredicateKind::ClosureKind(..)
305             | ty::PredicateKind::ConstEquate(..)
306             | ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"),
307         }
308     }
309 }
310
311 impl<'a> Clean<Option<WherePredicate>> for ty::PolyTraitPredicate<'a> {
312     fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> {
313         // `T: ~const Drop` is not equivalent to `T: Drop`, and we don't currently document `~const` bounds
314         // because of its experimental status, so just don't show these.
315         // `T: ~const Destruct` is hidden because `T: Destruct` is a no-op.
316         if self.skip_binder().constness == ty::BoundConstness::ConstIfConst
317             && [cx.tcx.lang_items().drop_trait(), cx.tcx.lang_items().destruct_trait()]
318                 .iter()
319                 .any(|tr| *tr == Some(self.skip_binder().def_id()))
320         {
321             return None;
322         }
323
324         #[cfg(bootstrap)]
325         {
326             // FIXME: remove `lang_items().drop_trait()` from above logic,
327             // as well as the comment about `~const Drop` because it was renamed to `Destruct`.
328         }
329
330         let poly_trait_ref = self.map_bound(|pred| pred.trait_ref);
331         Some(WherePredicate::BoundPredicate {
332             ty: poly_trait_ref.skip_binder().self_ty().clean(cx),
333             bounds: vec![poly_trait_ref.clean(cx)],
334             bound_params: Vec::new(),
335         })
336     }
337 }
338
339 impl<'tcx> Clean<Option<WherePredicate>>
340     for ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
341 {
342     fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> {
343         let ty::OutlivesPredicate(a, b) = self;
344
345         if a.is_empty() && b.is_empty() {
346             return None;
347         }
348
349         Some(WherePredicate::RegionPredicate {
350             lifetime: a.clean(cx).expect("failed to clean lifetime"),
351             bounds: vec![GenericBound::Outlives(b.clean(cx).expect("failed to clean bounds"))],
352         })
353     }
354 }
355
356 impl<'tcx> Clean<Option<WherePredicate>> for ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>> {
357     fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> {
358         let ty::OutlivesPredicate(ty, lt) = self;
359
360         if lt.is_empty() {
361             return None;
362         }
363
364         Some(WherePredicate::BoundPredicate {
365             ty: ty.clean(cx),
366             bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))],
367             bound_params: Vec::new(),
368         })
369     }
370 }
371
372 impl<'tcx> Clean<Term> for ty::Term<'tcx> {
373     fn clean(&self, cx: &mut DocContext<'_>) -> Term {
374         match self {
375             ty::Term::Ty(ty) => Term::Type(ty.clean(cx)),
376             ty::Term::Const(c) => Term::Constant(c.clean(cx)),
377         }
378     }
379 }
380
381 impl<'tcx> Clean<Term> for hir::Term<'tcx> {
382     fn clean(&self, cx: &mut DocContext<'_>) -> Term {
383         match self {
384             hir::Term::Ty(ty) => Term::Type(ty.clean(cx)),
385             hir::Term::Const(c) => {
386                 let def_id = cx.tcx.hir().local_def_id(c.hir_id);
387                 Term::Constant(ty::Const::from_anon_const(cx.tcx, def_id).clean(cx))
388             }
389         }
390     }
391 }
392
393 impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
394     fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate {
395         let ty::ProjectionPredicate { projection_ty, term } = self;
396         WherePredicate::EqPredicate { lhs: projection_ty.clean(cx), rhs: term.clean(cx) }
397     }
398 }
399
400 impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
401     fn clean(&self, cx: &mut DocContext<'_>) -> Type {
402         let lifted = self.lift_to_tcx(cx.tcx).unwrap();
403         let trait_ = lifted.trait_ref(cx.tcx).clean(cx);
404         let self_type = self.self_ty().clean(cx);
405         Type::QPath {
406             assoc: Box::new(projection_to_path_segment(*self, cx)),
407             self_def_id: self_type.def_id(&cx.cache),
408             self_type: box self_type,
409             trait_,
410         }
411     }
412 }
413
414 fn projection_to_path_segment(ty: ty::ProjectionTy<'_>, cx: &mut DocContext<'_>) -> PathSegment {
415     let item = cx.tcx.associated_item(ty.item_def_id);
416     let generics = cx.tcx.generics_of(ty.item_def_id);
417     PathSegment {
418         name: item.name,
419         args: GenericArgs::AngleBracketed {
420             args: substs_to_args(cx, &ty.substs[generics.parent_count..], false),
421             bindings: Default::default(),
422         },
423     }
424 }
425
426 impl Clean<GenericParamDef> for ty::GenericParamDef {
427     fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
428         let (name, kind) = match self.kind {
429             ty::GenericParamDefKind::Lifetime => {
430                 (self.name, GenericParamDefKind::Lifetime { outlives: vec![] })
431             }
432             ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
433                 let default = if has_default {
434                     let mut default = cx.tcx.type_of(self.def_id).clean(cx);
435
436                     // We need to reassign the `self_def_id`, if there's a parent (which is the
437                     // `Self` type), so we can properly render `<Self as X>` casts, because the
438                     // information about which type `Self` is, is only present here, but not in
439                     // the cleaning process of the type itself. To resolve this and have the
440                     // `self_def_id` set, we override it here.
441                     // See https://github.com/rust-lang/rust/issues/85454
442                     if let QPath { ref mut self_def_id, .. } = default {
443                         *self_def_id = cx.tcx.parent(self.def_id);
444                     }
445
446                     Some(default)
447                 } else {
448                     None
449                 };
450                 (
451                     self.name,
452                     GenericParamDefKind::Type {
453                         did: self.def_id,
454                         bounds: vec![], // These are filled in from the where-clauses.
455                         default: default.map(Box::new),
456                         synthetic,
457                     },
458                 )
459             }
460             ty::GenericParamDefKind::Const { has_default } => (
461                 self.name,
462                 GenericParamDefKind::Const {
463                     did: self.def_id,
464                     ty: Box::new(cx.tcx.type_of(self.def_id).clean(cx)),
465                     default: match has_default {
466                         true => Some(Box::new(cx.tcx.const_param_default(self.def_id).to_string())),
467                         false => None,
468                     },
469                 },
470             ),
471         };
472
473         GenericParamDef { name, kind }
474     }
475 }
476
477 impl Clean<GenericParamDef> for hir::GenericParam<'_> {
478     fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
479         let (name, kind) = match self.kind {
480             hir::GenericParamKind::Lifetime { .. } => {
481                 let outlives = self
482                     .bounds
483                     .iter()
484                     .map(|bound| match bound {
485                         hir::GenericBound::Outlives(lt) => lt.clean(cx),
486                         _ => panic!(),
487                     })
488                     .collect();
489                 (self.name.ident().name, GenericParamDefKind::Lifetime { outlives })
490             }
491             hir::GenericParamKind::Type { ref default, synthetic } => (
492                 self.name.ident().name,
493                 GenericParamDefKind::Type {
494                     did: cx.tcx.hir().local_def_id(self.hir_id).to_def_id(),
495                     bounds: self.bounds.iter().filter_map(|x| x.clean(cx)).collect(),
496                     default: default.map(|t| t.clean(cx)).map(Box::new),
497                     synthetic,
498                 },
499             ),
500             hir::GenericParamKind::Const { ref ty, default } => (
501                 self.name.ident().name,
502                 GenericParamDefKind::Const {
503                     did: cx.tcx.hir().local_def_id(self.hir_id).to_def_id(),
504                     ty: Box::new(ty.clean(cx)),
505                     default: default.map(|ct| {
506                         let def_id = cx.tcx.hir().local_def_id(ct.hir_id);
507                         Box::new(ty::Const::from_anon_const(cx.tcx, def_id).to_string())
508                     }),
509                 },
510             ),
511         };
512
513         GenericParamDef { name, kind }
514     }
515 }
516
517 impl Clean<Generics> for hir::Generics<'_> {
518     fn clean(&self, cx: &mut DocContext<'_>) -> Generics {
519         // Synthetic type-parameters are inserted after normal ones.
520         // In order for normal parameters to be able to refer to synthetic ones,
521         // scans them first.
522         fn is_impl_trait(param: &hir::GenericParam<'_>) -> bool {
523             match param.kind {
524                 hir::GenericParamKind::Type { synthetic, .. } => synthetic,
525                 _ => false,
526             }
527         }
528         /// This can happen for `async fn`, e.g. `async fn f<'_>(&'_ self)`.
529         ///
530         /// See [`lifetime_to_generic_param`] in [`rustc_ast_lowering`] for more information.
531         ///
532         /// [`lifetime_to_generic_param`]: rustc_ast_lowering::LoweringContext::lifetime_to_generic_param
533         fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool {
534             matches!(
535                 param.kind,
536                 hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided }
537             )
538         }
539
540         let impl_trait_params = self
541             .params
542             .iter()
543             .filter(|param| is_impl_trait(param))
544             .map(|param| {
545                 let param: GenericParamDef = param.clean(cx);
546                 match param.kind {
547                     GenericParamDefKind::Lifetime { .. } => unreachable!(),
548                     GenericParamDefKind::Type { did, ref bounds, .. } => {
549                         cx.impl_trait_bounds.insert(did.into(), bounds.clone());
550                     }
551                     GenericParamDefKind::Const { .. } => unreachable!(),
552                 }
553                 param
554             })
555             .collect::<Vec<_>>();
556
557         let mut params = Vec::with_capacity(self.params.len());
558         for p in self.params.iter().filter(|p| !is_impl_trait(p) && !is_elided_lifetime(p)) {
559             let p = p.clean(cx);
560             params.push(p);
561         }
562         params.extend(impl_trait_params);
563
564         let mut generics = Generics {
565             params,
566             where_predicates: self.where_clause.predicates.iter().map(|x| x.clean(cx)).collect(),
567         };
568
569         // Some duplicates are generated for ?Sized bounds between type params and where
570         // predicates. The point in here is to move the bounds definitions from type params
571         // to where predicates when such cases occur.
572         for where_pred in &mut generics.where_predicates {
573             match *where_pred {
574                 WherePredicate::BoundPredicate {
575                     ty: Generic(ref name), ref mut bounds, ..
576                 } => {
577                     if bounds.is_empty() {
578                         for param in &mut generics.params {
579                             match param.kind {
580                                 GenericParamDefKind::Lifetime { .. } => {}
581                                 GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
582                                     if &param.name == name {
583                                         mem::swap(bounds, ty_bounds);
584                                         break;
585                                     }
586                                 }
587                                 GenericParamDefKind::Const { .. } => {}
588                             }
589                         }
590                     }
591                 }
592                 _ => continue,
593             }
594         }
595         generics
596     }
597 }
598
599 fn clean_ty_generics(
600     cx: &mut DocContext<'_>,
601     gens: &ty::Generics,
602     preds: ty::GenericPredicates<'_>,
603 ) -> Generics {
604     // Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
605     // since `Clean for ty::Predicate` would consume them.
606     let mut impl_trait = BTreeMap::<ImplTraitParam, Vec<GenericBound>>::default();
607
608     // Bounds in the type_params and lifetimes fields are repeated in the
609     // predicates field (see rustc_typeck::collect::ty_generics), so remove
610     // them.
611     let stripped_params = gens
612         .params
613         .iter()
614         .filter_map(|param| match param.kind {
615             ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
616             ty::GenericParamDefKind::Type { synthetic, .. } => {
617                 if param.name == kw::SelfUpper {
618                     assert_eq!(param.index, 0);
619                     return None;
620                 }
621                 if synthetic {
622                     impl_trait.insert(param.index.into(), vec![]);
623                     return None;
624                 }
625                 Some(param.clean(cx))
626             }
627             ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)),
628         })
629         .collect::<Vec<GenericParamDef>>();
630
631     // param index -> [(DefId of trait, associated type name and generics, type)]
632     let mut impl_trait_proj = FxHashMap::<u32, Vec<(DefId, PathSegment, Ty<'_>)>>::default();
633
634     let where_predicates = preds
635         .predicates
636         .iter()
637         .flat_map(|(p, _)| {
638             let mut projection = None;
639             let param_idx = (|| {
640                 let bound_p = p.kind();
641                 match bound_p.skip_binder() {
642                     ty::PredicateKind::Trait(pred) => {
643                         if let ty::Param(param) = pred.self_ty().kind() {
644                             return Some(param.index);
645                         }
646                     }
647                     ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
648                         if let ty::Param(param) = ty.kind() {
649                             return Some(param.index);
650                         }
651                     }
652                     ty::PredicateKind::Projection(p) => {
653                         if let ty::Param(param) = p.projection_ty.self_ty().kind() {
654                             projection = Some(bound_p.rebind(p));
655                             return Some(param.index);
656                         }
657                     }
658                     _ => (),
659                 }
660
661                 None
662             })();
663
664             if let Some(param_idx) = param_idx {
665                 if let Some(b) = impl_trait.get_mut(&param_idx.into()) {
666                     let p: WherePredicate = p.clean(cx)?;
667
668                     b.extend(
669                         p.get_bounds()
670                             .into_iter()
671                             .flatten()
672                             .cloned()
673                             .filter(|b| !b.is_sized_bound(cx)),
674                     );
675
676                     let proj = projection
677                         .map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().term));
678                     if let Some(((_, trait_did, name), rhs)) = proj
679                         .as_ref()
680                         .and_then(|(lhs, rhs): &(Type, _)| Some((lhs.projection()?, rhs)))
681                     {
682                         // FIXME(...): Remove this unwrap()
683                         impl_trait_proj.entry(param_idx).or_default().push((
684                             trait_did,
685                             name,
686                             rhs.ty().unwrap(),
687                         ));
688                     }
689
690                     return None;
691                 }
692             }
693
694             Some(p)
695         })
696         .collect::<Vec<_>>();
697
698     for (param, mut bounds) in impl_trait {
699         // Move trait bounds to the front.
700         bounds.sort_by_key(|b| !matches!(b, GenericBound::TraitBound(..)));
701
702         if let crate::core::ImplTraitParam::ParamIndex(idx) = param {
703             if let Some(proj) = impl_trait_proj.remove(&idx) {
704                 for (trait_did, name, rhs) in proj {
705                     let rhs = rhs.clean(cx);
706                     simplify::merge_bounds(cx, &mut bounds, trait_did, name, &Term::Type(rhs));
707                 }
708             }
709         } else {
710             unreachable!();
711         }
712
713         cx.impl_trait_bounds.insert(param, bounds);
714     }
715
716     // Now that `cx.impl_trait_bounds` is populated, we can process
717     // remaining predicates which could contain `impl Trait`.
718     let mut where_predicates =
719         where_predicates.into_iter().flat_map(|p| p.clean(cx)).collect::<Vec<_>>();
720
721     // Type parameters have a Sized bound by default unless removed with
722     // ?Sized. Scan through the predicates and mark any type parameter with
723     // a Sized bound, removing the bounds as we find them.
724     //
725     // Note that associated types also have a sized bound by default, but we
726     // don't actually know the set of associated types right here so that's
727     // handled in cleaning associated types
728     let mut sized_params = FxHashSet::default();
729     where_predicates.retain(|pred| match *pred {
730         WherePredicate::BoundPredicate { ty: Generic(ref g), ref bounds, .. } => {
731             if bounds.iter().any(|b| b.is_sized_bound(cx)) {
732                 sized_params.insert(*g);
733                 false
734             } else {
735                 true
736             }
737         }
738         _ => true,
739     });
740
741     // Run through the type parameters again and insert a ?Sized
742     // unbound for any we didn't find to be Sized.
743     for tp in &stripped_params {
744         if matches!(tp.kind, types::GenericParamDefKind::Type { .. })
745             && !sized_params.contains(&tp.name)
746         {
747             where_predicates.push(WherePredicate::BoundPredicate {
748                 ty: Type::Generic(tp.name),
749                 bounds: vec![GenericBound::maybe_sized(cx)],
750                 bound_params: Vec::new(),
751             })
752         }
753     }
754
755     // It would be nice to collect all of the bounds on a type and recombine
756     // them if possible, to avoid e.g., `where T: Foo, T: Bar, T: Sized, T: 'a`
757     // and instead see `where T: Foo + Bar + Sized + 'a`
758
759     Generics {
760         params: stripped_params,
761         where_predicates: simplify::where_clauses(cx, where_predicates),
762     }
763 }
764
765 fn clean_fn_or_proc_macro(
766     item: &hir::Item<'_>,
767     sig: &hir::FnSig<'_>,
768     generics: &hir::Generics<'_>,
769     body_id: hir::BodyId,
770     name: &mut Symbol,
771     cx: &mut DocContext<'_>,
772 ) -> ItemKind {
773     let attrs = cx.tcx.hir().attrs(item.hir_id());
774     let macro_kind = attrs.iter().find_map(|a| {
775         if a.has_name(sym::proc_macro) {
776             Some(MacroKind::Bang)
777         } else if a.has_name(sym::proc_macro_derive) {
778             Some(MacroKind::Derive)
779         } else if a.has_name(sym::proc_macro_attribute) {
780             Some(MacroKind::Attr)
781         } else {
782             None
783         }
784     });
785     match macro_kind {
786         Some(kind) => {
787             if kind == MacroKind::Derive {
788                 *name = attrs
789                     .lists(sym::proc_macro_derive)
790                     .find_map(|mi| mi.ident())
791                     .expect("proc-macro derives require a name")
792                     .name;
793             }
794
795             let mut helpers = Vec::new();
796             for mi in attrs.lists(sym::proc_macro_derive) {
797                 if !mi.has_name(sym::attributes) {
798                     continue;
799                 }
800
801                 if let Some(list) = mi.meta_item_list() {
802                     for inner_mi in list {
803                         if let Some(ident) = inner_mi.ident() {
804                             helpers.push(ident.name);
805                         }
806                     }
807                 }
808             }
809             ProcMacroItem(ProcMacro { kind, helpers })
810         }
811         None => {
812             let mut func = clean_function(cx, sig, generics, body_id);
813             clean_fn_decl_legacy_const_generics(&mut func, attrs);
814             FunctionItem(func)
815         }
816     }
817 }
818
819 /// This is needed to make it more "readable" when documenting functions using
820 /// `rustc_legacy_const_generics`. More information in
821 /// <https://github.com/rust-lang/rust/issues/83167>.
822 fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[ast::Attribute]) {
823     for meta_item_list in attrs
824         .iter()
825         .filter(|a| a.has_name(sym::rustc_legacy_const_generics))
826         .filter_map(|a| a.meta_item_list())
827     {
828         for (pos, literal) in meta_item_list.iter().filter_map(|meta| meta.literal()).enumerate() {
829             match literal.kind {
830                 ast::LitKind::Int(a, _) => {
831                     let gen = func.generics.params.remove(0);
832                     if let GenericParamDef { name, kind: GenericParamDefKind::Const { ty, .. } } =
833                         gen
834                     {
835                         func.decl
836                             .inputs
837                             .values
838                             .insert(a as _, Argument { name, type_: *ty, is_const: true });
839                     } else {
840                         panic!("unexpected non const in position {pos}");
841                     }
842                 }
843                 _ => panic!("invalid arg index"),
844             }
845         }
846     }
847 }
848
849 fn clean_function(
850     cx: &mut DocContext<'_>,
851     sig: &hir::FnSig<'_>,
852     generics: &hir::Generics<'_>,
853     body_id: hir::BodyId,
854 ) -> Function {
855     let (generics, decl) = enter_impl_trait(cx, |cx| {
856         // NOTE: generics must be cleaned before args
857         let generics = generics.clean(cx);
858         let args = clean_args_from_types_and_body_id(cx, sig.decl.inputs, body_id);
859         let decl = clean_fn_decl_with_args(cx, sig.decl, args);
860         (generics, decl)
861     });
862     Function { decl, generics }
863 }
864
865 fn clean_args_from_types_and_names(
866     cx: &mut DocContext<'_>,
867     types: &[hir::Ty<'_>],
868     names: &[Ident],
869 ) -> Arguments {
870     Arguments {
871         values: types
872             .iter()
873             .enumerate()
874             .map(|(i, ty)| {
875                 let mut name = names.get(i).map_or(kw::Empty, |ident| ident.name);
876                 if name.is_empty() {
877                     name = kw::Underscore;
878                 }
879                 Argument { name, type_: ty.clean(cx), is_const: false }
880             })
881             .collect(),
882     }
883 }
884
885 fn clean_args_from_types_and_body_id(
886     cx: &mut DocContext<'_>,
887     types: &[hir::Ty<'_>],
888     body_id: hir::BodyId,
889 ) -> Arguments {
890     let body = cx.tcx.hir().body(body_id);
891
892     Arguments {
893         values: types
894             .iter()
895             .enumerate()
896             .map(|(i, ty)| Argument {
897                 name: name_from_pat(body.params[i].pat),
898                 type_: ty.clean(cx),
899                 is_const: false,
900             })
901             .collect(),
902     }
903 }
904
905 fn clean_fn_decl_with_args(
906     cx: &mut DocContext<'_>,
907     decl: &hir::FnDecl<'_>,
908     args: Arguments,
909 ) -> FnDecl {
910     FnDecl { inputs: args, output: decl.output.clean(cx), c_variadic: decl.c_variadic }
911 }
912
913 fn clean_fn_decl_from_did_and_sig(
914     cx: &mut DocContext<'_>,
915     did: Option<DefId>,
916     sig: ty::PolyFnSig<'_>,
917 ) -> FnDecl {
918     let mut names = did.map_or(&[] as &[_], |did| cx.tcx.fn_arg_names(did)).iter();
919
920     // We assume all empty tuples are default return type. This theoretically can discard `-> ()`,
921     // but shouldn't change any code meaning.
922     let output = match sig.skip_binder().output().clean(cx) {
923         Type::Tuple(inner) if inner.len() == 0 => DefaultReturn,
924         ty => Return(ty),
925     };
926
927     FnDecl {
928         output,
929         c_variadic: sig.skip_binder().c_variadic,
930         inputs: Arguments {
931             values: sig
932                 .skip_binder()
933                 .inputs()
934                 .iter()
935                 .map(|t| Argument {
936                     type_: t.clean(cx),
937                     name: names.next().map_or(kw::Empty, |i| i.name),
938                     is_const: false,
939                 })
940                 .collect(),
941         },
942     }
943 }
944
945 impl Clean<FnRetTy> for hir::FnRetTy<'_> {
946     fn clean(&self, cx: &mut DocContext<'_>) -> FnRetTy {
947         match *self {
948             Self::Return(ref typ) => Return(typ.clean(cx)),
949             Self::DefaultReturn(..) => DefaultReturn,
950         }
951     }
952 }
953
954 impl Clean<bool> for hir::IsAuto {
955     fn clean(&self, _: &mut DocContext<'_>) -> bool {
956         match *self {
957             hir::IsAuto::Yes => true,
958             hir::IsAuto::No => false,
959         }
960     }
961 }
962
963 impl Clean<Path> for hir::TraitRef<'_> {
964     fn clean(&self, cx: &mut DocContext<'_>) -> Path {
965         let path = self.path.clean(cx);
966         register_res(cx, path.res);
967         path
968     }
969 }
970
971 impl Clean<PolyTrait> for hir::PolyTraitRef<'_> {
972     fn clean(&self, cx: &mut DocContext<'_>) -> PolyTrait {
973         PolyTrait {
974             trait_: self.trait_ref.clean(cx),
975             generic_params: self.bound_generic_params.iter().map(|x| x.clean(cx)).collect(),
976         }
977     }
978 }
979
980 impl Clean<Item> for hir::TraitItem<'_> {
981     fn clean(&self, cx: &mut DocContext<'_>) -> Item {
982         let local_did = self.def_id.to_def_id();
983         cx.with_param_env(local_did, |cx| {
984             let inner = match self.kind {
985                 hir::TraitItemKind::Const(ref ty, default) => {
986                     let default =
987                         default.map(|e| ConstantKind::Local { def_id: local_did, body: e });
988                     AssocConstItem(ty.clean(cx), default)
989                 }
990                 hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
991                     let m = clean_function(cx, sig, &self.generics, body);
992                     MethodItem(m, None)
993                 }
994                 hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => {
995                     let (generics, decl) = enter_impl_trait(cx, |cx| {
996                         // NOTE: generics must be cleaned before args
997                         let generics = self.generics.clean(cx);
998                         let args = clean_args_from_types_and_names(cx, sig.decl.inputs, names);
999                         let decl = clean_fn_decl_with_args(cx, sig.decl, args);
1000                         (generics, decl)
1001                     });
1002                     TyMethodItem(Function { decl, generics })
1003                 }
1004                 hir::TraitItemKind::Type(bounds, ref default) => {
1005                     let generics = enter_impl_trait(cx, |cx| self.generics.clean(cx));
1006                     let bounds = bounds.iter().filter_map(|x| x.clean(cx)).collect();
1007                     let default = default.map(|t| t.clean(cx));
1008                     AssocTypeItem(Box::new(generics), bounds, default)
1009                 }
1010             };
1011             let what_rustc_thinks =
1012                 Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx);
1013             // Trait items always inherit the trait's visibility -- we don't want to show `pub`.
1014             Item { visibility: Inherited, ..what_rustc_thinks }
1015         })
1016     }
1017 }
1018
1019 impl Clean<Item> for hir::ImplItem<'_> {
1020     fn clean(&self, cx: &mut DocContext<'_>) -> Item {
1021         let local_did = self.def_id.to_def_id();
1022         cx.with_param_env(local_did, |cx| {
1023             let inner = match self.kind {
1024                 hir::ImplItemKind::Const(ref ty, expr) => {
1025                     let default = Some(ConstantKind::Local { def_id: local_did, body: expr });
1026                     AssocConstItem(ty.clean(cx), default)
1027                 }
1028                 hir::ImplItemKind::Fn(ref sig, body) => {
1029                     let m = clean_function(cx, sig, &self.generics, body);
1030                     let defaultness = cx.tcx.associated_item(self.def_id).defaultness;
1031                     MethodItem(m, Some(defaultness))
1032                 }
1033                 hir::ImplItemKind::TyAlias(ref hir_ty) => {
1034                     let type_ = hir_ty.clean(cx);
1035                     let generics = self.generics.clean(cx);
1036                     let item_type = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx);
1037                     TypedefItem(Typedef { type_, generics, item_type: Some(item_type) }, true)
1038                 }
1039             };
1040
1041             let mut what_rustc_thinks =
1042                 Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx);
1043
1044             let impl_ref = cx.tcx.parent(local_did).and_then(|did| cx.tcx.impl_trait_ref(did));
1045
1046             // Trait impl items always inherit the impl's visibility --
1047             // we don't want to show `pub`.
1048             if impl_ref.is_some() {
1049                 what_rustc_thinks.visibility = Inherited;
1050             }
1051
1052             what_rustc_thinks
1053         })
1054     }
1055 }
1056
1057 impl Clean<Item> for ty::AssocItem {
1058     fn clean(&self, cx: &mut DocContext<'_>) -> Item {
1059         let tcx = cx.tcx;
1060         let kind = match self.kind {
1061             ty::AssocKind::Const => {
1062                 let ty = tcx.type_of(self.def_id);
1063                 let default = if self.defaultness.has_value() {
1064                     Some(ConstantKind::Extern { def_id: self.def_id })
1065                 } else {
1066                     None
1067                 };
1068                 AssocConstItem(ty.clean(cx), default)
1069             }
1070             ty::AssocKind::Fn => {
1071                 let generics = clean_ty_generics(
1072                     cx,
1073                     tcx.generics_of(self.def_id),
1074                     tcx.explicit_predicates_of(self.def_id),
1075                 );
1076                 let sig = tcx.fn_sig(self.def_id);
1077                 let mut decl = clean_fn_decl_from_did_and_sig(cx, Some(self.def_id), sig);
1078
1079                 if self.fn_has_self_parameter {
1080                     let self_ty = match self.container {
1081                         ty::ImplContainer(def_id) => tcx.type_of(def_id),
1082                         ty::TraitContainer(_) => tcx.types.self_param,
1083                     };
1084                     let self_arg_ty = sig.input(0).skip_binder();
1085                     if self_arg_ty == self_ty {
1086                         decl.inputs.values[0].type_ = Generic(kw::SelfUpper);
1087                     } else if let ty::Ref(_, ty, _) = *self_arg_ty.kind() {
1088                         if ty == self_ty {
1089                             match decl.inputs.values[0].type_ {
1090                                 BorrowedRef { ref mut type_, .. } => {
1091                                     **type_ = Generic(kw::SelfUpper)
1092                                 }
1093                                 _ => unreachable!(),
1094                             }
1095                         }
1096                     }
1097                 }
1098
1099                 let provided = match self.container {
1100                     ty::ImplContainer(_) => true,
1101                     ty::TraitContainer(_) => self.defaultness.has_value(),
1102                 };
1103                 if provided {
1104                     let defaultness = match self.container {
1105                         ty::ImplContainer(_) => Some(self.defaultness),
1106                         ty::TraitContainer(_) => None,
1107                     };
1108                     MethodItem(Function { generics, decl }, defaultness)
1109                 } else {
1110                     TyMethodItem(Function { generics, decl })
1111                 }
1112             }
1113             ty::AssocKind::Type => {
1114                 let my_name = self.name;
1115
1116                 fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
1117                     match (&param.kind, arg) {
1118                         (GenericParamDefKind::Type { .. }, GenericArg::Type(Type::Generic(ty)))
1119                             if *ty == param.name =>
1120                         {
1121                             true
1122                         }
1123                         (
1124                             GenericParamDefKind::Lifetime { .. },
1125                             GenericArg::Lifetime(Lifetime(lt)),
1126                         ) if *lt == param.name => true,
1127                         (GenericParamDefKind::Const { .. }, GenericArg::Const(c)) => {
1128                             match &c.kind {
1129                                 ConstantKind::TyConst { expr } => expr == param.name.as_str(),
1130                                 _ => false,
1131                             }
1132                         }
1133                         _ => false,
1134                     }
1135                 }
1136
1137                 if let ty::TraitContainer(_) = self.container {
1138                     let bounds = tcx.explicit_item_bounds(self.def_id);
1139                     let predicates = ty::GenericPredicates { parent: None, predicates: bounds };
1140                     let mut generics =
1141                         clean_ty_generics(cx, tcx.generics_of(self.def_id), predicates);
1142                     // Filter out the bounds that are (likely?) directly attached to the associated type,
1143                     // as opposed to being located in the where clause.
1144                     let mut bounds = generics
1145                         .where_predicates
1146                         .drain_filter(|pred| match *pred {
1147                             WherePredicate::BoundPredicate {
1148                                 ty: QPath { ref assoc, ref self_type, ref trait_, .. },
1149                                 ..
1150                             } => {
1151                                 if assoc.name != my_name {
1152                                     return false;
1153                                 }
1154                                 if trait_.def_id() != self.container.id() {
1155                                     return false;
1156                                 }
1157                                 match **self_type {
1158                                     Generic(ref s) if *s == kw::SelfUpper => {}
1159                                     _ => return false,
1160                                 }
1161                                 match &assoc.args {
1162                                     GenericArgs::AngleBracketed { args, bindings } => {
1163                                         if !bindings.is_empty()
1164                                             || generics
1165                                                 .params
1166                                                 .iter()
1167                                                 .zip(args)
1168                                                 .any(|(param, arg)| !param_eq_arg(param, arg))
1169                                         {
1170                                             return false;
1171                                         }
1172                                     }
1173                                     GenericArgs::Parenthesized { .. } => {
1174                                         // The only time this happens is if we're inside the rustdoc for Fn(),
1175                                         // which only has one associated type, which is not a GAT, so whatever.
1176                                     }
1177                                 }
1178                                 true
1179                             }
1180                             _ => false,
1181                         })
1182                         .flat_map(|pred| {
1183                             if let WherePredicate::BoundPredicate { bounds, .. } = pred {
1184                                 bounds
1185                             } else {
1186                                 unreachable!()
1187                             }
1188                         })
1189                         .collect::<Vec<_>>();
1190                     // Our Sized/?Sized bound didn't get handled when creating the generics
1191                     // because we didn't actually get our whole set of bounds until just now
1192                     // (some of them may have come from the trait). If we do have a sized
1193                     // bound, we remove it, and if we don't then we add the `?Sized` bound
1194                     // at the end.
1195                     match bounds.iter().position(|b| b.is_sized_bound(cx)) {
1196                         Some(i) => {
1197                             bounds.remove(i);
1198                         }
1199                         None => bounds.push(GenericBound::maybe_sized(cx)),
1200                     }
1201
1202                     let ty = if self.defaultness.has_value() {
1203                         Some(tcx.type_of(self.def_id))
1204                     } else {
1205                         None
1206                     };
1207
1208                     AssocTypeItem(Box::new(generics), bounds, ty.map(|t| t.clean(cx)))
1209                 } else {
1210                     // FIXME: when could this happen? Associated items in inherent impls?
1211                     let type_ = tcx.type_of(self.def_id).clean(cx);
1212                     TypedefItem(
1213                         Typedef {
1214                             type_,
1215                             generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
1216                             item_type: None,
1217                         },
1218                         true,
1219                     )
1220                 }
1221             }
1222         };
1223
1224         let mut what_rustc_thinks =
1225             Item::from_def_id_and_parts(self.def_id, Some(self.name), kind, cx);
1226
1227         let impl_ref = tcx.parent(self.def_id).and_then(|did| tcx.impl_trait_ref(did));
1228
1229         // Trait impl items always inherit the impl's visibility --
1230         // we don't want to show `pub`.
1231         if impl_ref.is_some() {
1232             what_rustc_thinks.visibility = Visibility::Inherited;
1233         }
1234
1235         what_rustc_thinks
1236     }
1237 }
1238
1239 fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
1240     let hir::Ty { hir_id: _, span, ref kind } = *hir_ty;
1241     let hir::TyKind::Path(qpath) = kind else { unreachable!() };
1242
1243     match qpath {
1244         hir::QPath::Resolved(None, ref path) => {
1245             if let Res::Def(DefKind::TyParam, did) = path.res {
1246                 if let Some(new_ty) = cx.substs.get(&did).and_then(|p| p.as_ty()).cloned() {
1247                     return new_ty;
1248                 }
1249                 if let Some(bounds) = cx.impl_trait_bounds.remove(&did.into()) {
1250                     return ImplTrait(bounds);
1251                 }
1252             }
1253
1254             if let Some(expanded) = maybe_expand_private_type_alias(cx, path) {
1255                 expanded
1256             } else {
1257                 let path = path.clean(cx);
1258                 resolve_type(cx, path)
1259             }
1260         }
1261         hir::QPath::Resolved(Some(ref qself), p) => {
1262             // Try to normalize `<X as Y>::T` to a type
1263             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
1264             if let Some(normalized_value) = normalize(cx, ty) {
1265                 return normalized_value.clean(cx);
1266             }
1267
1268             let trait_segments = &p.segments[..p.segments.len() - 1];
1269             let trait_def = cx.tcx.associated_item(p.res.def_id()).container.id();
1270             let trait_ = self::Path {
1271                 res: Res::Def(DefKind::Trait, trait_def),
1272                 segments: trait_segments.iter().map(|x| x.clean(cx)).collect(),
1273             };
1274             register_res(cx, trait_.res);
1275             Type::QPath {
1276                 assoc: Box::new(p.segments.last().expect("segments were empty").clean(cx)),
1277                 self_def_id: Some(DefId::local(qself.hir_id.owner.local_def_index)),
1278                 self_type: box qself.clean(cx),
1279                 trait_,
1280             }
1281         }
1282         hir::QPath::TypeRelative(ref qself, segment) => {
1283             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
1284             let res = match ty.kind() {
1285                 ty::Projection(proj) => Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id),
1286                 // Rustdoc handles `ty::Error`s by turning them into `Type::Infer`s.
1287                 ty::Error(_) => return Type::Infer,
1288                 _ => bug!("clean: expected associated type, found `{:?}`", ty),
1289             };
1290             let trait_ = hir::Path { span, res, segments: &[] }.clean(cx);
1291             register_res(cx, trait_.res);
1292             Type::QPath {
1293                 assoc: Box::new(segment.clean(cx)),
1294                 self_def_id: res.opt_def_id(),
1295                 self_type: box qself.clean(cx),
1296                 trait_,
1297             }
1298         }
1299         hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"),
1300     }
1301 }
1302
1303 fn maybe_expand_private_type_alias(cx: &mut DocContext<'_>, path: &hir::Path<'_>) -> Option<Type> {
1304     let Res::Def(DefKind::TyAlias, def_id) = path.res else { return None };
1305     // Substitute private type aliases
1306     let Some(def_id) = def_id.as_local() else { return None };
1307     let alias = if !cx.cache.access_levels.is_exported(def_id.to_def_id()) {
1308         &cx.tcx.hir().expect_item(def_id).kind
1309     } else {
1310         return None;
1311     };
1312     let hir::ItemKind::TyAlias(ty, generics) = alias else { return None };
1313
1314     let provided_params = &path.segments.last().expect("segments were empty");
1315     let mut substs = FxHashMap::default();
1316     let generic_args = provided_params.args();
1317
1318     let mut indices: hir::GenericParamCount = Default::default();
1319     for param in generics.params.iter() {
1320         match param.kind {
1321             hir::GenericParamKind::Lifetime { .. } => {
1322                 let mut j = 0;
1323                 let lifetime = generic_args.args.iter().find_map(|arg| match arg {
1324                     hir::GenericArg::Lifetime(lt) => {
1325                         if indices.lifetimes == j {
1326                             return Some(lt);
1327                         }
1328                         j += 1;
1329                         None
1330                     }
1331                     _ => None,
1332                 });
1333                 if let Some(lt) = lifetime.cloned() {
1334                     let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
1335                     let cleaned = if !lt.is_elided() { lt.clean(cx) } else { Lifetime::elided() };
1336                     substs.insert(lt_def_id.to_def_id(), SubstParam::Lifetime(cleaned));
1337                 }
1338                 indices.lifetimes += 1;
1339             }
1340             hir::GenericParamKind::Type { ref default, .. } => {
1341                 let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
1342                 let mut j = 0;
1343                 let type_ = generic_args.args.iter().find_map(|arg| match arg {
1344                     hir::GenericArg::Type(ty) => {
1345                         if indices.types == j {
1346                             return Some(ty);
1347                         }
1348                         j += 1;
1349                         None
1350                     }
1351                     _ => None,
1352                 });
1353                 if let Some(ty) = type_ {
1354                     substs.insert(ty_param_def_id.to_def_id(), SubstParam::Type(ty.clean(cx)));
1355                 } else if let Some(default) = *default {
1356                     substs.insert(ty_param_def_id.to_def_id(), SubstParam::Type(default.clean(cx)));
1357                 }
1358                 indices.types += 1;
1359             }
1360             hir::GenericParamKind::Const { .. } => {
1361                 let const_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
1362                 let mut j = 0;
1363                 let const_ = generic_args.args.iter().find_map(|arg| match arg {
1364                     hir::GenericArg::Const(ct) => {
1365                         if indices.consts == j {
1366                             return Some(ct);
1367                         }
1368                         j += 1;
1369                         None
1370                     }
1371                     _ => None,
1372                 });
1373                 if let Some(ct) = const_ {
1374                     substs
1375                         .insert(const_param_def_id.to_def_id(), SubstParam::Constant(ct.clean(cx)));
1376                 }
1377                 // FIXME(const_generics_defaults)
1378                 indices.consts += 1;
1379             }
1380         }
1381     }
1382
1383     Some(cx.enter_alias(substs, |cx| ty.clean(cx)))
1384 }
1385
1386 impl Clean<Type> for hir::Ty<'_> {
1387     fn clean(&self, cx: &mut DocContext<'_>) -> Type {
1388         use rustc_hir::*;
1389
1390         match self.kind {
1391             TyKind::Never => Primitive(PrimitiveType::Never),
1392             TyKind::Ptr(ref m) => RawPointer(m.mutbl, box m.ty.clean(cx)),
1393             TyKind::Rptr(ref l, ref m) => {
1394                 // There are two times a `Fresh` lifetime can be created:
1395                 // 1. For `&'_ x`, written by the user. This corresponds to `lower_lifetime` in `rustc_ast_lowering`.
1396                 // 2. For `&x` as a parameter to an `async fn`. This corresponds to `elided_ref_lifetime in `rustc_ast_lowering`.
1397                 //    See #59286 for more information.
1398                 // Ideally we would only hide the `'_` for case 2., but I don't know a way to distinguish it.
1399                 // Turning `fn f(&'_ self)` into `fn f(&self)` isn't the worst thing in the world, though;
1400                 // there's no case where it could cause the function to fail to compile.
1401                 let elided =
1402                     l.is_elided() || matches!(l.name, LifetimeName::Param(ParamName::Fresh(_)));
1403                 let lifetime = if elided { None } else { Some(l.clean(cx)) };
1404                 BorrowedRef { lifetime, mutability: m.mutbl, type_: box m.ty.clean(cx) }
1405             }
1406             TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
1407             TyKind::Array(ref ty, ref length) => {
1408                 let length = match length {
1409                     hir::ArrayLen::Infer(_, _) => "_".to_string(),
1410                     hir::ArrayLen::Body(anon_const) => {
1411                         let def_id = cx.tcx.hir().local_def_id(anon_const.hir_id);
1412                         // NOTE(min_const_generics): We can't use `const_eval_poly` for constants
1413                         // as we currently do not supply the parent generics to anonymous constants
1414                         // but do allow `ConstKind::Param`.
1415                         //
1416                         // `const_eval_poly` tries to to first substitute generic parameters which
1417                         // results in an ICE while manually constructing the constant and using `eval`
1418                         // does nothing for `ConstKind::Param`.
1419                         let ct = ty::Const::from_anon_const(cx.tcx, def_id);
1420                         let param_env = cx.tcx.param_env(def_id);
1421                         print_const(cx, ct.eval(cx.tcx, param_env))
1422                     }
1423                 };
1424
1425                 Array(box ty.clean(cx), length)
1426             }
1427             TyKind::Tup(tys) => Tuple(tys.iter().map(|x| x.clean(cx)).collect()),
1428             TyKind::OpaqueDef(item_id, _) => {
1429                 let item = cx.tcx.hir().item(item_id);
1430                 if let hir::ItemKind::OpaqueTy(ref ty) = item.kind {
1431                     ImplTrait(ty.bounds.iter().filter_map(|x| x.clean(cx)).collect())
1432                 } else {
1433                     unreachable!()
1434                 }
1435             }
1436             TyKind::Path(_) => clean_qpath(self, cx),
1437             TyKind::TraitObject(bounds, ref lifetime, _) => {
1438                 let bounds = bounds.iter().map(|bound| bound.clean(cx)).collect();
1439                 let lifetime = if !lifetime.is_elided() { Some(lifetime.clean(cx)) } else { None };
1440                 DynTrait(bounds, lifetime)
1441             }
1442             TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
1443             // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s.
1444             TyKind::Infer | TyKind::Err => Infer,
1445             TyKind::Typeof(..) => panic!("unimplemented type {:?}", self.kind),
1446         }
1447     }
1448 }
1449
1450 /// Returns `None` if the type could not be normalized
1451 fn normalize<'tcx>(cx: &mut DocContext<'tcx>, ty: Ty<'_>) -> Option<Ty<'tcx>> {
1452     // HACK: low-churn fix for #79459 while we wait for a trait normalization fix
1453     if !cx.tcx.sess.opts.debugging_opts.normalize_docs {
1454         return None;
1455     }
1456
1457     use crate::rustc_trait_selection::infer::TyCtxtInferExt;
1458     use crate::rustc_trait_selection::traits::query::normalize::AtExt;
1459     use rustc_middle::traits::ObligationCause;
1460
1461     // Try to normalize `<X as Y>::T` to a type
1462     let lifted = ty.lift_to_tcx(cx.tcx).unwrap();
1463     let normalized = cx.tcx.infer_ctxt().enter(|infcx| {
1464         infcx
1465             .at(&ObligationCause::dummy(), cx.param_env)
1466             .normalize(lifted)
1467             .map(|resolved| infcx.resolve_vars_if_possible(resolved.value))
1468     });
1469     match normalized {
1470         Ok(normalized_value) => {
1471             debug!("normalized {:?} to {:?}", ty, normalized_value);
1472             Some(normalized_value)
1473         }
1474         Err(err) => {
1475             debug!("failed to normalize {:?}: {:?}", ty, err);
1476             None
1477         }
1478     }
1479 }
1480
1481 impl<'tcx> Clean<Type> for Ty<'tcx> {
1482     fn clean(&self, cx: &mut DocContext<'_>) -> Type {
1483         trace!("cleaning type: {:?}", self);
1484         let ty = normalize(cx, *self).unwrap_or(*self);
1485         match *ty.kind() {
1486             ty::Never => Primitive(PrimitiveType::Never),
1487             ty::Bool => Primitive(PrimitiveType::Bool),
1488             ty::Char => Primitive(PrimitiveType::Char),
1489             ty::Int(int_ty) => Primitive(int_ty.into()),
1490             ty::Uint(uint_ty) => Primitive(uint_ty.into()),
1491             ty::Float(float_ty) => Primitive(float_ty.into()),
1492             ty::Str => Primitive(PrimitiveType::Str),
1493             ty::Slice(ty) => Slice(box ty.clean(cx)),
1494             ty::Array(ty, n) => {
1495                 let mut n = cx.tcx.lift(n).expect("array lift failed");
1496                 n = n.eval(cx.tcx, ty::ParamEnv::reveal_all());
1497                 let n = print_const(cx, n);
1498                 Array(box ty.clean(cx), n)
1499             }
1500             ty::RawPtr(mt) => RawPointer(mt.mutbl, box mt.ty.clean(cx)),
1501             ty::Ref(r, ty, mutbl) => {
1502                 BorrowedRef { lifetime: r.clean(cx), mutability: mutbl, type_: box ty.clean(cx) }
1503             }
1504             ty::FnDef(..) | ty::FnPtr(_) => {
1505                 let ty = cx.tcx.lift(*self).expect("FnPtr lift failed");
1506                 let sig = ty.fn_sig(cx.tcx);
1507                 let decl = clean_fn_decl_from_did_and_sig(cx, None, sig);
1508                 BareFunction(box BareFunctionDecl {
1509                     unsafety: sig.unsafety(),
1510                     generic_params: Vec::new(),
1511                     decl,
1512                     abi: sig.abi(),
1513                 })
1514             }
1515             ty::Adt(def, substs) => {
1516                 let did = def.did();
1517                 let kind = match def.adt_kind() {
1518                     AdtKind::Struct => ItemType::Struct,
1519                     AdtKind::Union => ItemType::Union,
1520                     AdtKind::Enum => ItemType::Enum,
1521                 };
1522                 inline::record_extern_fqn(cx, did, kind);
1523                 let path = external_path(cx, did, false, vec![], substs);
1524                 Type::Path { path }
1525             }
1526             ty::Foreign(did) => {
1527                 inline::record_extern_fqn(cx, did, ItemType::ForeignType);
1528                 let path = external_path(cx, did, false, vec![], InternalSubsts::empty());
1529                 Type::Path { path }
1530             }
1531             ty::Dynamic(obj, ref reg) => {
1532                 // HACK: pick the first `did` as the `did` of the trait object. Someone
1533                 // might want to implement "native" support for marker-trait-only
1534                 // trait objects.
1535                 let mut dids = obj.principal_def_id().into_iter().chain(obj.auto_traits());
1536                 let did = dids
1537                     .next()
1538                     .unwrap_or_else(|| panic!("found trait object `{:?}` with no traits?", self));
1539                 let substs = match obj.principal() {
1540                     Some(principal) => principal.skip_binder().substs,
1541                     // marker traits have no substs.
1542                     _ => cx.tcx.intern_substs(&[]),
1543                 };
1544
1545                 inline::record_extern_fqn(cx, did, ItemType::Trait);
1546
1547                 let lifetime = reg.clean(cx);
1548                 let mut bounds = vec![];
1549
1550                 for did in dids {
1551                     let empty = cx.tcx.intern_substs(&[]);
1552                     let path = external_path(cx, did, false, vec![], empty);
1553                     inline::record_extern_fqn(cx, did, ItemType::Trait);
1554                     let bound = PolyTrait { trait_: path, generic_params: Vec::new() };
1555                     bounds.push(bound);
1556                 }
1557
1558                 let mut bindings = vec![];
1559                 for pb in obj.projection_bounds() {
1560                     bindings.push(TypeBinding {
1561                         assoc: projection_to_path_segment(
1562                             pb.skip_binder()
1563                                 .lift_to_tcx(cx.tcx)
1564                                 .unwrap()
1565                                 // HACK(compiler-errors): Doesn't actually matter what self
1566                                 // type we put here, because we're only using the GAT's substs.
1567                                 .with_self_ty(cx.tcx, cx.tcx.types.self_param)
1568                                 .projection_ty,
1569                             cx,
1570                         ),
1571                         kind: TypeBindingKind::Equality { term: pb.skip_binder().term.clean(cx) },
1572                     });
1573                 }
1574
1575                 let path = external_path(cx, did, false, bindings, substs);
1576                 bounds.insert(0, PolyTrait { trait_: path, generic_params: Vec::new() });
1577
1578                 DynTrait(bounds, lifetime)
1579             }
1580             ty::Tuple(t) => Tuple(t.iter().map(|t| t.clean(cx)).collect()),
1581
1582             ty::Projection(ref data) => data.clean(cx),
1583
1584             ty::Param(ref p) => {
1585                 if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) {
1586                     ImplTrait(bounds)
1587                 } else {
1588                     Generic(p.name)
1589                 }
1590             }
1591
1592             ty::Opaque(def_id, substs) => {
1593                 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
1594                 // by looking up the bounds associated with the def_id.
1595                 let substs = cx.tcx.lift(substs).expect("Opaque lift failed");
1596                 let bounds = cx
1597                     .tcx
1598                     .explicit_item_bounds(def_id)
1599                     .iter()
1600                     .map(|(bound, _)| bound.subst(cx.tcx, substs))
1601                     .collect::<Vec<_>>();
1602                 let mut regions = vec![];
1603                 let mut has_sized = false;
1604                 let mut bounds = bounds
1605                     .iter()
1606                     .filter_map(|bound| {
1607                         let bound_predicate = bound.kind();
1608                         let trait_ref = match bound_predicate.skip_binder() {
1609                             ty::PredicateKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
1610                             ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
1611                                 if let Some(r) = reg.clean(cx) {
1612                                     regions.push(GenericBound::Outlives(r));
1613                                 }
1614                                 return None;
1615                             }
1616                             _ => return None,
1617                         };
1618
1619                         if let Some(sized) = cx.tcx.lang_items().sized_trait() {
1620                             if trait_ref.def_id() == sized {
1621                                 has_sized = true;
1622                                 return None;
1623                             }
1624                         }
1625
1626                         let bindings: Vec<_> = bounds
1627                             .iter()
1628                             .filter_map(|bound| {
1629                                 if let ty::PredicateKind::Projection(proj) =
1630                                     bound.kind().skip_binder()
1631                                 {
1632                                     if proj.projection_ty.trait_ref(cx.tcx)
1633                                         == trait_ref.skip_binder()
1634                                     {
1635                                         Some(TypeBinding {
1636                                             assoc: projection_to_path_segment(
1637                                                 proj.projection_ty,
1638                                                 cx,
1639                                             ),
1640                                             kind: TypeBindingKind::Equality {
1641                                                 term: proj.term.clean(cx),
1642                                             },
1643                                         })
1644                                     } else {
1645                                         None
1646                                     }
1647                                 } else {
1648                                     None
1649                                 }
1650                             })
1651                             .collect();
1652
1653                         Some(clean_poly_trait_ref_with_bindings(cx, trait_ref, &bindings))
1654                     })
1655                     .collect::<Vec<_>>();
1656                 bounds.extend(regions);
1657                 if !has_sized && !bounds.is_empty() {
1658                     bounds.insert(0, GenericBound::maybe_sized(cx));
1659                 }
1660                 ImplTrait(bounds)
1661             }
1662
1663             ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton)
1664
1665             ty::Bound(..) => panic!("Bound"),
1666             ty::Placeholder(..) => panic!("Placeholder"),
1667             ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
1668             ty::Infer(..) => panic!("Infer"),
1669             ty::Error(_) => panic!("Error"),
1670         }
1671     }
1672 }
1673
1674 impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
1675     fn clean(&self, cx: &mut DocContext<'_>) -> Constant {
1676         // FIXME: instead of storing the stringified expression, store `self` directly instead.
1677         Constant {
1678             type_: self.ty().clean(cx),
1679             kind: ConstantKind::TyConst { expr: self.to_string() },
1680         }
1681     }
1682 }
1683
1684 impl Clean<Item> for hir::FieldDef<'_> {
1685     fn clean(&self, cx: &mut DocContext<'_>) -> Item {
1686         let def_id = cx.tcx.hir().local_def_id(self.hir_id).to_def_id();
1687         clean_field(def_id, self.ident.name, self.ty.clean(cx), cx)
1688     }
1689 }
1690
1691 impl Clean<Item> for ty::FieldDef {
1692     fn clean(&self, cx: &mut DocContext<'_>) -> Item {
1693         clean_field(self.did, self.name, cx.tcx.type_of(self.did).clean(cx), cx)
1694     }
1695 }
1696
1697 fn clean_field(def_id: DefId, name: Symbol, ty: Type, cx: &mut DocContext<'_>) -> Item {
1698     let what_rustc_thinks =
1699         Item::from_def_id_and_parts(def_id, Some(name), StructFieldItem(ty), cx);
1700     if is_field_vis_inherited(cx.tcx, def_id) {
1701         // Variant fields inherit their enum's visibility.
1702         Item { visibility: Visibility::Inherited, ..what_rustc_thinks }
1703     } else {
1704         what_rustc_thinks
1705     }
1706 }
1707
1708 fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
1709     let parent = tcx
1710         .parent(def_id)
1711         .expect("is_field_vis_inherited can only be called on struct or variant fields");
1712     match tcx.def_kind(parent) {
1713         DefKind::Struct | DefKind::Union => false,
1714         DefKind::Variant => true,
1715         // FIXME: what about DefKind::Ctor?
1716         parent_kind => panic!("unexpected parent kind: {:?}", parent_kind),
1717     }
1718 }
1719
1720 impl Clean<Visibility> for ty::Visibility {
1721     fn clean(&self, _cx: &mut DocContext<'_>) -> Visibility {
1722         match *self {
1723             ty::Visibility::Public => Visibility::Public,
1724             // NOTE: this is not quite right: `ty` uses `Invisible` to mean 'private',
1725             // while rustdoc really does mean inherited. That means that for enum variants, such as
1726             // `pub enum E { V }`, `V` will be marked as `Public` by `ty`, but as `Inherited` by rustdoc.
1727             // Various parts of clean override `tcx.visibility` explicitly to make sure this distinction is captured.
1728             ty::Visibility::Invisible => Visibility::Inherited,
1729             ty::Visibility::Restricted(module) => Visibility::Restricted(module),
1730         }
1731     }
1732 }
1733
1734 impl Clean<VariantStruct> for rustc_hir::VariantData<'_> {
1735     fn clean(&self, cx: &mut DocContext<'_>) -> VariantStruct {
1736         VariantStruct {
1737             struct_type: CtorKind::from_hir(self),
1738             fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
1739             fields_stripped: false,
1740         }
1741     }
1742 }
1743
1744 impl Clean<Vec<Item>> for hir::VariantData<'_> {
1745     fn clean(&self, cx: &mut DocContext<'_>) -> Vec<Item> {
1746         self.fields().iter().map(|x| x.clean(cx)).collect()
1747     }
1748 }
1749
1750 impl Clean<Item> for ty::VariantDef {
1751     fn clean(&self, cx: &mut DocContext<'_>) -> Item {
1752         let kind = match self.ctor_kind {
1753             CtorKind::Const => Variant::CLike,
1754             CtorKind::Fn => {
1755                 Variant::Tuple(self.fields.iter().map(|field| field.clean(cx)).collect())
1756             }
1757             CtorKind::Fictive => Variant::Struct(VariantStruct {
1758                 struct_type: CtorKind::Fictive,
1759                 fields_stripped: false,
1760                 fields: self.fields.iter().map(|field| field.clean(cx)).collect(),
1761             }),
1762         };
1763         let what_rustc_thinks =
1764             Item::from_def_id_and_parts(self.def_id, Some(self.name), VariantItem(kind), cx);
1765         // don't show `pub` for variants, which always inherit visibility
1766         Item { visibility: Inherited, ..what_rustc_thinks }
1767     }
1768 }
1769
1770 impl Clean<Variant> for hir::VariantData<'_> {
1771     fn clean(&self, cx: &mut DocContext<'_>) -> Variant {
1772         match self {
1773             hir::VariantData::Struct(..) => Variant::Struct(self.clean(cx)),
1774             hir::VariantData::Tuple(..) => Variant::Tuple(self.clean(cx)),
1775             hir::VariantData::Unit(..) => Variant::CLike,
1776         }
1777     }
1778 }
1779
1780 impl Clean<Path> for hir::Path<'_> {
1781     fn clean(&self, cx: &mut DocContext<'_>) -> Path {
1782         Path { res: self.res, segments: self.segments.iter().map(|x| x.clean(cx)).collect() }
1783     }
1784 }
1785
1786 impl Clean<GenericArgs> for hir::GenericArgs<'_> {
1787     fn clean(&self, cx: &mut DocContext<'_>) -> GenericArgs {
1788         if self.parenthesized {
1789             let output = self.bindings[0].ty().clean(cx);
1790             let output =
1791                 if output != Type::Tuple(Vec::new()) { Some(Box::new(output)) } else { None };
1792             let inputs = self.inputs().iter().map(|x| x.clean(cx)).collect();
1793             GenericArgs::Parenthesized { inputs, output }
1794         } else {
1795             let args = self
1796                 .args
1797                 .iter()
1798                 .map(|arg| match arg {
1799                     hir::GenericArg::Lifetime(lt) if !lt.is_elided() => {
1800                         GenericArg::Lifetime(lt.clean(cx))
1801                     }
1802                     hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
1803                     hir::GenericArg::Type(ty) => GenericArg::Type(ty.clean(cx)),
1804                     hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(ct.clean(cx))),
1805                     hir::GenericArg::Infer(_inf) => GenericArg::Infer,
1806                 })
1807                 .collect();
1808             let bindings = self.bindings.iter().map(|x| x.clean(cx)).collect();
1809             GenericArgs::AngleBracketed { args, bindings }
1810         }
1811     }
1812 }
1813
1814 impl Clean<PathSegment> for hir::PathSegment<'_> {
1815     fn clean(&self, cx: &mut DocContext<'_>) -> PathSegment {
1816         PathSegment { name: self.ident.name, args: self.args().clean(cx) }
1817     }
1818 }
1819
1820 impl Clean<BareFunctionDecl> for hir::BareFnTy<'_> {
1821     fn clean(&self, cx: &mut DocContext<'_>) -> BareFunctionDecl {
1822         let (generic_params, decl) = enter_impl_trait(cx, |cx| {
1823             // NOTE: generics must be cleaned before args
1824             let generic_params = self.generic_params.iter().map(|x| x.clean(cx)).collect();
1825             let args = clean_args_from_types_and_names(cx, self.decl.inputs, self.param_names);
1826             let decl = clean_fn_decl_with_args(cx, self.decl, args);
1827             (generic_params, decl)
1828         });
1829         BareFunctionDecl { unsafety: self.unsafety, abi: self.abi, decl, generic_params }
1830     }
1831 }
1832
1833 fn clean_maybe_renamed_item(
1834     cx: &mut DocContext<'_>,
1835     item: &hir::Item<'_>,
1836     renamed: Option<Symbol>,
1837 ) -> Vec<Item> {
1838     use hir::ItemKind;
1839
1840     let def_id = item.def_id.to_def_id();
1841     let mut name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
1842     cx.with_param_env(def_id, |cx| {
1843         let kind = match item.kind {
1844             ItemKind::Static(ty, mutability, body_id) => {
1845                 StaticItem(Static { type_: ty.clean(cx), mutability, expr: Some(body_id) })
1846             }
1847             ItemKind::Const(ty, body_id) => ConstantItem(Constant {
1848                 type_: ty.clean(cx),
1849                 kind: ConstantKind::Local { body: body_id, def_id },
1850             }),
1851             ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
1852                 bounds: ty.bounds.iter().filter_map(|x| x.clean(cx)).collect(),
1853                 generics: ty.generics.clean(cx),
1854             }),
1855             ItemKind::TyAlias(hir_ty, ref generics) => {
1856                 let rustdoc_ty = hir_ty.clean(cx);
1857                 let ty = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx);
1858                 TypedefItem(
1859                     Typedef {
1860                         type_: rustdoc_ty,
1861                         generics: generics.clean(cx),
1862                         item_type: Some(ty),
1863                     },
1864                     false,
1865                 )
1866             }
1867             ItemKind::Enum(ref def, ref generics) => EnumItem(Enum {
1868                 variants: def.variants.iter().map(|v| v.clean(cx)).collect(),
1869                 generics: generics.clean(cx),
1870                 variants_stripped: false,
1871             }),
1872             ItemKind::TraitAlias(ref generics, bounds) => TraitAliasItem(TraitAlias {
1873                 generics: generics.clean(cx),
1874                 bounds: bounds.iter().filter_map(|x| x.clean(cx)).collect(),
1875             }),
1876             ItemKind::Union(ref variant_data, ref generics) => UnionItem(Union {
1877                 generics: generics.clean(cx),
1878                 fields: variant_data.fields().iter().map(|x| x.clean(cx)).collect(),
1879                 fields_stripped: false,
1880             }),
1881             ItemKind::Struct(ref variant_data, ref generics) => StructItem(Struct {
1882                 struct_type: CtorKind::from_hir(variant_data),
1883                 generics: generics.clean(cx),
1884                 fields: variant_data.fields().iter().map(|x| x.clean(cx)).collect(),
1885                 fields_stripped: false,
1886             }),
1887             ItemKind::Impl(ref impl_) => return clean_impl(impl_, item.hir_id(), cx),
1888             // proc macros can have a name set by attributes
1889             ItemKind::Fn(ref sig, ref generics, body_id) => {
1890                 clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
1891             }
1892             ItemKind::Macro(ref macro_def, _) => {
1893                 let ty_vis = cx.tcx.visibility(def_id).clean(cx);
1894                 MacroItem(Macro {
1895                     source: display_macro_source(cx, name, macro_def, def_id, ty_vis),
1896                 })
1897             }
1898             ItemKind::Trait(is_auto, unsafety, ref generics, bounds, item_ids) => {
1899                 let items =
1900                     item_ids.iter().map(|ti| cx.tcx.hir().trait_item(ti.id).clean(cx)).collect();
1901                 TraitItem(Trait {
1902                     unsafety,
1903                     items,
1904                     generics: generics.clean(cx),
1905                     bounds: bounds.iter().filter_map(|x| x.clean(cx)).collect(),
1906                     is_auto: is_auto.clean(cx),
1907                 })
1908             }
1909             ItemKind::ExternCrate(orig_name) => {
1910                 return clean_extern_crate(item, name, orig_name, cx);
1911             }
1912             ItemKind::Use(path, kind) => {
1913                 return clean_use_statement(item, name, path, kind, cx);
1914             }
1915             _ => unreachable!("not yet converted"),
1916         };
1917
1918         vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)]
1919     })
1920 }
1921
1922 impl Clean<Item> for hir::Variant<'_> {
1923     fn clean(&self, cx: &mut DocContext<'_>) -> Item {
1924         let kind = VariantItem(self.data.clean(cx));
1925         let what_rustc_thinks =
1926             Item::from_hir_id_and_parts(self.id, Some(self.ident.name), kind, cx);
1927         // don't show `pub` for variants, which are always public
1928         Item { visibility: Inherited, ..what_rustc_thinks }
1929     }
1930 }
1931
1932 fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_>) -> Vec<Item> {
1933     let tcx = cx.tcx;
1934     let mut ret = Vec::new();
1935     let trait_ = impl_.of_trait.as_ref().map(|t| t.clean(cx));
1936     let items =
1937         impl_.items.iter().map(|ii| tcx.hir().impl_item(ii.id).clean(cx)).collect::<Vec<_>>();
1938     let def_id = tcx.hir().local_def_id(hir_id);
1939
1940     // If this impl block is an implementation of the Deref trait, then we
1941     // need to try inlining the target's inherent impl blocks as well.
1942     if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() {
1943         build_deref_target_impls(cx, &items, &mut ret);
1944     }
1945
1946     let for_ = impl_.self_ty.clean(cx);
1947     let type_alias = for_.def_id(&cx.cache).and_then(|did| match tcx.def_kind(did) {
1948         DefKind::TyAlias => Some(tcx.type_of(did).clean(cx)),
1949         _ => None,
1950     });
1951     let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| {
1952         let kind = ImplItem(Impl {
1953             unsafety: impl_.unsafety,
1954             generics: impl_.generics.clean(cx),
1955             trait_,
1956             for_,
1957             items,
1958             polarity: tcx.impl_polarity(def_id),
1959             kind: ImplKind::Normal,
1960         });
1961         Item::from_hir_id_and_parts(hir_id, None, kind, cx)
1962     };
1963     if let Some(type_alias) = type_alias {
1964         ret.push(make_item(trait_.clone(), type_alias, items.clone()));
1965     }
1966     ret.push(make_item(trait_, for_, items));
1967     ret
1968 }
1969
1970 fn clean_extern_crate(
1971     krate: &hir::Item<'_>,
1972     name: Symbol,
1973     orig_name: Option<Symbol>,
1974     cx: &mut DocContext<'_>,
1975 ) -> Vec<Item> {
1976     // this is the ID of the `extern crate` statement
1977     let cnum = cx.tcx.extern_mod_stmt_cnum(krate.def_id).unwrap_or(LOCAL_CRATE);
1978     // this is the ID of the crate itself
1979     let crate_def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
1980     let attrs = cx.tcx.hir().attrs(krate.hir_id());
1981     let ty_vis = cx.tcx.visibility(krate.def_id);
1982     let please_inline = ty_vis.is_public()
1983         && attrs.iter().any(|a| {
1984             a.has_name(sym::doc)
1985                 && match a.meta_item_list() {
1986                     Some(l) => attr::list_contains_name(&l, sym::inline),
1987                     None => false,
1988                 }
1989         });
1990
1991     if please_inline {
1992         let mut visited = FxHashSet::default();
1993
1994         let res = Res::Def(DefKind::Mod, crate_def_id);
1995
1996         if let Some(items) = inline::try_inline(
1997             cx,
1998             cx.tcx.parent_module(krate.hir_id()).to_def_id(),
1999             Some(krate.def_id.to_def_id()),
2000             res,
2001             name,
2002             Some(attrs),
2003             &mut visited,
2004         ) {
2005             return items;
2006         }
2007     }
2008
2009     // FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason
2010     vec![Item {
2011         name: Some(name),
2012         attrs: box attrs.clean(cx),
2013         def_id: crate_def_id.into(),
2014         visibility: ty_vis.clean(cx),
2015         kind: box ExternCrateItem { src: orig_name },
2016         cfg: attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
2017     }]
2018 }
2019
2020 fn clean_use_statement(
2021     import: &hir::Item<'_>,
2022     name: Symbol,
2023     path: &hir::Path<'_>,
2024     kind: hir::UseKind,
2025     cx: &mut DocContext<'_>,
2026 ) -> Vec<Item> {
2027     // We need this comparison because some imports (for std types for example)
2028     // are "inserted" as well but directly by the compiler and they should not be
2029     // taken into account.
2030     if import.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::StdImports) {
2031         return Vec::new();
2032     }
2033
2034     let visibility = cx.tcx.visibility(import.def_id);
2035     let attrs = cx.tcx.hir().attrs(import.hir_id());
2036     let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline);
2037     let pub_underscore = visibility.is_public() && name == kw::Underscore;
2038     let current_mod = cx.tcx.parent_module_from_def_id(import.def_id);
2039
2040     // The parent of the module in which this import resides. This
2041     // is the same as `current_mod` if that's already the top
2042     // level module.
2043     let parent_mod = cx.tcx.parent_module_from_def_id(current_mod);
2044
2045     // This checks if the import can be seen from a higher level module.
2046     // In other words, it checks if the visibility is the equivalent of
2047     // `pub(super)` or higher. If the current module is the top level
2048     // module, there isn't really a parent module, which makes the results
2049     // meaningless. In this case, we make sure the answer is `false`.
2050     let is_visible_from_parent_mod = visibility.is_accessible_from(parent_mod.to_def_id(), cx.tcx)
2051         && !current_mod.is_top_level_module();
2052
2053     if pub_underscore {
2054         if let Some(ref inline) = inline_attr {
2055             rustc_errors::struct_span_err!(
2056                 cx.tcx.sess,
2057                 inline.span(),
2058                 E0780,
2059                 "anonymous imports cannot be inlined"
2060             )
2061             .span_label(import.span, "anonymous import")
2062             .emit();
2063         }
2064     }
2065
2066     // We consider inlining the documentation of `pub use` statements, but we
2067     // forcefully don't inline if this is not public or if the
2068     // #[doc(no_inline)] attribute is present.
2069     // Don't inline doc(hidden) imports so they can be stripped at a later stage.
2070     let mut denied = !(visibility.is_public()
2071         || (cx.render_options.document_private && is_visible_from_parent_mod))
2072         || pub_underscore
2073         || attrs.iter().any(|a| {
2074             a.has_name(sym::doc)
2075                 && match a.meta_item_list() {
2076                     Some(l) => {
2077                         attr::list_contains_name(&l, sym::no_inline)
2078                             || attr::list_contains_name(&l, sym::hidden)
2079                     }
2080                     None => false,
2081                 }
2082         });
2083
2084     // Also check whether imports were asked to be inlined, in case we're trying to re-export a
2085     // crate in Rust 2018+
2086     let path = path.clean(cx);
2087     let inner = if kind == hir::UseKind::Glob {
2088         if !denied {
2089             let mut visited = FxHashSet::default();
2090             if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) {
2091                 return items;
2092             }
2093         }
2094         Import::new_glob(resolve_use_source(cx, path), true)
2095     } else {
2096         if inline_attr.is_none() {
2097             if let Res::Def(DefKind::Mod, did) = path.res {
2098                 if !did.is_local() && did.index == CRATE_DEF_INDEX {
2099                     // if we're `pub use`ing an extern crate root, don't inline it unless we
2100                     // were specifically asked for it
2101                     denied = true;
2102                 }
2103             }
2104         }
2105         if !denied {
2106             let mut visited = FxHashSet::default();
2107             let import_def_id = import.def_id.to_def_id();
2108
2109             if let Some(mut items) = inline::try_inline(
2110                 cx,
2111                 cx.tcx.parent_module(import.hir_id()).to_def_id(),
2112                 Some(import_def_id),
2113                 path.res,
2114                 name,
2115                 Some(attrs),
2116                 &mut visited,
2117             ) {
2118                 items.push(Item::from_def_id_and_parts(
2119                     import_def_id,
2120                     None,
2121                     ImportItem(Import::new_simple(name, resolve_use_source(cx, path), false)),
2122                     cx,
2123                 ));
2124                 return items;
2125             }
2126         }
2127         Import::new_simple(name, resolve_use_source(cx, path), true)
2128     };
2129
2130     vec![Item::from_def_id_and_parts(import.def_id.to_def_id(), None, ImportItem(inner), cx)]
2131 }
2132
2133 fn clean_maybe_renamed_foreign_item(
2134     cx: &mut DocContext<'_>,
2135     item: &hir::ForeignItem<'_>,
2136     renamed: Option<Symbol>,
2137 ) -> Item {
2138     let def_id = item.def_id.to_def_id();
2139     cx.with_param_env(def_id, |cx| {
2140         let kind = match item.kind {
2141             hir::ForeignItemKind::Fn(decl, names, ref generics) => {
2142                 let (generics, decl) = enter_impl_trait(cx, |cx| {
2143                     // NOTE: generics must be cleaned before args
2144                     let generics = generics.clean(cx);
2145                     let args = clean_args_from_types_and_names(cx, decl.inputs, names);
2146                     let decl = clean_fn_decl_with_args(cx, decl, args);
2147                     (generics, decl)
2148                 });
2149                 ForeignFunctionItem(Function { decl, generics })
2150             }
2151             hir::ForeignItemKind::Static(ref ty, mutability) => {
2152                 ForeignStaticItem(Static { type_: ty.clean(cx), mutability, expr: None })
2153             }
2154             hir::ForeignItemKind::Type => ForeignTypeItem,
2155         };
2156
2157         Item::from_hir_id_and_parts(
2158             item.hir_id(),
2159             Some(renamed.unwrap_or(item.ident.name)),
2160             kind,
2161             cx,
2162         )
2163     })
2164 }
2165
2166 impl Clean<TypeBinding> for hir::TypeBinding<'_> {
2167     fn clean(&self, cx: &mut DocContext<'_>) -> TypeBinding {
2168         TypeBinding {
2169             assoc: PathSegment { name: self.ident.name, args: self.gen_args.clean(cx) },
2170             kind: self.kind.clean(cx),
2171         }
2172     }
2173 }
2174
2175 impl Clean<TypeBindingKind> for hir::TypeBindingKind<'_> {
2176     fn clean(&self, cx: &mut DocContext<'_>) -> TypeBindingKind {
2177         match *self {
2178             hir::TypeBindingKind::Equality { ref term } => {
2179                 TypeBindingKind::Equality { term: term.clean(cx) }
2180             }
2181             hir::TypeBindingKind::Constraint { ref bounds } => TypeBindingKind::Constraint {
2182                 bounds: bounds.iter().filter_map(|b| b.clean(cx)).collect(),
2183             },
2184         }
2185     }
2186 }