Skip to content

Commit a38d668

Browse files
authored
Rollup merge of #91786 - tmiasko:const-prop, r=oli-obk
Return an error when `eval_rvalue_with_identities` fails Previously some code paths would fail to evaluate the rvalue, while incorrectly indicating success with `Ok`. As a result the previous value of lhs could have been incorrectly const propagated. Fixes #91725. r? `@oli-obk`
2 parents f608e51 + ffe067c commit a38d668

File tree

2 files changed

+46
-52
lines changed

2 files changed

+46
-52
lines changed

Diff for: compiler/rustc_mir_transform/src/const_prop.rs

+34-52
Original file line numberDiff line numberDiff line change
@@ -752,62 +752,44 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
752752
rvalue: &Rvalue<'tcx>,
753753
place: Place<'tcx>,
754754
) -> Option<()> {
755-
self.use_ecx(|this| {
756-
match rvalue {
757-
Rvalue::BinaryOp(op, box (left, right))
758-
| Rvalue::CheckedBinaryOp(op, box (left, right)) => {
759-
let l = this.ecx.eval_operand(left, None);
760-
let r = this.ecx.eval_operand(right, None);
761-
762-
let const_arg = match (l, r) {
763-
(Ok(ref x), Err(_)) | (Err(_), Ok(ref x)) => this.ecx.read_immediate(x)?,
764-
(Err(e), Err(_)) => return Err(e),
765-
(Ok(_), Ok(_)) => {
766-
this.ecx.eval_rvalue_into_place(rvalue, place)?;
767-
return Ok(());
768-
}
769-
};
770-
771-
let arg_value = const_arg.to_scalar()?.to_bits(const_arg.layout.size)?;
772-
let dest = this.ecx.eval_place(place)?;
773-
774-
match op {
775-
BinOp::BitAnd => {
776-
if arg_value == 0 {
777-
this.ecx.write_immediate(*const_arg, &dest)?;
778-
}
779-
}
780-
BinOp::BitOr => {
781-
if arg_value == const_arg.layout.size.truncate(u128::MAX)
782-
|| (const_arg.layout.ty.is_bool() && arg_value == 1)
783-
{
784-
this.ecx.write_immediate(*const_arg, &dest)?;
785-
}
786-
}
787-
BinOp::Mul => {
788-
if const_arg.layout.ty.is_integral() && arg_value == 0 {
789-
if let Rvalue::CheckedBinaryOp(_, _) = rvalue {
790-
let val = Immediate::ScalarPair(
791-
const_arg.to_scalar()?.into(),
792-
Scalar::from_bool(false).into(),
793-
);
794-
this.ecx.write_immediate(val, &dest)?;
795-
} else {
796-
this.ecx.write_immediate(*const_arg, &dest)?;
797-
}
798-
}
799-
}
800-
_ => {
801-
this.ecx.eval_rvalue_into_place(rvalue, place)?;
755+
self.use_ecx(|this| match rvalue {
756+
Rvalue::BinaryOp(op, box (left, right))
757+
| Rvalue::CheckedBinaryOp(op, box (left, right)) => {
758+
let l = this.ecx.eval_operand(left, None);
759+
let r = this.ecx.eval_operand(right, None);
760+
761+
let const_arg = match (l, r) {
762+
(Ok(ref x), Err(_)) | (Err(_), Ok(ref x)) => this.ecx.read_immediate(x)?,
763+
(Err(e), Err(_)) => return Err(e),
764+
(Ok(_), Ok(_)) => return this.ecx.eval_rvalue_into_place(rvalue, place),
765+
};
766+
767+
let arg_value = const_arg.to_scalar()?.to_bits(const_arg.layout.size)?;
768+
let dest = this.ecx.eval_place(place)?;
769+
770+
match op {
771+
BinOp::BitAnd if arg_value == 0 => this.ecx.write_immediate(*const_arg, &dest),
772+
BinOp::BitOr
773+
if arg_value == const_arg.layout.size.truncate(u128::MAX)
774+
|| (const_arg.layout.ty.is_bool() && arg_value == 1) =>
775+
{
776+
this.ecx.write_immediate(*const_arg, &dest)
777+
}
778+
BinOp::Mul if const_arg.layout.ty.is_integral() && arg_value == 0 => {
779+
if let Rvalue::CheckedBinaryOp(_, _) = rvalue {
780+
let val = Immediate::ScalarPair(
781+
const_arg.to_scalar()?.into(),
782+
Scalar::from_bool(false).into(),
783+
);
784+
this.ecx.write_immediate(val, &dest)
785+
} else {
786+
this.ecx.write_immediate(*const_arg, &dest)
802787
}
803788
}
804-
}
805-
_ => {
806-
this.ecx.eval_rvalue_into_place(rvalue, place)?;
789+
_ => this.ecx.eval_rvalue_into_place(rvalue, place),
807790
}
808791
}
809-
810-
Ok(())
792+
_ => this.ecx.eval_rvalue_into_place(rvalue, place),
811793
})
812794
}
813795

Diff for: src/test/ui/mir/mir_const_prop_identity.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Regression test for issue #91725.
2+
//
3+
// run-pass
4+
// compile-flags: -Zmir-opt-level=4
5+
6+
fn main() {
7+
let a = true;
8+
let _ = &a;
9+
let mut b = false;
10+
b |= a;
11+
assert!(b);
12+
}

0 commit comments

Comments
 (0)