]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #105612 - oli-obk:bind_rustdoc, r=GuillaumeGomez
authorbors <bors@rust-lang.org>
Tue, 13 Dec 2022 13:09:40 +0000 (13:09 +0000)
committerbors <bors@rust-lang.org>
Tue, 13 Dec 2022 13:09:40 +0000 (13:09 +0000)
use ty::Binder in rustdoc instead of `skip_binder`

r? `@GuillaumeGomez`

this is a preliminary cleanup required to be able to normalize correctly/conveniently in rustdoc

compiler/rustc_middle/src/ty/sty.rs
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/blanket_impl.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/clean/utils.rs

index 64033c351b1bfbdf60e9f9e7033c1c69c8ceb016..9b9c26d6a8b1b15927f0b66495f1b74c9e1e9b8c 100644 (file)
@@ -980,8 +980,12 @@ impl<'tcx, T> Binder<'tcx, T>
     /// contain any bound vars that would be bound by the
     /// binder. This is commonly used to 'inject' a value T into a
     /// different binding level.
+    #[track_caller]
     pub fn dummy(value: T) -> Binder<'tcx, T> {
-        assert!(!value.has_escaping_bound_vars());
+        assert!(
+            !value.has_escaping_bound_vars(),
+            "`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder."
+        );
         Binder(value, ty::List::empty())
     }
 
@@ -1128,6 +1132,13 @@ pub fn transpose(self) -> Option<Binder<'tcx, T>> {
     }
 }
 
+impl<'tcx, T: IntoIterator> Binder<'tcx, T> {
+    pub fn iter(self) -> impl Iterator<Item = ty::Binder<'tcx, T::Item>> {
+        let bound_vars = self.1;
+        self.0.into_iter().map(|v| Binder(v, bound_vars))
+    }
+}
+
 /// Represents the projection of an associated type. In explicit UFCS
 /// form this would be written `<T as Trait<..>>::N`.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
index 953f4aa8a1b482137f4f24d4cd9447ed84b76c25..4d6f1524732f77453e2ce2489cd3eee1b6f848e8 100644 (file)
@@ -44,7 +44,7 @@ fn generate_for_trait(
         discard_positive_impl: bool,
     ) -> Option<Item> {
         let tcx = self.cx.tcx;
-        let trait_ref = tcx.mk_trait_ref(trait_def_id, [ty]);
+        let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, [ty]));
         if !self.cx.generated_synthetics.insert((ty, trait_def_id)) {
             debug!("get_auto_trait_impl_for({:?}): already generated, aborting", trait_ref);
             return None;
@@ -124,7 +124,7 @@ fn generate_for_trait(
                 unsafety: hir::Unsafety::Normal,
                 generics: new_generics,
                 trait_: Some(clean_trait_ref_with_bindings(self.cx, trait_ref, ThinVec::new())),
-                for_: clean_middle_ty(ty, self.cx, None),
+                for_: clean_middle_ty(ty::Binder::dummy(ty), self.cx, None),
                 items: Vec::new(),
                 polarity,
                 kind: ImplKind::Auto,
index a1145b90d6580c7da0f996dbd4d9420eff7d5d7b..4ef5747596bb39a7d4900a393c216f84626f3447 100644 (file)
@@ -105,10 +105,10 @@ pub(crate) fn get_blanket_impls(&mut self, item_def_id: DefId) -> Vec<Item> {
                         // the post-inference `trait_ref`, as it's more accurate.
                         trait_: Some(clean_trait_ref_with_bindings(
                             cx,
-                            trait_ref.0,
+                            ty::Binder::dummy(trait_ref.0),
                             ThinVec::new(),
                         )),
-                        for_: clean_middle_ty(ty.0, cx, None),
+                        for_: clean_middle_ty(ty::Binder::dummy(ty.0), cx, None),
                         items: cx
                             .tcx
                             .associated_items(impl_def_id)
@@ -117,7 +117,7 @@ pub(crate) fn get_blanket_impls(&mut self, item_def_id: DefId) -> Vec<Item> {
                             .collect::<Vec<_>>(),
                         polarity: ty::ImplPolarity::Positive,
                         kind: ImplKind::Blanket(Box::new(clean_middle_ty(
-                            trait_ref.0.self_ty(),
+                            ty::Binder::dummy(trait_ref.0.self_ty()),
                             cx,
                             None,
                         ))),
index e7c3e5a45e8387f079015a7db93c30212ca8075f..50caef3553fdaf5f47d8e2248762494b06229750 100644 (file)
@@ -293,7 +293,7 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union {
 
 fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> Box<clean::Typedef> {
     let predicates = cx.tcx.explicit_predicates_of(did);
-    let type_ = clean_middle_ty(cx.tcx.type_of(did), cx, Some(did));
+    let type_ = clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did)), cx, Some(did));
 
     Box::new(clean::Typedef {
         type_,
@@ -405,7 +405,7 @@ pub(crate) fn build_impl(
 
     let for_ = match &impl_item {
         Some(impl_) => clean_ty(impl_.self_ty, cx),
-        None => clean_middle_ty(tcx.type_of(did), cx, Some(did)),
+        None => clean_middle_ty(ty::Binder::dummy(tcx.type_of(did)), cx, Some(did)),
     };
 
     // Only inline impl if the implementing type is
@@ -496,7 +496,8 @@ pub(crate) fn build_impl(
         ),
     };
     let polarity = tcx.impl_polarity(did);
-    let trait_ = associated_trait.map(|t| clean_trait_ref_with_bindings(cx, t, ThinVec::new()));
+    let trait_ = associated_trait
+        .map(|t| clean_trait_ref_with_bindings(cx, ty::Binder::dummy(t), ThinVec::new()));
     if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() {
         super::build_deref_target_impls(cx, &trait_items, ret);
     }
@@ -640,14 +641,14 @@ pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
 
 fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
     clean::Constant {
-        type_: clean_middle_ty(cx.tcx.type_of(def_id), cx, Some(def_id)),
+        type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(def_id)), cx, Some(def_id)),
         kind: clean::ConstantKind::Extern { def_id },
     }
 }
 
 fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {
     clean::Static {
-        type_: clean_middle_ty(cx.tcx.type_of(did), cx, Some(did)),
+        type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did)), cx, Some(did)),
         mutability: if mutable { Mutability::Mut } else { Mutability::Not },
         expr: None,
     }
