Skip to content

Commit f32095c

Browse files
committed
promotion: don't promote int::MIN / -1
1 parent 8f359be commit f32095c

8 files changed

+265
-734
lines changed

compiler/rustc_mir_transform/src/promote_consts.rs

+26-3
Original file line numberDiff line numberDiff line change
@@ -482,17 +482,40 @@ impl<'tcx> Validator<'_, 'tcx> {
482482
match op {
483483
BinOp::Div | BinOp::Rem => {
484484
if lhs_ty.is_integral() {
485+
let sz = lhs_ty.primitive_size(self.tcx);
485486
// Integer division: the RHS must be a non-zero const.
486-
let const_val = match rhs {
487+
let rhs_val = match rhs {
487488
Operand::Constant(c) => {
488-
c.const_.try_eval_bits(self.tcx, self.param_env)
489+
c.const_.try_eval_scalar_int(self.tcx, self.param_env)
489490
}
490491
_ => None,
491492
};
492-
match const_val {
493+
match rhs_val.map(|x| x.try_to_uint(sz).unwrap()) {
494+
// for the zero test, int vs uint does not matter
493495
Some(x) if x != 0 => {} // okay
494496
_ => return Err(Unpromotable), // value not known or 0 -- not okay
495497
}
498+
// Furthermore, for signed divison, we also have to exclude `int::MIN / -1`.
499+
if lhs_ty.is_signed() {
500+
match rhs_val.map(|x| x.try_to_int(sz).unwrap()) {
501+
Some(-1) | None => {
502+
// The RHS is -1 or unknown, so we have to be careful.
503+
// But is the LHS int::MIN?
504+
let lhs_val = match lhs {
505+
Operand::Constant(c) => c
506+
.const_
507+
.try_eval_scalar_int(self.tcx, self.param_env),
508+
_ => None,
509+
};
510+
let lhs_min = sz.signed_int_min();
511+
match lhs_val.map(|x| x.try_to_int(sz).unwrap()) {
512+
Some(x) if x != lhs_min => {} // okay
513+
_ => return Err(Unpromotable), // value not known or int::MIN -- not okay
514+
}
515+
}
516+
_ => {}
517+
}
518+
}
496519
}
497520
}
498521
// The remaining operations can never fail.

tests/ui/consts/promote-not.rs

+4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ fn main() {
4949
// No promotion of fallible operations.
5050
let _val: &'static _ = &(1/0); //~ ERROR temporary value dropped while borrowed
5151
let _val: &'static _ = &(1/(1-1)); //~ ERROR temporary value dropped while borrowed
52+
let _val: &'static _ = &((1+1)/(1-1)); //~ ERROR temporary value dropped while borrowed
53+
let _val: &'static _ = &(i32::MIN/-1); //~ ERROR temporary value dropped while borrowed
54+
let _val: &'static _ = &(i32::MIN/(0-1)); //~ ERROR temporary value dropped while borrowed
55+
let _val: &'static _ = &(-128i8/-1); //~ ERROR temporary value dropped while borrowed
5256
let _val: &'static _ = &(1%0); //~ ERROR temporary value dropped while borrowed
5357
let _val: &'static _ = &(1%(1-1)); //~ ERROR temporary value dropped while borrowed
5458
let _val: &'static _ = &([1,2,3][4]+1); //~ ERROR temporary value dropped while borrowed

tests/ui/consts/promote-not.stderr

+54-10
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,50 @@ LL | }
105105
error[E0716]: temporary value dropped while borrowed
106106
--> $DIR/promote-not.rs:52:29
107107
|
108+
LL | let _val: &'static _ = &((1+1)/(1-1));
109+
| ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
110+
| |
111+
| type annotation requires that borrow lasts for `'static`
112+
...
113+
LL | }
114+
| - temporary value is freed at the end of this statement
115+
116+
error[E0716]: temporary value dropped while borrowed
117+
--> $DIR/promote-not.rs:53:29
118+
|
119+
LL | let _val: &'static _ = &(i32::MIN/-1);
120+
| ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
121+
| |
122+
| type annotation requires that borrow lasts for `'static`
123+
...
124+
LL | }
125+
| - temporary value is freed at the end of this statement
126+
127+
error[E0716]: temporary value dropped while borrowed
128+
--> $DIR/promote-not.rs:54:29
129+
|
130+
LL | let _val: &'static _ = &(i32::MIN/(0-1));
131+
| ---------- ^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
132+
| |
133+
| type annotation requires that borrow lasts for `'static`
134+
...
135+
LL | }
136+
| - temporary value is freed at the end of this statement
137+
138+
error[E0716]: temporary value dropped while borrowed
139+
--> $DIR/promote-not.rs:55:29
140+
|
141+
LL | let _val: &'static _ = &(-128i8/-1);
142+
| ---------- ^^^^^^^^^^^ creates a temporary value which is freed while still in use
143+
| |
144+
| type annotation requires that borrow lasts for `'static`
145+
...
146+
LL | }
147+
| - temporary value is freed at the end of this statement
148+
149+
error[E0716]: temporary value dropped while borrowed
150+
--> $DIR/promote-not.rs:56:29
151+
|
108152
LL | let _val: &'static _ = &(1%0);
109153
| ---------- ^^^^^ creates a temporary value which is freed while still in use
110154
| |
@@ -114,7 +158,7 @@ LL | }
114158
| - temporary value is freed at the end of this statement
115159

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

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

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

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

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

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

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

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

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

213-
error: aborting due to 20 previous errors
257+
error: aborting due to 24 previous errors
214258

215259
For more information about this error, try `rustc --explain E0716`.

tests/ui/consts/promotion.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@ fn main() {
2828
// make sure that this does not cause trouble despite overflowing
2929
assert_static(&(0-1));
3030

31-
// div-by-non-0 is okay
31+
// div-by-non-0 (and also not MIN/-1) is okay
3232
assert_static(&(1/1));
33+
assert_static(&(0/1));
34+
assert_static(&(1/-1));
35+
assert_static(&(i32::MIN/1));
3336
assert_static(&(1%1));
3437

3538
// in-bounds array access is okay

0 commit comments

Comments
 (0)