Change:
The lint should fire on the following code, but it does not: (This testcase now exists in-tree as a FIXME in .) Cc <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --This issue has been assigned to via . <!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
I'd like to take this. claim
I have some plans to follow-up on with some cleanup. That might at least partially resolve this issue here. So it's probably best to wait until after that is done.
All right, landed, so what I planned here is done. The remaining issue is about associated consts. The issue there is that fails, or maybe we are hitting an , but I have not tried further. The issue is all yours, :)
Great! I'll start investigating.
Never mind, that one is already fixed on beta.
got reverted in , so we have to reopen this.

Discussion:
use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; <ins> use rustc_middle::mir::interpret::{InterpError, InterpErrorInfo}; </ins> use rustc_middle::ty; use rustc_middle::ty::layout::TyAndLayout; use rustc_span::symbol::{sym, Symbol};

}; macro_rules! throw_validation_failure { <del> ($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) => {{ </del> <ins> ($what:expr, $where:expr $(, $details:expr )?) => {{ </ins> let mut msg = format!("encountered {}", $what); let where_ = &$where; if !where_.is_empty() { msg.push_str(" at "); write_path(&mut msg, where_); } <ins> $( write!(&mut msg, ", but expected {}", $details).unwrap(); )? </ins> throw_ub!(ValidationFailure(msg)) }}; } <ins> /// Returns a validation failure for any Err value of $e. // FIXME: Replace all usages of try_validation! with try_validation_pat!. </ins> macro_rules! try_validation { <del> ($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), } </del> <ins> ($e:expr, $what:expr, $where:expr $(, $details:expr )?) => {{ try_validation_pat!($e, _, $what, $where $(, $details )?) </ins> }}; <del> ($e:expr, $what:expr, $where:expr) => {{ </del> <ins> } /// 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: /// /// ```rust /// let v = try_validation_pat!(some_fn(), Foo | Bar | Baz, "some failure", path); /// // Failures that match $p are thrown up as validation errors, but other errors are passed back /// // unchanged. /// ``` macro_rules! try_validation_pat { ($e:expr, $( $p:pat )|*, $what:expr, $where:expr $(, $details:expr )?) => {{ </ins> match $e { Ok(x) => x, <del> // 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), </del> <ins> // 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, .. }) )|* if true => throw_validation_failure!($what, $where $(, $details)?), Err(e) => Err::<!, _>(e)?, </ins> } }}; }

// 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`). <del> let place = try_validation!( </del> <ins> let place = try_validation_pat!( </ins> self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?), <ins> err_ub!(InvalidUndefBytes(..)), </ins> "uninitialized raw pointer", self.path );

// Run it. match visitor.visit_value(op) { Ok(()) => Ok(()), <del> // We should only get validation errors here. Avoid other errors as // those do not show *where* in the value the issue lies. </del> <ins> // Pass through validation failures. </ins> Err(err) if matches!(err.kind, err_ub!(ValidationFailure { .. })) => Err(err), <ins> // 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. </ins> Err(err) => bug!("Unexpected error during validation: {}", err), } }

return None; } <del> // FIXME we need to revisit this for #67176 if rvalue.needs_subst() { return None; } </del> // Perform any special handling for specific Rvalue types. // Generally, checks here fall into one of two categories: //   1. Additional checking to provide useful lints to the user

_ => {} } <ins> // FIXME we need to revisit this for #67176 if rvalue.needs_subst() { return None; } </ins> self.use_ecx(|this| { trace!("calling eval_rvalue_into_place(rvalue = {:?}, place = {:?})", rvalue, place); this.ecx.eval_rvalue_into_place(rvalue, place)?;

