Skip to content

Commit d890b01

Browse files
assign upvars with saved locals for analysis
Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
1 parent db7503b commit d890b01

File tree

14 files changed

+409
-39
lines changed

14 files changed

+409
-39
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ use rustc_middle::ty::cast::CastTy;
2727
use rustc_middle::ty::fold::fold_regions;
2828
use rustc_middle::ty::visit::TypeVisitableExt;
2929
use rustc_middle::ty::{
30-
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt,
31-
Dynamic, GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserArgs,
30+
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
31+
GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserArgs,
3232
UserTypeAnnotationIndex,
3333
};
3434
use rustc_middle::{bug, span_bug};
@@ -2174,14 +2174,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21742174
}
21752175
}
21762176
AggregateKind::Coroutine(_, args) => {
2177-
// It doesn't make sense to look at a field beyond the prefix;
2178-
// these require a variant index, and are not initialized in
2179-
// aggregate rvalues.
2180-
match args.as_coroutine().prefix_tys().get(field_index.as_usize()) {
2181-
Some(ty) => Ok(*ty),
2182-
None => Err(FieldAccessError::OutOfRange {
2183-
field_count: args.as_coroutine().prefix_tys().len(),
2184-
}),
2177+
// It doesn't make sense to look at a field beyond the captured
2178+
// upvars.
2179+
// Otherwise it require a variant index, and are not initialized
2180+
// in aggregate rvalues.
2181+
let upvar_tys = &args.as_coroutine().upvar_tys();
2182+
if let Some(ty) = upvar_tys.get(field_index.as_usize()) {
2183+
Ok(*ty)
2184+
} else {
2185+
Err(FieldAccessError::OutOfRange { field_count: upvar_tys.len() })
21852186
}
21862187
}
21872188
AggregateKind::CoroutineClosure(_, args) => {

compiler/rustc_codegen_cranelift/src/base.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,9 @@ fn codegen_stmt<'tcx>(
915915
let variant_dest = lval.downcast_variant(fx, variant_index);
916916
(variant_index, variant_dest, active_field_index)
917917
}
918+
mir::AggregateKind::Coroutine(_def_id, _args) => {
919+
(FIRST_VARIANT, lval.downcast_variant(fx, FIRST_VARIANT), None)
920+
}
918921
_ => (FIRST_VARIANT, lval, None),
919922
};
920923
if active_field_index.is_some() {

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
144144
let variant_dest = dest.project_downcast(bx, variant_index);
145145
(variant_index, variant_dest, active_field_index)
146146
}
147+
mir::AggregateKind::Coroutine(_, _) => {
148+
(FIRST_VARIANT, dest.project_downcast(bx, FIRST_VARIANT), None)
149+
}
147150
_ => (FIRST_VARIANT, dest, None),
148151
};
149152
if active_field_index.is_some() {

compiler/rustc_index/src/vec.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,11 @@ impl<I: Idx, T> IndexVec<I, T> {
197197
pub fn append(&mut self, other: &mut Self) {
198198
self.raw.append(&mut other.raw);
199199
}
200+
201+
#[inline]
202+
pub fn debug_map_view(&self) -> IndexSliceMapView<'_, I, T> {
203+
IndexSliceMapView(self.as_slice())
204+
}
200205
}
201206

202207
/// `IndexVec` is often used as a map, so it provides some map-like APIs.
@@ -220,14 +225,44 @@ impl<I: Idx, T> IndexVec<I, Option<T>> {
220225
pub fn contains(&self, index: I) -> bool {
221226
self.get(index).and_then(Option::as_ref).is_some()
222227
}
228+
229+
#[inline]
230+
pub fn debug_map_view_compact(&self) -> IndexSliceMapViewCompact<'_, I, T> {
231+
IndexSliceMapViewCompact(self.as_slice())
232+
}
223233
}
224234

235+
pub struct IndexSliceMapView<'a, I: Idx, T>(&'a IndexSlice<I, T>);
236+
pub struct IndexSliceMapViewCompact<'a, I: Idx, T>(&'a IndexSlice<I, Option<T>>);
237+
225238
impl<I: Idx, T: fmt::Debug> fmt::Debug for IndexVec<I, T> {
226239
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
227240
fmt::Debug::fmt(&self.raw, fmt)
228241
}
229242
}
230243

