-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Fix exceeding bitshifts not emitting for assoc. consts (properly this time, I swear!) #71663
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
14d90de
326d38f
e66e37c
bc7b714
6b413d9
2887d79
5b1d600
894a83d
656ab76
eca1478
9c898d6
9459b37
cb96d41
425a99f
65c36f6
f1d778f
8175c4c
8304739
bd18ad4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ use std::ops::RangeInclusive; | |
|
||
use rustc_data_structures::fx::FxHashSet; | ||
use rustc_hir as hir; | ||
use rustc_middle::mir::interpret::{InterpError, InterpErrorInfo}; | ||
use rustc_middle::ty; | ||
use rustc_middle::ty::layout::TyAndLayout; | ||
use rustc_span::symbol::{sym, Symbol}; | ||
|
@@ -24,43 +25,71 @@ use super::{ | |
}; | ||
|
||
macro_rules! throw_validation_failure { | ||
($what:expr, $where:expr, $details:expr) => {{ | ||
let mut msg = format!("encountered {}", $what); | ||
let where_ = &$where; | ||
if !where_.is_empty() { | ||
msg.push_str(" at "); | ||
write_path(&mut msg, where_); | ||
} | ||
write!(&mut msg, ", but expected {}", $details).unwrap(); | ||
throw_ub!(ValidationFailure(msg)) | ||
}}; | ||
($what:expr, $where:expr) => {{ | ||
($what:expr, $where:expr $(, $expected:expr )?) => {{ | ||
let mut msg = format!("encountered {}", $what); | ||
let where_ = &$where; | ||
if !where_.is_empty() { | ||
msg.push_str(" at "); | ||
write_path(&mut msg, where_); | ||
} | ||
$( write!(&mut msg, ", but expected {}", $expected).unwrap(); )? | ||
throw_ub!(ValidationFailure(msg)) | ||
}}; | ||
} | ||
|
||
/// Returns a validation failure for any Err value of $e. | ||
// FIXME: Replace all usages of try_validation! with try_validation_pat!. | ||
macro_rules! try_validation { | ||
($e:expr, $what:expr, $where:expr, $details:expr) => {{ | ||
match $e { | ||
Ok(x) => x, | ||
// We re-throw the error, so we are okay with allocation: | ||
// this can only slow down builds that fail anyway. | ||
Err(_) => throw_validation_failure!($what, $where, $details), | ||
} | ||
($e:expr, $what:expr, $where:expr $(, $expected:expr )?) => {{ | ||
try_validation_pat!($e, $where, { | ||
_ => { "{}", $what } $( expected { "{}", $expected } )?, | ||
}) | ||
}}; | ||
|
||
($e:expr, $what:expr, $where:expr) => {{ | ||
} | ||
/// Like try_validation, but will throw a validation error if any of the patterns in $p are | ||
/// matched. Other errors are passed back to the caller, unchanged. This lets you use the patterns | ||
/// as a kind of validation blacklist: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't it more of a whitelist? Unexpected errors will bubble up to the root and cause ICEs. |
||
/// | ||
/// ``` | ||
/// let v = try_validation_pat!(some_fn(), some_path, { | ||
/// Foo | Bar | Baz => { "some failure" }, | ||
/// }); | ||
/// // Failures that match $p are thrown up as validation errors, but other errors are passed back | ||
/// // unchanged. | ||
/// ``` | ||
/// | ||
/// An additional expected parameter can also be added to the failure message: | ||
/// | ||
/// ``` | ||
/// let v = try_validation_pat!(some_fn(), some_path, { | ||
/// Foo | Bar | Baz => { "some failure" } expected { "something that wasn't a failure" }, | ||
/// }); | ||
/// ``` | ||
/// | ||
/// An additional nicety is that both parameters actually take format args, so you can just write | ||
/// the format string in directly: | ||
/// | ||
/// ``` | ||
/// let v = try_validation_pat!(some_fn(), some_path, { | ||
/// Foo | Bar | Baz => { "{:?}", some_failure } expected { "{}", expected_value }, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is great. :D I think my one complaint is that using curly braces to delemit parameters is a bit odd. We don't write There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't come up with a nicer syntax off the top of my head. Parens would definitely look worse:
I think it's fine as it is. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, let's go with curly braces then. Should we replace There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's standing out enough by the definitely not-legal-rust syntax. But I wouldn't mind an additional There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, let's go with this for now, we can always change it later. |
||
/// }); | ||
/// ``` | ||
/// | ||
macro_rules! try_validation_pat { | ||
($e:expr, $where:expr, { $( $p:pat )|+ => | ||
{ $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )? $( , )?}) => {{ | ||
match $e { | ||
Ok(x) => x, | ||
// We re-throw the error, so we are okay with allocation: | ||
// this can only slow down builds that fail anyway. | ||
Err(_) => throw_validation_failure!($what, $where), | ||
// We catch the error and turn it into a validation failure. We are okay with | ||
// allocation here as this can only slow down builds that fail anyway. | ||
$( Err(InterpErrorInfo { kind: $p, .. }) )|+ => | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wow this is advanced macro magic, cool stuff. |
||
throw_validation_failure!( | ||
format_args!($( $what_fmt ),+), | ||
$where | ||
$(, format_args!($( $expected_fmt ),+))? | ||
), | ||
#[allow(unreachable_patterns)] | ||
Err(e) => Err::<!, _>(e)?, | ||
} | ||
}}; | ||
} | ||
|
@@ -492,11 +521,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' | |
// We are conservative with undef for integers, but try to | ||
// actually enforce the strict rules for raw pointers (mostly because | ||
// that lets us re-use `ref_to_mplace`). | ||
let place = try_validation!( | ||
self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?), | ||
"uninitialized raw pointer", | ||
self.path | ||
); | ||
let place = try_validation_pat!(self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?), self.path, { | ||
err_ub!(InvalidUndefBytes(..)) => { "uninitialized raw pointer" }, | ||
}); | ||
if place.layout.is_unsized() { | ||
self.check_wide_ptr_meta(place.meta, place.layout)?; | ||
} | ||
|
@@ -800,7 +827,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> | |
|
||
throw_validation_failure!("uninitialized bytes", self.path) | ||
} | ||
// Other errors shouldn't be possible | ||
// Propagate upwards (that will also check for unexpected errors). | ||
_ => return Err(err), | ||
} | ||
} | ||
|
@@ -843,9 +870,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | |
// Run it. | ||
jumbatm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
match visitor.visit_value(op) { | ||
Ok(()) => Ok(()), | ||
// We should only get validation errors here. Avoid other errors as | ||
// those do not show *where* in the value the issue lies. | ||
// Pass through validation failures. | ||
Err(err) if matches!(err.kind, err_ub!(ValidationFailure { .. })) => Err(err), | ||
// Also pass through InvalidProgram, those just indicate that we could not | ||
// validate and each caller will know best what to do with them. | ||
Err(err) if matches!(err.kind, InterpError::InvalidProgram(_)) => Err(err), | ||
// Avoid other errors as those do not show *where* in the value the issue lies. | ||
Err(err) => bug!("Unexpected error during validation: {}", err), | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,146 +1,152 @@ | ||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:22:13 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:17:20 | ||
| | ||
LL | let _ = x << 42; | ||
| ^^^^^^^ attempt to shift left with overflow | ||
LL | const N: i32 = T::N << 42; | ||
| ^^^^^^^^^^ attempt to shift left with overflow | ||
| | ||
note: the lint level is defined here | ||
--> $DIR/lint-exceeding-bitshifts.rs:9:9 | ||
--> $DIR/lint-exceeding-bitshifts.rs:8:9 | ||
| | ||
LL | #![deny(arithmetic_overflow, const_err)] | ||
LL | #![warn(arithmetic_overflow, const_err)] | ||
| ^^^^^^^^^^^^^^^^^^^ | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:27:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:21:13 | ||
| | ||
LL | let _ = x << 42; | ||
| ^^^^^^^ attempt to shift left with overflow | ||
|
||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:26:15 | ||
| | ||
LL | let n = 1u8 << 8; | ||
| ^^^^^^^^ attempt to shift left with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:29:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:28:15 | ||
| | ||
LL | let n = 1u16 << 16; | ||
| ^^^^^^^^^^ attempt to shift left with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:31:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:30:15 | ||
| | ||
LL | let n = 1u32 << 32; | ||
| ^^^^^^^^^^ attempt to shift left with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:33:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:32:15 | ||
| | ||
LL | let n = 1u64 << 64; | ||
| ^^^^^^^^^^ attempt to shift left with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:35:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:34:15 | ||
| | ||
LL | let n = 1i8 << 8; | ||
| ^^^^^^^^ attempt to shift left with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:37:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:36:15 | ||
| | ||
LL | let n = 1i16 << 16; | ||
| ^^^^^^^^^^ attempt to shift left with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:39:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:38:15 | ||
| | ||
LL | let n = 1i32 << 32; | ||
| ^^^^^^^^^^ attempt to shift left with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:41:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:40:15 | ||
| | ||
LL | let n = 1i64 << 64; | ||
| ^^^^^^^^^^ attempt to shift left with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:44:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:43:15 | ||
| | ||
LL | let n = 1u8 >> 8; | ||
| ^^^^^^^^ attempt to shift right with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:46:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:45:15 | ||
| | ||
LL | let n = 1u16 >> 16; | ||
| ^^^^^^^^^^ attempt to shift right with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:48:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:47:15 | ||
| | ||
LL | let n = 1u32 >> 32; | ||
| ^^^^^^^^^^ attempt to shift right with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:50:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:49:15 | ||
| | ||
LL | let n = 1u64 >> 64; | ||
| ^^^^^^^^^^ attempt to shift right with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:52:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:51:15 | ||
| | ||
LL | let n = 1i8 >> 8; | ||
| ^^^^^^^^ attempt to shift right with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:54:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:53:15 | ||
| | ||
LL | let n = 1i16 >> 16; | ||
| ^^^^^^^^^^ attempt to shift right with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:56:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:55:15 | ||
| | ||
LL | let n = 1i32 >> 32; | ||
| ^^^^^^^^^^ attempt to shift right with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:58:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:57:15 | ||
| | ||
LL | let n = 1i64 >> 64; | ||
| ^^^^^^^^^^ attempt to shift right with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:62:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:61:15 | ||
| | ||
LL | let n = n << 8; | ||
| ^^^^^^ attempt to shift left with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:64:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:63:15 | ||
| | ||
LL | let n = 1u8 << -8; | ||
| ^^^^^^^^^ attempt to shift left with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:69:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:68:15 | ||
| | ||
LL | let n = 1u8 << (4+4); | ||
| ^^^^^^^^^^^^ attempt to shift left with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:71:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:70:15 | ||
| | ||
LL | let n = 1i64 >> [64][0]; | ||
| ^^^^^^^^^^^^^^^ attempt to shift right with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:77:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:76:15 | ||
| | ||
LL | let n = 1_isize << BITS; | ||
| ^^^^^^^^^^^^^^^ attempt to shift left with overflow | ||
|
||
error: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:78:15 | ||
warning: this arithmetic operation will overflow | ||
--> $DIR/lint-exceeding-bitshifts.rs:77:15 | ||
| | ||
LL | let n = 1_usize << BITS; | ||
| ^^^^^^^^^^^^^^^ attempt to shift left with overflow | ||
|
||
error: aborting due to 23 previous errors | ||
warning: 24 warnings emitted | ||
|
Uh oh!
There was an error while loading. Please reload this page.