index 2a2a9470d25c0ee4da19badf253f0207a6dcdda7..c6ab8e1a83bef786d0167c204065dccb6275951b 100644 (file)
@@ -22,6 +22,7 @@
 use rustc_middle::middle::resolve_lifetime as rl;
 use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::InternalSubsts;
+use rustc_middle::ty::TypeVisitable;
 use rustc_middle::ty::{self, AdtKind, DefIdTree, EarlyBinder, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_span::hygiene::{AstPass, MacroKind};
@@ -127,7 +128,7 @@ fn clean_generic_bound<'tcx>(
         hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
             let def_id = cx.tcx.require_lang_item(lang_item, Some(span));
 
-            let trait_ref = ty::TraitRef::identity(cx.tcx, def_id).skip_binder();
+            let trait_ref = ty::TraitRef::identity(cx.tcx, def_id);
 
             let generic_args = clean_generic_args(generic_args, cx);
             let GenericArgs::AngleBracketed { bindings, .. } = generic_args
@@ -156,17 +157,18 @@ fn clean_generic_bound<'tcx>(
 
 pub(crate) fn clean_trait_ref_with_bindings<'tcx>(
     cx: &mut DocContext<'tcx>,
-    trait_ref: ty::TraitRef<'tcx>,
+    trait_ref: ty::PolyTraitRef<'tcx>,
     bindings: ThinVec<TypeBinding>,
 ) -> Path {
-    let kind = cx.tcx.def_kind(trait_ref.def_id).into();
+    let kind = cx.tcx.def_kind(trait_ref.def_id()).into();
     if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) {
-        span_bug!(cx.tcx.def_span(trait_ref.def_id), "`TraitRef` had unexpected kind {:?}", kind);
+        span_bug!(cx.tcx.def_span(trait_ref.def_id()), "`TraitRef` had unexpected kind {:?}", kind);
     }
-    inline::record_extern_fqn(cx, trait_ref.def_id, kind);
-    let path = external_path(cx, trait_ref.def_id, true, bindings, trait_ref.substs);
+    inline::record_extern_fqn(cx, trait_ref.def_id(), kind);
+    let path =
+        external_path(cx, trait_ref.def_id(), true, bindings, trait_ref.map_bound(|tr| tr.substs));
 
-    debug!("ty::TraitRef\n  subst: {:?}\n", trait_ref.substs);
+    debug!(?trait_ref);
 
     path
 }
@@ -187,7 +189,7 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
         })
         .collect();
 
