From 6555ef7f09a5b23a8eea05cba499a5b9fd16909a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 20 May 2025 10:28:31 +0000 Subject: [PATCH] Querify coroutine_hidden_types --- compiler/rustc_middle/src/query/erase.rs | 7 +++- compiler/rustc_middle/src/query/mod.rs | 6 +++ compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 36 +----------------- .../src/solve/assembly/structural_traits.rs | 4 +- .../src/traits/select/mod.rs | 2 +- .../rustc_traits/src/coroutine_witnesses.rs | 37 +++++++++++++++++++ compiler/rustc_traits/src/lib.rs | 2 + compiler/rustc_type_ir/src/interner.rs | 2 +- compiler/rustc_type_ir/src/ty_kind.rs | 10 +++++ 10 files changed, 67 insertions(+), 41 deletions(-) create mode 100644 compiler/rustc_traits/src/coroutine_witnesses.rs diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 5bd111fa2f22d..2d248e028fe8b 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -6,7 +6,7 @@ use rustc_span::ErrorGuaranteed; use crate::query::CyclePlaceholder; use crate::ty::adjustment::CoerceUnsizedInfo; -use crate::ty::{self, Ty}; +use crate::ty::{self, Ty, TyCtxt}; use crate::{mir, traits}; #[derive(Copy, Clone)] @@ -207,6 +207,11 @@ impl EraseType for ty::Binder<'_, ty::FnSig<'_>> { type Result = [u8; size_of::>>()]; } +impl EraseType for ty::Binder<'_, ty::CoroutineWitnessTypes>> { + type Result = + [u8; size_of::>>>()]; +} + impl EraseType for ty::Binder<'_, &'_ ty::List>> { type Result = [u8; size_of::>>>()]; } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index b2133fea08cc3..b6218fff0c417 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -922,6 +922,12 @@ rustc_queries! { separate_provide_extern } + query coroutine_hidden_types( + def_id: DefId + ) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, ty::CoroutineWitnessTypes>>> { + desc { "looking up the hidden types stored across await points in a coroutine" } + } + /// Gets a map with the variances of every item in the local crate. /// ///
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 0759fa3da428a..c205d53b93f1f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -340,7 +340,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { fn coroutine_hidden_types( self, def_id: DefId, - ) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, &'tcx ty::List>>> { + ) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, ty::CoroutineWitnessTypes>>> { self.coroutine_hidden_types(def_id) } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 9676aa4044823..ecf83926df7d2 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -26,7 +26,7 @@ use crate::query::Providers; use crate::ty::layout::{FloatExt, IntegerExt}; use crate::ty::{ self, Asyncness, FallibleTypeFolder, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeFoldable, - TypeFolder, TypeSuperFoldable, TypeVisitableExt, Upcast, fold_regions, + TypeFolder, TypeSuperFoldable, TypeVisitableExt, Upcast, }; #[derive(Copy, Clone, Debug)] @@ -737,40 +737,6 @@ 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. This properly replaces - /// `ReErased` with new existential bound lifetimes. - pub fn coroutine_hidden_types( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, &'tcx ty::List>>> { - let coroutine_layout = self.mir_coroutine_witnesses(def_id); - let mut vars = vec![]; - let bound_tys = self.mk_type_list_from_iter( - coroutine_layout - .as_ref() - .map_or_else(|| [].iter(), |l| l.field_tys.iter()) - .filter(|decl| !decl.ignore_for_traits) - .map(|decl| { - let ty = fold_regions(self, 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::BoundRegionKind::Anon)); - ty::Region::new_bound( - self, - debruijn, - ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon }, - ) - }); - ty - }), - ); - ty::EarlyBinder::bind(ty::Binder::bind_with_vars( - bound_tys, - 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( diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 2a2b462a36cbd..9b89b9fad8626 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -83,7 +83,7 @@ where .cx() .coroutine_hidden_types(def_id) .instantiate(cx, args) - .map_bound(|tys| tys.to_vec())), + .map_bound(|bound| bound.types.to_vec())), ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])), @@ -249,7 +249,7 @@ where .cx() .coroutine_hidden_types(def_id) .instantiate(ecx.cx(), args) - .map_bound(|tys| tys.to_vec())), + .map_bound(|bound| bound.types.to_vec())), } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 44a76f6e08327..549aed908f381 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2866,7 +2866,7 @@ fn rebind_coroutine_witness_types<'tcx>( let shifted_coroutine_types = tcx.shift_bound_var_indices(bound_vars.len(), bound_coroutine_types.skip_binder()); ty::Binder::bind_with_vars( - ty::EarlyBinder::bind(shifted_coroutine_types.to_vec()).instantiate(tcx, args), + ty::EarlyBinder::bind(shifted_coroutine_types.types.to_vec()).instantiate(tcx, args), tcx.mk_bound_variable_kinds_from_iter( bound_vars.iter().chain(bound_coroutine_types.bound_vars()), ), diff --git a/compiler/rustc_traits/src/coroutine_witnesses.rs b/compiler/rustc_traits/src/coroutine_witnesses.rs new file mode 100644 index 0000000000000..447e13126ccdc --- /dev/null +++ b/compiler/rustc_traits/src/coroutine_witnesses.rs @@ -0,0 +1,37 @@ +use rustc_hir::def_id::DefId; +use rustc_middle::ty::{self, TyCtxt, fold_regions}; + +/// 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(crate) fn coroutine_hidden_types<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, +) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, ty::CoroutineWitnessTypes>>> { + let coroutine_layout = tcx.mir_coroutine_witnesses(def_id); + let mut vars = vec![]; + let bound_tys = tcx.mk_type_list_from_iter( + coroutine_layout + .as_ref() + .map_or_else(|| [].iter(), |l| l.field_tys.iter()) + .filter(|decl| !decl.ignore_for_traits) + .map(|decl| { + let ty = fold_regions(tcx, decl.ty, |re, debruijn| { + assert_eq!(re, tcx.lifetimes.re_erased); + let var = ty::BoundVar::from_usize(vars.len()); + vars.push(ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon)); + ty::Region::new_bound( + tcx, + debruijn, + ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon }, + ) + }); + ty + }), + ); + + ty::EarlyBinder::bind(ty::Binder::bind_with_vars( + ty::CoroutineWitnessTypes { types: bound_tys }, + tcx.mk_bound_variable_kinds(&vars), + )) +} diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs index 697c839180312..32d8c3f58e08a 100644 --- a/compiler/rustc_traits/src/lib.rs +++ b/compiler/rustc_traits/src/lib.rs @@ -5,6 +5,7 @@ // tidy-alphabetical-end mod codegen; +mod coroutine_witnesses; mod dropck_outlives; mod evaluate_obligation; mod implied_outlives_bounds; @@ -24,4 +25,5 @@ pub fn provide(p: &mut Providers) { normalize_erasing_regions::provide(p); type_op::provide(p); p.codegen_select_candidate = codegen::codegen_select_candidate; + p.coroutine_hidden_types = coroutine_witnesses::coroutine_hidden_types; } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 0fd2d9f3ad38b..c10241cfcf0f6 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -210,7 +210,7 @@ pub trait Interner: fn coroutine_hidden_types( self, def_id: Self::DefId, - ) -> ty::EarlyBinder>; + ) -> ty::EarlyBinder>>; fn fn_sig( self, diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index cf2e4284d10da..0cd98b5aa53b4 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -1163,3 +1163,13 @@ pub struct FnHeader { pub safety: I::Safety, pub abi: I::Abi, } + +#[derive_where(Clone, Copy, Debug, PartialEq, Eq, Hash; I: Interner)] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] +pub struct CoroutineWitnessTypes { + pub types: I::Tys, +}