Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarify semantics of SetDiscriminant and change enum deaggregation to match those semantics #94590

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions compiler/rustc_const_eval/src/interpret/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,11 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRefMut<'a, 'tcx, Tag, Extra> {
) -> InterpResult<'tcx> {
self.write_scalar(alloc_range(offset, self.tcx.data_layout().pointer_size), val)
}

/// Mark the entire referenced range as uninitalized
pub fn write_uninit(&mut self) {
self.alloc.mark_init(self.range, false);
}
}

impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> {
Expand Down
15 changes: 14 additions & 1 deletion compiler/rustc_const_eval/src/interpret/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,16 @@ where
}
}

fn write_uninit(&mut self, dest: &PlaceTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> {
let mplace = self.force_allocation(dest)?;
let Some(mut alloc) = self.get_alloc_mut(&mplace)? else {
// Zero-sized access
return Ok(());
JakobDegen marked this conversation as resolved.
Show resolved Hide resolved
};
alloc.write_uninit();
Ok(())
}

/// Copies the data from an operand to a place. This does not support transmuting!
/// Use `copy_op_transmute` if the layouts could disagree.
#[inline(always)]
Expand Down Expand Up @@ -1011,7 +1021,10 @@ where
) -> InterpResult<'tcx> {
// This must be an enum or generator.
match dest.layout.ty.kind() {
ty::Adt(adt, _) => assert!(adt.is_enum()),
ty::Adt(adt, _) => {
assert!(adt.is_enum());
self.write_uninit(dest)?;
JakobDegen marked this conversation as resolved.
Show resolved Hide resolved
}
ty::Generator(..) => {}
_ => span_bug!(
self.cur_span(),
Expand Down
40 changes: 17 additions & 23 deletions compiler/rustc_const_eval/src/util/aggregate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,27 +50,21 @@ pub fn expand_aggregate<'tcx>(
_ => None,
};

operands
.enumerate()
.map(move |(i, (op, ty))| {
let lhs_field = if let AggregateKind::Array(_) = kind {
let offset = u64::try_from(i).unwrap();
tcx.mk_place_elem(
lhs,
ProjectionElem::ConstantIndex {
offset,
min_length: offset + 1,
from_end: false,
},
)
} else {
let field = Field::new(active_field_index.unwrap_or(i));
tcx.mk_place_field(lhs, field, ty)
};
Statement {
source_info,
kind: StatementKind::Assign(Box::new((lhs_field, Rvalue::Use(op)))),
}
})
.chain(set_discriminant)
let op_iter = operands.enumerate().map(move |(i, (op, ty))| {
let lhs_field = if let AggregateKind::Array(_) = kind {
let offset = u64::try_from(i).unwrap();
tcx.mk_place_elem(
lhs,
ProjectionElem::ConstantIndex { offset, min_length: offset + 1, from_end: false },
)
} else {
let field = Field::new(active_field_index.unwrap_or(i));
tcx.mk_place_field(lhs, field, ty)
};
Statement {
source_info,
kind: StatementKind::Assign(Box::new((lhs_field, Rvalue::Use(op)))),
}
});
set_discriminant.into_iter().chain(op_iter)
}
16 changes: 15 additions & 1 deletion compiler/rustc_middle/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1553,7 +1553,21 @@ pub enum StatementKind<'tcx> {
/// never accessed still get some sanity checks for, e.g., `let x: ! = ..;`
FakeRead(Box<(FakeReadCause, Place<'tcx>)>),

/// Write the discriminant for a variant to the enum Place.
/// Initialize the place with the given variant and all fields uninit.
JakobDegen marked this conversation as resolved.
Show resolved Hide resolved
///
/// If `place` is an ADT, this corresponds to the Rust code `place = Variant(uninit, uninit,
/// uninit)`. If each of the fields is initialized after the `SetDiscriminant`, the place is
/// completely initialized. Of course, you cannot initialize the fields first, as
/// `SetDiscriminant` invalidates them.
///
/// Computing the `Rvalue::Discriminant` of this place after `SetDiscriminant` is not
/// necessarily well defined if the fields have not also been initialized. See [#91095][91095]
/// for discussion around this topic.
///
/// If `place` is a generator, then this invalidates only those fields which are not also
/// present in another variant. Those fields that are present in another variant are unchanged.
///
/// [91095]: https://github.com/rust-lang/rust/issues/91095
SetDiscriminant { place: Box<Place<'tcx>>, variant_index: VariantIdx },

/// Start a live range for the storage of the local.
Expand Down
24 changes: 0 additions & 24 deletions compiler/rustc_mir_dataflow/src/impls/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,6 @@ use crate::{AnalysisDomain, Backward, CallReturnPlaces, GenKill, GenKillAnalysis
/// such an assignment is currently marked as a "use" of `x` in an attempt to be maximally
/// conservative.
///
/// ## Enums and `SetDiscriminant`
///
/// Assigning a literal value to an `enum` (e.g. `Option<i32>`), does not result in a simple
/// assignment of the form `_1 = /*...*/` in the MIR. For example, the following assignment to `x`:
///
/// ```
/// x = Some(4);
/// ```
///
/// compiles to this MIR
///
/// ```
/// ((_1 as Some).0: i32) = const 4_i32;
/// discriminant(_1) = 1;
/// ```
///
/// However, `MaybeLiveLocals` **does** mark `x` (`_1`) as "killed" after a statement like this.
/// That's because it treats the `SetDiscriminant` operation as a definition of `x`, even though
/// the writes that actually initialized the locals happened earlier.
///
/// This makes `MaybeLiveLocals` unsuitable for certain classes of optimization normally associated
/// with a live variables analysis, notably dead-store elimination. It's a dirty hack, but it works
/// okay for the generator state transform (currently the main consumuer of this analysis).
///
/// [`MaybeBorrowedLocals`]: super::MaybeBorrowedLocals
/// [flow-test]: https://github.com/rust-lang/rust/blob/a08c47310c7d49cbdc5d7afb38408ba519967ecd/src/test/ui/mir-dataflow/liveness-ptr.rs
/// [liveness]: https://en.wikipedia.org/wiki/Live_variable_analysis
Expand Down
3 changes: 2 additions & 1 deletion src/test/codegen/try_identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ type R = Result<u64, i32>;
#[no_mangle]
pub fn try_identity(x: R) -> R {
// CHECK: start:
// CHECK-NOT: br {{.*}}
// FIXME(JakobDegen CHECK-NOT): br {{.*}} . This test was broken by changes to enum deaggregation,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of these should get an issue filed, though more generally this test in particular seems quite awkward to me, given that it relies on -Zunsound-mir-opts...

// and will be fixed when the `SimplifyArmIdentity` pass is fixed.
// CHECK ret void
let y = match into_result(x) {
Err(e) => return from_error(From::from(e)),
Expand Down
2 changes: 1 addition & 1 deletion src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@
(_10.1: bool) = const false; // scope 5 at $DIR/const_debuginfo.rs:16:13: 16:34
(_10.2: u32) = const 123_u32; // scope 5 at $DIR/const_debuginfo.rs:16:13: 16:34
StorageLive(_11); // scope 6 at $DIR/const_debuginfo.rs:18:9: 18:10
((_11 as Some).0: u16) = const 99_u16; // scope 6 at $DIR/const_debuginfo.rs:18:13: 18:24
discriminant(_11) = 1; // scope 6 at $DIR/const_debuginfo.rs:18:13: 18:24
((_11 as Some).0: u16) = const 99_u16; // scope 6 at $DIR/const_debuginfo.rs:18:13: 18:24
StorageLive(_12); // scope 7 at $DIR/const_debuginfo.rs:20:9: 20:10
(_12.0: u32) = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:20:13: 20:35
(_12.1: u32) = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:20:13: 20:35
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
StorageLive(_1); // scope 0 at $DIR/discriminant.rs:11:9: 11:10
StorageLive(_2); // scope 0 at $DIR/discriminant.rs:11:13: 11:64
StorageLive(_3); // scope 0 at $DIR/discriminant.rs:11:34: 11:44
((_3 as Some).0: bool) = const true; // scope 0 at $DIR/discriminant.rs:11:34: 11:44
discriminant(_3) = 1; // scope 0 at $DIR/discriminant.rs:11:34: 11:44
((_3 as Some).0: bool) = const true; // scope 0 at $DIR/discriminant.rs:11:34: 11:44
- _4 = discriminant(_3); // scope 0 at $DIR/discriminant.rs:11:21: 11:31
- switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
+ _4 = const 1_isize; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
StorageLive(_1); // scope 0 at $DIR/discriminant.rs:11:9: 11:10
StorageLive(_2); // scope 0 at $DIR/discriminant.rs:11:13: 11:64
StorageLive(_3); // scope 0 at $DIR/discriminant.rs:11:34: 11:44
((_3 as Some).0: bool) = const true; // scope 0 at $DIR/discriminant.rs:11:34: 11:44
discriminant(_3) = 1; // scope 0 at $DIR/discriminant.rs:11:34: 11:44
((_3 as Some).0: bool) = const true; // scope 0 at $DIR/discriminant.rs:11:34: 11:44
- _4 = discriminant(_3); // scope 0 at $DIR/discriminant.rs:11:21: 11:31
- switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
+ _4 = const 1_isize; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
StorageLive(_2); // scope 0 at $DIR/deaggregator_test_enum.rs:8:19: 8:20
_2 = _1; // scope 0 at $DIR/deaggregator_test_enum.rs:8:19: 8:20
- _0 = Baz::Foo { x: move _2 }; // scope 0 at $DIR/deaggregator_test_enum.rs:8:5: 8:22
+ ((_0 as Foo).0: usize) = move _2; // scope 0 at $DIR/deaggregator_test_enum.rs:8:5: 8:22
+ discriminant(_0) = 1; // scope 0 at $DIR/deaggregator_test_enum.rs:8:5: 8:22
+ ((_0 as Foo).0: usize) = move _2; // scope 0 at $DIR/deaggregator_test_enum.rs:8:5: 8:22
StorageDead(_2); // scope 0 at $DIR/deaggregator_test_enum.rs:8:21: 8:22
return; // scope 0 at $DIR/deaggregator_test_enum.rs:9:2: 9:2
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
StorageLive(_4); // scope 0 at $DIR/deaggregator_test_enum_2.rs:11:16: 11:17
_4 = _2; // scope 0 at $DIR/deaggregator_test_enum_2.rs:11:16: 11:17
- _0 = Foo::A(move _4); // scope 0 at $DIR/deaggregator_test_enum_2.rs:11:9: 11:18
+ ((_0 as A).0: i32) = move _4; // scope 0 at $DIR/deaggregator_test_enum_2.rs:11:9: 11:18
+ discriminant(_0) = 0; // scope 0 at $DIR/deaggregator_test_enum_2.rs:11:9: 11:18
+ ((_0 as A).0: i32) = move _4; // scope 0 at $DIR/deaggregator_test_enum_2.rs:11:9: 11:18
StorageDead(_4); // scope 0 at $DIR/deaggregator_test_enum_2.rs:11:17: 11:18
goto -> bb3; // scope 0 at $DIR/deaggregator_test_enum_2.rs:10:5: 14:6
}
Expand All @@ -29,8 +29,8 @@
StorageLive(_5); // scope 0 at $DIR/deaggregator_test_enum_2.rs:13:16: 13:17
_5 = _2; // scope 0 at $DIR/deaggregator_test_enum_2.rs:13:16: 13:17
- _0 = Foo::B(move _5); // scope 0 at $DIR/deaggregator_test_enum_2.rs:13:9: 13:18
+ ((_0 as B).0: i32) = move _5; // scope 0 at $DIR/deaggregator_test_enum_2.rs:13:9: 13:18
+ discriminant(_0) = 1; // scope 0 at $DIR/deaggregator_test_enum_2.rs:13:9: 13:18
+ ((_0 as B).0: i32) = move _5; // scope 0 at $DIR/deaggregator_test_enum_2.rs:13:9: 13:18
StorageDead(_5); // scope 0 at $DIR/deaggregator_test_enum_2.rs:13:17: 13:18
goto -> bb3; // scope 0 at $DIR/deaggregator_test_enum_2.rs:10:5: 14:6
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
StorageLive(_3); // scope 0 at $DIR/deaggregator_test_multiple.rs:10:13: 10:14
_3 = _1; // scope 0 at $DIR/deaggregator_test_multiple.rs:10:13: 10:14
- _2 = Foo::A(move _3); // scope 0 at $DIR/deaggregator_test_multiple.rs:10:6: 10:15
+ ((_2 as A).0: i32) = move _3; // scope 0 at $DIR/deaggregator_test_multiple.rs:10:6: 10:15
+ discriminant(_2) = 0; // scope 0 at $DIR/deaggregator_test_multiple.rs:10:6: 10:15
+ ((_2 as A).0: i32) = move _3; // scope 0 at $DIR/deaggregator_test_multiple.rs:10:6: 10:15
StorageDead(_3); // scope 0 at $DIR/deaggregator_test_multiple.rs:10:14: 10:15
StorageLive(_4); // scope 0 at $DIR/deaggregator_test_multiple.rs:10:17: 10:26
StorageLive(_5); // scope 0 at $DIR/deaggregator_test_multiple.rs:10:24: 10:25
_5 = _1; // scope 0 at $DIR/deaggregator_test_multiple.rs:10:24: 10:25
- _4 = Foo::A(move _5); // scope 0 at $DIR/deaggregator_test_multiple.rs:10:17: 10:26
+ ((_4 as A).0: i32) = move _5; // scope 0 at $DIR/deaggregator_test_multiple.rs:10:17: 10:26
+ discriminant(_4) = 0; // scope 0 at $DIR/deaggregator_test_multiple.rs:10:17: 10:26
+ ((_4 as A).0: i32) = move _5; // scope 0 at $DIR/deaggregator_test_multiple.rs:10:17: 10:26
StorageDead(_5); // scope 0 at $DIR/deaggregator_test_multiple.rs:10:25: 10:26
_0 = [move _2, move _4]; // scope 0 at $DIR/deaggregator_test_multiple.rs:10:5: 10:27
StorageDead(_4); // scope 0 at $DIR/deaggregator_test_multiple.rs:10:26: 10:27
Expand Down
5 changes: 4 additions & 1 deletion src/test/mir-opt/early_otherwise_branch_68867.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub enum ViewportPercentageLength {
}

// EMIT_MIR early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
// EMIT_MIR early_otherwise_branch_68867.try_sum EarlyOtherwiseBranch.before SimplifyConstCondition-final.after
// FIXME(JakobDegen) EarlyOtherwiseBranch.before SimplifyConstCondition-final.after
#[no_mangle]
pub extern "C" fn try_sum(
x: &ViewportPercentageLength,
Expand All @@ -30,3 +30,6 @@ pub extern "C" fn try_sum(
fn main() {
try_sum(&ViewportPercentageLength::Vw(1.0), &ViewportPercentageLength::Vw(2.0));
}

// The test above was broken by changes to enum deaggregation, and will be fixed when
// `SimplifyArmIdentity` is fixed more generally
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@
- bb2: {
+ StorageDead(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:25: 26:27
StorageLive(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:25: 26:27
- nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:21: 26:28
discriminant(_0) = 1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:21: 26:28
- nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:21: 26:28
StorageDead(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:26:27: 26:28
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2
Expand Down Expand Up @@ -121,8 +121,8 @@
_14 = Add(move _15, move _16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49
StorageDead(_16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:48: 22:49
StorageDead(_15); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:48: 22:49
((_3 as Vw).0: f32) = move _14; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:35: 22:50
discriminant(_3) = 0; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:35: 22:50
((_3 as Vw).0: f32) = move _14; // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:35: 22:50
StorageDead(_14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
StorageDead(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
Expand All @@ -144,8 +144,8 @@
_19 = Add(move _20, move _21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49
StorageDead(_21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49
StorageDead(_20); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:48: 23:49
((_3 as Vh).0: f32) = move _19; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50
discriminant(_3) = 1; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50
((_3 as Vh).0: f32) = move _19; // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:35: 23:50
StorageDead(_19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
StorageDead(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
StorageDead(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
Expand All @@ -167,8 +167,8 @@
_24 = Add(move _25, move _26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55
StorageDead(_26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:54: 24:55
StorageDead(_25); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:54: 24:55
((_3 as Vmin).0: f32) = move _24; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:39: 24:56
discriminant(_3) = 2; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:39: 24:56
((_3 as Vmin).0: f32) = move _24; // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:39: 24:56
StorageDead(_24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
StorageDead(_23); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
StorageDead(_22); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
Expand All @@ -190,8 +190,8 @@
_29 = Add(move _30, move _31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55
StorageDead(_31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55
StorageDead(_30); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:54: 25:55
((_3 as Vmax).0: f32) = move _29; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56
discriminant(_3) = 3; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56
((_3 as Vmax).0: f32) = move _29; // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:39: 25:56
StorageDead(_29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
StorageDead(_28); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
StorageDead(_27); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
Expand All @@ -201,8 +201,8 @@

- bb10: {
+ bb6: {
((_0 as Ok).0: ViewportPercentageLength) = move _3; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7
discriminant(_0) = 0; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7
((_0 as Ok).0: ViewportPercentageLength) = move _3; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2
return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:2: 28:2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 25:6]
bb2: {
StorageLive(_6); // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
StorageLive(_7); // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
((_0 as Yielded).0: ()) = move _7; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
discriminant(_0) = 0; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
((_0 as Yielded).0: ()) = move _7; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
discriminant((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 25:6]))) = 3; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
return; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
}
Expand Down
Loading