-    let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref.skip_binder(), bindings);
+    let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref, bindings);
     GenericBound::TraitBound(
         PolyTrait { trait_, generic_params: late_bound_regions },
         hir::TraitBoundModifier::None,
@@ -212,19 +214,19 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
 pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'tcx>) -> Constant {
     let def_id = cx.tcx.hir().body_owner_def_id(constant.value.body).to_def_id();
     Constant {
-        type_: clean_middle_ty(cx.tcx.type_of(def_id), cx, Some(def_id)),
+        type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(def_id)), cx, Some(def_id)),
         kind: ConstantKind::Anonymous { body: constant.value.body },
     }
 }
 
 pub(crate) fn clean_middle_const<'tcx>(
-    constant: ty::Const<'tcx>,
+    constant: ty::Binder<'tcx, ty::Const<'tcx>>,
     cx: &mut DocContext<'tcx>,
 ) -> Constant {
     // FIXME: instead of storing the stringified expression, store `self` directly instead.
     Constant {
-        type_: clean_middle_ty(constant.ty(), cx, None),
-        kind: ConstantKind::TyConst { expr: constant.to_string().into() },
+        type_: clean_middle_ty(constant.map_bound(|c| c.ty()), cx, None),
+        kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() },
     }
 }
 
@@ -333,7 +335,7 @@ fn clean_poly_trait_predicate<'tcx>(
 
     let poly_trait_ref = pred.map_bound(|pred| pred.trait_ref);
     Some(WherePredicate::BoundPredicate {
-        ty: clean_middle_ty(poly_trait_ref.skip_binder().self_ty(), cx, None),
+        ty: clean_middle_ty(poly_trait_ref.self_ty(), cx, None),
         bounds: vec![clean_poly_trait_ref_with_bindings(cx, poly_trait_ref, ThinVec::new())],
         bound_params: Vec::new(),
     })
@@ -359,7 +361,7 @@ fn clean_type_outlives_predicate<'tcx>(
     let ty::OutlivesPredicate(ty, lt) = pred;
 
     Some(WherePredicate::BoundPredicate {
-        ty: clean_middle_ty(ty, cx, None),
+        ty: clean_middle_ty(ty::Binder::dummy(ty), cx, None),
         bounds: vec![GenericBound::Outlives(
             clean_middle_region(lt).expect("failed to clean lifetimes"),
         )],
@@ -367,10 +369,13 @@ fn clean_type_outlives_predicate<'tcx>(
     })
 }
 
-fn clean_middle_term<'tcx>(term: ty::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term {
-    match term.unpack() {
-        ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(ty, cx, None)),
-        ty::TermKind::Const(c) => Term::Constant(clean_middle_const(c, cx)),
+fn clean_middle_term<'tcx>(
+    term: ty::Binder<'tcx, ty::Term<'tcx>>,
+    cx: &mut DocContext<'tcx>,
+) -> Term {
+    match term.skip_binder().unpack() {
+        ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(term.rebind(ty), cx, None)),
+        ty::TermKind::Const(c) => Term::Constant(clean_middle_const(term.rebind(c), cx)),
     }
 }
 
@@ -379,7 +384,10 @@ fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Te
         hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)),
         hir::Term::Const(c) => {
             let def_id = cx.tcx.hir().local_def_id(c.hir_id);
-            Term::Constant(clean_middle_const(ty::Const::from_anon_const(cx.tcx, def_id), cx))
+            Term::Constant(clean_middle_const(
+                ty::Binder::dummy(ty::Const::from_anon_const(cx.tcx, def_id)),
+                cx,
+            ))
         }
     }
 }
@@ -398,32 +406,31 @@ fn clean_projection_predicate<'tcx>(
         })
         .collect();
 
-    let ty::ProjectionPredicate { projection_ty, term } = pred.skip_binder();
-
     WherePredicate::EqPredicate {
-        lhs: Box::new(clean_projection(projection_ty, cx, None)),
-        rhs: Box::new(clean_middle_term(term, cx)),
+        lhs: Box::new(clean_projection(pred.map_bound(|p| p.projection_ty), cx, None)),
+        rhs: Box::new(clean_middle_term(pred.map_bound(|p| p.term), cx)),
         bound_params: late_bound_regions,
     }
 }
 
 fn clean_projection<'tcx>(
