Skip to content

Commit da13acc

Browse files
relocate upvars onto Unresumed state
1 parent 159bdc1 commit da13acc

File tree

32 files changed

+671
-352
lines changed

32 files changed

+671
-352
lines changed

compiler/rustc_abi/src/lib.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1510,8 +1510,7 @@ pub struct LayoutS<FieldIdx: Idx, VariantIdx: Idx> {
15101510

15111511
/// Encodes information about multi-variant layouts.
15121512
/// Even with `Multiple` variants, a layout still has its own fields! Those are then
1513-
/// shared between all variants. One of them will be the discriminant,
1514-
/// but e.g. coroutines can have more.
1513+
/// shared between all variants. One of them will be the discriminant.
15151514
///
15161515
/// To access all fields of this layout, both `fields` and the fields of the active variant
15171516
/// must be taken into account.

compiler/rustc_borrowck/src/type_check/mod.rs

+9-13
Original file line numberDiff line numberDiff line change
@@ -802,14 +802,11 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
802802
}),
803803
};
804804
}
805-
ty::Coroutine(_, args) => {
806-
// Only prefix fields (upvars and current state) are
807-
// accessible without a variant index.
808-
return match args.as_coroutine().prefix_tys().get(field.index()) {
809-
Some(ty) => Ok(*ty),
810-
None => Err(FieldAccessError::OutOfRange {
811-
field_count: args.as_coroutine().prefix_tys().len(),
812-
}),
805+
ty::Coroutine(_def_id, args) => {
806+
let upvar_tys = args.as_coroutine().upvar_tys();
807+
return match upvar_tys.get(field.index()) {
808+
Some(&ty) => Ok(ty),
809+
None => Err(FieldAccessError::OutOfRange { field_count: upvar_tys.len() }),
813810
};
814811
}
815812
ty::Tuple(tys) => {
@@ -1822,11 +1819,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
18221819
// It doesn't make sense to look at a field beyond the prefix;
18231820
// these require a variant index, and are not initialized in
18241821
// aggregate rvalues.
1825-
match args.as_coroutine().prefix_tys().get(field_index.as_usize()) {
1822+
let upvar_tys = args.as_coroutine().upvar_tys();
1823+
match upvar_tys.get(field_index.as_usize()) {
18261824
Some(ty) => Ok(*ty),
1827-
None => Err(FieldAccessError::OutOfRange {
1828-
field_count: args.as_coroutine().prefix_tys().len(),
1829-
}),
1825+
None => Err(FieldAccessError::OutOfRange { field_count: upvar_tys.len() }),
18301826
}
18311827
}
18321828
AggregateKind::Array(ty) => Ok(ty),
@@ -2443,7 +2439,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
24432439

24442440
self.prove_aggregate_predicates(aggregate_kind, location);
24452441

2446-
if *aggregate_kind == AggregateKind::Tuple {
2442+
if matches!(aggregate_kind, AggregateKind::Tuple) {
24472443
// tuple rvalue field type is always the type of the op. Nothing to check here.
24482444
return;
24492445
}

compiler/rustc_codegen_cranelift/src/base.rs

+3
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,9 @@ fn codegen_stmt<'tcx>(
781781
let variant_dest = lval.downcast_variant(fx, variant_index);
782782
(variant_index, variant_dest, active_field_index)
783783
}
784+
mir::AggregateKind::Coroutine(_, _) => {
785+
(FIRST_VARIANT, lval.downcast_variant(fx, FIRST_VARIANT), None)
786+
}
784787
_ => (FIRST_VARIANT, lval, None),
785788
};
786789
if active_field_index.is_some() {

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use rustc_hir::def::CtorKind;
2929
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
3030
use rustc_middle::bug;
3131
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
32+
use rustc_middle::ty::List;
3233
use rustc_middle::ty::{
3334
self, AdtKind, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt, Visibility,
3435
};
@@ -1066,7 +1067,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>(
10661067
closure_or_coroutine_di_node: &'ll DIType,
10671068
) -> SmallVec<&'ll DIType> {
10681069
let (&def_id, up_var_tys) = match closure_or_coroutine_ty.kind() {
1069-
ty::Coroutine(def_id, args) => (def_id, args.as_coroutine().prefix_tys()),
1070+
ty::Coroutine(def_id, _args) => (def_id, List::empty()),
10701071
ty::Closure(def_id, args) => (def_id, args.as_closure().upvar_tys()),
10711072
_ => {
10721073
bug!(

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs

-2
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,6 @@ fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>(
685685

686686
let coroutine_layout = cx.tcx.optimized_mir(coroutine_def_id).coroutine_layout().unwrap();
687687

688-
let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(coroutine_def_id);
689688
let variant_range = coroutine_args.variant_range(coroutine_def_id, cx.tcx);
690689
let variant_count = (variant_range.start.as_u32()..variant_range.end.as_u32()).len();
691690

@@ -720,7 +719,6 @@ fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>(
720719
coroutine_type_and_layout,
721720
coroutine_type_di_node,
722721
coroutine_layout,
723-
common_upvar_names,
724722
);
725723

726724
let span = coroutine_layout.variant_source_info[variant_index].span;

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs

+2-31
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use rustc_codegen_ssa::debuginfo::{
33
wants_c_like_enum_debuginfo,
44
};
55
use rustc_hir::def::CtorKind;
6-
use rustc_index::IndexSlice;
76
use rustc_middle::{
87
bug,
98
mir::CoroutineLayout,
@@ -13,7 +12,6 @@ use rustc_middle::{
1312
AdtDef, CoroutineArgs, Ty, VariantDef,
1413
},
1514
};
16-
use rustc_span::Symbol;
1715
use rustc_target::abi::{
1816
FieldIdx, HasDataLayout, Integer, Primitive, TagEncoding, VariantIdx, Variants,
1917
};
@@ -324,7 +322,6 @@ pub fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
324322
coroutine_type_and_layout: TyAndLayout<'tcx>,
325323
coroutine_type_di_node: &'ll DIType,
326324
coroutine_layout: &CoroutineLayout<'tcx>,
327-
common_upvar_names: &IndexSlice<FieldIdx, Symbol>,
328325
) -> &'ll DIType {
329326
let variant_name = CoroutineArgs::variant_name(variant_index);
330327
let unique_type_id = UniqueTypeId::for_enum_variant_struct_type(
@@ -335,11 +332,6 @@ pub fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
335332

336333
let variant_layout = coroutine_type_and_layout.for_variant(cx, variant_index);
337334

338-
let coroutine_args = match coroutine_type_and_layout.ty.kind() {
339-
ty::Coroutine(_, args) => args.as_coroutine(),
340-
_ => unreachable!(),
341-
};
342-
343335
type_map::build_type_with_children(
344336
cx,
345337
type_map::stub(
@@ -353,7 +345,7 @@ pub fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
353345
),
354346
|cx, variant_struct_type_di_node| {
355347
// Fields that just belong to this variant/state
356-
let state_specific_fields: SmallVec<_> = (0..variant_layout.fields.count())
348+
(0..variant_layout.fields.count())
357349
.map(|field_index| {
358350
let coroutine_saved_local = coroutine_layout.variant_fields[variant_index]
359351
[FieldIdx::from_usize(field_index)];
@@ -375,28 +367,7 @@ pub fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
375367
type_di_node(cx, field_type),
376368
)
377369
})
378-
.collect();
379-
380-
// Fields that are common to all states
381-
let common_fields: SmallVec<_> = coroutine_args
382-
.prefix_tys()
383-
.iter()
384-
.zip(common_upvar_names)
385-
.enumerate()
386-
.map(|(index, (upvar_ty, upvar_name))| {
387-
build_field_di_node(
388-
cx,
389-
variant_struct_type_di_node,
390-
upvar_name.as_str(),
391-
cx.size_and_align_of(upvar_ty),
392-
coroutine_type_and_layout.fields.offset(index),
393-
DIFlags::FlagZero,
394-
type_di_node(cx, upvar_ty),
395-
)
396-
})
397-
.collect();
398-
399-
state_specific_fields.into_iter().chain(common_fields).collect()
370+
.collect()
400371
},
401372
|cx| build_generic_type_param_di_nodes(cx, coroutine_type_and_layout.ty),
402373
)

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs

-4
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,6 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
170170
)
171171
};
172172

173-
let common_upvar_names =
174-
cx.tcx.closure_saved_names_of_captured_variables(coroutine_def_id);
175-
176173
// Build variant struct types
177174
let variant_struct_type_di_nodes: SmallVec<_> = variants
178175
.indices()
@@ -200,7 +197,6 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
200197
coroutine_type_and_layout,
201198
coroutine_type_di_node,
202199
coroutine_layout,
203-
common_upvar_names,
204200
),
205201
source_info,
206202
}

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+3
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
126126
let variant_dest = dest.project_downcast(bx, variant_index);
127127
(variant_index, variant_dest, active_field_index)
128128
}
129+
mir::AggregateKind::Coroutine(_, _) => {
130+
(FIRST_VARIANT, dest.project_downcast(bx, FIRST_VARIANT), None)
131+
}
129132
_ => (FIRST_VARIANT, dest, None),
130133
};
131134
if active_field_index.is_some() {

compiler/rustc_const_eval/src/interpret/step.rs

+3
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
295295
let variant_dest = self.project_downcast(dest, variant_index)?;
296296
(variant_index, variant_dest, active_field_index)
297297
}
298+
mir::AggregateKind::Coroutine(_def_id, _args) => {
299+
(FIRST_VARIANT, self.project_downcast(dest, FIRST_VARIANT)?, None)
300+
}
298301
_ => (FIRST_VARIANT, dest.clone(), None),
299302
};
300303
if active_field_index.is_some() {

compiler/rustc_const_eval/src/transform/validate.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -695,14 +695,12 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
695695
};
696696

