From 1833d91e12793b9a0d82aebf9795f1f3a3102513 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orb=C3=A1n=20Levente?= Date: Tue, 22 Sep 2026 01:32:59 +0200 Subject: [PATCH 1/3] wrap ty field of CoroutineSavedTy in EarlyBinder --- .../rustc_hir_analysis/src/check/check.rs | 3 ++- compiler/rustc_middle/src/mir/pretty.rs | 1 + compiler/rustc_middle/src/mir/query.rs | 6 +++-- compiler/rustc_middle/src/ty/sty.rs | 7 +++--- .../src/coroutine/layout.rs | 25 +++++++++++++------ .../rustc_mir_transform/src/coroutine/mod.rs | 2 +- compiler/rustc_mir_transform/src/validate.rs | 4 +-- .../src/error_reporting/traits/suggestions.rs | 3 ++- .../src/traits/query/dropck_outlives.rs | 9 +++++-- .../rustc_traits/src/coroutine_witnesses.rs | 24 ++++++++++-------- compiler/rustc_ty_utils/src/layout.rs | 7 +++--- compiler/rustc_ty_utils/src/needs_drop.rs | 4 +-- .../clippy_lints/src/await_holding_invalid.rs | 4 ++- 13 files changed, 59 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 1e75902884fe1..d513e3c602086 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -2300,7 +2300,8 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'_>, opaque_def_id: LocalDefId) -> ErrorG && let Some(coroutine_layout) = tcx.mir_coroutine_witnesses(closure_def_id) { for interior_ty in &coroutine_layout.field_tys { - label_match(interior_ty.ty, interior_ty.source_info.span); + let ty = interior_ty.ty.instantiate_identity().skip_norm_wip(); + label_match(ty, interior_ty.source_info.span); } } } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 159a0f9883db3..25bfa564d22fe 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -577,6 +577,7 @@ fn write_coroutine_layout<'tcx>( field_tys.iter_enumerated() { let ignore_for_traits = if *ignore_for_traits { " (ignored for traits)" } else { "" }; + let ty = ty.instantiate_identity().skip_norm_wip(); let indented_body = format!("{INDENT}{INDENT}field {field:?}: {ty}{ignore_for_traits};",); if options.include_extra_comments { writeln!(w, "{0:ALIGN$} // in {1}", indented_body, comment(tcx, *source_info))?; diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 616b1719359f1..a48f7f3fb4d83 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -10,7 +10,7 @@ use rustc_macros::{StableHash, TyDecodable, TyEncodable, TypeFoldable, TypeVisit use rustc_span::{Span, Symbol}; use super::{ConstValue, SourceInfo}; -use crate::ty::{self, CoroutineArgsExt, Ty}; +use crate::ty::{self, CoroutineArgsExt, EarlyBinder, Ty}; rustc_index::newtype_index! { #[stable_hash] @@ -22,7 +22,9 @@ rustc_index::newtype_index! { #[derive(Clone, Debug, PartialEq, Eq)] #[derive(TyEncodable, TyDecodable, StableHash, TypeFoldable, TypeVisitable)] pub struct CoroutineSavedTy<'tcx> { - pub ty: Ty<'tcx>, + #[type_foldable(identity)] + #[type_visitable(ignore)] + pub ty: EarlyBinder<'tcx, Ty<'tcx>>, /// Source info corresponding to the local in the original MIR body. pub source_info: SourceInfo, /// Whether the local should be ignored for trait bound computations. diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 243ad73e3dfb8..f89174ac8153b 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -165,11 +165,10 @@ impl<'tcx> ty::CoroutineArgs> { layout.variant_fields.iter().map(move |variant| { variant.iter().map(move |field| { if tcx.is_async_drop_in_place_coroutine(def_id) { - layout.field_tys[*field].ty + // FIXME(async_drop): this needs a comment for why its correct + layout.field_tys[*field].ty.instantiate_identity().skip_norm_wip() } else { - ty::EarlyBinder::bind(tcx, layout.field_tys[*field].ty) - .instantiate(tcx, self.args) - .skip_norm_wip() + layout.field_tys[*field].ty.instantiate(tcx, self.args).skip_norm_wip() } }) }) diff --git a/compiler/rustc_mir_transform/src/coroutine/layout.rs b/compiler/rustc_mir_transform/src/coroutine/layout.rs index ab500d12b8aa3..e01dd9f4ddead 100644 --- a/compiler/rustc_mir_transform/src/coroutine/layout.rs +++ b/compiler/rustc_mir_transform/src/coroutine/layout.rs @@ -35,7 +35,9 @@ use rustc_infer::traits::TraitErrors; use rustc_lint_defs::builtin::MUST_NOT_SUSPEND; use rustc_middle::mir::*; use rustc_middle::ty::consts::ConstExt; -use rustc_middle::ty::{self, CoroutineArgs, CoroutineArgsExt, Ty, TyCtxt, TypingMode}; +use rustc_middle::ty::{ + self, CoroutineArgs, CoroutineArgsExt, EarlyBinder, Ty, TyCtxt, TypingMode, +}; use rustc_mir_dataflow::impls::{ MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive, always_storage_live_locals, @@ -341,8 +343,9 @@ impl StorageConflictVisitor<'_> { } } -#[tracing::instrument(level = "trace", skip(liveness, body))] +#[tracing::instrument(level = "trace", skip(tcx, liveness, body))] pub(super) fn compute_layout<'tcx>( + tcx: TyCtxt<'tcx>, liveness: LivenessInfo, body: &Body<'tcx>, ) -> ( @@ -383,7 +386,7 @@ pub(super) fn compute_layout<'tcx>( }; CoroutineSavedTy { - ty: decl.ty, + ty: EarlyBinder::bind(tcx, decl.ty), source_info: decl.source_info, ignore_for_traits, // Will be set later when walking debuginfo. @@ -426,7 +429,11 @@ pub(super) fn compute_layout<'tcx>( // just use the first one here. That's fine; fields do not move // around inside coroutines, so it doesn't matter which variant // index we access them by. - remap[reverse_local_map[saved_local]] = Some((tys[saved_local].ty, variant_index, idx)); + remap[reverse_local_map[saved_local]] = Some(( + tys[saved_local].ty.instantiate_identity().skip_norm_wip(), + variant_index, + idx, + )); } variant_source_info.push(source_info_at_suspension_point); } @@ -479,7 +486,7 @@ pub(crate) fn mir_coroutine_witnesses<'tcx>( // Extract locals which are live across suspension point into `layout` // `remap` gives a mapping from local indices onto coroutine struct indices // `storage_liveness` tells us which locals have live storage at suspension points - let (_, coroutine_layout, _) = compute_layout(liveness_info, body); + let (_, coroutine_layout, _) = compute_layout(tcx, liveness_info, body); check_suspend_tys(tcx, &coroutine_layout, body); check_field_tys_sized(tcx, &coroutine_layout, def_id); @@ -514,7 +521,7 @@ fn check_field_tys_sized<'tcx>( ObligationCauseCode::SizedCoroutineInterior(def_id), ), param_env, - field_ty.ty, + field_ty.ty.instantiate_identity().skip_norm_wip(), tcx.require_lang_item(LangItem::Sized, field_ty.source_info.span), ); } @@ -537,14 +544,16 @@ fn check_suspend_tys<'tcx>(tcx: TyCtxt<'tcx>, layout: &CoroutineLayout<'tcx>, bo let decl = &layout.field_tys[local]; debug!(?decl); - if !decl.ignore_for_traits && linted_tys.insert(decl.ty) { + let ty = decl.ty.instantiate_identity().skip_norm_wip(); + + if !decl.ignore_for_traits && linted_tys.insert(ty) { let Some(hir_id) = decl.source_info.scope.lint_root(&body.source_scopes) else { continue; }; check_must_not_suspend_ty( tcx, - decl.ty, + ty, hir_id, SuspendCheckData { source_span: decl.source_info.span, diff --git a/compiler/rustc_mir_transform/src/coroutine/mod.rs b/compiler/rustc_mir_transform/src/coroutine/mod.rs index 1e63dca78adbb..6069ebde50b2b 100644 --- a/compiler/rustc_mir_transform/src/coroutine/mod.rs +++ b/compiler/rustc_mir_transform/src/coroutine/mod.rs @@ -1119,7 +1119,7 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform { // Extract locals which are live across suspension point into `layout` // `remap` gives a mapping from local indices onto coroutine struct indices // `storage_liveness` tells us which locals have live storage at suspension points - let (remap, layout, storage_liveness) = compute_layout(liveness_info, body); + let (remap, layout, storage_liveness) = compute_layout(tcx, liveness_info, body); let can_return = can_return(tcx, body, body.typing_env(tcx)); diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 28a508bde9eca..dea16ce39b816 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -802,9 +802,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { return; }; - ty::EarlyBinder::bind(self.tcx, f_ty.ty) - .instantiate(self.tcx, args) - .skip_norm_wip() + f_ty.ty.instantiate(self.tcx, args).skip_norm_wip() } else if let Some(&f_ty) = args.as_coroutine().upvar_tys().get(f.index()) { f_ty } else { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 47d2b7a8c98d5..2ec50c6f71ecc 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3494,7 +3494,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { for &local in variant { let decl = &coroutine_info.field_tys[local]; debug!(?decl); - if ty_matches(ty::Binder::dummy(decl.ty)) && !decl.ignore_for_traits { + let ty = decl.ty.instantiate_identity().skip_norm_wip(); + if ty_matches(ty::Binder::dummy(ty)) && !decl.ignore_for_traits { interior_or_upvar_span = Some(CoroutineInteriorOrUpvar::Interior( decl.source_info.span, Some((source_info.span, from_awaited_ty)), diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 31d2e8620af90..c344abe65ff56 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -343,10 +343,15 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( // redundant; there is no storage for the resume type, so if it is actually stored // in the interior, we'll already detect the need for a drop by checking the interior. // - // FIXME(@lcnr): Why do we erase regions in the env here? Seems odd + // FIXME(@lcnr): We erase regions in the `param_env` here because old solver + // canonicalization replaces free regions with existential variables. With the new + // solver these are replaced with placeholders instead, at which point this becomes + // unnecessary. let typing_env = tcx.erase_and_anonymize_regions(typing_env); let needs_drop = tcx.mir_coroutine_witnesses(def_id).is_some_and(|witness| { - witness.field_tys.iter().any(|field| field.ty.needs_drop(tcx, typing_env)) + witness.field_tys.iter().any(|field| { + field.ty.instantiate(tcx, args.args).skip_norm_wip().needs_drop(tcx, typing_env) + }) }); if needs_drop { // Pushing types directly to `constraints.outlives` is equivalent diff --git a/compiler/rustc_traits/src/coroutine_witnesses.rs b/compiler/rustc_traits/src/coroutine_witnesses.rs index 624db7747d1f0..52d9fa2407a66 100644 --- a/compiler/rustc_traits/src/coroutine_witnesses.rs +++ b/compiler/rustc_traits/src/coroutine_witnesses.rs @@ -21,16 +21,20 @@ pub(crate) fn coroutine_hidden_types<'tcx>( .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 }, - ) - }); + let ty = fold_regions( + tcx, + decl.ty.instantiate_identity().skip_norm_wip(), + |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 }), ); diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 8d8e501391c43..667caffc50438 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -20,8 +20,8 @@ use rustc_middle::ty::layout::{ }; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ - self, AdtDef, CoroutineArgsExt, EarlyBinder, PseudoCanonicalInput, Ty, TyCtxt, - TypeVisitableExt, Unnormalized, + self, AdtDef, CoroutineArgsExt, PseudoCanonicalInput, Ty, TyCtxt, TypeVisitableExt, + Unnormalized, }; use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo}; use rustc_span::{Symbol, bug, sym}; @@ -570,9 +570,8 @@ fn layout_of_uncached<'tcx>( .field_tys .iter() .map(|local| { - let field_ty = EarlyBinder::bind(tcx, local.ty); let uninit_ty = - Ty::new_maybe_uninit(tcx, field_ty.instantiate(tcx, args).skip_norm_wip()); + Ty::new_maybe_uninit(tcx, local.ty.instantiate(tcx, args).skip_norm_wip()); cx.spanned_layout_of(uninit_ty, local.source_info.span) }) .try_collect::>()?; diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 094cf5aec0bd1..ba01f15857a37 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -222,9 +222,7 @@ where for field_ty in &witness.field_tys { queue_type( self, - EarlyBinder::bind(tcx, field_ty.ty) - .instantiate(tcx, args) - .skip_norm_wip(), + field_ty.ty.instantiate(tcx, args).skip_norm_wip(), ); } } diff --git a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs index fdab7704f3815..51fcedcac5744 100644 --- a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs +++ b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs @@ -212,7 +212,9 @@ impl<'tcx> LateLintPass<'tcx> for AwaitHolding { impl AwaitHolding { fn check_interior_types(&self, cx: &LateContext<'_>, coroutine: &CoroutineLayout<'_>) { for (ty_index, ty_cause) in coroutine.field_tys.iter_enumerated() { - if let rustc_middle::ty::Adt(adt, _) = ty_cause.ty.kind() { + let ty = ty_cause.ty.instantiate_identity().skip_norm_wip(); + + if let rustc_middle::ty::Adt(adt, _) = ty.kind() { let await_points = || { coroutine .variant_source_info From d608a4908a765d39664cc7195086e8acf76acc8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orb=C3=A1n=20Levente?= Date: Wed, 30 Sep 2026 14:25:27 +0200 Subject: [PATCH 2/3] create wrapper around `CoroutineLayout` --- compiler/rustc_middle/src/mir/query.rs | 56 +++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index a48f7f3fb4d83..5bf67a7a12cca 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -10,7 +10,7 @@ use rustc_macros::{StableHash, TyDecodable, TyEncodable, TypeFoldable, TypeVisit use rustc_span::{Span, Symbol}; use super::{ConstValue, SourceInfo}; -use crate::ty::{self, CoroutineArgsExt, EarlyBinder, Ty}; +use crate::ty::{self, CoroutineArgsExt, EarlyBinder, GenericArgsRef, Ty, TyCtxt, Unnormalized}; rustc_index::newtype_index! { #[stable_hash] @@ -83,6 +83,60 @@ impl Debug for CoroutineLayout<'_> { } } +/// The result of the `coroutine_layout` function. +/// +/// Wraps a regular `CoroutineLayout` with its arguments, providing accessors +/// that instantiate the stored `Ty` if necessary. +#[derive(Debug, Copy, Clone)] +pub struct QueriedCoroutineLayout<'tcx> { + layout: &'tcx CoroutineLayout<'tcx>, + args: Option>, +} + +impl<'tcx> QueriedCoroutineLayout<'tcx> { + pub fn new(layout: &'tcx CoroutineLayout<'tcx>, args: Option>) -> Self { + Self { layout, args } + } + + pub fn get_ty( + &self, + tcx: TyCtxt<'tcx>, + field: CoroutineSavedLocal, + ) -> Unnormalized<'tcx, Ty<'tcx>> { + if let Some(args) = self.args { + self.layout.field_tys[field].ty.instantiate(tcx, args) + } else { + self.layout.field_tys[field].ty.instantiate_identity() + } + } + + pub fn get_identity_ty(&self, field: CoroutineSavedLocal) -> Unnormalized<'tcx, Ty<'tcx>> { + self.layout.field_tys[field].ty.instantiate_identity() + } + + pub fn field_tys(&self) -> &'tcx IndexVec> { + &self.layout.field_tys + } + + pub fn variant_fields( + &self, + ) -> &'tcx IndexVec> { + &self.layout.variant_fields + } + + pub fn variant_source_info(&self) -> &'tcx IndexVec { + &self.layout.variant_source_info + } + + pub fn storage_conflicts(&self) -> &'tcx BitMatrix { + &self.layout.storage_conflicts + } + + pub fn raw_layout(self) -> &'tcx CoroutineLayout<'tcx> { + self.layout + } +} + /// The result of the `mir_const_qualif` query. /// /// Each field (except `tainted_by_errors`) corresponds to an implementer of the `Qualif` trait in From cd123207e7b41911a732ed45b02eb929770527c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orb=C3=A1n=20Levente?= Date: Wed, 30 Sep 2026 16:33:00 +0200 Subject: [PATCH 3/3] make coroutine_layout query return layout wrapper --- .../src/debuginfo/metadata/enums/cpp_like.rs | 2 +- .../src/debuginfo/metadata/enums/mod.rs | 8 +++---- .../src/debuginfo/metadata/enums/native.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 21 +++++++++++++------ compiler/rustc_middle/src/ty/sty.rs | 9 ++++---- compiler/rustc_mir_transform/src/validate.rs | 14 +++++++++---- compiler/rustc_ty_utils/src/layout.rs | 20 +++++++++--------- 7 files changed, 46 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index fe7f38fb195bc..842f7faf6775e 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -764,7 +764,7 @@ fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>( common_upvar_names, ); - let span = coroutine_layout.variant_source_info[variant_index].span; + let span = coroutine_layout.variant_source_info()[variant_index].span; let source_info = if !span.is_dummy() { let loc = cx.lookup_debug_loc(span.lo()); Some((file_metadata(cx, &loc.file), loc.line as c_uint)) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 37f114fc5b09e..319835e8a4e65 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -6,7 +6,7 @@ use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo}; use rustc_codegen_ssa::traits::MiscCodegenMethods; use rustc_hir::def::CtorKind; use rustc_index::IndexSlice; -use rustc_middle::mir::CoroutineLayout; +use rustc_middle::mir::QueriedCoroutineLayout; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, AdtDef, CoroutineArgs, CoroutineArgsExt, Ty, VariantDef}; use rustc_span::{Span, Symbol, bug}; @@ -292,7 +292,7 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>( variant_index: VariantIdx, coroutine_type_and_layout: TyAndLayout<'tcx>, coroutine_type_di_node: &'ll DIType, - coroutine_layout: &CoroutineLayout<'tcx>, + coroutine_layout: QueriedCoroutineLayout<'tcx>, common_upvar_names: &IndexSlice, ) -> &'ll DIType { let variant_name = CoroutineArgs::variant_name(variant_index); @@ -325,10 +325,10 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>( // Fields that just belong to this variant/state let state_specific_fields: SmallVec<_> = (0..variant_layout.fields.count()) .map(|field_index| { - let coroutine_saved_local = coroutine_layout.variant_fields[variant_index] + let coroutine_saved_local = coroutine_layout.variant_fields()[variant_index] [FieldIdx::from_usize(field_index)]; let field_name_maybe = - coroutine_layout.field_tys[coroutine_saved_local].debuginfo_name; + coroutine_layout.field_tys()[coroutine_saved_local].debuginfo_name; let field_name = field_name_maybe .as_ref() .map(|s| Cow::from(s.as_str())) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index c0ecb14d21926..043e20c4032dd 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -198,7 +198,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( // with enums? let variant_name = format!("{}", variant_index.as_usize()).into(); - let span = coroutine_layout.variant_source_info[variant_index].span; + let span = coroutine_layout.variant_source_info()[variant_index].span; let source_info = if !span.is_dummy() { let loc = cx.lookup_debug_loc(span.lo()); Some((file_metadata(cx, &loc.file), loc.line)) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 1f2ffb17cc2c7..97d3501b34b3d 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -109,7 +109,9 @@ pub use self::typeck_results::{ UserTypeKind, }; use crate::diagnostics::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; -use crate::mir::{Body, CoroutineLayout, CoroutineSavedLocal, MirPhase, SourceInfo}; +use crate::mir::{ + Body, CoroutineLayout, CoroutineSavedLocal, MirPhase, QueriedCoroutineLayout, SourceInfo, +}; use crate::query::{IntoQueryKey, Providers}; use crate::ty; use crate::ty::codec::{TyDecoder, TyEncoder}; @@ -1942,13 +1944,15 @@ impl<'tcx> TyCtxt<'tcx> { self, def_id: DefId, args: GenericArgsRef<'tcx>, - ) -> Result<&'tcx CoroutineLayout<'tcx>, &'tcx LayoutError<'tcx>> { + ) -> Result, &'tcx LayoutError<'tcx>> { let coroutine_kind_ty = args.as_coroutine().kind_ty(); let mir = self.optimized_mir(def_id); let ty = || Ty::new_coroutine(self, def_id, args); // Regular coroutine if coroutine_kind_ty.is_unit() { - mir.coroutine_layout_raw().ok_or_else(|| self.layout_error(LayoutError::Unknown(ty()))) + mir.coroutine_layout_raw() + .map(|layout| QueriedCoroutineLayout::new(layout, Some(args))) + .ok_or_else(|| self.layout_error(LayoutError::Unknown(ty()))) } else { // If we have a `Coroutine` that comes from an coroutine-closure, // then it may be a by-move or by-ref body. @@ -1962,6 +1966,7 @@ impl<'tcx> TyCtxt<'tcx> { // a by-ref coroutine. if identity_kind_ty == coroutine_kind_ty { mir.coroutine_layout_raw() + .map(|layout| QueriedCoroutineLayout::new(layout, Some(args))) .ok_or_else(|| self.layout_error(LayoutError::Unknown(ty()))) } else { assert_matches!(coroutine_kind_ty.to_opt_closure_kind(), Some(ClosureKind::FnOnce)); @@ -1971,6 +1976,7 @@ impl<'tcx> TyCtxt<'tcx> { ); self.optimized_mir(self.coroutine_by_move_body_def_id(def_id)) .coroutine_layout_raw() + .map(|layout| QueriedCoroutineLayout::new(layout, Some(args))) .ok_or_else(|| self.layout_error(LayoutError::Unknown(ty()))) } } @@ -1983,7 +1989,7 @@ impl<'tcx> TyCtxt<'tcx> { self, def_id: DefId, args: GenericArgsRef<'tcx>, - ) -> Result<&'tcx CoroutineLayout<'tcx>, &'tcx LayoutError<'tcx>> { + ) -> Result, &'tcx LayoutError<'tcx>> { let ty = || Ty::new_coroutine(self, def_id, args); if args[0].has_placeholders() || args[0].has_non_region_param() { return Err(self.layout_error(LayoutError::TooGeneric(ty()))); @@ -1991,6 +1997,7 @@ impl<'tcx> TyCtxt<'tcx> { let instance = ShimKind::AsyncDropGlue(def_id, Ty::new_coroutine(self, def_id, args)); self.mir_shims(instance) .coroutine_layout_raw() + .map(|layout| QueriedCoroutineLayout::new(layout, Some(args))) .ok_or_else(|| self.layout_error(LayoutError::Unknown(ty()))) } @@ -2000,7 +2007,7 @@ impl<'tcx> TyCtxt<'tcx> { self, def_id: DefId, args: GenericArgsRef<'tcx>, - ) -> Result<&'tcx CoroutineLayout<'tcx>, &'tcx LayoutError<'tcx>> { + ) -> Result, &'tcx LayoutError<'tcx>> { if self.is_async_drop_in_place_coroutine(def_id) { // layout of `async_drop_in_place::{closure}` in case, // when T is a coroutine, contains this internal coroutine's ptr in upvars @@ -2021,7 +2028,9 @@ impl<'tcx> TyCtxt<'tcx> { variant_source_info, storage_conflicts: BitMatrix::new(0, 0), }; - return Ok(self.arena.alloc(proxy_layout)); + let layout = self.arena.alloc(proxy_layout); + let queried_layout = QueriedCoroutineLayout::new(layout, Some(args)); + return Ok(queried_layout); } else { self.async_drop_coroutine_layout(def_id, args) } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index f89174ac8153b..a541dab383e5e 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -101,7 +101,8 @@ impl<'tcx> ty::CoroutineArgs> { #[inline] fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range { // FIXME requires optimized MIR - FIRST_VARIANT..tcx.coroutine_layout(def_id, self.args).unwrap().variant_fields.next_index() + FIRST_VARIANT + ..tcx.coroutine_layout(def_id, self.args).unwrap().variant_fields().next_index() } /// The discriminant for the given variant. Panics if the `variant_index` is @@ -162,13 +163,13 @@ impl<'tcx> ty::CoroutineArgs> { tcx: TyCtxt<'tcx>, ) -> impl Iterator>> { let layout = tcx.coroutine_layout(def_id, self.args).unwrap(); - layout.variant_fields.iter().map(move |variant| { + layout.variant_fields().iter().map(move |variant| { variant.iter().map(move |field| { if tcx.is_async_drop_in_place_coroutine(def_id) { // FIXME(async_drop): this needs a comment for why its correct - layout.field_tys[*field].ty.instantiate_identity().skip_norm_wip() + layout.get_identity_ty(*field).skip_norm_wip() } else { - layout.field_tys[*field].ty.instantiate(tcx, self.args).skip_norm_wip() + layout.get_ty(tcx, *field).skip_norm_wip() } }) }) diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index dea16ce39b816..435570664658b 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -766,9 +766,12 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { // since we may be in the process of computing this MIR in the // first place. let layout = if def_id == self.caller_body.source.def_id() { - self.caller_body - .coroutine_layout_raw() - .or_else(|| self.tcx.coroutine_layout(def_id, args).ok()) + self.caller_body.coroutine_layout_raw().or_else(|| { + self.tcx + .coroutine_layout(def_id, args) + .ok() + .map(|queried| queried.raw_layout()) + }) } else if self.tcx.needs_coroutine_by_move_body_def_id(def_id) && let ty::ClosureKind::FnOnce = args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap() @@ -778,7 +781,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { // Same if this is the by-move body of a coroutine-closure. self.caller_body.coroutine_layout_raw() } else { - self.tcx.coroutine_layout(def_id, args).ok() + self.tcx + .coroutine_layout(def_id, args) + .ok() + .map(|queried| queried.raw_layout()) }; let Some(layout) = layout else { diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 667caffc50438..68e6acfd76a24 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -567,12 +567,12 @@ fn layout_of_uncached<'tcx>( let info = tcx.coroutine_layout(def_id, args)?; let local_layouts = info - .field_tys - .iter() - .map(|local| { - let uninit_ty = - Ty::new_maybe_uninit(tcx, local.ty.instantiate(tcx, args).skip_norm_wip()); - cx.spanned_layout_of(uninit_ty, local.source_info.span) + .field_tys() + .iter_enumerated() + .map(|(local, saved_ty)| { + let ty = info.get_ty(tcx, local).skip_norm_wip(); + let uninit_ty = Ty::new_maybe_uninit(tcx, ty); + cx.spanned_layout_of(uninit_ty, saved_ty.source_info.span) }) .try_collect::>()?; @@ -588,8 +588,8 @@ fn layout_of_uncached<'tcx>( .layout_of_coroutine( &local_layouts, prefix_layouts, - &info.variant_fields, - &info.storage_conflicts, + info.variant_fields(), + info.storage_conflicts(), |tag| TyAndLayout { ty: tag.primitive().to_ty(tcx), layout: tcx.mk_layout(LayoutData::scalar(cx, tag)), @@ -1024,7 +1024,7 @@ fn variant_info_for_coroutine<'tcx>( .collect(); let mut variant_infos: Vec<_> = coroutine - .variant_fields + .variant_fields() .iter_enumerated() .map(|(variant_idx, variant_def)| { let variant_layout = layout.for_variant(cx, variant_idx); @@ -1033,7 +1033,7 @@ fn variant_info_for_coroutine<'tcx>( .iter() .enumerate() .map(|(field_idx, local)| { - let field_name = coroutine.field_tys[*local].debuginfo_name; + let field_name = coroutine.field_tys()[*local].debuginfo_name; let field_layout = variant_layout.field(cx, field_idx); let offset = variant_layout.fields.offset(field_idx); // The struct is as large as the last field's end