-    ty: ty::ProjectionTy<'tcx>,
+    ty: ty::Binder<'tcx, ty::ProjectionTy<'tcx>>,
     cx: &mut DocContext<'tcx>,
     def_id: Option<DefId>,
 ) -> Type {
-    if cx.tcx.def_kind(ty.item_def_id) == DefKind::ImplTraitPlaceholder {
+    if cx.tcx.def_kind(ty.skip_binder().item_def_id) == DefKind::ImplTraitPlaceholder {
         let bounds = cx
             .tcx
-            .explicit_item_bounds(ty.item_def_id)
+            .explicit_item_bounds(ty.skip_binder().item_def_id)
             .iter()
-            .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.substs))
+            .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.skip_binder().substs))
             .collect::<Vec<_>>();
         return clean_middle_opaque_bounds(cx, bounds);
     }
 
-    let trait_ = clean_trait_ref_with_bindings(cx, ty.trait_ref(cx.tcx), ThinVec::new());
-    let self_type = clean_middle_ty(ty.self_ty(), cx, None);
+    let trait_ =
+        clean_trait_ref_with_bindings(cx, ty.map_bound(|ty| ty.trait_ref(cx.tcx)), ThinVec::new());
+    let self_type = clean_middle_ty(ty.map_bound(|ty| ty.self_ty()), cx, None);
     let self_def_id = if let Some(def_id) = def_id {
         cx.tcx.opt_parent(def_id).or(Some(def_id))
     } else {
@@ -446,15 +453,16 @@ fn compute_should_show_cast(self_def_id: Option<DefId>, trait_: &Path, self_type
 }
 
 fn projection_to_path_segment<'tcx>(
-    ty: ty::ProjectionTy<'tcx>,
+    ty: ty::Binder<'tcx, ty::ProjectionTy<'tcx>>,
     cx: &mut DocContext<'tcx>,
 ) -> PathSegment {
-    let item = cx.tcx.associated_item(ty.item_def_id);
-    let generics = cx.tcx.generics_of(ty.item_def_id);
+    let item = cx.tcx.associated_item(ty.skip_binder().item_def_id);
+    let generics = cx.tcx.generics_of(ty.skip_binder().item_def_id);
     PathSegment {
         name: item.name,
         args: GenericArgs::AngleBracketed {
-            args: substs_to_args(cx, &ty.substs[generics.parent_count..], false).into(),
+            args: substs_to_args(cx, ty.map_bound(|ty| &ty.substs[generics.parent_count..]), false)
+                .into(),
             bindings: Default::default(),
         },
     }
@@ -470,7 +478,11 @@ fn clean_generic_param_def<'tcx>(
         }
         ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
             let default = if has_default {
-                Some(clean_middle_ty(cx.tcx.type_of(def.def_id), cx, Some(def.def_id)))
+                Some(clean_middle_ty(
+                    ty::Binder::dummy(cx.tcx.type_of(def.def_id)),
+                    cx,
+                    Some(def.def_id),
+                ))
             } else {
                 None
             };
