Skip to content

Commit 9e9e4e0

Browse files
assign upvars with saved locals for analysis
Co-authored-by: Dario Nieuwenhuis <[email protected]>
1 parent f7da7ba commit 9e9e4e0

File tree

14 files changed

+410
-38
lines changed

14 files changed

+410
-38
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ use rustc_middle::traits::query::NoSolution;
2525
use rustc_middle::ty::adjustment::PointerCoercion;
2626
use rustc_middle::ty::cast::CastTy;
2727
use rustc_middle::ty::{
28-
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt,
29-
Dynamic, GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt,
30-
TypeVisitableExt, UserArgs, UserTypeAnnotationIndex, fold_regions,
28+
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
29+
GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, TypeVisitableExt,
30+
UserArgs, UserTypeAnnotationIndex, fold_regions,
3131
};
3232
use rustc_middle::{bug, span_bug};
3333
use rustc_mir_dataflow::ResultsCursor;
@@ -2188,14 +2188,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21882188
}
21892189
}
21902190
AggregateKind::Coroutine(_, args) => {
2191-
// It doesn't make sense to look at a field beyond the prefix;
2192-
// these require a variant index, and are not initialized in
2193-
// aggregate rvalues.
2194-
match args.as_coroutine().prefix_tys().get(field_index.as_usize()) {
2195-
Some(ty) => Ok(*ty),
2196-
None => Err(FieldAccessError::OutOfRange {
2197-
field_count: args.as_coroutine().prefix_tys().len(),
2198-
}),
2191+
// It doesn't make sense to look at a field beyond the captured
2192+
// upvars.
2193+
// Otherwise it require a variant index, and are not initialized
2194+
// in aggregate rvalues.
2195+
let upvar_tys = &args.as_coroutine().upvar_tys();
2196+
if let Some(ty) = upvar_tys.get(field_index.as_usize()) {
2197+
Ok(*ty)
2198+
} else {
2199+
Err(FieldAccessError::OutOfRange { field_count: upvar_tys.len() })
21992200
}
22002201
}
22012202
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
@@ -367,6 +367,9 @@ pub struct Body<'tcx> {
367367
#[type_foldable(identity)]
368368
#[type_visitable(ignore)]
369369
pub function_coverage_info: Option<Box<coverage::FunctionCoverageInfo>>,
370+
371+
/// Coroutine local-upvar map
372+
pub local_upvar_map: IndexVec<FieldIdx, Option<Local>>,
370373
}
371374

372375
impl<'tcx> Body<'tcx> {
@@ -410,6 +413,7 @@ impl<'tcx> Body<'tcx> {
410413
tainted_by_errors,
411414
coverage_info_hi: None,
412415
function_coverage_info: None,
416+
local_upvar_map: IndexVec::new(),
413417
};
414418
body.is_polymorphic = body.has_non_region_param();
415419
body
@@ -441,6 +445,7 @@ impl<'tcx> Body<'tcx> {
441445
tainted_by_errors: None,
442446
coverage_info_hi: None,
443447
function_coverage_info: None,
448+
local_upvar_map: IndexVec::new(),
444449
};
445450
body.is_polymorphic = body.has_non_region_param();
446451
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};
@@ -18,7 +19,7 @@ use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty, TyCtxt, fold_regio
1819
rustc_index::newtype_index! {
1920
#[derive(HashStable)]
2021
#[encodable]
21-
#[debug_format = "_{}"]
22+
#[debug_format = "corsl_{}"]
2223
pub struct CoroutineSavedLocal {}
2324
}
2425

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

6169
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
@@ -145,13 +145,6 @@ impl<'tcx> ty::CoroutineArgs<TyCtxt<'tcx>> {
145145
})
146146
})
147147
}
148-
149-
/// This is the types of the fields of a coroutine which are not stored in a
150-
/// variant.
151-
#[inline]
152-
fn prefix_tys(self) -> &'tcx List<Ty<'tcx>> {
153-
self.upvar_tys()
154-
}
155148
}
156149

157150
#[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)