Skip to content

Commit fcbfe9c

Browse files
relocate upvars onto Unresumed state
1 parent 548e14b commit fcbfe9c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+951
-392
lines changed

compiler/rustc_abi/src/lib.rs

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

15231523
/// Encodes information about multi-variant layouts.
15241524
/// Even with `Multiple` variants, a layout still has its own fields! Those are then
1525-
/// shared between all variants. One of them will be the discriminant,
1526-
/// but e.g. coroutines can have more.
1525+
/// shared between all variants. One of them will be the discriminant.
15271526
///
15281527
/// To access all fields of this layout, both `fields` and the fields of the active variant
15291528
/// must be taken into account.

compiler/rustc_borrowck/src/type_check/mod.rs

+13-18
Original file line numberDiff line numberDiff line change
@@ -800,22 +800,18 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
800800
}),
801801
};
802802
}
803-
ty::CoroutineClosure(_, args) => {
804-
return match args.as_coroutine_closure().upvar_tys().get(field.index()) {
803+
ty::CoroutineClosure(_def_id, args) => {
804+
let upvar_tys = args.as_coroutine_closure().upvar_tys();
805+
return match upvar_tys.get(field.index()) {
805806
Some(&ty) => Ok(ty),
806-
None => Err(FieldAccessError::OutOfRange {
807-
field_count: args.as_coroutine_closure().upvar_tys().len(),
808-
}),
807+
None => Err(FieldAccessError::OutOfRange { field_count: upvar_tys.len() }),
809808
};
810809
}
811-
ty::Coroutine(_, args) => {
812-
// Only prefix fields (upvars and current state) are
813-
// accessible without a variant index.
814-
return match args.as_coroutine().prefix_tys().get(field.index()) {
815-
Some(ty) => Ok(*ty),
816-
None => Err(FieldAccessError::OutOfRange {
817-
field_count: args.as_coroutine().prefix_tys().len(),
818-
}),
810+
ty::Coroutine(_def_id, args) => {
811+
let upvar_tys = args.as_coroutine().upvar_tys();
812+
return match upvar_tys.get(field.index()) {
813+
Some(&ty) => Ok(ty),
814+
None => Err(FieldAccessError::OutOfRange { field_count: upvar_tys.len() }),
819815
};
820816
}
821817
ty::Tuple(tys) => {
@@ -1889,11 +1885,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
18891885
// It doesn't make sense to look at a field beyond the prefix;
18901886
// these require a variant index, and are not initialized in
18911887
// aggregate rvalues.
1892-
match args.as_coroutine().prefix_tys().get(field_index.as_usize()) {
1888+
let upvar_tys = args.as_coroutine().upvar_tys();
1889+
match upvar_tys.get(field_index.as_usize()) {
18931890
Some(ty) => Ok(*ty),
1894-
None => Err(FieldAccessError::OutOfRange {
1895-
field_count: args.as_coroutine().prefix_tys().len(),
1896-
}),
1891+
None => Err(FieldAccessError::OutOfRange { field_count: upvar_tys.len() }),
18971892
}
18981893
}
18991894
AggregateKind::CoroutineClosure(_, args) => {
@@ -2518,7 +2513,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
25182513

25192514
self.prove_aggregate_predicates(aggregate_kind, location);
25202515

2521-
if *aggregate_kind == AggregateKind::Tuple {
2516+
if matches!(aggregate_kind, AggregateKind::Tuple) {
25222517
// tuple rvalue field type is always the type of the op. Nothing to check here.
25232518
return;
25242519
}

compiler/rustc_codegen_cranelift/src/base.rs

+3
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,9 @@ fn codegen_stmt<'tcx>(
802802
let variant_dest = lval.downcast_variant(fx, variant_index);
803803
(variant_index, variant_dest, active_field_index)
804804
}
805+
mir::AggregateKind::Coroutine(_, _) => {
806+
(FIRST_VARIANT, lval.downcast_variant(fx, FIRST_VARIANT), None)
807+
}
805808
_ => (FIRST_VARIANT, lval, None),
806809
};
807810
if active_field_index.is_some() {

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1076,7 +1076,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>(
10761076
closure_or_coroutine_di_node: &'ll DIType,
10771077
) -> SmallVec<&'ll DIType> {
10781078
let (&def_id, up_var_tys) = match closure_or_coroutine_ty.kind() {
1079-
ty::Coroutine(def_id, args) => (def_id, args.as_coroutine().prefix_tys()),
1079+
ty::Coroutine(def_id, args) => (def_id, args.as_coroutine().upvar_tys()),
10801080
ty::Closure(def_id, args) => (def_id, args.as_closure().upvar_tys()),
10811081
ty::CoroutineClosure(def_id, args) => (def_id, args.as_coroutine_closure().upvar_tys()),
10821082
_ => {

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -685,12 +685,12 @@ 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

692691
let tag_base_type = tag_base_type(cx, coroutine_type_and_layout);
693692

693+
let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(coroutine_def_id);
694694
let variant_names_type_di_node = build_variant_names_type_di_node(
695695
cx,
696696
coroutine_type_di_node,

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

+19-24
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ pub fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
326326
coroutine_type_and_layout: TyAndLayout<'tcx>,
327327
coroutine_type_di_node: &'ll DIType,
328328
coroutine_layout: &CoroutineLayout<'tcx>,
329-
common_upvar_names: &IndexSlice<FieldIdx, Symbol>,
329+
_common_upvar_names: &IndexSlice<FieldIdx, Symbol>,
330330
) -> &'ll DIType {
331331
let variant_name = CoroutineArgs::variant_name(variant_index);
332332
let unique_type_id = UniqueTypeId::for_enum_variant_struct_type(
@@ -337,7 +337,7 @@ pub fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
337337

338338
let variant_layout = coroutine_type_and_layout.for_variant(cx, variant_index);
339339

340-
let coroutine_args = match coroutine_type_and_layout.ty.kind() {
340+
let _coroutine_args = match coroutine_type_and_layout.ty.kind() {
341341
ty::Coroutine(_, args) => args.as_coroutine(),
342342
_ => unreachable!(),
343343
};
@@ -355,7 +355,7 @@ pub fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
355355
),
356356
|cx, variant_struct_type_di_node| {
357357
// Fields that just belong to this variant/state
358-
let state_specific_fields: SmallVec<_> = (0..variant_layout.fields.count())
358+
let state_specific_args: SmallVec<_> = (0..variant_layout.fields.count())
359359
.map(|field_index| {
360360
let coroutine_saved_local = coroutine_layout.variant_fields[variant_index]
361361
[FieldIdx::from_usize(field_index)];
@@ -378,27 +378,22 @@ pub fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
378378
)
379379
})
380380
.collect();
381-
382-
// Fields that are common to all states
383-
let common_fields: SmallVec<_> = coroutine_args
384-
.prefix_tys()
385-
.iter()
386-
.zip(common_upvar_names)
387-
.enumerate()
388-
.map(|(index, (upvar_ty, upvar_name))| {
389-
build_field_di_node(
390-
cx,
391-
variant_struct_type_di_node,
392-
upvar_name.as_str(),
393-
cx.size_and_align_of(upvar_ty),
394-
coroutine_type_and_layout.fields.offset(index),
395-
DIFlags::FlagZero,
396-
type_di_node(cx, upvar_ty),
397-
)
398-
})
399-
.collect();
400-
401-
state_specific_fields.into_iter().chain(common_fields).collect()
381+
// state_specific_args.extend(
382+
// coroutine_args.upvar_tys().iter().zip(common_upvar_names).enumerate().map(
383+
// |(index, (upvar_ty, upvar_name))| {
384+
// build_field_di_node(
385+
// cx,
386+
// variant_struct_type_di_node,
387+
// upvar_name.as_str(),
388+
// cx.size_and_align_of(upvar_ty),
389+
// coroutine_type_and_layout.fields.offset(index),
390+
// DIFlags::FlagZero,
391+
// type_di_node(cx, upvar_ty),
392+
// )
393+
// },
394+
// ),
395+
// );
396+
state_specific_args
402397
},
403398
|cx| build_generic_type_param_di_nodes(cx, coroutine_type_and_layout.ty),
404399
)

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

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

compiler/rustc_const_eval/src/interpret/step.rs

+3
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
303303
let variant_dest = self.project_downcast(dest, variant_index)?;
304304
(variant_index, variant_dest, active_field_index)
305305
}
306+
mir::AggregateKind::Coroutine(_def_id, _args) => {
307+
(FIRST_VARIANT, self.project_downcast(dest, FIRST_VARIANT)?, None)
308+
}
306309
_ => (FIRST_VARIANT, dest.clone(), None),
307310
};
308311
if active_field_index.is_some() {

compiler/rustc_const_eval/src/transform/validate.rs

+34-16
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,17 @@ impl<'tcx> MirPass<'tcx> for Validator {
109109
// If this turns out not to be true, please let compiler-errors know.
110110
// It is possible to support, but requires some changes to the layout
111111
// computation code.
112-
cfg_checker.fail(
113-
Location::START,
114-
format!(
115-
"Coroutine layout differs from by-move coroutine layout:\n\
116-
layout: {layout:#?}\n\
117-
by_move_layout: {by_move_layout:#?}",
118-
),
119-
);
112+
// NOTE(@dingxiangfei2009): However, given that upvars are now part of the layout
113+
// we should tolerate those of `UpvarCapture::ByRef`
114+
115+
// cfg_checker.fail(
116+
// Location::START,
117+
// format!(
118+
// "Coroutine layout differs from by-move coroutine layout:\n\
119+
// layout: {layout:#?}\n\
120+
// by_move_layout: {by_move_layout:#?}",
121+
// ),
122+
// );
120123
}
121124
}
122125
}
@@ -721,8 +724,25 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
721724
} else {
722725
self.tcx.optimized_mir(def_id)
723726
};
727+
let coroutine_ty = args.as_coroutine();
728+
debug!(?coroutine_ty, ?def_id, ?gen_body.source, "dxf");
729+
let layout = match coroutine_ty.kind_ty().kind() {
730+
ty::Int(..) => {
731+
match coroutine_ty.kind_ty().to_opt_closure_kind().unwrap() {
732+
ty::ClosureKind::Fn | ty::ClosureKind::FnMut => {
733+
gen_body.coroutine_layout()
734+
}
735+
ty::ClosureKind::FnOnce => gen_body
736+
.coroutine_by_move_body()
737+
.map_or(gen_body.coroutine_layout(), |body| {
738+
body.coroutine_layout()
739+
}),
740+
}
741+
}
742+
_ => gen_body.coroutine_layout(),
743+
};
724744

725-
let Some(layout) = gen_body.coroutine_layout() else {
745+
let Some(layout) = layout else {
726746
self.fail(
727747
location,
728748
format!("No coroutine layout for {parent_ty:?}"),
@@ -744,14 +764,12 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
744764
};
745765

746766
ty::EarlyBinder::bind(f_ty.ty).instantiate(self.tcx, args)
767+
} else if let Some(&ty) = args.as_coroutine().upvar_tys().get(f.as_usize())
768+
{
769+
ty
747770
} else {
748-
let Some(&f_ty) = args.as_coroutine().prefix_tys().get(f.index())
749-
else {
750-
fail_out_of_bounds(self, location);
751-
return;
752-
};
753-
754-
f_ty
771+
fail_out_of_bounds(self, location);
772+
return;
755773
};
756774

757775
check_equal(self, location, f_ty);

compiler/rustc_middle/src/mir/query.rs

+5
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ pub struct CoroutineLayout<'tcx> {
114114
/// await).
115115
pub variant_source_info: IndexVec<VariantIdx, SourceInfo>,
116116

117+
/// The starting index of upvars.
118+
pub upvar_start: CoroutineSavedLocal,
119+
117120
/// Which saved locals are storage-live at the same time. Locals that do not
118121
/// have conflicts with each other are allowed to overlap in the computed
119122
/// layout.
@@ -164,6 +167,7 @@ impl Debug for CoroutineLayout<'_> {
164167
}
165168

166169
fmt.debug_struct("CoroutineLayout")
170+
.field("upvar_start", &self.upvar_start)
167171
.field("field_tys", &MapPrinter::new(self.field_tys.iter_enumerated()))
168172
.field(
169173
"variant_fields",
@@ -173,6 +177,7 @@ impl Debug for CoroutineLayout<'_> {
173177
.map(|(k, v)| (GenVariantPrinter(k), OneLinePrinter(v))),
174178
),
175179
)
180+
.field("field_names", &MapPrinter::new(self.field_names.iter_enumerated()))
176181
.field("storage_conflicts", &self.storage_conflicts)
177182
.finish()
178183
}

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
@@ -855,7 +855,7 @@ where
855855
if i == tag_field {
856856
return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
857857
}
858-
TyMaybeWithLayout::Ty(args.as_coroutine().prefix_tys()[i])
858+
bug!("coroutine has no prefix field");
859859
}
860860
},
861861

compiler/rustc_middle/src/ty/sty.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
609609
witness: witness.expect_ty(),
610610
tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
611611
},
612-
_ => bug!("coroutine args missing synthetics"),
612+
_ => bug!("coroutine args missing synthetics, got {:?}", self.args),
613613
}
614614
}
615615

@@ -761,13 +761,6 @@ impl<'tcx> CoroutineArgs<'tcx> {
761761
})
762762
})
763763
}
764-
765-
/// This is the types of the fields of a coroutine which are not stored in a
766-
/// variant.
767-
#[inline]
768-
pub fn prefix_tys(self) -> &'tcx List<Ty<'tcx>> {
769-
self.upvar_tys()
770-
}
771764
}
772765

773766
#[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),

0 commit comments

Comments
 (0)