@@ -488,7 +500,11 @@ fn clean_generic_param_def<'tcx>(
             def.name,
             GenericParamDefKind::Const {
                 did: def.def_id,
-                ty: Box::new(clean_middle_ty(cx.tcx.type_of(def.def_id), cx, Some(def.def_id))),
+                ty: Box::new(clean_middle_ty(
+                    ty::Binder::dummy(cx.tcx.type_of(def.def_id)),
+                    cx,
+                    Some(def.def_id),
+                )),
                 default: match has_default {
                     true => Some(Box::new(cx.tcx.const_param_default(def.def_id).to_string())),
                     false => None,
@@ -733,8 +749,10 @@ fn clean_ty_generics<'tcx>(
         .collect::<ThinVec<GenericParamDef>>();
 
     // param index -> [(trait DefId, associated type name & generics, type, higher-ranked params)]
-    let mut impl_trait_proj =
-        FxHashMap::<u32, Vec<(DefId, PathSegment, Ty<'_>, Vec<GenericParamDef>)>>::default();
+    let mut impl_trait_proj = FxHashMap::<
+        u32,
+        Vec<(DefId, PathSegment, ty::Binder<'_, Ty<'_>>, Vec<GenericParamDef>)>,
+    >::default();
 
     let where_predicates = preds
         .predicates
@@ -783,8 +801,8 @@ fn clean_ty_generics<'tcx>(
 
                     let proj = projection.map(|p| {
                         (
-                            clean_projection(p.skip_binder().projection_ty, cx, None),
-                            p.skip_binder().term,
+                            clean_projection(p.map_bound(|p| p.projection_ty), cx, None),
+                            p.map_bound(|p| p.term),
                         )
                     });
                     if let Some(((_, trait_did, name), rhs)) = proj
@@ -795,7 +813,7 @@ fn clean_ty_generics<'tcx>(
                         impl_trait_proj.entry(param_idx).or_default().push((
                             trait_did,
                             name,
-                            rhs.ty().unwrap(),
+                            rhs.map_bound(|rhs| rhs.ty().unwrap()),
                             p.get_bound_params()
                                 .into_iter()
                                 .flatten()
@@ -1066,7 +1084,7 @@ fn clean_fn_decl_from_did_and_sig<'tcx>(
 
     // We assume all empty tuples are default return type. This theoretically can discard `-> ()`,
     // but shouldn't change any code meaning.
-    let output = match clean_middle_ty(sig.skip_binder().output(), cx, None) {
+    let output = match clean_middle_ty(sig.output(), cx, None) {
         Type::Tuple(inner) if inner.is_empty() => DefaultReturn,
         ty => Return(ty),
     };
@@ -1076,11 +1094,10 @@ fn clean_fn_decl_from_did_and_sig<'tcx>(
         c_variadic: sig.skip_binder().c_variadic,
         inputs: Arguments {
             values: sig
-                .skip_binder()
                 .inputs()
                 .iter()
                 .map(|t| Argument {
-                    type_: clean_middle_ty(*t, cx, None),
+                    type_: clean_middle_ty(t.map_bound(|t| *t), cx, None),
                     name: names
                         .next()
                         .map(|i| i.name)
@@ -1134,7 +1151,8 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
             hir::TraitItemKind::Type(bounds, Some(default)) => {
                 let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
                 let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect();
-                let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, default), cx, None);
+                let item_type =
+                    clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, default)), cx, None);
                 AssocTypeItem(
                     Box::new(Typedef {
                         type_: clean_ty(default, cx),
@@ -1173,7 +1191,8 @@ pub(crate) fn clean_impl_item<'tcx>(
             hir::ImplItemKind::Type(hir_ty) => {
                 let type_ = clean_ty(hir_ty, cx);
                 let generics = clean_generics(impl_.generics, cx);
-                let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, hir_ty), cx, None);
+                let item_type =
+                    clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, hir_ty)), cx, None);
                 AssocTypeItem(
                     Box::new(Typedef { type_, generics, item_type: Some(item_type) }),
                     Vec::new(),
@@ -1192,7 +1211,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
     let tcx = cx.tcx;
     let kind = match assoc_item.kind {
         ty::AssocKind::Const => {
-            let ty = clean_middle_ty(tcx.type_of(assoc_item.def_id), cx, Some(assoc_item.def_id));
+            let ty = clean_middle_ty(
+                ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
+                cx,
+                Some(assoc_item.def_id),
+            );
 
             let provided = match assoc_item.container {
                 ty::ImplContainer => true,
@@ -1375,7 +1398,7 @@ fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
                     AssocTypeItem(
                         Box::new(Typedef {
                             type_: clean_middle_ty(
-                                tcx.type_of(assoc_item.def_id),
+                                ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
                                 cx,
                                 Some(assoc_item.def_id),
                             ),
@@ -1393,7 +1416,7 @@ fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
                 AssocTypeItem(
                     Box::new(Typedef {
                         type_: clean_middle_ty(
-                            tcx.type_of(assoc_item.def_id),
+                            ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
                             cx,
                             Some(assoc_item.def_id),
                         ),
@@ -1437,8 +1460,11 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
         hir::QPath::Resolved(Some(qself), p) => {
             // Try to normalize `<X as Y>::T` to a type
             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
-            if let Some(normalized_value) = normalize(cx, ty) {
-                return clean_middle_ty(normalized_value, cx, None);
+            // `hir_to_ty` can return projection types with escaping vars for GATs, e.g. `<() as Trait>::Gat<'_>`
+            if !ty.has_escaping_bound_vars() {
+                if let Some(normalized_value) = normalize(cx, ty::Binder::dummy(ty)) {
+                    return clean_middle_ty(normalized_value, cx, None);
+                }
             }
 
             let trait_segments = &p.segments[..p.segments.len() - 1];
@@ -1465,7 +1491,7 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
                 // Rustdoc handles `ty::Error`s by turning them into `Type::Infer`s.
                 ty::Error(_) => return Type::Infer,
                 // Otherwise, this is an inherent associated type.
-                _ => return clean_middle_ty(ty, cx, None),
+                _ => return clean_middle_ty(ty::Binder::dummy(ty), cx, None),
             };
             let trait_ = clean_path(&hir::Path { span, res, segments: &[] }, cx);
             register_res(cx, trait_.res);
@@ -1632,7 +1658,10 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
 }
 
 /// Returns `None` if the type could not be normalized
-fn normalize<'tcx>(cx: &mut DocContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
+fn normalize<'tcx>(
+    cx: &mut DocContext<'tcx>,
+    ty: ty::Binder<'tcx, Ty<'tcx>>,
+) -> Option<ty::Binder<'tcx, Ty<'tcx>>> {
     // HACK: low-churn fix for #79459 while we wait for a trait normalization fix
     if !cx.tcx.sess.opts.unstable_opts.normalize_docs {
         return None;
@@ -1660,14 +1689,14 @@ fn normalize<'tcx>(cx: &mut DocContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>>
     }
 }
 
+#[instrument(level = "trace", skip(cx), ret)]
 pub(crate) fn clean_middle_ty<'tcx>(
-    ty: Ty<'tcx>,
+    bound_ty: ty::Binder<'tcx, Ty<'tcx>>,
     cx: &mut DocContext<'tcx>,
     def_id: Option<DefId>,
 ) -> Type {
-    trace!("cleaning type: {:?}", ty);
-    let ty = normalize(cx, ty).unwrap_or(ty);
-    match *ty.kind() {
+    let bound_ty = normalize(cx, bound_ty).unwrap_or(bound_ty);
+    match *bound_ty.skip_binder().kind() {
         ty::Never => Primitive(PrimitiveType::Never),
         ty::Bool => Primitive(PrimitiveType::Bool),
         ty::Char => Primitive(PrimitiveType::Char),
@@ -1675,20 +1704,23 @@ pub(crate) fn clean_middle_ty<'tcx>(
         ty::Uint(uint_ty) => Primitive(uint_ty.into()),
         ty::Float(float_ty) => Primitive(float_ty.into()),
         ty::Str => Primitive(PrimitiveType::Str),
-        ty::Slice(ty) => Slice(Box::new(clean_middle_ty(ty, cx, None))),
+        ty::Slice(ty) => Slice(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None))),
         ty::Array(ty, mut n) => {
             n = n.eval(cx.tcx, ty::ParamEnv::reveal_all());
             let n = print_const(cx, n);
-            Array(Box::new(clean_middle_ty(ty, cx, None)), n.into())
+            Array(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None)), n.into())
+        }
+        ty::RawPtr(mt) => {
+            RawPointer(mt.mutbl, Box::new(clean_middle_ty(bound_ty.rebind(mt.ty), cx, None)))
         }
-        ty::RawPtr(mt) => RawPointer(mt.mutbl, Box::new(clean_middle_ty(mt.ty, cx, None))),
         ty::Ref(r, ty, mutbl) => BorrowedRef {
             lifetime: clean_middle_region(r),
             mutability: mutbl,
-            type_: Box::new(clean_middle_ty(ty, cx, None)),
+            type_: Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None)),
         },
         ty::FnDef(..) | ty::FnPtr(_) => {
-            let sig = ty.fn_sig(cx.tcx);
+            // FIXME: should we merge the outer and inner binders somehow?
+            let sig = bound_ty.skip_binder().fn_sig(cx.tcx);
             let decl = clean_fn_decl_from_did_and_sig(cx, None, sig);
             BareFunction(Box::new(BareFunctionDecl {
                 unsafety: sig.unsafety(),
@@ -1705,12 +1737,18 @@ pub(crate) fn clean_middle_ty<'tcx>(
                 AdtKind::Enum => ItemType::Enum,
             };
             inline::record_extern_fqn(cx, did, kind);
-            let path = external_path(cx, did, false, ThinVec::new(), substs);
+            let path = external_path(cx, did, false, ThinVec::new(), bound_ty.rebind(substs));
             Type::Path { path }
         }
         ty::Foreign(did) => {
             inline::record_extern_fqn(cx, did, ItemType::ForeignType);
-            let path = external_path(cx, did, false, ThinVec::new(), InternalSubsts::empty());
+            let path = external_path(
+                cx,
+                did,
+                false,
+                ThinVec::new(),
+                ty::Binder::dummy(InternalSubsts::empty()),
+            );
             Type::Path { path }
         }
         ty::Dynamic(obj, ref reg, _) => {
@@ -1721,11 +1759,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
             let did = obj
                 .principal_def_id()
                 .or_else(|| dids.next())
-                .unwrap_or_else(|| panic!("found trait object `{:?}` with no traits?", ty));
+                .unwrap_or_else(|| panic!("found trait object `{bound_ty:?}` with no traits?"));
             let substs = match obj.principal() {
-                Some(principal) => principal.skip_binder().substs,
+                Some(principal) => principal.map_bound(|p| p.substs),
                 // marker traits have no substs.
-                _ => cx.tcx.intern_substs(&[]),
+                _ => ty::Binder::dummy(InternalSubsts::empty()),
             };
 
             inline::record_extern_fqn(cx, did, ItemType::Trait);
@@ -1736,7 +1774,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
             let lifetime = clean_middle_region(*reg);
             let mut bounds = dids
                 .map(|did| {
-                    let empty = cx.tcx.intern_substs(&[]);
+                    let empty = ty::Binder::dummy(InternalSubsts::empty());
                     let path = external_path(cx, did, false, ThinVec::new(), empty);
                     inline::record_extern_fqn(cx, did, ItemType::Trait);
                     PolyTrait { trait_: path, generic_params: Vec::new() }
@@ -1747,15 +1785,17 @@ pub(crate) fn clean_middle_ty<'tcx>(
                 .projection_bounds()
                 .map(|pb| TypeBinding {
                     assoc: projection_to_path_segment(
-                        pb.skip_binder()
-                            // HACK(compiler-errors): Doesn't actually matter what self
-                            // type we put here, because we're only using the GAT's substs.
-                            .with_self_ty(cx.tcx, cx.tcx.types.self_param)
-                            .projection_ty,
+                        pb.map_bound(|pb| {
+                            pb
+                                // HACK(compiler-errors): Doesn't actually matter what self
+                                // type we put here, because we're only using the GAT's substs.
+                                .with_self_ty(cx.tcx, cx.tcx.types.self_param)
+                                .projection_ty
+                        }),
                         cx,
                     ),
                     kind: TypeBindingKind::Equality {
-                        term: clean_middle_term(pb.skip_binder().term, cx),
+                        term: clean_middle_term(pb.map_bound(|pb| pb.term), cx),
                     },
                 })
                 .collect();
@@ -1779,9 +1819,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
 
             DynTrait(bounds, lifetime)
         }
-        ty::Tuple(t) => Tuple(t.iter().map(|t| clean_middle_ty(t, cx, None)).collect()),
+        ty::Tuple(t) => {
+            Tuple(t.iter().map(|t| clean_middle_ty(bound_ty.rebind(t), cx, None)).collect())
+        }
 
-        ty::Projection(ref data) => clean_projection(*data, cx, def_id),
+        ty::Projection(ref data) => clean_projection(bound_ty.rebind(*data), cx, def_id),
 
         ty::Param(ref p) => {
             if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) {
@@ -1854,9 +1896,12 @@ fn clean_middle_opaque_bounds<'tcx>(
                     {
                         if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() {
                             Some(TypeBinding {
-                                assoc: projection_to_path_segment(proj.projection_ty, cx),
+                                assoc: projection_to_path_segment(
+                                    bound.kind().rebind(proj.projection_ty),
+                                    cx,
+                                ),
                                 kind: TypeBindingKind::Equality {
-                                    term: clean_middle_term(proj.term, cx),
+                                    term: clean_middle_term(bound.kind().rebind(proj.term), cx),
                                 },
                             })
                         } else {
@@ -1887,7 +1932,7 @@ pub(crate) fn clean_middle_field<'tcx>(field: &ty::FieldDef, cx: &mut DocContext
     clean_field_with_def_id(
         field.did,
         field.name,
-        clean_middle_ty(cx.tcx.type_of(field.did), cx, Some(field.did)),
+        clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(field.did)), cx, Some(field.did)),
         cx,
     )
 }
@@ -2100,7 +2145,7 @@ fn clean_maybe_renamed_item<'tcx>(
             }),
             ItemKind::TyAlias(hir_ty, generics) => {
                 let rustdoc_ty = clean_ty(hir_ty, cx);
-                let ty = clean_middle_ty(hir_ty_to_ty(cx.tcx, hir_ty), cx, None);
+                let ty = clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, hir_ty)), cx, None);
                 TypedefItem(Box::new(Typedef {
                     type_: rustdoc_ty,
                     generics: clean_generics(generics, cx),
@@ -2211,7 +2256,9 @@ fn clean_impl<'tcx>(
 
     let for_ = clean_ty(impl_.self_ty, cx);
     let type_alias = for_.def_id(&cx.cache).and_then(|did| match tcx.def_kind(did) {
-        DefKind::TyAlias => Some(clean_middle_ty(tcx.type_of(did), cx, Some(did))),
+        DefKind::TyAlias => {
+            Some(clean_middle_ty(ty::Binder::dummy(tcx.type_of(did)), cx, Some(did)))
+        }
         _ => None,
     });
     let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| {
index 98329e7fc91935d61601a784ced2f4773fd4c866..7a7313c4bc99d90e5987fa6d2864d7fedfea3a17 100644 (file)
@@ -1343,7 +1343,7 @@ pub(crate) enum GenericBound {
 impl GenericBound {
     pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
         let did = cx.tcx.require_lang_item(LangItem::Sized, None);
-        let empty = cx.tcx.intern_substs(&[]);
+        let empty = ty::Binder::dummy(ty::InternalSubsts::empty());
         let path = external_path(cx, did, false, ThinVec::new(), empty);
         inline::record_extern_fqn(cx, did, ItemType::Trait);
         GenericBound::TraitBound(
index 246560bad291ffcc173fd72610030f1138951f75..a12f764fa8e3b739404df7937b83969a10e6bb8f 100644 (file)
@@ -78,12 +78,16 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
 
 pub(crate) fn substs_to_args<'tcx>(
     cx: &mut DocContext<'tcx>,
-    substs: &[ty::subst::GenericArg<'tcx>],
+    substs: ty::Binder<'tcx, &[ty::subst::GenericArg<'tcx>]>,
     mut skip_first: bool,
 ) -> Vec<GenericArg> {
     let mut ret_val =
-        Vec::with_capacity(substs.len().saturating_sub(if skip_first { 1 } else { 0 }));
-    ret_val.extend(substs.iter().filter_map(|kind| match kind.unpack() {
+        Vec::with_capacity(substs.skip_binder().len().saturating_sub(if skip_first {
+            1
+        } else {
+            0
+        }));
+    ret_val.extend(substs.iter().filter_map(|kind| match kind.skip_binder().unpack() {
         GenericArgKind::Lifetime(lt) => {
             Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided())))
         }
@@ -91,8 +95,12 @@ pub(crate) fn substs_to_args<'tcx>(
             skip_first = false;
             None
         }
-        GenericArgKind::Type(ty) => Some(GenericArg::Type(clean_middle_ty(ty, cx, None))),
-        GenericArgKind::Const(ct) => Some(GenericArg::Const(Box::new(clean_middle_const(ct, cx)))),
+        GenericArgKind::Type(ty) => {
+            Some(GenericArg::Type(clean_middle_ty(kind.rebind(ty), cx, None)))
+        }
+        GenericArgKind::Const(ct) => {
+            Some(GenericArg::Const(Box::new(clean_middle_const(kind.rebind(ct), cx))))
+        }
     }));
     ret_val
 }
@@ -102,15 +110,20 @@ fn external_generic_args<'tcx>(
     did: DefId,
     has_self: bool,
     bindings: ThinVec<TypeBinding>,
-    substs: SubstsRef<'tcx>,
+    substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
 ) -> GenericArgs {
-    let args = substs_to_args(cx, substs, has_self);
+    let args = substs_to_args(cx, substs.map_bound(|substs| &substs[..]), has_self);
 
     if cx.tcx.fn_trait_kind_from_def_id(did).is_some() {
+        let ty = substs
+            .iter()
+            .nth(if has_self { 1 } else { 0 })
+            .unwrap()
+            .map_bound(|arg| arg.expect_ty());
         let inputs =
             // The trait's first substitution is the one after self, if there is one.
-            match substs.iter().nth(if has_self { 1 } else { 0 }).unwrap().expect_ty().kind() {
-                ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(t, cx, None)).collect::<Vec<_>>().into(),
+            match ty.skip_binder().kind() {
+                ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(ty.rebind(t), cx, None)).collect::<Vec<_>>().into(),
                 _ => return GenericArgs::AngleBracketed { args: args.into(), bindings },
             };
         let output = bindings.into_iter().next().and_then(|binding| match binding.kind {
@@ -130,7 +143,7 @@ pub(super) fn external_path<'tcx>(
     did: DefId,
     has_self: bool,
     bindings: ThinVec<TypeBinding>,
-    substs: SubstsRef<'tcx>,
+    substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
 ) -> Path {
     let def_kind = cx.tcx.def_kind(did);
     let name = cx.tcx.item_name(did);