<del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:22:13 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:17:20 </ins> | <del> LL |     let _ = x << 42; |             ^^^^^^^ attempt to shift left with overflow </del> <ins> LL |     const N: i32 = T::N << 42; |                    ^^^^^^^^^^ attempt to shift left with overflow </ins> | note: the lint level is defined here <del> --> $DIR/lint-exceeding-bitshifts.rs:9:9 </del> <ins> --> $DIR/lint-exceeding-bitshifts.rs:8:9 </ins> | <del> LL | #![deny(arithmetic_overflow, const_err)] </del> <ins> LL | #![warn(arithmetic_overflow, const_err)] </ins> |         ^^^^^^^^^^^^^^^^^^^ <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:27:15 </del> <ins> 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 </ins> | LL |       let n = 1u8 << 8; |               ^^^^^^^^ attempt to shift left with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:29:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:28:15 </ins> | LL |       let n = 1u16 << 16; |               ^^^^^^^^^^ attempt to shift left with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:31:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:30:15 </ins> | LL |       let n = 1u32 << 32; |               ^^^^^^^^^^ attempt to shift left with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:33:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:32:15 </ins> | LL |       let n = 1u64 << 64; |               ^^^^^^^^^^ attempt to shift left with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:35:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:34:15 </ins> | LL |       let n = 1i8 << 8; |               ^^^^^^^^ attempt to shift left with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:37:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:36:15 </ins> | LL |       let n = 1i16 << 16; |               ^^^^^^^^^^ attempt to shift left with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:39:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:38:15 </ins> | LL |       let n = 1i32 << 32; |               ^^^^^^^^^^ attempt to shift left with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:41:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:40:15 </ins> | LL |       let n = 1i64 << 64; |               ^^^^^^^^^^ attempt to shift left with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:44:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:43:15 </ins> | LL |       let n = 1u8 >> 8; |               ^^^^^^^^ attempt to shift right with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:46:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:45:15 </ins> | LL |       let n = 1u16 >> 16; |               ^^^^^^^^^^ attempt to shift right with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:48:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:47:15 </ins> | LL |       let n = 1u32 >> 32; |               ^^^^^^^^^^ attempt to shift right with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:50:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:49:15 </ins> | LL |       let n = 1u64 >> 64; |               ^^^^^^^^^^ attempt to shift right with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:52:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:51:15 </ins> | LL |       let n = 1i8 >> 8; |               ^^^^^^^^ attempt to shift right with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:54:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:53:15 </ins> | LL |       let n = 1i16 >> 16; |               ^^^^^^^^^^ attempt to shift right with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:56:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:55:15 </ins> | LL |       let n = 1i32 >> 32; |               ^^^^^^^^^^ attempt to shift right with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:58:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:57:15 </ins> | LL |       let n = 1i64 >> 64; |               ^^^^^^^^^^ attempt to shift right with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:62:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:61:15 </ins> | LL |       let n = n << 8; |               ^^^^^^ attempt to shift left with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:64:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:63:15 </ins> | LL |       let n = 1u8 << -8; |               ^^^^^^^^^ attempt to shift left with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:69:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:68:15 </ins> | LL |       let n = 1u8 << (4+4); |               ^^^^^^^^^^^^ attempt to shift left with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:71:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:70:15 </ins> | LL |       let n = 1i64 >> [64][0]; |               ^^^^^^^^^^^^^^^ attempt to shift right with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:77:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:76:15 </ins> | LL |       let n = 1_isize << BITS; |               ^^^^^^^^^^^^^^^ attempt to shift left with overflow <del> error: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:78:15 </del> <ins> warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:77:15 </ins> | LL |       let n = 1_usize << BITS; |               ^^^^^^^^^^^^^^^ attempt to shift left with overflow <del> error: aborting due to 23 previous errors </del> <ins> warning: 24 warnings emitted </ins>

