Skip to content

Commit 434232f

Browse files
authored
Rollup merge of #118426 - aDotInTheVoid:const-wat, r=compiler-errors,cjgillot
ConstProp: Correctly remove const if unknown value assigned to it. Closes #118328 The problematic sequence of MIR is: ```rust _1 = const 0_usize; _1 = const _; // This is an associated constant we can't know before monomorphization. _0 = _1; ``` 1. When `ConstProp::visit_assign` happens on `_1 = const 0_usize;`, it records that `0x0usize` is the value for `_1`. 2. Next `visit_assign` happens on `_1 = const _;`. Because the rvalue `.has_param()`, it can't be const evaled. 3. Finaly, `visit_assign` happens on `_0 = _1;`. Here it would think the value of `_1` was `0x0usize` from step 1. The solution is to remove consts when checking the RValue fails, as they may have contained values that should now be invalidated, as that local was overwritten. This should probably be back-ported to beta. Stable is more iffy, as it's gone unidentified since 1.70, so I only think it's worthwhile if there's another reason for a 1.74.1 release anyway.
2 parents 911a5ee + 6e956c0 commit 434232f

File tree

4 files changed

+73
-1
lines changed

4 files changed

+73
-1
lines changed

compiler/rustc_mir_transform/src/const_prop.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
439439

440440
// FIXME we need to revisit this for #67176
441441
if rvalue.has_param() {
442+
trace!("skipping, has param");
442443
return None;
443444
}
444445
if !rvalue
@@ -707,7 +708,11 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
707708
fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
708709
self.super_assign(place, rvalue, location);
709710

710-
let Some(()) = self.check_rvalue(rvalue) else { return };
711+
let Some(()) = self.check_rvalue(rvalue) else {
712+
trace!("rvalue check failed, removing const");
713+
Self::remove_const(&mut self.ecx, place.local);
714+
return;
715+
};
711716

712717
match self.ecx.machine.can_const_prop[place.local] {
713718
// Do nothing if the place is indirect.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// unit-test: ConstProp
2+
// compile-flags: -O
3+
4+
// Regression test for https://github.com/rust-lang/rust/issues/118328
5+
6+
#![allow(unused_assignments)]
7+
8+
struct SizeOfConst<T>(std::marker::PhantomData<T>);
9+
impl<T> SizeOfConst<T> {
10+
const SIZE: usize = std::mem::size_of::<T>();
11+
}
12+
13+
// EMIT_MIR overwrite_with_const_with_params.size_of.ConstProp.diff
14+
fn size_of<T>() -> usize {
15+
// CHECK-LABEL: fn size_of(
16+
// CHECK: _1 = const 0_usize;
17+
// CHECK-NEXT: _1 = const _;
18+
// CHECK-NEXT: _0 = _1;
19+
let mut a = 0;
20+
a = SizeOfConst::<T>::SIZE;
21+
a
22+
}
23+
24+
fn main() {
25+
assert_eq!(size_of::<u32>(), std::mem::size_of::<u32>());
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
- // MIR for `size_of` before ConstProp
2+
+ // MIR for `size_of` after ConstProp
3+
4+
fn size_of() -> usize {
5+
let mut _0: usize;
6+
let mut _1: usize;
7+
scope 1 {
8+
debug a => _1;
9+
}
10+
11+
bb0: {
12+
StorageLive(_1);
13+
_1 = const 0_usize;
14+
_1 = const _;
15+
_0 = _1;
16+
StorageDead(_1);
17+
return;
18+
}
19+
}
20+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// compile-flags: -O
2+
// run-pass
3+
4+
// Regression test for https://github.com/rust-lang/rust/issues/118328
5+
6+
#![allow(unused_assignments)]
7+
8+
struct SizeOfConst<T>(std::marker::PhantomData<T>);
9+
impl<T> SizeOfConst<T> {
10+
const SIZE: usize = std::mem::size_of::<T>();
11+
}
12+
13+
fn size_of<T>() -> usize {
14+
let mut a = 0;
15+
a = SizeOfConst::<T>::SIZE;
16+
a
17+
}
18+
19+
fn main() {
20+
assert_eq!(size_of::<u32>(), std::mem::size_of::<u32>());
21+
}

0 commit comments

Comments
 (0)