697697
ty::EarlyBinder::bind(f_ty.ty).instantiate(self.tcx, args)
698+
} else if let Some(&ty) = args.as_coroutine().upvar_tys().get(f.as_usize())
699+
{
700+
ty
698701
} else {
699-
let Some(&f_ty) = args.as_coroutine().prefix_tys().get(f.index())
700-
else {
701-
fail_out_of_bounds(self, location);
702-
return;
703-
};
704-
705-
f_ty
702+
fail_out_of_bounds(self, location);
703+
return;
706704
};
707705

708706
check_equal(self, location, f_ty);

compiler/rustc_middle/src/mir/tcx.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,11 @@ impl<'tcx> PlaceTy<'tcx> {
7474
T: ::std::fmt::Debug + Copy,
7575
{
7676
if self.variant_index.is_some() && !matches!(elem, ProjectionElem::Field(..)) {
77-
bug!("cannot use non field projection on downcasted place")
77+
bug!(
78+
"cannot use non field projection on downcasted place from {:?} (variant {:?}), got {elem:?}",
79+
self.ty,
80+
self.variant_index
81+
)
7882
}
7983
let answer = match *elem {
8084
ProjectionElem::Deref => {

compiler/rustc_middle/src/ty/layout.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -919,7 +919,7 @@ where
919919
if i == tag_field {
920920
return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
921921
}
922-
TyMaybeWithLayout::Ty(args.as_coroutine().prefix_tys()[i])
922+
bug!("coroutine has no prefix field");
923923
}
924924
},
925925

compiler/rustc_middle/src/ty/sty.rs

-7
Original file line numberDiff line numberDiff line change
@@ -549,13 +549,6 @@ impl<'tcx> CoroutineArgs<'tcx> {
549549
})
550550
})
551551
}
552-
553-
/// This is the types of the fields of a coroutine which are not stored in a
554-
/// variant.
555-
#[inline]
556-
pub fn prefix_tys(self) -> &'tcx List<Ty<'tcx>> {
557-
self.upvar_tys()
558-
}
559552
}
560553

