diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index a6526b068517b..e1081423489ba 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -682,6 +682,9 @@ impl<'tcx> TyCtxt<'tcx> { /// Return the set of types that should be taken into account when checking /// trait bounds on a coroutine's internal state. + // FIXME(compiler-errors): We should remove this when the old solver goes away; + // and all other usages of this function should go through `bound_coroutine_hidden_types` + // instead. pub fn coroutine_hidden_types( self, def_id: DefId, @@ -694,6 +697,33 @@ impl<'tcx> TyCtxt<'tcx> { .map(|decl| ty::EarlyBinder::bind(decl.ty)) } + /// Return the set of types that should be taken into account when checking + /// trait bounds on a coroutine's internal state. This properly replaces + /// `ReErased` with new existential bound lifetimes. + pub fn bound_coroutine_hidden_types( + self, + def_id: DefId, + ) -> impl Iterator>>> { + let coroutine_layout = self.mir_coroutine_witnesses(def_id); + coroutine_layout + .as_ref() + .map_or_else(|| [].iter(), |l| l.field_tys.iter()) + .filter(|decl| !decl.ignore_for_traits) + .map(move |decl| { + let mut vars = vec![]; + let ty = self.fold_regions(decl.ty, |re, debruijn| { + assert_eq!(re, self.lifetimes.re_erased); + let var = ty::BoundVar::from_usize(vars.len()); + vars.push(ty::BoundVariableKind::Region(ty::BrAnon)); + ty::Region::new_bound(self, debruijn, ty::BoundRegion { var, kind: ty::BrAnon }) + }); + ty::EarlyBinder::bind(ty::Binder::bind_with_vars( + ty, + self.mk_bound_variable_kinds(&vars), + )) + }) + } + /// Expands the given impl trait type, stopping if the type is recursive. #[instrument(skip(self), level = "debug", ret)] pub fn try_expand_impl_trait_type( @@ -998,8 +1028,10 @@ impl<'tcx> OpaqueTypeExpander<'tcx> { Some(expanded_ty) => *expanded_ty, None => { if matches!(self.inspect_coroutine_fields, InspectCoroutineFields::Yes) { - for bty in self.tcx.coroutine_hidden_types(def_id) { - let hidden_ty = bty.instantiate(self.tcx, args); + for bty in self.tcx.bound_coroutine_hidden_types(def_id) { + let hidden_ty = self.tcx.instantiate_bound_regions_with_erased( + bty.instantiate(self.tcx, args), + ); self.fold_ty(hidden_ty); } } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 51a3298a90bb0..80c31831462d4 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -6,7 +6,7 @@ use rustc_hir::{def_id::DefId, Movability, Mutability}; use rustc_infer::traits::query::NoSolution; use rustc_middle::traits::solve::Goal; use rustc_middle::ty::{ - self, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, + self, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, }; use rustc_span::sym; @@ -73,8 +73,8 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( ty::CoroutineWitness(def_id, args) => Ok(ecx .tcx() - .coroutine_hidden_types(def_id) - .map(|bty| replace_erased_lifetimes_with_bound_vars(tcx, bty.instantiate(tcx, args))) + .bound_coroutine_hidden_types(def_id) + .map(|bty| bty.instantiate(tcx, args)) .collect()), // For `PhantomData`, we pass `T`. @@ -93,26 +93,6 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( } } -pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>( - tcx: TyCtxt<'tcx>, - ty: Ty<'tcx>, -) -> ty::Binder<'tcx, Ty<'tcx>> { - let mut counter = 0; - let ty = tcx.fold_regions(ty, |r, current_depth| match r.kind() { - ty::ReErased => { - let br = ty::BoundRegion { var: ty::BoundVar::from_u32(counter), kind: ty::BrAnon }; - counter += 1; - ty::Region::new_bound(tcx, current_depth, br) - } - // All free regions should be erased here. - r => bug!("unexpected region: {r:?}"), - }); - let bound_vars = tcx.mk_bound_variable_kinds_from_iter( - (0..counter).map(|_| ty::BoundVariableKind::Region(ty::BrAnon)), - ); - ty::Binder::bind_with_vars(ty, bound_vars) -} - #[instrument(level = "debug", skip(ecx), ret)] pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, @@ -240,13 +220,8 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( // impl Copy/Clone for CoroutineWitness where T: Copy/Clone forall T in coroutine_hidden_types ty::CoroutineWitness(def_id, args) => Ok(ecx .tcx() - .coroutine_hidden_types(def_id) - .map(|bty| { - replace_erased_lifetimes_with_bound_vars( - ecx.tcx(), - bty.instantiate(ecx.tcx(), args), - ) - }) + .bound_coroutine_hidden_types(def_id) + .map(|bty| bty.instantiate(ecx.tcx(), args)) .collect()), } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 51fc223a5d1b3..557fc99a53653 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -14,7 +14,7 @@ use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData}; use rustc_middle::ty::{ self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, ToPredicate, - TraitPredicate, Ty, TyCtxt, TypeVisitableExt, + TraitPredicate, Ty, TyCtxt, }; use rustc_span::def_id::DefId; @@ -1438,10 +1438,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::CoroutineWitness(def_id, args) => { let tcx = self.tcx(); - stack.extend(tcx.coroutine_hidden_types(def_id).map(|bty| { - let ty = bty.instantiate(tcx, args); - debug_assert!(!ty.has_bound_regions()); - ty + stack.extend(tcx.bound_coroutine_hidden_types(def_id).map(|bty| { + self.infcx.enter_forall_and_leak_universe(bty.instantiate(tcx, args)) })) }