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`
This commit is contained in:
commit
a38d668296
@ -752,62 +752,44 @@ fn eval_rvalue_with_identities(
|
|||||||
rvalue: &Rvalue<'tcx>,
|
rvalue: &Rvalue<'tcx>,
|
||||||
place: Place<'tcx>,
|
place: Place<'tcx>,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
self.use_ecx(|this| {
|
self.use_ecx(|this| match rvalue {
|
||||||
match rvalue {
|
Rvalue::BinaryOp(op, box (left, right))
|
||||||
Rvalue::BinaryOp(op, box (left, right))
|
| Rvalue::CheckedBinaryOp(op, box (left, right)) => {
|
||||||
| Rvalue::CheckedBinaryOp(op, box (left, right)) => {
|
let l = this.ecx.eval_operand(left, None);
|
||||||
let l = this.ecx.eval_operand(left, None);
|
let r = this.ecx.eval_operand(right, None);
|
||||||
let r = this.ecx.eval_operand(right, None);
|
|
||||||
|
|
||||||
let const_arg = match (l, r) {
|
let const_arg = match (l, r) {
|
||||||
(Ok(ref x), Err(_)) | (Err(_), Ok(ref x)) => this.ecx.read_immediate(x)?,
|
(Ok(ref x), Err(_)) | (Err(_), Ok(ref x)) => this.ecx.read_immediate(x)?,
|
||||||
(Err(e), Err(_)) => return Err(e),
|
(Err(e), Err(_)) => return Err(e),
|
||||||
(Ok(_), Ok(_)) => {
|
(Ok(_), Ok(_)) => return this.ecx.eval_rvalue_into_place(rvalue, place),
|
||||||
this.ecx.eval_rvalue_into_place(rvalue, place)?;
|
};
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let arg_value = const_arg.to_scalar()?.to_bits(const_arg.layout.size)?;
|
let arg_value = const_arg.to_scalar()?.to_bits(const_arg.layout.size)?;
|
||||||
let dest = this.ecx.eval_place(place)?;
|
let dest = this.ecx.eval_place(place)?;
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
BinOp::BitAnd => {
|
BinOp::BitAnd if arg_value == 0 => this.ecx.write_immediate(*const_arg, &dest),
|
||||||
if arg_value == 0 {
|
BinOp::BitOr
|
||||||
this.ecx.write_immediate(*const_arg, &dest)?;
|
if arg_value == const_arg.layout.size.truncate(u128::MAX)
|
||||||
}
|
|| (const_arg.layout.ty.is_bool() && arg_value == 1) =>
|
||||||
}
|
{
|
||||||
BinOp::BitOr => {
|
this.ecx.write_immediate(*const_arg, &dest)
|
||||||
if arg_value == const_arg.layout.size.truncate(u128::MAX)
|
}
|
||||||
|| (const_arg.layout.ty.is_bool() && arg_value == 1)
|
BinOp::Mul if const_arg.layout.ty.is_integral() && arg_value == 0 => {
|
||||||
{
|
if let Rvalue::CheckedBinaryOp(_, _) = rvalue {
|
||||||
this.ecx.write_immediate(*const_arg, &dest)?;
|
let val = Immediate::ScalarPair(
|
||||||
}
|
const_arg.to_scalar()?.into(),
|
||||||
}
|
Scalar::from_bool(false).into(),
|
||||||
BinOp::Mul => {
|
);
|
||||||
if const_arg.layout.ty.is_integral() && arg_value == 0 {
|
this.ecx.write_immediate(val, &dest)
|
||||||
if let Rvalue::CheckedBinaryOp(_, _) = rvalue {
|
} else {
|
||||||
let val = Immediate::ScalarPair(
|
this.ecx.write_immediate(*const_arg, &dest)
|
||||||
const_arg.to_scalar()?.into(),
|
|
||||||
Scalar::from_bool(false).into(),
|
|
||||||
);
|
|
||||||
this.ecx.write_immediate(val, &dest)?;
|
|
||||||
} else {
|
|
||||||
this.ecx.write_immediate(*const_arg, &dest)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
this.ecx.eval_rvalue_into_place(rvalue, place)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
_ => this.ecx.eval_rvalue_into_place(rvalue, place),
|
||||||
_ => {
|
|
||||||
this.ecx.eval_rvalue_into_place(rvalue, place)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ => this.ecx.eval_rvalue_into_place(rvalue, place),
|
||||||
Ok(())
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
src/test/ui/mir/mir_const_prop_identity.rs
Normal file
12
src/test/ui/mir/mir_const_prop_identity.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// Regression test for issue #91725.
|
||||||
|
//
|
||||||
|
// run-pass
|
||||||
|
// compile-flags: -Zmir-opt-level=4
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a = true;
|
||||||
|
let _ = &a;
|
||||||
|
let mut b = false;
|
||||||
|
b |= a;
|
||||||
|
assert!(b);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user