Skip to content

Commit

Permalink
Rollup merge of rust-lang#121515 - RalfJung:fallible-promotion, r=oli…
Browse files Browse the repository at this point in the history
…-obk

promotion: don't promote int::MIN / -1

Looks like I entirely forgot about this case when adding the div-by-zero check, which was supposed to ensure that we never promote operations that can fail...
Cc rust-lang#80619

This is a breaking change, so needs a crater run.
r? ``@oli-obk``
  • Loading branch information
matthiaskrgr committed Feb 24, 2024
2 parents 59a2cd4 + f32095c commit a189c89
Show file tree
Hide file tree
Showing 8 changed files with 265 additions and 734 deletions.
29 changes: 26 additions & 3 deletions compiler/rustc_mir_transform/src/promote_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,17 +482,40 @@ impl<'tcx> Validator<'_, 'tcx> {
match op {
BinOp::Div | BinOp::Rem => {
if lhs_ty.is_integral() {
let sz = lhs_ty.primitive_size(self.tcx);
// Integer division: the RHS must be a non-zero const.
let const_val = match rhs {
let rhs_val = match rhs {
Operand::Constant(c) => {
c.const_.try_eval_bits(self.tcx, self.param_env)
c.const_.try_eval_scalar_int(self.tcx, self.param_env)
}
_ => None,
};
match const_val {
match rhs_val.map(|x| x.try_to_uint(sz).unwrap()) {
// for the zero test, int vs uint does not matter
Some(x) if x != 0 => {} // okay
_ => return Err(Unpromotable), // value not known or 0 -- not okay
}
// Furthermore, for signed divison, we also have to exclude `int::MIN / -1`.
if lhs_ty.is_signed() {
match rhs_val.map(|x| x.try_to_int(sz).unwrap()) {
Some(-1) | None => {
// The RHS is -1 or unknown, so we have to be careful.
// But is the LHS int::MIN?
let lhs_val = match lhs {
Operand::Constant(c) => c
.const_
.try_eval_scalar_int(self.tcx, self.param_env),
_ => None,
};
let lhs_min = sz.signed_int_min();
match lhs_val.map(|x| x.try_to_int(sz).unwrap()) {
Some(x) if x != lhs_min => {} // okay
_ => return Err(Unpromotable), // value not known or int::MIN -- not okay
}
}
_ => {}
}
}
}
}
// The remaining operations can never fail.
Expand Down
4 changes: 4 additions & 0 deletions tests/ui/consts/promote-not.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ fn main() {
// No promotion of fallible operations.
let _val: &'static _ = &(1/0); //~ ERROR temporary value dropped while borrowed
let _val: &'static _ = &(1/(1-1)); //~ ERROR temporary value dropped while borrowed
let _val: &'static _ = &((1+1)/(1-1)); //~ ERROR temporary value dropped while borrowed
let _val: &'static _ = &(i32::MIN/-1); //~ ERROR temporary value dropped while borrowed
let _val: &'static _ = &(i32::MIN/(0-1)); //~ ERROR temporary value dropped while borrowed
let _val: &'static _ = &(-128i8/-1); //~ ERROR temporary value dropped while borrowed
let _val: &'static _ = &(1%0); //~ ERROR temporary value dropped while borrowed
let _val: &'static _ = &(1%(1-1)); //~ ERROR temporary value dropped while borrowed
let _val: &'static _ = &([1,2,3][4]+1); //~ ERROR temporary value dropped while borrowed
Expand Down
64 changes: 54 additions & 10 deletions tests/ui/consts/promote-not.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,50 @@ LL | }
error[E0716]: temporary value dropped while borrowed
--> $DIR/promote-not.rs:52:29
|
LL | let _val: &'static _ = &((1+1)/(1-1));
| ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
...
LL | }
| - temporary value is freed at the end of this statement

error[E0716]: temporary value dropped while borrowed
--> $DIR/promote-not.rs:53:29
|
LL | let _val: &'static _ = &(i32::MIN/-1);
| ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
...
LL | }
| - temporary value is freed at the end of this statement

error[E0716]: temporary value dropped while borrowed
--> $DIR/promote-not.rs:54:29
|
LL | let _val: &'static _ = &(i32::MIN/(0-1));
| ---------- ^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
...
LL | }
| - temporary value is freed at the end of this statement