//[noopt]compile-flags: -C opt-level=0 //[opt]compile-flags: -O //[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O <del> // build-fail </del> <ins> // build-pass </ins> #![crate_type="lib"] <del> #![deny(arithmetic_overflow, const_err)] </del> <ins> #![warn(arithmetic_overflow, const_err)] </ins> #![allow(unused_variables)] #![allow(dead_code)]

} impl<T: Foo> Foo for Vec<T> { <del> const N: i32 = T::N << 42; // FIXME this should warn </del> <ins> const N: i32 = T::N << 42; //~ WARN: arithmetic operation will overflow </ins> } pub fn foo(x: i32) { <del> let _ = x << 42; //~ ERROR: arithmetic operation will overflow </del> <ins> let _ = x << 42; //~ WARN: arithmetic operation will overflow </ins> } pub fn main() { let n = 1u8 << 7; <del> let n = 1u8 << 8;   //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1u8 << 8;   //~ WARN: arithmetic operation will overflow </ins> let n = 1u16 << 15; <del> let n = 1u16 << 16; //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1u16 << 16; //~ WARN: arithmetic operation will overflow </ins> let n = 1u32 << 31; <del> let n = 1u32 << 32; //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1u32 << 32; //~ WARN: arithmetic operation will overflow </ins> let n = 1u64 << 63; <del> let n = 1u64 << 64; //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1u64 << 64; //~ WARN: arithmetic operation will overflow </ins> let n = 1i8 << 7; <del> let n = 1i8 << 8;   //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1i8 << 8;   //~ WARN: arithmetic operation will overflow </ins> let n = 1i16 << 15; <del> let n = 1i16 << 16; //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1i16 << 16; //~ WARN: arithmetic operation will overflow </ins> let n = 1i32 << 31; <del> let n = 1i32 << 32; //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1i32 << 32; //~ WARN: arithmetic operation will overflow </ins> let n = 1i64 << 63; <del> let n = 1i64 << 64; //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1i64 << 64; //~ WARN: arithmetic operation will overflow </ins> let n = 1u8 >> 7; <del> let n = 1u8 >> 8;   //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1u8 >> 8;   //~ WARN: arithmetic operation will overflow </ins> let n = 1u16 >> 15; <del> let n = 1u16 >> 16; //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1u16 >> 16; //~ WARN: arithmetic operation will overflow </ins> let n = 1u32 >> 31; <del> let n = 1u32 >> 32; //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1u32 >> 32; //~ WARN: arithmetic operation will overflow </ins> let n = 1u64 >> 63; <del> let n = 1u64 >> 64; //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1u64 >> 64; //~ WARN: arithmetic operation will overflow </ins> let n = 1i8 >> 7; <del> let n = 1i8 >> 8;   //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1i8 >> 8;   //~ WARN: arithmetic operation will overflow </ins> let n = 1i16 >> 15; <del> let n = 1i16 >> 16; //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1i16 >> 16; //~ WARN: arithmetic operation will overflow </ins> let n = 1i32 >> 31; <del> let n = 1i32 >> 32; //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1i32 >> 32; //~ WARN: arithmetic operation will overflow </ins> let n = 1i64 >> 63; <del> let n = 1i64 >> 64; //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1i64 >> 64; //~ WARN: arithmetic operation will overflow </ins> let n = 1u8; let n = n << 7; <del> let n = n << 8; //~ ERROR: arithmetic operation will overflow </del> <ins> let n = n << 8; //~ WARN: arithmetic operation will overflow </ins> <del> let n = 1u8 << -8; //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1u8 << -8; //~ WARN: arithmetic operation will overflow </ins> let n = 1i8<<(1isize+-1); let n = 1u8 << (4+3); <del> let n = 1u8 << (4+4); //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1u8 << (4+4); //~ WARN: arithmetic operation will overflow </ins> let n = 1i64 >> [63][0]; <del> let n = 1i64 >> [64][0]; //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1i64 >> [64][0]; //~ WARN: arithmetic operation will overflow </ins> #[cfg(target_pointer_width = "32")] const BITS: usize = 32; #[cfg(target_pointer_width = "64")] const BITS: usize = 64; <del> let n = 1_isize << BITS; //~ ERROR: arithmetic operation will overflow let n = 1_usize << BITS; //~ ERROR: arithmetic operation will overflow </del> <ins> let n = 1_isize << BITS; //~ WARN: arithmetic operation will overflow let n = 1_usize << BITS; //~ WARN: arithmetic operation will overflow </ins> }