561554
#[derive(Debug, Copy, Clone, HashStable)]

compiler/rustc_mir_dataflow/src/framework/engine.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ where
288288
}
289289

290290
None if dump_enabled(tcx, A::NAME, def_id) => {
291-
create_dump_file(tcx, ".dot", false, A::NAME, &pass_name.unwrap_or("-----"), body)?
291+
create_dump_file(tcx, ".dot", true, A::NAME, &pass_name.unwrap_or("-----"), body)?
292292
}
293293

294294
_ => return (Ok(()), results),

compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs

+58-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use rustc_index::bit_set::BitSet;
2-
use rustc_middle::mir::visit::Visitor;
32
use rustc_middle::mir::*;
3+
use rustc_middle::{mir::visit::Visitor, ty};
44

55
use crate::{AnalysisDomain, GenKill, GenKillAnalysis};
66

@@ -12,11 +12,28 @@ use crate::{AnalysisDomain, GenKill, GenKillAnalysis};
1212
/// `MaybeBorrowedLocals` is used to compute which locals are live during a yield expression for
1313
/// immovable coroutines.
1414
#[derive(Clone, Copy)]
15-
pub struct MaybeBorrowedLocals;
15+
pub struct MaybeBorrowedLocals {
16+
upvar_start: Option<(Local, usize)>,
17+
}
1618

