-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Open
Labels
A-mir-optArea: MIR optimizationsArea: MIR optimizationsA-miriArea: The miri toolArea: The miri toolC-bugCategory: This is a bug.Category: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-opsemRelevant to the opsem teamRelevant to the opsem team
Description
Given this sample program:
#![feature(generators)]
fn main() {
let x = Some(22);
let _a = match x {
Some(y) if foo() => (),
_ => (),
};
}
fn foo() -> bool {
true
}
the desugaring of the match intentionally adds some borrows when executing the guard:
bb3: {
StorageLive(_6); // scope 1 at foo.rs:6:14: 6:15
_6 = &((_1 as Some).0: i32); // scope 1 at foo.rs:6:14: 6:15
_4 = &shallow _1; // scope 1 at foo.rs:5:20: 5:21
StorageLive(_7); // scope 1 at foo.rs:6:20: 6:25
_7 = foo() -> [return: bb4, unwind: bb8]; // scope 1 at foo.rs:6:20: 6:25
// mir::Constant
// + span: foo.rs:6:20: 6:23
// + literal: Const { ty: fn() -> bool {foo}, val: Value(Scalar(<ZST>)) }
}
bb4: {
switchInt(move _7) -> [false: bb6, otherwise: bb5]; // scope 1 at foo.rs:6:20: 6:25
}
bb5: {
StorageDead(_7); // scope 1 at foo.rs:6:24: 6:25
FakeRead(ForMatchGuard, _4); // scope 1 at foo.rs:6:24: 6:25
FakeRead(ForGuardBinding, _6); // scope 1 at foo.rs:6:24: 6:25
The purposeof the FakeRead
of _4
and _6
is to ensure that the discriminant does not change while the guard executes -- i.e., that the guard doesn't (via unsafe code, say) mutate x
to be None
. But after optimizations those FakeReads are removed:
bb0: {
Deinit(_1); // scope 0 at foo.rs:4:13: 4:21
((_1 as Some).0: i32) = const 22_i32; // scope 0 at foo.rs:4:13: 4:21
discriminant(_1) = 1; // scope 0 at foo.rs:4:13: 4:21
_4 = &((_1 as Some).0: i32); // scope 1 at foo.rs:6:14: 6:15
_5 = foo() -> bb1; // scope 1 at foo.rs:6:20: 6:25
// mir::Constant
// + span: foo.rs:6:20: 6:23
// + literal: Const { ty: fn() -> bool {foo}, val: Value(Scalar(<ZST>)) }
}
bb1: {
switchInt(move _5) -> [false: bb3, otherwise: bb2]; // scope 1 at foo.rs:6:20: 6:25
}
this means that foo()
could trigger writes without causing UB. This seems bad!
UPDATE: This is overstating the case. It's ok for us to optimize FakeRead away, but tools like miri or some future sanitizers would still want to see them (for the reasons give above).
Metadata
Metadata
Assignees
Labels
A-mir-optArea: MIR optimizationsArea: MIR optimizationsA-miriArea: The miri toolArea: The miri toolC-bugCategory: This is a bug.Category: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-opsemRelevant to the opsem teamRelevant to the opsem team