error[E0716]: temporary value dropped while borrowed
--> $DIR/promote-not.rs:55:29
|
LL | let _val: &'static _ = &(-128i8/-1);
| ---------- ^^^^^^^^^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
...
LL | }
| - temporary value is freed at the end of this statement

error[E0716]: temporary value dropped while borrowed
--> $DIR/promote-not.rs:56:29
|
LL | let _val: &'static _ = &(1%0);
| ---------- ^^^^^ creates a temporary value which is freed while still in use
| |
Expand All @@ -114,7 +158,7 @@ LL | }
| - temporary value is freed at the end of this statement

error[E0716]: temporary value dropped while borrowed
--> $DIR/promote-not.rs:53:29
--> $DIR/promote-not.rs:57:29
|
LL | let _val: &'static _ = &(1%(1-1));
| ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use
Expand All @@ -125,7 +169,7 @@ LL | }
| - temporary value is freed at the end of this statement

error[E0716]: temporary value dropped while borrowed
--> $DIR/promote-not.rs:54:29
--> $DIR/promote-not.rs:58:29
|
LL | let _val: &'static _ = &([1,2,3][4]+1);
| ---------- ^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
Expand All @@ -136,7 +180,7 @@ LL | }
| - temporary value is freed at the end of this statement

error[E0716]: temporary value dropped while borrowed
--> $DIR/promote-not.rs:57:29
--> $DIR/promote-not.rs:61:29
|
LL | let _val: &'static _ = &TEST_DROP;
| ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use
Expand All @@ -147,7 +191,7 @@ LL | }
| - temporary value is freed at the end of this statement

error[E0716]: temporary value dropped while borrowed
--> $DIR/promote-not.rs:59:29
--> $DIR/promote-not.rs:63:29
|
LL | let _val: &'static _ = &&TEST_DROP;
| ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use
Expand All @@ -158,7 +202,7 @@ LL | }
| - temporary value is freed at the end of this statement

error[E0716]: temporary value dropped while borrowed
--> $DIR/promote-not.rs:59:30
--> $DIR/promote-not.rs:63:30
|
LL | let _val: &'static _ = &&TEST_DROP;
| ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use
Expand All @@ -169,7 +213,7 @@ LL | }
| - temporary value is freed at the end of this statement

error[E0716]: temporary value dropped while borrowed
--> $DIR/promote-not.rs:62:29
--> $DIR/promote-not.rs:66:29
|
LL | let _val: &'static _ = &(&TEST_DROP,);
| ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
Expand All @@ -180,7 +224,7 @@ LL | }
| - temporary value is freed at the end of this statement

error[E0716]: temporary value dropped while borrowed
--> $DIR/promote-not.rs:62:31
--> $DIR/promote-not.rs:66:31
|
LL | let _val: &'static _ = &(&TEST_DROP,);
| ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use
Expand All @@ -191,7 +235,7 @@ LL | }
| - temporary value is freed at the end of this statement

error[E0716]: temporary value dropped while borrowed
--> $DIR/promote-not.rs:65:29
--> $DIR/promote-not.rs:69:29
|
LL | let _val: &'static _ = &[&TEST_DROP; 1];
| ---------- ^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
Expand All @@ -202,14 +246,14 @@ LL | }
| - temporary value is freed at the end of this statement

error[E0716]: temporary value dropped while borrowed
--> $DIR/promote-not.rs:65:31
--> $DIR/promote-not.rs:69:31
|
LL | let _val: &'static _ = &[&TEST_DROP; 1];
| ---------- ^^^^^^^^^ - temporary value is freed at the end of this statement
| | |
| | creates a temporary value which is freed while still in use
| type annotation requires that borrow lasts for `'static`

error: aborting due to 20 previous errors
error: aborting due to 24 previous errors

For more information about this error, try `rustc --explain E0716`.
5 changes: 4 additions & 1 deletion tests/ui/consts/promotion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@ fn main() {
// make sure that this does not cause trouble despite overflowing
assert_static(&(0-1));

// div-by-non-0 is okay
// div-by-non-0 (and also not MIN/-1) is okay
assert_static(&(1/1));
assert_static(&(0/1));
assert_static(&(1/-1));
assert_static(&(i32::MIN/1));
assert_static(&(1%1));

// in-bounds array access is okay
Expand Down
Loading

0 comments on commit a189c89

Please sign in to comment.