avoid promoting division, modulo and indexing operations that could fail

This commit is contained in:
Ralf Jung 2021-01-01 14:47:45 +01:00
parent dc1eee2f25
commit 5be27b7a70
17 changed files with 316 additions and 290 deletions

View File

@ -505,6 +505,10 @@ impl<'tcx> Validator<'_, 'tcx> {
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {}
ProjectionElem::Index(local) => {
// This could be OOB, so reject for implicit promotion.
if !self.explicit {
return Err(Unpromotable);
}
self.validate_local(local)?;
}
@ -589,9 +593,7 @@ impl<'tcx> Validator<'_, 'tcx> {
fn validate_rvalue(&self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable> {
match rvalue {
Rvalue::Use(operand)
| Rvalue::Repeat(operand, _)
| Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, operand) => {
Rvalue::Use(operand) | Rvalue::Repeat(operand, _) => {
self.validate_operand(operand)?;
}
@ -616,10 +618,26 @@ impl<'tcx> Validator<'_, 'tcx> {
self.validate_operand(operand)?;
}
Rvalue::NullaryOp(op, _) => match op {
NullOp::Box => return Err(Unpromotable),
NullOp::SizeOf => {}
},
Rvalue::UnaryOp(op, operand) => {
match op {
// These operations can never fail.
UnOp::Neg | UnOp::Not => {}
}
self.validate_operand(operand)?;
}
Rvalue::BinaryOp(op, lhs, rhs) | Rvalue::CheckedBinaryOp(op, lhs, rhs) => {
let op = *op;
if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind() {
// raw pointer operations are not allowed inside consts and thus not promotable
let lhs_ty = lhs.ty(self.body, self.tcx);
if let ty::RawPtr(_) | ty::FnPtr(..) = lhs_ty.kind() {
// Raw and fn pointer operations are not allowed inside consts and thus not promotable.
assert!(matches!(
op,
BinOp::Eq
@ -634,7 +652,22 @@ impl<'tcx> Validator<'_, 'tcx> {
}
match op {
// FIXME: reject operations that can fail -- namely, division and modulo.
BinOp::Div | BinOp::Rem => {
if !self.explicit && lhs_ty.is_integral() {
// Integer division: the RHS must be a non-zero const.
let const_val = match rhs {
Operand::Constant(c) => {
c.literal.try_eval_bits(self.tcx, self.param_env, lhs_ty)
}
_ => None,
};
match const_val {
Some(x) if x != 0 => {} // okay
_ => return Err(Unpromotable), // value not known or 0 -- not okay
}
}
}
// The remaining operations can never fail.
BinOp::Eq
| BinOp::Ne
| BinOp::Le
@ -645,8 +678,6 @@ impl<'tcx> Validator<'_, 'tcx> {
| BinOp::Add
| BinOp::Sub
| BinOp::Mul
| BinOp::Div
| BinOp::Rem
| BinOp::BitXor
| BinOp::BitAnd
| BinOp::BitOr
@ -658,11 +689,6 @@ impl<'tcx> Validator<'_, 'tcx> {
self.validate_operand(rhs)?;
}
Rvalue::NullaryOp(op, _) => match op {
NullOp::Box => return Err(Unpromotable),
NullOp::SizeOf => {}
},
Rvalue::AddressOf(_, place) => {
// We accept `&raw *`, i.e., raw reborrows -- creating a raw pointer is
// no problem, only using it is.

View File

@ -24,41 +24,41 @@ fn main() -> () {
}
alloc0 (static: FOO, size: 8, align: 4) {
alloc27 03 00 00 00 ....
alloc31 03 00 00 00 ....
}
alloc27 (size: 48, align: 4) {
0x00 00 00 00 00 __ __ __ __ alloc12 00 00 00 00 ........
0x10 00 00 00 00 __ __ __ __ alloc17 02 00 00 00 ........
0x20 01 00 00 00 2a 00 00 00 alloc25 03 00 00 00 ....*.......
alloc31 (size: 48, align: 4) {
0x00 00 00 00 00 __ __ __ __ alloc8 00 00 00 00 ........
0x10 00 00 00 00 __ __ __ __ alloc14 02 00 00 00 ........
0x20 01 00 00 00 2a 00 00 00 alloc29 03 00 00 00 ....*.......
}
alloc12 (size: 0, align: 4) {}
alloc8 (size: 0, align: 4) {}
alloc17 (size: 8, align: 4) {
alloc15 alloc16
alloc14 (size: 8, align: 4) {
alloc12 alloc13
}
alloc15 (size: 1, align: 1) {
alloc12 (size: 1, align: 1) {
05 .
}
alloc16 (size: 1, align: 1) {
alloc13 (size: 1, align: 1) {
06 .
}
alloc25 (size: 12, align: 4) {
a21+0x3 alloc22 a24+0x2
alloc29 (size: 12, align: 4) {
a21+0x3 alloc23 a28+0x2
}
alloc21 (size: 4, align: 1) {
2a 45 15 6f *E.o
}
alloc22 (size: 1, align: 1) {
alloc23 (size: 1, align: 1) {
2a *
}
alloc24 (size: 4, align: 1) {
alloc28 (size: 4, align: 1) {
2a 45 15 6f *E.o
}

View File

@ -24,44 +24,44 @@ fn main() -> () {
}
alloc0 (static: FOO, size: 16, align: 8) {
alloc27 03 00 00 00 00 00 00 00 ........
alloc31 03 00 00 00 00 00 00 00 ........
}
alloc27 (size: 72, align: 8) {
0x00 00 00 00 00 __ __ __ __ alloc12 ....
alloc31 (size: 72, align: 8) {
0x00 00 00 00 00 __ __ __ __ alloc8 ....
0x10 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ ............
0x20 alloc17 02 00 00 00 00 00 00 00 ........
0x30 01 00 00 00 2a 00 00 00 alloc25 ....*...
0x20 alloc14 02 00 00 00 00 00 00 00 ........
0x30 01 00 00 00 2a 00 00 00 alloc29 ....*...
0x40 03 00 00 00 00 00 00 00 ........
}
alloc12 (size: 0, align: 8) {}
alloc8 (size: 0, align: 8) {}
alloc17 (size: 16, align: 8) {
alloc15 alloc16
alloc14 (size: 16, align: 8) {
alloc12 alloc13
}
alloc15 (size: 1, align: 1) {
alloc12 (size: 1, align: 1) {
05 .
}
alloc16 (size: 1, align: 1) {
alloc13 (size: 1, align: 1) {
06 .
}
alloc25 (size: 24, align: 8) {
0x00 alloc21+0x3 alloc22
0x10 alloc24+0x2
alloc29 (size: 24, align: 8) {
0x00 alloc21+0x3 alloc23
0x10 alloc28+0x2
}
alloc21 (size: 4, align: 1) {
2a 45 15 6f *E.o
}
alloc22 (size: 1, align: 1) {
alloc23 (size: 1, align: 1) {
2a *
}
alloc24 (size: 4, align: 1) {
alloc28 (size: 4, align: 1) {
2a 45 15 6f *E.o
}

View File

@ -24,30 +24,30 @@ fn main() -> () {
}
alloc0 (static: FOO, size: 4, align: 4) {
alloc10
alloc11
}
alloc10 (size: 168, align: 1) {
alloc11 (size: 168, align: 1) {
0x00 ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ................
0x10 ab ab ab ab ab ab ab ab ab ab ab ab alloc5 ............
0x10 ab ab ab ab ab ab ab ab ab ab ab ab alloc4 ............
0x20 01 ef cd ab 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x80 00 00 00 00 00 00 00 00 00 00 alloc7 00 00 ............
0x90 a8+0x63 00 00 00 00 00 00 00 00 00 00 00 00 ............
0x80 00 00 00 00 00 00 00 00 00 00 alloc6 00 00 ............
0x90 a9+0x63 00 00 00 00 00 00 00 00 00 00 00 00 ............
0xa0 00 00 00 00 00 00 00 00 ........
}
alloc5 (size: 4, align: 4) {
alloc4 (size: 4, align: 4) {
2a 00 00 00 *...
}
alloc7 (fn: main)
alloc6 (fn: main)
alloc8 (size: 100, align: 1) {
alloc9 (size: 100, align: 1) {
0x00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................

View File

@ -24,12 +24,12 @@ fn main() -> () {
}
alloc0 (static: FOO, size: 8, align: 8) {
alloc10
alloc11
}
alloc10 (size: 180, align: 1) {
alloc11 (size: 180, align: 1) {
0x00 ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ................
0x10 ab ab ab ab ab ab ab ab ab ab ab ab alloc5 ............
0x10 ab ab ab ab ab ab ab ab ab ab ab ab alloc4 ............
0x20 01 ef cd ab 00 00 00 00 00 00 00 00 ............
0x30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
@ -37,18 +37,18 @@ alloc10 (size: 180, align: 1) {
0x60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..............
0x90 alloc7 00 00 alloc8+0x63 ..
0x90 alloc6 00 00 alloc9+0x63 ..
0xa0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0xb0 00 00 00 00 ....
}
alloc5 (size: 4, align: 4) {
alloc4 (size: 4, align: 4) {
2a 00 00 00 *...
}
alloc7 (fn: main)
alloc6 (fn: main)
alloc8 (size: 100, align: 1) {
alloc9 (size: 100, align: 1) {
0x00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................

View File

@ -6,6 +6,4 @@
fn main() {
&{ [1, 2, 3][4] };
//~^ WARN operation will panic
//~| WARN reaching this expression at runtime will panic or abort
//~| WARN erroneous constant used [const_err]
}

View File

@ -10,25 +10,5 @@ note: the lint level is defined here
LL | #![warn(const_err, unconditional_panic)]
| ^^^^^^^^^^^^^^^^^^^
warning: reaching this expression at runtime will panic or abort
--> $DIR/array-literal-index-oob.rs:7:8
|
LL | &{ [1, 2, 3][4] };
| ---^^^^^^^^^^^^--
| |
| indexing out of bounds: the len is 3 but the index is 4
|
note: the lint level is defined here
--> $DIR/array-literal-index-oob.rs:4:9
|
LL | #![warn(const_err, unconditional_panic)]
| ^^^^^^^^^
warning: erroneous constant used
--> $DIR/array-literal-index-oob.rs:7:5
|
LL | &{ [1, 2, 3][4] };
| ^^^^^^^^^^^^^^^^^ referenced constant has errors
warning: 3 warnings emitted
warning: 1 warning emitted

View File

@ -1,4 +1,5 @@
// compile-flags: -Ztreat-err-as-bug
//~ERROR constructed but no error reported
// compile-flags: -Ztreat-err-as-bug=2
// build-fail
// failure-status: 101
// rustc-env:RUST_BACKTRACE=1
@ -15,8 +16,11 @@
#![allow(unconditional_panic)]
#[warn(const_err)]
const X: i32 = 1 / 0; //~WARN any use of this value will cause an error
fn main() {
let x: &'static i32 = &(1 / 0);
//~^ ERROR reaching this expression at runtime will panic or abort [const_err]
let x: &'static i32 = &X;
//~^ ERROR evaluation of constant expression failed
println!("x={}", x);
}

View File

@ -1,18 +1,26 @@
error: reaching this expression at runtime will panic or abort
--> $DIR/const-eval-query-stack.rs:19:28
warning: any use of this value will cause an error
--> $DIR/const-eval-query-stack.rs:20:16
|
LL | let x: &'static i32 = &(1 / 0);
| -^^^^^^^
| |
| dividing by zero
LL | const X: i32 = 1 / 0;
| ---------------^^^^^-
| |
| attempt to divide `1_i32` by zero
|
= note: `#[deny(const_err)]` on by default
note: the lint level is defined here
--> $DIR/const-eval-query-stack.rs:19:8
|
LL | #[warn(const_err)]
| ^^^^^^^^^
error[E0080]: evaluation of constant expression failed
--> $DIR/const-eval-query-stack.rs:23:27
|
LL | let x: &'static i32 = &X;
| ^-
| |
| referenced constant has errors
query stack during panic:
#0 [eval_to_allocation_raw] const-evaluating + checking `main::promoted[1]`
#1 [eval_to_const_value_raw] simplifying constant for the type system `main::promoted[1]`
#2 [eval_to_const_value_raw] simplifying constant for the type system `main::promoted[1]`
#3 [normalize_generic_arg_after_erasing_regions] normalizing `main::promoted[1]`
#4 [optimized_mir] optimizing MIR for `main`
#5 [collect_and_partition_mono_items] collect_and_partition_mono_items
#0 [normalize_generic_arg_after_erasing_regions] normalizing `main::promoted[1]`
#1 [optimized_mir] optimizing MIR for `main`
#2 [collect_and_partition_mono_items] collect_and_partition_mono_items
end of query stack

View File

@ -1,8 +1,8 @@
warning: this arithmetic operation will overflow
--> $DIR/promoted_errors.rs:12:20
--> $DIR/promoted_errors.rs:13:5
|
LL | println!("{}", 0u32 - 1);
| ^^^^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
LL | 0 - 1
| ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
|
note: the lint level is defined here
--> $DIR/promoted_errors.rs:9:20
@ -10,29 +10,24 @@ note: the lint level is defined here
LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
| ^^^^^^^^^^^^^^^^^^^
warning: this arithmetic operation will overflow
--> $DIR/promoted_errors.rs:14:14
warning: any use of this value will cause an error
--> $DIR/promoted_errors.rs:13:5
|
LL | let _x = 0u32 - 1;
| ^^^^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
warning: this operation will panic at runtime
--> $DIR/promoted_errors.rs:16:20
|
LL | println!("{}", 1 / (1 - 1));
| ^^^^^^^^^^^ attempt to divide `1_i32` by zero
|
note: the lint level is defined here
--> $DIR/promoted_errors.rs:9:41
|
LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
| ^^^^^^^^^^^^^^^^^^^
warning: reaching this expression at runtime will panic or abort
--> $DIR/promoted_errors.rs:16:20
|
LL | println!("{}", 1 / (1 - 1));
| ^^^^^^^^^^^ dividing by zero
LL | 0 - 1
| ^^^^^
| |
| attempt to compute `0_u32 - 1_u32`, which would overflow
| inside `overflow` at $DIR/promoted_errors.rs:13:5
| inside `X` at $DIR/promoted_errors.rs:31:29
...
LL | / const X: () = {
LL | | let _x: &'static u32 = &overflow();
LL | |
LL | | let _x: &'static i32 = &div_by_zero1();
... |
LL | | let _x: &'static i32 = &oob();
LL | | };
| |__-
|
note: the lint level is defined here
--> $DIR/promoted_errors.rs:9:9
@ -40,41 +35,18 @@ note: the lint level is defined here
LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
| ^^^^^^^^^
warning: erroneous constant used
--> $DIR/promoted_errors.rs:16:20
warning: any use of this value will cause an error
--> $DIR/promoted_errors.rs:31:28
|
LL | println!("{}", 1 / (1 - 1));
| ^^^^^^^^^^^ referenced constant has errors
LL | / const X: () = {
LL | | let _x: &'static u32 = &overflow();
| | ^^^^^^^^^^^ referenced constant has errors
LL | |
LL | | let _x: &'static i32 = &div_by_zero1();
... |
LL | | let _x: &'static i32 = &oob();
LL | | };
| |__-
warning: this operation will panic at runtime
--> $DIR/promoted_errors.rs:20:14
|
LL | let _x = 1 / (1 - 1);
| ^^^^^^^^^^^ attempt to divide `1_i32` by zero
warning: this operation will panic at runtime
--> $DIR/promoted_errors.rs:22:20
|
LL | println!("{}", 1 / (false as u32));
| ^^^^^^^^^^^^^^^^^^ attempt to divide `1_u32` by zero
warning: reaching this expression at runtime will panic or abort
--> $DIR/promoted_errors.rs:22:20
|
LL | println!("{}", 1 / (false as u32));
| ^^^^^^^^^^^^^^^^^^ dividing by zero
warning: erroneous constant used
--> $DIR/promoted_errors.rs:22:20
|
LL | println!("{}", 1 / (false as u32));
| ^^^^^^^^^^^^^^^^^^ referenced constant has errors
warning: this operation will panic at runtime
--> $DIR/promoted_errors.rs:26:14
|
LL | let _x = 1 / (false as u32);
| ^^^^^^^^^^^^^^^^^^ attempt to divide `1_u32` by zero
warning: 10 warnings emitted
warning: 3 warnings emitted

View File

@ -1,8 +1,8 @@
warning: this arithmetic operation will overflow
--> $DIR/promoted_errors.rs:14:14
--> $DIR/promoted_errors.rs:13:5
|
LL | let _x = 0u32 - 1;
| ^^^^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
LL | 0 - 1
| ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
|
note: the lint level is defined here
--> $DIR/promoted_errors.rs:9:20
@ -11,10 +11,10 @@ LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
| ^^^^^^^^^^^^^^^^^^^
warning: this operation will panic at runtime
--> $DIR/promoted_errors.rs:16:20
--> $DIR/promoted_errors.rs:17:5
|
LL | println!("{}", 1 / (1 - 1));
| ^^^^^^^^^^^ attempt to divide `1_i32` by zero
LL | 1 / 0
| ^^^^^ attempt to divide `1_i32` by zero
|
note: the lint level is defined here
--> $DIR/promoted_errors.rs:9:41
@ -22,11 +22,24 @@ note: the lint level is defined here
LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
| ^^^^^^^^^^^^^^^^^^^
warning: reaching this expression at runtime will panic or abort
--> $DIR/promoted_errors.rs:16:20
warning: any use of this value will cause an error
--> $DIR/promoted_errors.rs:17:5
|
LL | println!("{}", 1 / (1 - 1));
| ^^^^^^^^^^^ dividing by zero
LL | 1 / 0
| ^^^^^
| |
| attempt to divide `1_i32` by zero
| inside `div_by_zero1` at $DIR/promoted_errors.rs:17:5
| inside `X` at $DIR/promoted_errors.rs:33:29
...
LL | / const X: () = {
LL | | let _x: &'static u32 = &overflow();
LL | |
LL | | let _x: &'static i32 = &div_by_zero1();
... |
LL | | let _x: &'static i32 = &oob();
LL | | };
| |__-
|
note: the lint level is defined here
--> $DIR/promoted_errors.rs:9:9
@ -34,41 +47,18 @@ note: the lint level is defined here
LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
| ^^^^^^^^^
warning: erroneous constant used
--> $DIR/promoted_errors.rs:16:20
warning: any use of this value will cause an error
--> $DIR/promoted_errors.rs:33:28
|
LL | println!("{}", 1 / (1 - 1));
| ^^^^^^^^^^^ referenced constant has errors
LL | / const X: () = {
LL | | let _x: &'static u32 = &overflow();
LL | |
LL | | let _x: &'static i32 = &div_by_zero1();
| | ^^^^^^^^^^^^^^^ referenced constant has errors
... |
LL | | let _x: &'static i32 = &oob();
LL | | };
| |__-
warning: this operation will panic at runtime
--> $DIR/promoted_errors.rs:20:14
|
LL | let _x = 1 / (1 - 1);
| ^^^^^^^^^^^ attempt to divide `1_i32` by zero
warning: this operation will panic at runtime
--> $DIR/promoted_errors.rs:22:20
|
LL | println!("{}", 1 / (false as u32));
| ^^^^^^^^^^^^^^^^^^ attempt to divide `1_u32` by zero
warning: reaching this expression at runtime will panic or abort
--> $DIR/promoted_errors.rs:22:20
|
LL | println!("{}", 1 / (false as u32));
| ^^^^^^^^^^^^^^^^^^ dividing by zero
warning: erroneous constant used
--> $DIR/promoted_errors.rs:22:20
|
LL | println!("{}", 1 / (false as u32));
| ^^^^^^^^^^^^^^^^^^ referenced constant has errors
warning: this operation will panic at runtime
--> $DIR/promoted_errors.rs:26:14
|
LL | let _x = 1 / (false as u32);
| ^^^^^^^^^^^^^^^^^^ attempt to divide `1_u32` by zero
warning: 9 warnings emitted
warning: 4 warnings emitted

View File

@ -1,8 +1,8 @@
warning: this arithmetic operation will overflow
--> $DIR/promoted_errors.rs:12:20
--> $DIR/promoted_errors.rs:13:5
|
LL | println!("{}", 0u32 - 1);
| ^^^^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
LL | 0 - 1
| ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
|
note: the lint level is defined here
--> $DIR/promoted_errors.rs:9:20
@ -10,29 +10,24 @@ note: the lint level is defined here
LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
| ^^^^^^^^^^^^^^^^^^^
warning: this arithmetic operation will overflow
--> $DIR/promoted_errors.rs:14:14
warning: any use of this value will cause an error
--> $DIR/promoted_errors.rs:13:5
|
LL | let _x = 0u32 - 1;
| ^^^^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
warning: this operation will panic at runtime
--> $DIR/promoted_errors.rs:16:20
|
LL | println!("{}", 1 / (1 - 1));
| ^^^^^^^^^^^ attempt to divide `1_i32` by zero
|
note: the lint level is defined here
--> $DIR/promoted_errors.rs:9:41
|
LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
| ^^^^^^^^^^^^^^^^^^^
warning: reaching this expression at runtime will panic or abort
--> $DIR/promoted_errors.rs:16:20
|
LL | println!("{}", 1 / (1 - 1));
| ^^^^^^^^^^^ dividing by zero
LL | 0 - 1
| ^^^^^
| |
| attempt to compute `0_u32 - 1_u32`, which would overflow
| inside `overflow` at $DIR/promoted_errors.rs:13:5
| inside `X` at $DIR/promoted_errors.rs:31:29
...
LL | / const X: () = {
LL | | let _x: &'static u32 = &overflow();
LL | |
LL | | let _x: &'static i32 = &div_by_zero1();
... |
LL | | let _x: &'static i32 = &oob();
LL | | };
| |__-
|
note: the lint level is defined here
--> $DIR/promoted_errors.rs:9:9
@ -40,41 +35,18 @@ note: the lint level is defined here
LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
| ^^^^^^^^^
warning: erroneous constant used
--> $DIR/promoted_errors.rs:16:20
warning: any use of this value will cause an error
--> $DIR/promoted_errors.rs:31:28
|
LL | println!("{}", 1 / (1 - 1));
| ^^^^^^^^^^^ referenced constant has errors
LL | / const X: () = {
LL | | let _x: &'static u32 = &overflow();
| | ^^^^^^^^^^^ referenced constant has errors
LL | |
LL | | let _x: &'static i32 = &div_by_zero1();
... |
LL | | let _x: &'static i32 = &oob();
LL | | };
| |__-
warning: this operation will panic at runtime
--> $DIR/promoted_errors.rs:20:14
|
LL | let _x = 1 / (1 - 1);
| ^^^^^^^^^^^ attempt to divide `1_i32` by zero
warning: this operation will panic at runtime
--> $DIR/promoted_errors.rs:22:20
|
LL | println!("{}", 1 / (false as u32));
| ^^^^^^^^^^^^^^^^^^ attempt to divide `1_u32` by zero
warning: reaching this expression at runtime will panic or abort
--> $DIR/promoted_errors.rs:22:20
|
LL | println!("{}", 1 / (false as u32));
| ^^^^^^^^^^^^^^^^^^ dividing by zero
warning: erroneous constant used
--> $DIR/promoted_errors.rs:22:20
|
LL | println!("{}", 1 / (false as u32));
| ^^^^^^^^^^^^^^^^^^ referenced constant has errors
warning: this operation will panic at runtime
--> $DIR/promoted_errors.rs:26:14
|
LL | let _x = 1 / (false as u32);
| ^^^^^^^^^^^^^^^^^^ attempt to divide `1_u32` by zero
warning: 10 warnings emitted
warning: 3 warnings emitted

View File

@ -8,21 +8,34 @@
#![warn(const_err, arithmetic_overflow, unconditional_panic)]
fn main() {
println!("{}", 0u32 - 1);
//[opt_with_overflow_checks,noopt]~^ WARN [arithmetic_overflow]
let _x = 0u32 - 1;
//~^ WARN [arithmetic_overflow]
println!("{}", 1 / (1 - 1));
//~^ WARN [unconditional_panic]
//~| WARN panic or abort [const_err]
//~| WARN erroneous constant used [const_err]
let _x = 1 / (1 - 1);
//~^ WARN [unconditional_panic]
println!("{}", 1 / (false as u32));
//~^ WARN [unconditional_panic]
//~| WARN panic or abort [const_err]
//~| WARN erroneous constant used [const_err]
let _x = 1 / (false as u32);
//~^ WARN [unconditional_panic]
// The only way to have promoteds that fail is in `const fn` called from `const`/`static`.
const fn overflow() -> u32 {
0 - 1 //~WARN arithmetic_overflow
//[opt_with_overflow_checks,noopt]~^ WARN any use of this value will cause an error
}
const fn div_by_zero1() -> i32 {
1 / 0 //[opt]~WARN unconditional_panic
//[opt]~^ WARN any use of this value will cause an error
}
const fn div_by_zero2() -> i32 {
1 / (1-1)
}
const fn div_by_zero3() -> i32 {
1 / (false as i32)
}
const fn oob() -> i32 {
[1,2,3][4]
}
const X: () = {
let _x: &'static u32 = &overflow();
//[opt_with_overflow_checks,noopt]~^ WARN any use of this value will cause an error
let _x: &'static i32 = &div_by_zero1();
//[opt]~^ WARN any use of this value will cause an error
let _x: &'static i32 = &div_by_zero2();
let _x: &'static i32 = &div_by_zero3();
let _x: &'static i32 = &oob();
};
fn main() {
}

View File

@ -44,4 +44,11 @@ fn main() {
// We must not promote things with interior mutability. Not even if we "project it away".
let _val: &'static _ = &(Cell::new(1), 2).0; //~ ERROR temporary value dropped while borrowed
let _val: &'static _ = &(Cell::new(1), 2).1; //~ ERROR temporary value dropped while borrowed
// 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%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
}

View File

@ -65,7 +65,7 @@ LL | let _val: &'static _ = &(Cell::new(1), 2).0;
| ---------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
LL | let _val: &'static _ = &(Cell::new(1), 2).1;
...
LL | }
| - temporary value is freed at the end of this statement
@ -76,9 +76,64 @@ LL | let _val: &'static _ = &(Cell::new(1), 2).1;
| ---------- ^^^^^^^^^^^^^^^^^ creates a temporary 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: aborting due to 8 previous errors
error[E0716]: temporary value dropped while borrowed
--> $DIR/promote-not.rs:49:29
|
LL | let _val: &'static _ = &(1/0);
| ---------- ^^^^^ creates a temporary 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:50:29
|
LL | let _val: &'static _ = &(1/(1-1));
| ---------- ^^^^^^^^^ creates a temporary 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:51:29
|
LL | let _val: &'static _ = &(1%0);
| ---------- ^^^^^ creates a temporary 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:52:29
|
LL | let _val: &'static _ = &(1%(1-1));
| ---------- ^^^^^^^^^ creates a temporary which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
LL | let _val: &'static _ = &([1,2,3][4]+1);
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 _ = &([1,2,3][4]+1);
| ---------- ^^^^^^^^^^^^^^ creates a temporary 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: aborting due to 13 previous errors
For more information about this error, try `rustc --explain E0716`.

View File

@ -1,9 +0,0 @@
#![allow(unconditional_panic, const_err)]
// run-fail
// error-pattern: attempt to divide by zero
// ignore-emscripten no processes
fn main() {
let x = &(1 / (1 - 1));
}

View File

@ -1,4 +1,4 @@
// check-pass
// run-pass
// compile-flags: -O
@ -25,4 +25,14 @@ fn main() {
// make sure that these do not cause trouble despite overflowing
baz_u32(&(0-1));
baz_i32(&-i32::MIN);
// div-by-non-0 is okay
baz_i32(&(1/1));
baz_i32(&(1%1));
// Top-level projections do not get promoted, so no error here.
if false {
#[allow(unconditional_panic)]
baz_i32(&[1,2,3][4]);
}
}