244+
impl<'a, I: Idx, T: fmt::Debug> fmt::Debug for IndexSliceMapView<'a, I, T> {
245+
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
246+
let mut entries = fmt.debug_map();
247+
for (idx, val) in self.0.iter_enumerated() {
248+
entries.entry(&idx, val);
249+
}
250+
entries.finish()
251+
}
252+
}
253+
254+
impl<'a, I: Idx, T: fmt::Debug> fmt::Debug for IndexSliceMapViewCompact<'a, I, T> {
255+
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
256+
let mut entries = fmt.debug_map();
257+
for (idx, val) in self.0.iter_enumerated() {
258+
if let Some(val) = val {
259+
entries.entry(&idx, val);
260+
}
261+
}
262+
entries.finish()
263+
}
264+
}
265+
231266
impl<I: Idx, T> Deref for IndexVec<I, T> {
232267
type Target = IndexSlice<I, T>;
233268

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,9 @@ pub struct Body<'tcx> {
368368
#[type_foldable(identity)]
369369
#[type_visitable(ignore)]
370370
pub function_coverage_info: Option<Box<coverage::FunctionCoverageInfo>>,
371+
372+
/// Coroutine local-upvar map
373+
pub local_upvar_map: IndexVec<FieldIdx, Option<Local>>,
371374
}
372375

373376
impl<'tcx> Body<'tcx> {
@@ -411,6 +414,7 @@ impl<'tcx> Body<'tcx> {
411414
tainted_by_errors,
412415
coverage_info_hi: None,
413416
function_coverage_info: None,
417+
local_upvar_map: IndexVec::new(),
414418
};
415419
body.is_polymorphic = body.has_non_region_param();
416420
body
@@ -442,6 +446,7 @@ impl<'tcx> Body<'tcx> {
442446
tainted_by_errors: None,
443447
coverage_info_hi: None,
444448
function_coverage_info: None,
449+
local_upvar_map: IndexVec::new(),
445450
};
446451
body.is_polymorphic = body.has_non_region_param();
447452
body

compiler/rustc_middle/src/mir/query.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_index::bit_set::BitMatrix;
1010
use rustc_index::{Idx, IndexVec};
1111
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
1212
use rustc_span::{Span, Symbol};
13+
use rustc_type_ir::data_structures::IndexMap;
1314
use smallvec::SmallVec;
1415

1516
use super::{ConstValue, SourceInfo};
@@ -19,7 +20,7 @@ use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty, TyCtxt};
1920
rustc_index::newtype_index! {
2021
#[derive(HashStable)]
2122
#[encodable]
22-
#[debug_format = "_{}"]
23+
#[debug_format = "corsl_{}"]
2324
pub struct CoroutineSavedLocal {}
2425
}
2526

@@ -57,6 +58,13 @@ pub struct CoroutineLayout<'tcx> {
5758
#[type_foldable(identity)]
5859
#[type_visitable(ignore)]
5960
pub storage_conflicts: BitMatrix<CoroutineSavedLocal, CoroutineSavedLocal>,
61+
62+
/// This map `A -> B` allows later MIR passes, error reporters
63+
/// and layout calculator to relate saved locals `A` sourced from upvars
64+
/// and locals `B` that upvars are moved into.
65+
#[type_foldable(identity)]
66+
#[type_visitable(ignore)]
67+
pub relocated_upvars: IndexMap<CoroutineSavedLocal, CoroutineSavedLocal>,
6068
}
6169

6270
impl Debug for CoroutineLayout<'_> {

compiler/rustc_middle/src/mir/statement.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,10 @@ impl<'tcx> PlaceTy<'tcx> {
123123
.get(f.index())
124124
.copied()
125125
.unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
126-
// Only prefix fields (upvars and current state) are
127-
// accessible without a variant index.
126+
// Only upvars are accessible without a variant index.
128127
ty::Coroutine(_, args) => args
129128
.as_coroutine()
130-
.prefix_tys()
129+
.upvar_tys()
131130
.get(f.index())
132131
.copied()
133132
.unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),

compiler/rustc_middle/src/ty/layout.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -935,9 +935,10 @@ where
935935
),
936936
Variants::Multiple { tag, tag_field, .. } => {
937937
if i == tag_field {
938-
return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
938+
TyMaybeWithLayout::TyAndLayout(tag_layout(tag))
939+
} else {
940+
TyMaybeWithLayout::Ty(args.as_coroutine().upvar_tys()[i])
939941
}
940-
TyMaybeWithLayout::Ty(args.as_coroutine().prefix_tys()[i])
941942
}
942943
},
943944

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -146,13 +146,6 @@ impl<'tcx> ty::CoroutineArgs<TyCtxt<'tcx>> {
146146
})
147147
})
148148
}
149-
150-
/// This is the types of the fields of a coroutine which are not stored in a
151-
/// variant.
152-
#[inline]
153-
fn prefix_tys(self) -> &'tcx List<Ty<'tcx>> {
154-
self.upvar_tys()
155-
}
156149
}
157150

158151
#[derive(Debug, Copy, Clone, HashStable, TypeFoldable, TypeVisitable)]

compiler/rustc_mir_build/src/builder/custom/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ pub(super) fn build_custom_mir<'tcx>(
6161
pass_count: 0,
6262
coverage_info_hi: None,
6363
function_coverage_info: None,
64+
local_upvar_map: IndexVec::new(),
6465
};
6566

6667
body.local_decls.push(LocalDecl::new(return_ty, return_ty_span));

0 commit comments

Comments
 (0)