1719
impl MaybeBorrowedLocals {
20+
/// `upvar_start` is to signal that upvars are treated as locals,
21+
/// and locals greater than this value refers to upvars accessed
22+
/// through the tuple `ty::CAPTURE_STRUCT_LOCAL`, aka. _1.
23+
pub fn new(upvar_start: Option<(Local, usize)>) -> Self {
24+
Self { upvar_start }
25+
}
26+
1827
pub(super) fn transfer_function<'a, T>(&'a self, trans: &'a mut T) -> TransferFunction<'a, T> {
19-
TransferFunction { trans }
28+
TransferFunction { trans, upvar_start: self.upvar_start }
29+
}
30+
31+
pub fn domain_size(&self, body: &Body<'_>) -> usize {
32+
if let Some((start, len)) = self.upvar_start {
33+
start.as_usize() + len
34+
} else {
35+
body.local_decls.len()
36+
}
2037
}
2138
}
2239

@@ -26,7 +43,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeBorrowedLocals {
2643

2744
fn bottom_value(&self, body: &Body<'tcx>) -> Self::Domain {
2845
// bottom = unborrowed
29-
BitSet::new_empty(body.local_decls().len())
46+
BitSet::new_empty(self.domain_size(body))
3047
}
3148

3249
fn initialize_start_block(&self, _: &Body<'tcx>, _: &mut Self::Domain) {
@@ -38,7 +55,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeBorrowedLocals {
3855
type Idx = Local;
3956

4057
fn domain_size(&self, body: &Body<'tcx>) -> usize {
41-
body.local_decls.len()
58+
self.domain_size(body)
4259
}
4360

4461
fn statement_effect(
@@ -72,6 +89,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeBorrowedLocals {
7289
/// A `Visitor` that defines the transfer function for `MaybeBorrowedLocals`.
7390
pub(super) struct TransferFunction<'a, T> {
7491
trans: &'a mut T,
92+
upvar_start: Option<(Local, usize)>,
7593
}
7694

7795
impl<'tcx, T> Visitor<'tcx> for TransferFunction<'_, T>
@@ -97,7 +115,20 @@ where
97115
Rvalue::AddressOf(_, borrowed_place)
98116
| Rvalue::Ref(_, BorrowKind::Mut { .. } | BorrowKind::Shared, borrowed_place) => {
99117
if !borrowed_place.is_indirect() {
100-
self.trans.gen(borrowed_place.local);
118+
if borrowed_place.local == ty::CAPTURE_STRUCT_LOCAL
119+
&& let Some((upvar_start, nr_upvars)) = self.upvar_start
120+
{
121+
match **borrowed_place.projection {
122+
[ProjectionElem::Field(field, _), ..]
123+
if field.as_usize() < nr_upvars =>
124+
{
125+
self.trans.gen(upvar_start + field.as_usize())
126+
}
127+
_ => bug!("unexpected upvar access"),
128+
}
129+
} else {
130+
self.trans.gen(borrowed_place.local);
131+
}
101132
}
102133
}
103134

@@ -132,7 +163,26 @@ where
132163
//
133164
// [#61069]: https://github.com/rust-lang/rust/pull/61069
134165
if !dropped_place.is_indirect() {
135-
self.trans.gen(dropped_place.local);
166+
if dropped_place.local == ty::CAPTURE_STRUCT_LOCAL
167+
&& let Some((upvar_start, nr_upvars)) = self.upvar_start
168+
{
169+
match **dropped_place.projection {
170+
[] => {
171+
for field in 0..nr_upvars {
172+
self.trans.gen(upvar_start + field)
173+
}
174+
self.trans.gen(dropped_place.local)
175+
}
176+
[ProjectionElem::Field(field, _), ..]
177+
if field.as_usize() < nr_upvars =>
178+
{
179+
self.trans.gen(upvar_start + field.as_usize())
180+
}
181+
_ => bug!("unexpected upvar access"),
182+
}
183+
} else {
184+
self.trans.gen(dropped_place.local);
185+
}
136186
}
137187
}
138188

@@ -169,6 +219,6 @@ pub fn borrowed_locals(body: &Body<'_>) -> BitSet<Local> {
169219
}
170220

171221
let mut borrowed = Borrowed(BitSet::new_empty(body.local_decls.len()));
172-
TransferFunction { trans: &mut borrowed }.visit_body(body);
222+
TransferFunction { trans: &mut borrowed, upvar_start: None }.visit_body(body);
173223
borrowed.0
174224
}

0 commit comments

Comments
 (0)