Skip to content

Commit 626a6ab

Browse files
committed
Auto merge of rust-lang#115531 - RalfJung:read_via_copy, r=scottmcm
read_via_copy: don't prematurely optimize away the read Always do the read to ensure consistent UB error messages in const-eval/Miri. r? `@scottmcm`
2 parents 9c609ae + 7093903 commit 626a6ab

5 files changed

+39
-16
lines changed

compiler/rustc_mir_transform/src/lower_intrinsics.rs

+11-12
Original file line numberDiff line numberDiff line change
@@ -176,23 +176,22 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
176176
} else {
177177
span_bug!(terminator.source_info.span, "Only passing a local is supported");
178178
};
179+
// Add new statement at the end of the block that does the read, and patch
180+
// up the terminator.
181+
block.statements.push(Statement {
182+
source_info: terminator.source_info,
183+
kind: StatementKind::Assign(Box::new((
184+
*destination,
185+
Rvalue::Use(Operand::Copy(derefed_place)),
186+
))),
187+
});
179188
terminator.kind = match *target {
180189
None => {
181190
// No target means this read something uninhabited,
182-
// so it must be unreachable, and we don't need to
183-
// preserve the assignment either.
191+
// so it must be unreachable.
184192
TerminatorKind::Unreachable
185193
}
186-
Some(target) => {
187-
block.statements.push(Statement {
188-
source_info: terminator.source_info,
189-
kind: StatementKind::Assign(Box::new((
190-
*destination,
191-
Rvalue::Use(Operand::Copy(derefed_place)),
192-
))),
193-
});
194-
TerminatorKind::Goto { target }
195-
}
194+
Some(target) => TerminatorKind::Goto { target },
196195
}
197196
}
198197
sym::write_via_move => {

tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.panic-abort.diff

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
StorageLive(_2);
1313
_2 = &raw const (*_1);
1414
- _0 = read_via_copy::<Never>(move _2) -> unwind unreachable;
15+
+ _0 = (*_2);
1516
+ unreachable;
1617
}
1718
}

tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.panic-unwind.diff

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
StorageLive(_2);
1313
_2 = &raw const (*_1);
1414
- _0 = read_via_copy::<Never>(move _2) -> unwind unreachable;
15+
+ _0 = (*_2);
1516
+ unreachable;
1617
}
1718
}

tests/ui/consts/const-eval/ub-uninhabit.rs

+16
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
// Strip out raw byte dumps to make comparison platform-independent:
22
// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
33
// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP"
4+
#![feature(core_intrinsics)]
5+
#![feature(never_type)]
46

7+
use std::intrinsics;
58
use std::mem;
69

710
#[derive(Copy, Clone)]
@@ -15,11 +18,24 @@ union MaybeUninit<T: Copy> {
1518

1619
const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init };
1720
//~^ ERROR evaluation of constant value failed
21+
//~| constructing invalid value
1822

1923
const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
2024
//~^ ERROR it is undefined behavior to use this value
25+
//~| constructing invalid value
2126

2227
const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init };
2328
//~^ ERROR evaluation of constant value failed
29+
//~| constructing invalid value
30+
31+
32+
const READ_NEVER: () = unsafe {
33+
let mem = [0u32; 8];
34+
let ptr = mem.as_ptr().cast::<!>();
35+
let _val = intrinsics::read_via_copy(ptr);
36+
//~^ ERROR evaluation of constant value failed
37+
//~| constructing invalid value
38+
};
39+
2440

2541
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0080]: evaluation of constant value failed
2-
--> $DIR/ub-uninhabit.rs:16:35
2+
--> $DIR/ub-uninhabit.rs:19:35
33
|
44
LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init };
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of uninhabited type `Bar`
66

77
error[E0080]: it is undefined behavior to use this value
8-
--> $DIR/ub-uninhabit.rs:19:1
8+
--> $DIR/ub-uninhabit.rs:23:1
99
|
1010
LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
1111
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type Bar
@@ -16,11 +16,17 @@ LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
1616
}
1717

1818
error[E0080]: evaluation of constant value failed
19-
--> $DIR/ub-uninhabit.rs:22:42
19+
--> $DIR/ub-uninhabit.rs:27:42
2020
|
2121
LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init };
2222
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered a value of uninhabited type `Bar`
2323

24-
error: aborting due to 3 previous errors
24+
error[E0080]: evaluation of constant value failed
25+
--> $DIR/ub-uninhabit.rs:35:16
26+
|
27+
LL | let _val = intrinsics::read_via_copy(ptr);
28+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of the never type `!`
29+
30+
error: aborting due to 4 previous errors
2531

2632
For more information about this error, try `rustc --explain E0080`.

0 commit comments

Comments
 (0)