From f121f094fe4d4f4e92142984e9230373c311e1e6 Mon Sep 17 00:00:00 2001 From: ThinkChaos Date: Tue, 21 Apr 2020 20:03:50 +0200 Subject: [PATCH 01/29] Add `RefCell::take` In the same vein as `Cell::take` and `Option::take`. --- src/libcore/cell.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index a922d4f118b5a..05c9c97a6126e 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -1023,6 +1023,27 @@ impl RefCell { } } +impl RefCell { + /// Takes the wrapped value, leaving `Default::default()` in its place. + /// + /// # Examples + /// + /// ``` + /// #![feature(refcell_take)] + /// use std::cell::RefCell; + /// + /// let c = RefCell::new(5); + /// let five = c.take(); + /// + /// assert_eq!(five, 5); + /// assert_eq!(c.into_inner(), 0); + /// ``` + #[unstable(feature = "refcell_take", issue = "71395")] + pub fn take(&self) -> T { + self.replace(Default::default()) + } +} + #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Send for RefCell where T: Send {} From 4ea83bfb3d457770f2e54965dd86f672fbbc87c2 Mon Sep 17 00:00:00 2001 From: ThinkChaos Date: Tue, 21 Apr 2020 21:11:32 +0200 Subject: [PATCH 02/29] Use Cell::take in a couple places --- src/libstd/sync/once.rs | 2 +- src/test/run-make/wasm-panic-small/foo.rs | 2 +- .../ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs | 2 +- .../traits/negative-impls/pin-unsound-issue-66544-derefmut.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 1e6b6c430be90..a3ee14e85d222 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -497,7 +497,7 @@ impl Drop for WaiterQueue<'_> { let mut queue = (state_and_queue & !STATE_MASK) as *const Waiter; while !queue.is_null() { let next = (*queue).next; - let thread = (*queue).thread.replace(None).unwrap(); + let thread = (*queue).thread.take().unwrap(); (*queue).signaled.store(true, Ordering::Release); // ^- FIXME (maybe): This is another case of issue #55005 // `store()` has a potentially dangling ref to `signaled`. diff --git a/src/test/run-make/wasm-panic-small/foo.rs b/src/test/run-make/wasm-panic-small/foo.rs index fd3dddb18eb20..6df52affe3993 100644 --- a/src/test/run-make/wasm-panic-small/foo.rs +++ b/src/test/run-make/wasm-panic-small/foo.rs @@ -23,5 +23,5 @@ pub fn foo() { pub fn foo() -> usize { use std::cell::Cell; thread_local!(static A: Cell> = Cell::new(Vec::new())); - A.try_with(|x| x.replace(Vec::new()).len()).unwrap_or(0) + A.try_with(|x| x.take().len()).unwrap_or(0) } diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs index 499ac461e59a5..a5b85646581bf 100644 --- a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs +++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs @@ -7,7 +7,7 @@ struct MyType<'a>(Cell>>, PhantomPinned); impl<'a> Clone for &'a mut MyType<'a> { //~^ ERROR E0751 fn clone(&self) -> &'a mut MyType<'a> { - self.0.replace(None).unwrap() + self.0.take().unwrap() } } diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs index 245be80078056..606cc65a84bc2 100644 --- a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs +++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs @@ -12,7 +12,7 @@ struct MyType<'a>(Cell>>, PhantomPinned); impl<'a> DerefMut for &'a MyType<'a> { //~^ ERROR E0751 fn deref_mut(&mut self) -> &mut MyType<'a> { - self.0.replace(None).unwrap() + self.0.take().unwrap() } } From 14d90deab9cbbc1bfb45af52f9dc9fbce945da91 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Thu, 23 Apr 2020 20:17:15 +1000 Subject: [PATCH 03/29] Don't duplicate macro for optional arg. --- src/librustc_mir/interpret/validity.rs | 30 ++++++-------------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index df3c353220318..0b6422316ead7 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -24,43 +24,25 @@ 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 $(, $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)) }}; } 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) => {{ + ($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), + // 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(_) => throw_validation_failure!($what, $where $(, $details)?), } }}; } From 326d38fa09cfdf9e611b8828604a7a05c7f55c85 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Thu, 23 Apr 2020 22:00:06 +1000 Subject: [PATCH 04/29] Add try_validation_pat. --- src/librustc_mir/interpret/validity.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 0b6422316ead7..1e4c9367f6a6c 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -36,6 +36,7 @@ macro_rules! throw_validation_failure { }}; } +/// Returns a validation failure for any Err value of $e. macro_rules! try_validation { ($e:expr, $what:expr, $where:expr $(, $details:expr )?) => {{ match $e { @@ -46,6 +47,24 @@ macro_rules! try_validation { } }}; } +/// 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", "some place"); +/// // 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 )?) => {{ + match $e { + Ok(x) => x, + $( Err($p) )|* if true => throw_validation_failure!($what, $where $(, $details)?), + Err(e) => Err::(e)?, + } + }}; +} /// We want to show a nice path to the invalid field for diagnostics, /// but avoid string operations in the happy case where no error happens. @@ -474,8 +493,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!( + let place = try_validation_pat!( self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?), + _, "uninitialized raw pointer", self.path ); From e66e37cbf1806f4e0b7a9e6935c8198b3a6c4b2f Mon Sep 17 00:00:00 2001 From: jumbatm Date: Thu, 23 Apr 2020 22:52:27 +1000 Subject: [PATCH 05/29] Don't duplicate body of try_validation. --- src/librustc_mir/interpret/validity.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 1e4c9367f6a6c..42cdb1dc2a651 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -39,12 +39,7 @@ macro_rules! throw_validation_failure { /// Returns a validation failure for any Err value of $e. macro_rules! try_validation { ($e:expr, $what:expr, $where:expr $(, $details:expr )?) => {{ - match $e { - Ok(x) => x, - // 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(_) => throw_validation_failure!($what, $where $(, $details)?), - } + try_validation_pat!($e, _, $what, $where $(, $details )?) }}; } /// Like try_validation, but will throw a validation error if any of the patterns in $p are @@ -60,6 +55,8 @@ macro_rules! try_validation_pat { ($e:expr, $( $p:pat )|*, $what:expr, $where:expr $(, $details:expr )?) => {{ match $e { Ok(x) => x, + // 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($p) )|* if true => throw_validation_failure!($what, $where $(, $details)?), Err(e) => Err::(e)?, } From bc7b7140b9a5ea4e764c9f53a915d26baa4326be Mon Sep 17 00:00:00 2001 From: jumbatm Date: Wed, 29 Apr 2020 09:45:13 +1000 Subject: [PATCH 06/29] Don't fail for UndefinedBehaviourInfo in validation. --- src/librustc_mir/interpret/validity.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 42cdb1dc2a651..d6202638fd912 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -842,9 +842,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Run it. 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. + // Allow validation failures to be returned. Err(err) if matches!(err.kind, err_ub!(ValidationFailure { .. })) => Err(err), + // Also allow InvalidProgram to be returned, because it's likely that different callers + // will want to do different things in this situation. + 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), } } From 6b413d95fc3035fff80c0388049d5b7c178a3c59 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Wed, 29 Apr 2020 09:41:01 +1000 Subject: [PATCH 07/29] Throw validation failure for InvalidUndefBytes. --- src/librustc_mir/interpret/validity.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index d6202638fd912..ab440cc5ebab8 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -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}; @@ -492,7 +493,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // that lets us re-use `ref_to_mplace`). let place = try_validation_pat!( self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?), - _, + InterpErrorInfo { kind: err_ub!(InvalidUndefBytes(..)), ..}, "uninitialized raw pointer", self.path ); From 2887d7923ebac8a1bed6e019550c177e3f2fa6b6 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Wed, 29 Apr 2020 19:35:45 +1000 Subject: [PATCH 08/29] Partially unrevert #70566. This partially reverts commit 4b5b6cbe60a8dd1822cfa46c41cf1ad58c113e18, reversing some changes made to 62b362472dbf8bdf43b252ac5ea53b527a8dbee3. --- src/librustc_mir/transform/const_prop.rs | 10 +-- .../lint-exceeding-bitshifts.noopt.stderr | 62 ++++++++++--------- .../lint/lint-exceeding-bitshifts.opt.stderr | 62 ++++++++++--------- ...-bitshifts.opt_with_overflow_checks.stderr | 62 ++++++++++--------- src/test/ui/lint/lint-exceeding-bitshifts.rs | 53 ++++++++-------- 5 files changed, 133 insertions(+), 116 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 09d8f89676a66..1573769a1570c 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -549,11 +549,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { return None; } - // FIXME we need to revisit this for #67176 - if rvalue.needs_subst() { - return None; - } - // 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 @@ -594,6 +589,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { _ => {} } + // FIXME we need to revisit this for #67176 + if rvalue.needs_subst() { + return None; + } + self.use_ecx(|this| { trace!("calling eval_rvalue_into_place(rvalue = {:?}, place = {:?})", rvalue, place); this.ecx.eval_rvalue_into_place(rvalue, place)?; diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr index ce9b02b6d82a7..a2fb5ad8b8b8b 100644 --- a/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr +++ b/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr @@ -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:18: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 | -LL | #![deny(arithmetic_overflow, const_err)] +LL | #![warn(arithmetic_overflow, const_err)] | ^^^^^^^^^^^^^^^^^^^ -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:22:13 + | +LL | let _ = x << 42; + | ^^^^^^^ attempt to shift left with overflow + +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:27:15 | LL | let n = 1u8 << 8; | ^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:29:15 | LL | let n = 1u16 << 16; | ^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:31:15 | LL | let n = 1u32 << 32; | ^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:33:15 | LL | let n = 1u64 << 64; | ^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:35:15 | LL | let n = 1i8 << 8; | ^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:37:15 | LL | let n = 1i16 << 16; | ^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:39:15 | LL | let n = 1i32 << 32; | ^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:41:15 | LL | let n = 1i64 << 64; | ^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:44:15 | LL | let n = 1u8 >> 8; | ^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:46:15 | LL | let n = 1u16 >> 16; | ^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:48:15 | LL | let n = 1u32 >> 32; | ^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:50:15 | LL | let n = 1u64 >> 64; | ^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:52:15 | LL | let n = 1i8 >> 8; | ^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:54:15 | LL | let n = 1i16 >> 16; | ^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:56:15 | LL | let n = 1i32 >> 32; | ^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:58:15 | LL | let n = 1i64 >> 64; | ^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:62:15 | LL | let n = n << 8; | ^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:64:15 | LL | let n = 1u8 << -8; | ^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:69:15 | LL | let n = 1u8 << (4+4); | ^^^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:71:15 | LL | let n = 1i64 >> [64][0]; | ^^^^^^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:77:15 | LL | let n = 1_isize << BITS; | ^^^^^^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:78:15 | LL | let n = 1_usize << BITS; | ^^^^^^^^^^^^^^^ attempt to shift left with overflow -error: aborting due to 23 previous errors +warning: 24 warnings emitted diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr index ce9b02b6d82a7..a2fb5ad8b8b8b 100644 --- a/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr +++ b/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr @@ -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:18: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 | -LL | #![deny(arithmetic_overflow, const_err)] +LL | #![warn(arithmetic_overflow, const_err)] | ^^^^^^^^^^^^^^^^^^^ -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:22:13 + | +LL | let _ = x << 42; + | ^^^^^^^ attempt to shift left with overflow + +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:27:15 | LL | let n = 1u8 << 8; | ^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:29:15 | LL | let n = 1u16 << 16; | ^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:31:15 | LL | let n = 1u32 << 32; | ^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:33:15 | LL | let n = 1u64 << 64; | ^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:35:15 | LL | let n = 1i8 << 8; | ^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:37:15 | LL | let n = 1i16 << 16; | ^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:39:15 | LL | let n = 1i32 << 32; | ^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:41:15 | LL | let n = 1i64 << 64; | ^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:44:15 | LL | let n = 1u8 >> 8; | ^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:46:15 | LL | let n = 1u16 >> 16; | ^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:48:15 | LL | let n = 1u32 >> 32; | ^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:50:15 | LL | let n = 1u64 >> 64; | ^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:52:15 | LL | let n = 1i8 >> 8; | ^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:54:15 | LL | let n = 1i16 >> 16; | ^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:56:15 | LL | let n = 1i32 >> 32; | ^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:58:15 | LL | let n = 1i64 >> 64; | ^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:62:15 | LL | let n = n << 8; | ^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:64:15 | LL | let n = 1u8 << -8; | ^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:69:15 | LL | let n = 1u8 << (4+4); | ^^^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:71:15 | LL | let n = 1i64 >> [64][0]; | ^^^^^^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:77:15 | LL | let n = 1_isize << BITS; | ^^^^^^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:78:15 | LL | let n = 1_usize << BITS; | ^^^^^^^^^^^^^^^ attempt to shift left with overflow -error: aborting due to 23 previous errors +warning: 24 warnings emitted diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr index ce9b02b6d82a7..a2fb5ad8b8b8b 100644 --- a/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr +++ b/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr @@ -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:18: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 | -LL | #![deny(arithmetic_overflow, const_err)] +LL | #![warn(arithmetic_overflow, const_err)] | ^^^^^^^^^^^^^^^^^^^ -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:22:13 + | +LL | let _ = x << 42; + | ^^^^^^^ attempt to shift left with overflow + +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:27:15 | LL | let n = 1u8 << 8; | ^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:29:15 | LL | let n = 1u16 << 16; | ^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:31:15 | LL | let n = 1u32 << 32; | ^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:33:15 | LL | let n = 1u64 << 64; | ^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:35:15 | LL | let n = 1i8 << 8; | ^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:37:15 | LL | let n = 1i16 << 16; | ^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:39:15 | LL | let n = 1i32 << 32; | ^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:41:15 | LL | let n = 1i64 << 64; | ^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:44:15 | LL | let n = 1u8 >> 8; | ^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:46:15 | LL | let n = 1u16 >> 16; | ^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:48:15 | LL | let n = 1u32 >> 32; | ^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:50:15 | LL | let n = 1u64 >> 64; | ^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:52:15 | LL | let n = 1i8 >> 8; | ^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:54:15 | LL | let n = 1i16 >> 16; | ^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:56:15 | LL | let n = 1i32 >> 32; | ^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:58:15 | LL | let n = 1i64 >> 64; | ^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:62:15 | LL | let n = n << 8; | ^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:64:15 | LL | let n = 1u8 << -8; | ^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:69:15 | LL | let n = 1u8 << (4+4); | ^^^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:71:15 | LL | let n = 1i64 >> [64][0]; | ^^^^^^^^^^^^^^^ attempt to shift right with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:77:15 | LL | let n = 1_isize << BITS; | ^^^^^^^^^^^^^^^ attempt to shift left with overflow -error: this arithmetic operation will overflow +warning: this arithmetic operation will overflow --> $DIR/lint-exceeding-bitshifts.rs:78:15 | LL | let n = 1_usize << BITS; | ^^^^^^^^^^^^^^^ attempt to shift left with overflow -error: aborting due to 23 previous errors +warning: 24 warnings emitted diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.rs b/src/test/ui/lint/lint-exceeding-bitshifts.rs index 7deee5320a878..565bef49c9f8c 100644 --- a/src/test/ui/lint/lint-exceeding-bitshifts.rs +++ b/src/test/ui/lint/lint-exceeding-bitshifts.rs @@ -2,11 +2,10 @@ //[noopt]compile-flags: -C opt-level=0 //[opt]compile-flags: -O //[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O - -// build-fail +// build-pass #![crate_type="lib"] -#![deny(arithmetic_overflow, const_err)] +#![warn(arithmetic_overflow, const_err)] #![allow(unused_variables)] #![allow(dead_code)] @@ -15,65 +14,65 @@ pub trait Foo { } impl Foo for Vec { - const N: i32 = T::N << 42; // FIXME this should warn + const N: i32 = T::N << 42; //~ WARN: arithmetic operation will overflow } pub fn foo(x: i32) { - let _ = x << 42; //~ ERROR: arithmetic operation will overflow + let _ = x << 42; //~ WARN: arithmetic operation will overflow } pub fn main() { let n = 1u8 << 7; - let n = 1u8 << 8; //~ ERROR: arithmetic operation will overflow + let n = 1u8 << 8; //~ WARN: arithmetic operation will overflow let n = 1u16 << 15; - let n = 1u16 << 16; //~ ERROR: arithmetic operation will overflow + let n = 1u16 << 16; //~ WARN: arithmetic operation will overflow let n = 1u32 << 31; - let n = 1u32 << 32; //~ ERROR: arithmetic operation will overflow + let n = 1u32 << 32; //~ WARN: arithmetic operation will overflow let n = 1u64 << 63; - let n = 1u64 << 64; //~ ERROR: arithmetic operation will overflow + let n = 1u64 << 64; //~ WARN: arithmetic operation will overflow let n = 1i8 << 7; - let n = 1i8 << 8; //~ ERROR: arithmetic operation will overflow + let n = 1i8 << 8; //~ WARN: arithmetic operation will overflow let n = 1i16 << 15; - let n = 1i16 << 16; //~ ERROR: arithmetic operation will overflow + let n = 1i16 << 16; //~ WARN: arithmetic operation will overflow let n = 1i32 << 31; - let n = 1i32 << 32; //~ ERROR: arithmetic operation will overflow + let n = 1i32 << 32; //~ WARN: arithmetic operation will overflow let n = 1i64 << 63; - let n = 1i64 << 64; //~ ERROR: arithmetic operation will overflow + let n = 1i64 << 64; //~ WARN: arithmetic operation will overflow let n = 1u8 >> 7; - let n = 1u8 >> 8; //~ ERROR: arithmetic operation will overflow + let n = 1u8 >> 8; //~ WARN: arithmetic operation will overflow let n = 1u16 >> 15; - let n = 1u16 >> 16; //~ ERROR: arithmetic operation will overflow + let n = 1u16 >> 16; //~ WARN: arithmetic operation will overflow let n = 1u32 >> 31; - let n = 1u32 >> 32; //~ ERROR: arithmetic operation will overflow + let n = 1u32 >> 32; //~ WARN: arithmetic operation will overflow let n = 1u64 >> 63; - let n = 1u64 >> 64; //~ ERROR: arithmetic operation will overflow + let n = 1u64 >> 64; //~ WARN: arithmetic operation will overflow let n = 1i8 >> 7; - let n = 1i8 >> 8; //~ ERROR: arithmetic operation will overflow + let n = 1i8 >> 8; //~ WARN: arithmetic operation will overflow let n = 1i16 >> 15; - let n = 1i16 >> 16; //~ ERROR: arithmetic operation will overflow + let n = 1i16 >> 16; //~ WARN: arithmetic operation will overflow let n = 1i32 >> 31; - let n = 1i32 >> 32; //~ ERROR: arithmetic operation will overflow + let n = 1i32 >> 32; //~ WARN: arithmetic operation will overflow let n = 1i64 >> 63; - let n = 1i64 >> 64; //~ ERROR: arithmetic operation will overflow + let n = 1i64 >> 64; //~ WARN: arithmetic operation will overflow let n = 1u8; let n = n << 7; - let n = n << 8; //~ ERROR: arithmetic operation will overflow + let n = n << 8; //~ WARN: arithmetic operation will overflow - let n = 1u8 << -8; //~ ERROR: arithmetic operation will overflow + let n = 1u8 << -8; //~ WARN: arithmetic operation will overflow let n = 1i8<<(1isize+-1); let n = 1u8 << (4+3); - let n = 1u8 << (4+4); //~ ERROR: arithmetic operation will overflow + let n = 1u8 << (4+4); //~ WARN: arithmetic operation will overflow let n = 1i64 >> [63][0]; - let n = 1i64 >> [64][0]; //~ ERROR: arithmetic operation will overflow + let n = 1i64 >> [64][0]; //~ WARN: arithmetic operation will overflow #[cfg(target_pointer_width = "32")] const BITS: usize = 32; #[cfg(target_pointer_width = "64")] const BITS: usize = 64; - let n = 1_isize << BITS; //~ ERROR: arithmetic operation will overflow - let n = 1_usize << BITS; //~ ERROR: arithmetic operation will overflow + let n = 1_isize << BITS; //~ WARN: arithmetic operation will overflow + let n = 1_usize << BITS; //~ WARN: arithmetic operation will overflow } From 5b1d6000a0095c81aeabee22f09f38110960415b Mon Sep 17 00:00:00 2001 From: jumbatm Date: Fri, 1 May 2020 20:09:09 +1000 Subject: [PATCH 09/29] Update stderrs. --- .../lint-exceeding-bitshifts.noopt.stderr | 50 +++++++++---------- .../lint/lint-exceeding-bitshifts.opt.stderr | 50 +++++++++---------- ...-bitshifts.opt_with_overflow_checks.stderr | 50 +++++++++---------- 3 files changed, 75 insertions(+), 75 deletions(-) diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr index a2fb5ad8b8b8b..0c328a2594a46 100644 --- a/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr +++ b/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr @@ -1,149 +1,149 @@ warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:18:20 + --> $DIR/lint-exceeding-bitshifts.rs:17:20 | 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 | #![warn(arithmetic_overflow, const_err)] | ^^^^^^^^^^^^^^^^^^^ warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:22:13 + --> $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:27:15 + --> $DIR/lint-exceeding-bitshifts.rs:26:15 | LL | let n = 1u8 << 8; | ^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:29:15 + --> $DIR/lint-exceeding-bitshifts.rs:28:15 | LL | let n = 1u16 << 16; | ^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:31:15 + --> $DIR/lint-exceeding-bitshifts.rs:30:15 | LL | let n = 1u32 << 32; | ^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:33:15 + --> $DIR/lint-exceeding-bitshifts.rs:32:15 | LL | let n = 1u64 << 64; | ^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:35:15 + --> $DIR/lint-exceeding-bitshifts.rs:34:15 | LL | let n = 1i8 << 8; | ^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:37:15 + --> $DIR/lint-exceeding-bitshifts.rs:36:15 | LL | let n = 1i16 << 16; | ^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:39:15 + --> $DIR/lint-exceeding-bitshifts.rs:38:15 | LL | let n = 1i32 << 32; | ^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:41:15 + --> $DIR/lint-exceeding-bitshifts.rs:40:15 | LL | let n = 1i64 << 64; | ^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:44:15 + --> $DIR/lint-exceeding-bitshifts.rs:43:15 | LL | let n = 1u8 >> 8; | ^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:46:15 + --> $DIR/lint-exceeding-bitshifts.rs:45:15 | LL | let n = 1u16 >> 16; | ^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:48:15 + --> $DIR/lint-exceeding-bitshifts.rs:47:15 | LL | let n = 1u32 >> 32; | ^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:50:15 + --> $DIR/lint-exceeding-bitshifts.rs:49:15 | LL | let n = 1u64 >> 64; | ^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:52:15 + --> $DIR/lint-exceeding-bitshifts.rs:51:15 | LL | let n = 1i8 >> 8; | ^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:54:15 + --> $DIR/lint-exceeding-bitshifts.rs:53:15 | LL | let n = 1i16 >> 16; | ^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:56:15 + --> $DIR/lint-exceeding-bitshifts.rs:55:15 | LL | let n = 1i32 >> 32; | ^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:58:15 + --> $DIR/lint-exceeding-bitshifts.rs:57:15 | LL | let n = 1i64 >> 64; | ^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:62:15 + --> $DIR/lint-exceeding-bitshifts.rs:61:15 | LL | let n = n << 8; | ^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:64:15 + --> $DIR/lint-exceeding-bitshifts.rs:63:15 | LL | let n = 1u8 << -8; | ^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:69:15 + --> $DIR/lint-exceeding-bitshifts.rs:68:15 | LL | let n = 1u8 << (4+4); | ^^^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:71:15 + --> $DIR/lint-exceeding-bitshifts.rs:70:15 | LL | let n = 1i64 >> [64][0]; | ^^^^^^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:77:15 + --> $DIR/lint-exceeding-bitshifts.rs:76:15 | LL | let n = 1_isize << BITS; | ^^^^^^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:78:15 + --> $DIR/lint-exceeding-bitshifts.rs:77:15 | LL | let n = 1_usize << BITS; | ^^^^^^^^^^^^^^^ attempt to shift left with overflow diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr index a2fb5ad8b8b8b..0c328a2594a46 100644 --- a/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr +++ b/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr @@ -1,149 +1,149 @@ warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:18:20 + --> $DIR/lint-exceeding-bitshifts.rs:17:20 | 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 | #![warn(arithmetic_overflow, const_err)] | ^^^^^^^^^^^^^^^^^^^ warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:22:13 + --> $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:27:15 + --> $DIR/lint-exceeding-bitshifts.rs:26:15 | LL | let n = 1u8 << 8; | ^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:29:15 + --> $DIR/lint-exceeding-bitshifts.rs:28:15 | LL | let n = 1u16 << 16; | ^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:31:15 + --> $DIR/lint-exceeding-bitshifts.rs:30:15 | LL | let n = 1u32 << 32; | ^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:33:15 + --> $DIR/lint-exceeding-bitshifts.rs:32:15 | LL | let n = 1u64 << 64; | ^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:35:15 + --> $DIR/lint-exceeding-bitshifts.rs:34:15 | LL | let n = 1i8 << 8; | ^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:37:15 + --> $DIR/lint-exceeding-bitshifts.rs:36:15 | LL | let n = 1i16 << 16; | ^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:39:15 + --> $DIR/lint-exceeding-bitshifts.rs:38:15 | LL | let n = 1i32 << 32; | ^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:41:15 + --> $DIR/lint-exceeding-bitshifts.rs:40:15 | LL | let n = 1i64 << 64; | ^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:44:15 + --> $DIR/lint-exceeding-bitshifts.rs:43:15 | LL | let n = 1u8 >> 8; | ^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:46:15 + --> $DIR/lint-exceeding-bitshifts.rs:45:15 | LL | let n = 1u16 >> 16; | ^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:48:15 + --> $DIR/lint-exceeding-bitshifts.rs:47:15 | LL | let n = 1u32 >> 32; | ^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:50:15 + --> $DIR/lint-exceeding-bitshifts.rs:49:15 | LL | let n = 1u64 >> 64; | ^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:52:15 + --> $DIR/lint-exceeding-bitshifts.rs:51:15 | LL | let n = 1i8 >> 8; | ^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:54:15 + --> $DIR/lint-exceeding-bitshifts.rs:53:15 | LL | let n = 1i16 >> 16; | ^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:56:15 + --> $DIR/lint-exceeding-bitshifts.rs:55:15 | LL | let n = 1i32 >> 32; | ^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:58:15 + --> $DIR/lint-exceeding-bitshifts.rs:57:15 | LL | let n = 1i64 >> 64; | ^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:62:15 + --> $DIR/lint-exceeding-bitshifts.rs:61:15 | LL | let n = n << 8; | ^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:64:15 + --> $DIR/lint-exceeding-bitshifts.rs:63:15 | LL | let n = 1u8 << -8; | ^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:69:15 + --> $DIR/lint-exceeding-bitshifts.rs:68:15 | LL | let n = 1u8 << (4+4); | ^^^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:71:15 + --> $DIR/lint-exceeding-bitshifts.rs:70:15 | LL | let n = 1i64 >> [64][0]; | ^^^^^^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:77:15 + --> $DIR/lint-exceeding-bitshifts.rs:76:15 | LL | let n = 1_isize << BITS; | ^^^^^^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:78:15 + --> $DIR/lint-exceeding-bitshifts.rs:77:15 | LL | let n = 1_usize << BITS; | ^^^^^^^^^^^^^^^ attempt to shift left with overflow diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr index a2fb5ad8b8b8b..0c328a2594a46 100644 --- a/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr +++ b/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr @@ -1,149 +1,149 @@ warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:18:20 + --> $DIR/lint-exceeding-bitshifts.rs:17:20 | 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 | #![warn(arithmetic_overflow, const_err)] | ^^^^^^^^^^^^^^^^^^^ warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:22:13 + --> $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:27:15 + --> $DIR/lint-exceeding-bitshifts.rs:26:15 | LL | let n = 1u8 << 8; | ^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:29:15 + --> $DIR/lint-exceeding-bitshifts.rs:28:15 | LL | let n = 1u16 << 16; | ^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:31:15 + --> $DIR/lint-exceeding-bitshifts.rs:30:15 | LL | let n = 1u32 << 32; | ^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:33:15 + --> $DIR/lint-exceeding-bitshifts.rs:32:15 | LL | let n = 1u64 << 64; | ^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:35:15 + --> $DIR/lint-exceeding-bitshifts.rs:34:15 | LL | let n = 1i8 << 8; | ^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:37:15 + --> $DIR/lint-exceeding-bitshifts.rs:36:15 | LL | let n = 1i16 << 16; | ^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:39:15 + --> $DIR/lint-exceeding-bitshifts.rs:38:15 | LL | let n = 1i32 << 32; | ^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:41:15 + --> $DIR/lint-exceeding-bitshifts.rs:40:15 | LL | let n = 1i64 << 64; | ^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:44:15 + --> $DIR/lint-exceeding-bitshifts.rs:43:15 | LL | let n = 1u8 >> 8; | ^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:46:15 + --> $DIR/lint-exceeding-bitshifts.rs:45:15 | LL | let n = 1u16 >> 16; | ^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:48:15 + --> $DIR/lint-exceeding-bitshifts.rs:47:15 | LL | let n = 1u32 >> 32; | ^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:50:15 + --> $DIR/lint-exceeding-bitshifts.rs:49:15 | LL | let n = 1u64 >> 64; | ^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:52:15 + --> $DIR/lint-exceeding-bitshifts.rs:51:15 | LL | let n = 1i8 >> 8; | ^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:54:15 + --> $DIR/lint-exceeding-bitshifts.rs:53:15 | LL | let n = 1i16 >> 16; | ^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:56:15 + --> $DIR/lint-exceeding-bitshifts.rs:55:15 | LL | let n = 1i32 >> 32; | ^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:58:15 + --> $DIR/lint-exceeding-bitshifts.rs:57:15 | LL | let n = 1i64 >> 64; | ^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:62:15 + --> $DIR/lint-exceeding-bitshifts.rs:61:15 | LL | let n = n << 8; | ^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:64:15 + --> $DIR/lint-exceeding-bitshifts.rs:63:15 | LL | let n = 1u8 << -8; | ^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:69:15 + --> $DIR/lint-exceeding-bitshifts.rs:68:15 | LL | let n = 1u8 << (4+4); | ^^^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:71:15 + --> $DIR/lint-exceeding-bitshifts.rs:70:15 | LL | let n = 1i64 >> [64][0]; | ^^^^^^^^^^^^^^^ attempt to shift right with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:77:15 + --> $DIR/lint-exceeding-bitshifts.rs:76:15 | LL | let n = 1_isize << BITS; | ^^^^^^^^^^^^^^^ attempt to shift left with overflow warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:78:15 + --> $DIR/lint-exceeding-bitshifts.rs:77:15 | LL | let n = 1_usize << BITS; | ^^^^^^^^^^^^^^^ attempt to shift left with overflow From 894a83d4098a5b390484473ab8608fdd113ff9ba Mon Sep 17 00:00:00 2001 From: jumbatm Date: Thu, 30 Apr 2020 14:38:02 +1000 Subject: [PATCH 10/29] Apply suggestions from code review Co-Authored-By: Ralf Jung Co-Authored-By: Oliver Scherer --- src/librustc_mir/interpret/validity.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index ab440cc5ebab8..ac05b3b1ff498 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -48,7 +48,7 @@ macro_rules! try_validation { /// as a kind of validation blacklist: /// /// ```rust -/// let v = try_validation_pat(some_fn(), Foo | Bar | Baz, "some failure", "some place"); +/// 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. /// ``` @@ -59,7 +59,7 @@ macro_rules! try_validation_pat { // 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($p) )|* if true => throw_validation_failure!($what, $where $(, $details)?), - Err(e) => Err::(e)?, + Err(e) => Err::(e)?, } }}; } @@ -843,10 +843,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Run it. match visitor.visit_value(op) { Ok(()) => Ok(()), - // Allow validation failures to be returned. + // Pass through validation failures. Err(err) if matches!(err.kind, err_ub!(ValidationFailure { .. })) => Err(err), - // Also allow InvalidProgram to be returned, because it's likely that different callers - // will want to do different things in this situation. + // 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), From 656ab7639737bd406591a4198633cd3ab0ad0c41 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Thu, 30 Apr 2020 00:00:08 +1000 Subject: [PATCH 11/29] Add FIXME about replacing all usages of try_validation. --- src/librustc_mir/interpret/validity.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index ac05b3b1ff498..80e39e83d47e8 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -38,6 +38,7 @@ macro_rules! throw_validation_failure { } /// 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 )?) => {{ try_validation_pat!($e, _, $what, $where $(, $details )?) From eca147896f2582d1dc7735fd238956082ea92280 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Thu, 30 Apr 2020 09:47:58 +1000 Subject: [PATCH 12/29] Match kind in try_validation_pat!. Avoids having to repeat InterpErrorInfo { .. } --- src/librustc_mir/interpret/validity.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 80e39e83d47e8..d6f73fa2d0258 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -49,7 +49,7 @@ macro_rules! try_validation { /// as a kind of validation blacklist: /// /// ```rust -/// let v = try_validation_pat(some_fn(), Foo | Bar | Baz, "some failure", path); +/// 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. /// ``` @@ -59,7 +59,7 @@ macro_rules! try_validation_pat { Ok(x) => x, // 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($p) )|* if true => throw_validation_failure!($what, $where $(, $details)?), + $( Err(InterpErrorInfo { kind: $p, .. }) )|* if true => throw_validation_failure!($what, $where $(, $details)?), Err(e) => Err::(e)?, } }}; @@ -494,7 +494,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // that lets us re-use `ref_to_mplace`). let place = try_validation_pat!( self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?), - InterpErrorInfo { kind: err_ub!(InvalidUndefBytes(..)), ..}, + err_ub!(InvalidUndefBytes(..)), "uninitialized raw pointer", self.path ); From 9c898d65b8e83adf56576616d120d33945a28409 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Thu, 30 Apr 2020 09:54:26 +1000 Subject: [PATCH 13/29] Allow unreachable_patterns instead of using `if true` --- src/librustc_mir/interpret/validity.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index d6f73fa2d0258..262a01eab3ca6 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -59,7 +59,8 @@ macro_rules! try_validation_pat { Ok(x) => x, // 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(InterpErrorInfo { kind: $p, .. }) )|* => throw_validation_failure!($what, $where $(, $details)?), + #[allow(unreachable_patterns)] Err(e) => Err::(e)?, } }}; From 9459b3778009cf067b4ae0cae7c27de683b5ced5 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Thu, 30 Apr 2020 13:01:36 +1000 Subject: [PATCH 14/29] Fix comment to reflect error handling behaviour. --- src/librustc_mir/interpret/validity.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 262a01eab3ca6..b931ed61cdd2e 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -802,7 +802,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), } } From cb96d41fa1961974aff9405aa323779d6b3d6849 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Thu, 30 Apr 2020 15:22:40 +1000 Subject: [PATCH 15/29] Apply suggestions for try_validation_pat!. --- src/librustc_mir/interpret/validity.rs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index b931ed61cdd2e..5192dfaa4043d 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -25,14 +25,14 @@ use super::{ }; macro_rules! throw_validation_failure { - ($what:expr, $where:expr $(, $details: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 {}", $details).unwrap(); )? + $( write!(&mut msg, ", but expected {}", $expected).unwrap(); )? throw_ub!(ValidationFailure(msg)) }}; } @@ -40,8 +40,10 @@ macro_rules! throw_validation_failure { /// 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 )?) => {{ - try_validation_pat!($e, _, $what, $where $(, $details )?) + ($e:expr, $what:expr, $where:expr $(, $expected:expr )?) => {{ + try_validation_pat!($e, $where, { + _ => { $what } $( expected { $expected } )?, + }) }}; } /// Like try_validation, but will throw a validation error if any of the patterns in $p are @@ -54,12 +56,12 @@ macro_rules! try_validation { /// // unchanged. /// ``` macro_rules! try_validation_pat { - ($e:expr, $( $p:pat )|*, $what:expr, $where:expr $(, $details:expr )?) => {{ + ($e:expr, $where:expr, { $( $p:pat )|* => { $what:tt } $( expected { $expected:expr } )? $( , )?}) => {{ match $e { Ok(x) => x, // 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, .. }) )|* => throw_validation_failure!($what, $where $(, $details)?), + $( Err(InterpErrorInfo { kind: $p, .. }) )|* => throw_validation_failure!($what, $where $(, $expected)?), #[allow(unreachable_patterns)] Err(e) => Err::(e)?, } @@ -493,12 +495,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_pat!( - self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?), - err_ub!(InvalidUndefBytes(..)), - "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)?; } From 425a99f1eb233659403329fb4f117b1d39c7362c Mon Sep 17 00:00:00 2001 From: jumbatm Date: Fri, 1 May 2020 17:52:42 +1000 Subject: [PATCH 16/29] Update try_validation_pat! doc comment. --- src/librustc_mir/interpret/validity.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 5192dfaa4043d..c64458bd98944 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -50,11 +50,22 @@ macro_rules! try_validation { /// 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); +/// ``` +/// 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" }, +/// }); +/// ``` +/// macro_rules! try_validation_pat { ($e:expr, $where:expr, { $( $p:pat )|* => { $what:tt } $( expected { $expected:expr } )? $( , )?}) => {{ match $e { From 65c36f6e386cd3fad6515e66ddc4721328ae6ef9 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Fri, 1 May 2020 20:07:17 +1000 Subject: [PATCH 17/29] Wrap try_validation_pat! args in format_args! --- src/librustc_mir/interpret/validity.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index c64458bd98944..731f6e6aede37 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -42,7 +42,7 @@ macro_rules! throw_validation_failure { macro_rules! try_validation { ($e:expr, $what:expr, $where:expr $(, $expected:expr )?) => {{ try_validation_pat!($e, $where, { - _ => { $what } $( expected { $expected } )?, + _ => { "{}", $what } $( expected { $expected } )?, }) }}; } @@ -67,12 +67,12 @@ macro_rules! try_validation { /// ``` /// macro_rules! try_validation_pat { - ($e:expr, $where:expr, { $( $p:pat )|* => { $what:tt } $( expected { $expected:expr } )? $( , )?}) => {{ + ($e:expr, $where:expr, { $( $p:pat )|* => { $( $what_fmt:expr ),* } $( expected { $expected:expr } )? $( , )?}) => {{ match $e { Ok(x) => x, // 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, .. }) )|* => throw_validation_failure!($what, $where $(, $expected)?), + $( Err(InterpErrorInfo { kind: $p, .. }) )|* => throw_validation_failure!(format_args!($( $what_fmt ),*), $where $(, $expected)?), #[allow(unreachable_patterns)] Err(e) => Err::(e)?, } From f1d778fef1c77412580142c25cf7711b89444c81 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Fri, 1 May 2020 21:30:46 +1000 Subject: [PATCH 18/29] Also make expected param wrapped in format_args. --- src/librustc_mir/interpret/validity.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 731f6e6aede37..239e5c4fa4aa6 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -42,7 +42,7 @@ macro_rules! throw_validation_failure { macro_rules! try_validation { ($e:expr, $what:expr, $where:expr $(, $expected:expr )?) => {{ try_validation_pat!($e, $where, { - _ => { "{}", $what } $( expected { $expected } )?, + _ => { "{}", $what } $( expected { "{}", $expected } )?, }) }}; } @@ -67,12 +67,12 @@ macro_rules! try_validation { /// ``` /// macro_rules! try_validation_pat { - ($e:expr, $where:expr, { $( $p:pat )|* => { $( $what_fmt:expr ),* } $( expected { $expected:expr } )? $( , )?}) => {{ + ($e:expr, $where:expr, { $( $p:pat )|* => { $( $what_fmt:expr ),* } $( expected { $( $expected_fmt:expr ),* } )? $( , )?}) => {{ match $e { Ok(x) => x, // 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, .. }) )|* => throw_validation_failure!(format_args!($( $what_fmt ),*), $where $(, $expected)?), + $( Err(InterpErrorInfo { kind: $p, .. }) )|* => throw_validation_failure!(format_args!($( $what_fmt ),*), $where $(, format_args!($( $expected_fmt ),*))?), #[allow(unreachable_patterns)] Err(e) => Err::(e)?, } From 8175c4ceec9e19193e99f054f2b743f77a42a54f Mon Sep 17 00:00:00 2001 From: jumbatm Date: Fri, 1 May 2020 21:32:15 +1000 Subject: [PATCH 19/29] Expect at least one expr for p, what_fmt and expected_fmt. --- src/librustc_mir/interpret/validity.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 239e5c4fa4aa6..3395c19400a50 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -67,12 +67,12 @@ macro_rules! try_validation { /// ``` /// macro_rules! try_validation_pat { - ($e:expr, $where:expr, { $( $p:pat )|* => { $( $what_fmt:expr ),* } $( expected { $( $expected_fmt:expr ),* } )? $( , )?}) => {{ + ($e:expr, $where:expr, { $( $p:pat )|+ => { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )? $( , )?}) => {{ match $e { Ok(x) => x, // 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, .. }) )|* => throw_validation_failure!(format_args!($( $what_fmt ),*), $where $(, format_args!($( $expected_fmt ),*))?), + $( Err(InterpErrorInfo { kind: $p, .. }) )|+ => throw_validation_failure!(format_args!($( $what_fmt ),+), $where $(, format_args!($( $expected_fmt ),+))?), #[allow(unreachable_patterns)] Err(e) => Err::(e)?, } From 830473959adef21d6d9a9e13faadc0776b64e925 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Fri, 1 May 2020 21:45:55 +1000 Subject: [PATCH 20/29] Manually format macro to not go over text width. --- src/librustc_mir/interpret/validity.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 3395c19400a50..54da0ba9eedde 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -67,12 +67,18 @@ macro_rules! try_validation { /// ``` /// macro_rules! try_validation_pat { - ($e:expr, $where:expr, { $( $p:pat )|+ => { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )? $( , )?}) => {{ + ($e:expr, $where:expr, { $( $p:pat )|+ => + { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )? $( , )?}) => {{ match $e { Ok(x) => x, // 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, .. }) )|+ => throw_validation_failure!(format_args!($( $what_fmt ),+), $where $(, format_args!($( $expected_fmt ),+))?), + $( Err(InterpErrorInfo { kind: $p, .. }) )|+ => + throw_validation_failure!( + format_args!($( $what_fmt ),+), + $where + $(, format_args!($( $expected_fmt ),+))? + ), #[allow(unreachable_patterns)] Err(e) => Err::(e)?, } From bd18ad4fef9ca3d618521b8268183497b6104ff9 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Fri, 1 May 2020 21:49:42 +1000 Subject: [PATCH 21/29] Note that try_validation_pat can take a format str directly. --- src/librustc_mir/interpret/validity.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 54da0ba9eedde..fe584596f01b9 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -66,6 +66,15 @@ macro_rules! try_validation { /// }); /// ``` /// +/// 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 }, +/// }); +/// ``` +/// macro_rules! try_validation_pat { ($e:expr, $where:expr, { $( $p:pat )|+ => { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )? $( , )?}) => {{ From 60d62bee36074d24f4995287ba3b12adf1df0888 Mon Sep 17 00:00:00 2001 From: Donough Liu Date: Fri, 1 May 2020 06:36:06 +0800 Subject: [PATCH 22/29] Suggest deref when coercing `ty::Ref` to `ty::RawPtr` with arbitrary mutability --- src/librustc_typeck/check/coercion.rs | 15 ++- src/librustc_typeck/check/demand.rs | 125 ++++++++++++++++-------- src/librustc_typeck/check/mod.rs | 4 +- src/test/ui/issues/issue-32122-1.stderr | 2 +- src/test/ui/issues/issue-32122-2.stderr | 2 +- src/test/ui/issues/issue-71676-1.fixed | 54 ++++++++++ src/test/ui/issues/issue-71676-1.rs | 54 ++++++++++ src/test/ui/issues/issue-71676-1.stderr | 55 +++++++++++ src/test/ui/issues/issue-71676-2.rs | 43 ++++++++ src/test/ui/issues/issue-71676-2.stderr | 16 +++ 10 files changed, 323 insertions(+), 47 deletions(-) create mode 100644 src/test/ui/issues/issue-71676-1.fixed create mode 100644 src/test/ui/issues/issue-71676-1.rs create mode 100644 src/test/ui/issues/issue-71676-1.stderr create mode 100644 src/test/ui/issues/issue-71676-2.rs create mode 100644 src/test/ui/issues/issue-71676-2.stderr diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index e3b16eaaef2a2..c336ec1347949 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -74,7 +74,7 @@ use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; use smallvec::{smallvec, SmallVec}; use std::ops::Deref; -pub struct Coerce<'a, 'tcx> { +struct Coerce<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, cause: ObligationCause<'tcx>, use_lub: bool, @@ -126,7 +126,7 @@ fn success<'tcx>( } impl<'f, 'tcx> Coerce<'f, 'tcx> { - pub fn new( + fn new( fcx: &'f FnCtxt<'f, 'tcx>, cause: ObligationCause<'tcx>, allow_two_phase: AllowTwoPhase, @@ -134,7 +134,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { Coerce { fcx, cause, allow_two_phase, use_lub: false } } - pub fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> { + fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> { debug!("unify(a: {:?}, b: {:?}, use_lub: {})", a, b, self.use_lub); self.commit_if_ok(|_| { if self.use_lub { @@ -831,6 +831,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.probe(|_| coerce.coerce(source, target)).is_ok() } + pub fn deref_steps(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> Option { + let cause = self.cause(rustc_span::DUMMY_SP, ObligationCauseCode::ExprAssignable); + // We don't ever need two-phase here since we throw out the result of the coercion + let coerce = Coerce::new(self, cause, AllowTwoPhase::No); + coerce + .autoderef(rustc_span::DUMMY_SP, expr_ty) + .find_map(|(ty, steps)| coerce.unify(ty, target).ok().map(|_| steps)) + } + /// Given some expressions, their known unified type and another expression, /// tries to unify the types, potentially inserting coercions on any of the /// provided expressions and returns their LUB (aka "common supertype"). diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 65ef9cad87448..2c4ab40ccd443 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -1,4 +1,3 @@ -use crate::check::coercion::Coerce; use crate::check::FnCtxt; use rustc_infer::infer::InferOk; use rustc_trait_selection::infer::InferCtxtExt as _; @@ -9,7 +8,6 @@ use rustc_ast::util::parser::PREC_POSTFIX; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::{is_range_literal, Node}; -use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut}; use rustc_span::symbol::sym; @@ -376,7 +374,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &hir::Expr<'_>, checked_ty: Ty<'tcx>, expected: Ty<'tcx>, - ) -> Option<(Span, &'static str, String)> { + ) -> Option<(Span, &'static str, String, Applicability)> { let sm = self.sess().source_map(); let sp = expr.span; if sm.is_imported(sp) { @@ -395,16 +393,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `ExprKind::DropTemps` is semantically irrelevant for these suggestions. let expr = expr.peel_drop_temps(); + let remove_prefix = |s: String, prefix: &str| { + if s.starts_with(prefix) { Some(s[prefix.len()..].to_string()) } else { None } + }; + match (&expr.kind, &expected.kind, &checked_ty.kind) { (_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.kind, &check.kind) { (&ty::Str, &ty::Array(arr, _) | &ty::Slice(arr)) if arr == self.tcx.types.u8 => { if let hir::ExprKind::Lit(_) = expr.kind { if let Ok(src) = sm.span_to_snippet(sp) { - if src.starts_with("b\"") { + if let Some(src) = remove_prefix(src, "b\"") { return Some(( sp, "consider removing the leading `b`", - src[1..].to_string(), + format!("\"{}", src), + Applicability::MachineApplicable, )); } } @@ -413,11 +416,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (&ty::Array(arr, _) | &ty::Slice(arr), &ty::Str) if arr == self.tcx.types.u8 => { if let hir::ExprKind::Lit(_) = expr.kind { if let Ok(src) = sm.span_to_snippet(sp) { - if src.starts_with('"') { + if let Some(src) = remove_prefix(src, "\"") { return Some(( sp, "consider adding a leading `b`", - format!("b{}", src), + format!("b\"{}", src), + Applicability::MachineApplicable, )); } } @@ -470,7 +474,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sugg_expr = if needs_parens { format!("({})", src) } else { src }; if let Some(sugg) = self.can_use_as_ref(expr) { - return Some(sugg); + return Some(( + sugg.0, + sugg.1, + sugg.2, + Applicability::MachineApplicable, + )); } let field_name = if is_struct_pat_shorthand_field { format!("{}: ", sugg_expr) @@ -495,6 +504,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "consider dereferencing here to assign to the mutable \ borrowed piece of memory", format!("*{}", src), + Applicability::MachineApplicable, )); } } @@ -505,11 +515,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sp, "consider mutably borrowing here", format!("{}&mut {}", field_name, sugg_expr), + Applicability::MachineApplicable, ), hir::Mutability::Not => ( sp, "consider borrowing here", format!("{}&{}", field_name, sugg_expr), + Applicability::MachineApplicable, ), }); } @@ -526,51 +538,84 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We have `&T`, check if what was expected was `T`. If so, // we may want to suggest removing a `&`. if sm.is_imported(expr.span) { - if let Ok(code) = sm.span_to_snippet(sp) { - if code.starts_with('&') { + if let Ok(src) = sm.span_to_snippet(sp) { + if let Some(src) = remove_prefix(src, "&") { return Some(( sp, "consider removing the borrow", - code[1..].to_string(), + src, + Applicability::MachineApplicable, )); } } return None; } if let Ok(code) = sm.span_to_snippet(expr.span) { - return Some((sp, "consider removing the borrow", code)); + return Some(( + sp, + "consider removing the borrow", + code, + Applicability::MachineApplicable, + )); } } ( _, - &ty::RawPtr(TypeAndMut { ty: _, mutbl: hir::Mutability::Not }), - &ty::Ref(_, _, hir::Mutability::Not), + &ty::RawPtr(TypeAndMut { ty: ty_b, mutbl: mutbl_b }), + &ty::Ref(_, ty_a, mutbl_a), ) => { - let cause = self.cause(rustc_span::DUMMY_SP, ObligationCauseCode::ExprAssignable); - // We don't ever need two-phase here since we throw out the result of the coercion - let coerce = Coerce::new(self, cause, AllowTwoPhase::No); - - if let Some(steps) = - coerce.autoderef(sp, checked_ty).skip(1).find_map(|(referent_ty, steps)| { - coerce - .unify( - coerce.tcx.mk_ptr(ty::TypeAndMut { - mutbl: hir::Mutability::Not, - ty: referent_ty, - }), - expected, - ) - .ok() - .map(|_| steps) - }) - { - // The pointer type implements `Copy` trait so the suggestion is always valid. - if let Ok(code) = sm.span_to_snippet(sp) { - if code.starts_with('&') { - let derefs = "*".repeat(steps - 1); - let message = "consider dereferencing the reference"; - let suggestion = format!("&{}{}", derefs, code[1..].to_string()); - return Some((sp, message, suggestion)); + if let Some(steps) = self.deref_steps(ty_a, ty_b) { + // Only suggest valid if dereferencing needed. + if steps > 0 { + // The pointer type implements `Copy` trait so the suggestion is always valid. + if let Ok(src) = sm.span_to_snippet(sp) { + let derefs = "*".repeat(steps); + match mutbl_b { + hir::Mutability::Mut => match mutbl_a { + hir::Mutability::Mut => { + if let Some(src) = remove_prefix(src, "&mut ") { + return Some(( + sp, + "consider dereferencing", + format!("&mut {}{}", derefs, src), + Applicability::MachineApplicable, + )); + } + } + hir::Mutability::Not => { + if let Some(src) = remove_prefix(src, "&") { + return Some(( + sp, + "consider dereferencing", + format!("&mut {}{}", derefs, src), + Applicability::Unspecified, + )); + } + } + }, + hir::Mutability::Not => match mutbl_a { + hir::Mutability::Mut => { + if let Some(src) = remove_prefix(src, "&mut ") { + return Some(( + sp, + "consider dereferencing", + format!("&{}{}", derefs, src), + Applicability::MachineApplicable, + )); + } + } + hir::Mutability::Not => { + if let Some(src) = remove_prefix(src, "&") { + return Some(( + sp, + "consider dereferencing", + format!("&{}{}", derefs, src), + Applicability::MachineApplicable, + )); + } + } + }, + } } } } @@ -616,7 +661,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { format!("*{}", code) }; - return Some((sp, message, suggestion)); + return Some((sp, message, suggestion, Applicability::MachineApplicable)); } } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index adbab3d4cb620..68817d3fe0f16 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5036,8 +5036,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, found: Ty<'tcx>, ) { - if let Some((sp, msg, suggestion)) = self.check_ref(expr, found, expected) { - err.span_suggestion(sp, msg, suggestion, Applicability::MachineApplicable); + if let Some((sp, msg, suggestion, applicability)) = self.check_ref(expr, found, expected) { + err.span_suggestion(sp, msg, suggestion, applicability); } else if let (ty::FnDef(def_id, ..), true) = (&found.kind, self.suggest_fn_call(err, expr, expected, found)) { diff --git a/src/test/ui/issues/issue-32122-1.stderr b/src/test/ui/issues/issue-32122-1.stderr index 313de275c53ee..dfbd3223efc86 100644 --- a/src/test/ui/issues/issue-32122-1.stderr +++ b/src/test/ui/issues/issue-32122-1.stderr @@ -5,7 +5,7 @@ LL | let _: *const u8 = &a; | --------- ^^ | | | | | expected `u8`, found struct `Foo` - | | help: consider dereferencing the reference: `&*a` + | | help: consider dereferencing: `&*a` | expected due to this | = note: expected raw pointer `*const u8` diff --git a/src/test/ui/issues/issue-32122-2.stderr b/src/test/ui/issues/issue-32122-2.stderr index 959a49507e4f5..2e199e2a19f73 100644 --- a/src/test/ui/issues/issue-32122-2.stderr +++ b/src/test/ui/issues/issue-32122-2.stderr @@ -5,7 +5,7 @@ LL | let _: *const u8 = &a; | --------- ^^ | | | | | expected `u8`, found struct `Emm` - | | help: consider dereferencing the reference: `&***a` + | | help: consider dereferencing: `&***a` | expected due to this | = note: expected raw pointer `*const u8` diff --git a/src/test/ui/issues/issue-71676-1.fixed b/src/test/ui/issues/issue-71676-1.fixed new file mode 100644 index 0000000000000..d2be0db95fb8c --- /dev/null +++ b/src/test/ui/issues/issue-71676-1.fixed @@ -0,0 +1,54 @@ +// run-rustfix +use std::ops::Deref; +use std::ops::DerefMut; +struct Bar(u8); +struct Foo(Bar); +struct Emm(Foo); +impl Deref for Bar{ + type Target = u8; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Foo { + type Target = Bar; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Emm { + type Target = Foo; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl DerefMut for Bar{ + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl DerefMut for Foo { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl DerefMut for Emm { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +fn main() { + // Suggest dereference with arbitrary mutability + let a = Emm(Foo(Bar(0))); + let _: *const u8 = &***a; //~ ERROR mismatched types + + let mut a = Emm(Foo(Bar(0))); + let _: *mut u8 = &mut ***a; //~ ERROR mismatched types + + let a = Emm(Foo(Bar(0))); + let _: *const u8 = &***a; //~ ERROR mismatched types + + let mut a = Emm(Foo(Bar(0))); + let _: *mut u8 = &mut ***a; //~ ERROR mismatched types + +} diff --git a/src/test/ui/issues/issue-71676-1.rs b/src/test/ui/issues/issue-71676-1.rs new file mode 100644 index 0000000000000..c09ad6dabaa9a --- /dev/null +++ b/src/test/ui/issues/issue-71676-1.rs @@ -0,0 +1,54 @@ +// run-rustfix +use std::ops::Deref; +use std::ops::DerefMut; +struct Bar(u8); +struct Foo(Bar); +struct Emm(Foo); +impl Deref for Bar{ + type Target = u8; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Foo { + type Target = Bar; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Emm { + type Target = Foo; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl DerefMut for Bar{ + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl DerefMut for Foo { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl DerefMut for Emm { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +fn main() { + // Suggest dereference with arbitrary mutability + let a = Emm(Foo(Bar(0))); + let _: *const u8 = &a; //~ ERROR mismatched types + + let mut a = Emm(Foo(Bar(0))); + let _: *mut u8 = &a; //~ ERROR mismatched types + + let a = Emm(Foo(Bar(0))); + let _: *const u8 = &mut a; //~ ERROR mismatched types + + let mut a = Emm(Foo(Bar(0))); + let _: *mut u8 = &mut a; //~ ERROR mismatched types + +} diff --git a/src/test/ui/issues/issue-71676-1.stderr b/src/test/ui/issues/issue-71676-1.stderr new file mode 100644 index 0000000000000..bbabc2202dc84 --- /dev/null +++ b/src/test/ui/issues/issue-71676-1.stderr @@ -0,0 +1,55 @@ +error[E0308]: mismatched types + --> $DIR/issue-71676-1.rs:43:24 + | +LL | let _: *const u8 = &a; + | --------- ^^ + | | | + | | expected `u8`, found struct `Emm` + | | help: consider dereferencing: `&***a` + | expected due to this + | + = note: expected raw pointer `*const u8` + found reference `&Emm` + +error[E0308]: mismatched types + --> $DIR/issue-71676-1.rs:46:22 + | +LL | let _: *mut u8 = &a; + | ------- ^^ + | | | + | | types differ in mutability + | | help: consider dereferencing: `&mut ***a` + | expected due to this + | + = note: expected raw pointer `*mut u8` + found reference `&Emm` + +error[E0308]: mismatched types + --> $DIR/issue-71676-1.rs:49:24 + | +LL | let _: *const u8 = &mut a; + | --------- ^^^^^^ + | | | + | | expected `u8`, found struct `Emm` + | | help: consider dereferencing: `&***a` + | expected due to this + | + = note: expected raw pointer `*const u8` + found mutable reference `&mut Emm` + +error[E0308]: mismatched types + --> $DIR/issue-71676-1.rs:52:22 + | +LL | let _: *mut u8 = &mut a; + | ------- ^^^^^^ + | | | + | | expected `u8`, found struct `Emm` + | | help: consider dereferencing: `&mut ***a` + | expected due to this + | + = note: expected raw pointer `*mut u8` + found mutable reference `&mut Emm` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-71676-2.rs b/src/test/ui/issues/issue-71676-2.rs new file mode 100644 index 0000000000000..d11fce567ce51 --- /dev/null +++ b/src/test/ui/issues/issue-71676-2.rs @@ -0,0 +1,43 @@ +use std::ops::Deref; +use std::ops::DerefMut; +struct Bar(u8); +struct Foo(Bar); +struct Emm(Foo); +impl Deref for Bar{ + type Target = u8; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Foo { + type Target = Bar; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Emm { + type Target = Foo; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl DerefMut for Bar{ + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl DerefMut for Foo { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl DerefMut for Emm { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +fn main() { + // Should not suggest when a is immutable + let a = Emm(Foo(Bar(0))); + let _: *mut u8 = &a; //~ ERROR mismatched types +} diff --git a/src/test/ui/issues/issue-71676-2.stderr b/src/test/ui/issues/issue-71676-2.stderr new file mode 100644 index 0000000000000..273ae9cb4dba8 --- /dev/null +++ b/src/test/ui/issues/issue-71676-2.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/issue-71676-2.rs:42:22 + | +LL | let _: *mut u8 = &a; + | ------- ^^ + | | | + | | types differ in mutability + | | help: consider dereferencing: `&mut ***a` + | expected due to this + | + = note: expected raw pointer `*mut u8` + found reference `&Emm` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 80d04cc1ba610d796c84427622ce17eb2ca9c771 Mon Sep 17 00:00:00 2001 From: Donough Liu Date: Fri, 1 May 2020 21:56:10 +0800 Subject: [PATCH 23/29] Add comments for deref_steps() --- src/librustc_typeck/check/coercion.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index c336ec1347949..7437c87a25763 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -831,6 +831,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.probe(|_| coerce.coerce(source, target)).is_ok() } + /// Given a type and a target type, this function will calculate and return + /// how many dereference steps needed to achieve `expr_ty <: target`. If + /// it's not possible, return `None`. pub fn deref_steps(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> Option { let cause = self.cause(rustc_span::DUMMY_SP, ObligationCauseCode::ExprAssignable); // We don't ever need two-phase here since we throw out the result of the coercion From 089d4bbfd79c4ae2e735154cff4448ecd5fc4afc Mon Sep 17 00:00:00 2001 From: Donough Liu Date: Fri, 1 May 2020 21:57:19 +0800 Subject: [PATCH 24/29] Suggestion for immutable reference -> mutable pointer should be emitted as `Applicability::Unspecified` --- src/test/ui/issues/issue-71676-2.rs | 1 - src/test/ui/issues/issue-71676-2.stderr | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/ui/issues/issue-71676-2.rs b/src/test/ui/issues/issue-71676-2.rs index d11fce567ce51..f3183899dc523 100644 --- a/src/test/ui/issues/issue-71676-2.rs +++ b/src/test/ui/issues/issue-71676-2.rs @@ -37,7 +37,6 @@ impl DerefMut for Emm { } } fn main() { - // Should not suggest when a is immutable let a = Emm(Foo(Bar(0))); let _: *mut u8 = &a; //~ ERROR mismatched types } diff --git a/src/test/ui/issues/issue-71676-2.stderr b/src/test/ui/issues/issue-71676-2.stderr index 273ae9cb4dba8..ebdd345809af5 100644 --- a/src/test/ui/issues/issue-71676-2.stderr +++ b/src/test/ui/issues/issue-71676-2.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-71676-2.rs:42:22 + --> $DIR/issue-71676-2.rs:41:22 | LL | let _: *mut u8 = &a; | ------- ^^ From 9a212c1625514fdc5588cdfe6f2d58290e73248d Mon Sep 17 00:00:00 2001 From: Donough Liu Date: Fri, 1 May 2020 21:59:09 +0800 Subject: [PATCH 25/29] Replace convenient function `remove_prefix()` with `replace_prefix()` --- src/librustc_typeck/check/demand.rs | 109 ++++++++++++++----------- src/test/ui/issues/issue-71676-1.fixed | 1 - src/test/ui/issues/issue-71676-1.rs | 1 - 3 files changed, 60 insertions(+), 51 deletions(-) diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 2c4ab40ccd443..9e14efb67a94c 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -353,6 +353,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } + fn replace_prefix(&self, s: A, old: B, new: C) -> Option + where + A: AsRef, + B: AsRef, + C: AsRef, + { + let s = s.as_ref(); + let old = old.as_ref(); + if s.starts_with(old) { Some(new.as_ref().to_owned() + &s[old.len()..]) } else { None } + } + /// This function is used to determine potential "simple" improvements or users' errors and /// provide them useful help. For example: /// @@ -393,20 +404,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `ExprKind::DropTemps` is semantically irrelevant for these suggestions. let expr = expr.peel_drop_temps(); - let remove_prefix = |s: String, prefix: &str| { - if s.starts_with(prefix) { Some(s[prefix.len()..].to_string()) } else { None } - }; - match (&expr.kind, &expected.kind, &checked_ty.kind) { (_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.kind, &check.kind) { (&ty::Str, &ty::Array(arr, _) | &ty::Slice(arr)) if arr == self.tcx.types.u8 => { if let hir::ExprKind::Lit(_) = expr.kind { if let Ok(src) = sm.span_to_snippet(sp) { - if let Some(src) = remove_prefix(src, "b\"") { + if let Some(src) = self.replace_prefix(src, "b\"", "\"") { return Some(( sp, "consider removing the leading `b`", - format!("\"{}", src), + src, Applicability::MachineApplicable, )); } @@ -416,11 +423,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (&ty::Array(arr, _) | &ty::Slice(arr), &ty::Str) if arr == self.tcx.types.u8 => { if let hir::ExprKind::Lit(_) = expr.kind { if let Ok(src) = sm.span_to_snippet(sp) { - if let Some(src) = remove_prefix(src, "\"") { + if let Some(src) = self.replace_prefix(src, "\"", "b\"") { return Some(( sp, "consider adding a leading `b`", - format!("b\"{}", src), + src, Applicability::MachineApplicable, )); } @@ -539,7 +546,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // we may want to suggest removing a `&`. if sm.is_imported(expr.span) { if let Ok(src) = sm.span_to_snippet(sp) { - if let Some(src) = remove_prefix(src, "&") { + if let Some(src) = self.replace_prefix(src, "&", "") { return Some(( sp, "consider removing the borrow", @@ -569,52 +576,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if steps > 0 { // The pointer type implements `Copy` trait so the suggestion is always valid. if let Ok(src) = sm.span_to_snippet(sp) { - let derefs = "*".repeat(steps); - match mutbl_b { - hir::Mutability::Mut => match mutbl_a { - hir::Mutability::Mut => { - if let Some(src) = remove_prefix(src, "&mut ") { - return Some(( - sp, - "consider dereferencing", - format!("&mut {}{}", derefs, src), - Applicability::MachineApplicable, - )); + let derefs = &"*".repeat(steps); + if let Some((src, applicability)) = match mutbl_b { + hir::Mutability::Mut => { + let new_prefix = "&mut ".to_owned() + derefs; + match mutbl_a { + hir::Mutability::Mut => { + if let Some(s) = + self.replace_prefix(src, "&mut ", new_prefix) + { + Some((s, Applicability::MachineApplicable)) + } else { + None + } } - } - hir::Mutability::Not => { - if let Some(src) = remove_prefix(src, "&") { - return Some(( - sp, - "consider dereferencing", - format!("&mut {}{}", derefs, src), - Applicability::Unspecified, - )); + hir::Mutability::Not => { + if let Some(s) = + self.replace_prefix(src, "&", new_prefix) + { + Some((s, Applicability::Unspecified)) + } else { + None + } } } - }, - hir::Mutability::Not => match mutbl_a { - hir::Mutability::Mut => { - if let Some(src) = remove_prefix(src, "&mut ") { - return Some(( - sp, - "consider dereferencing", - format!("&{}{}", derefs, src), - Applicability::MachineApplicable, - )); + } + hir::Mutability::Not => { + let new_prefix = "&".to_owned() + derefs; + match mutbl_a { + hir::Mutability::Mut => { + if let Some(s) = + self.replace_prefix(src, "&mut ", new_prefix) + { + Some((s, Applicability::MachineApplicable)) + } else { + None + } } - } - hir::Mutability::Not => { - if let Some(src) = remove_prefix(src, "&") { - return Some(( - sp, - "consider dereferencing", - format!("&{}{}", derefs, src), - Applicability::MachineApplicable, - )); + hir::Mutability::Not => { + if let Some(s) = + self.replace_prefix(src, "&", new_prefix) + { + Some((s, Applicability::MachineApplicable)) + } else { + None + } } } - }, + } + } { + return Some((sp, "consider dereferencing", src, applicability)); } } } diff --git a/src/test/ui/issues/issue-71676-1.fixed b/src/test/ui/issues/issue-71676-1.fixed index d2be0db95fb8c..cbc0e8c061b82 100644 --- a/src/test/ui/issues/issue-71676-1.fixed +++ b/src/test/ui/issues/issue-71676-1.fixed @@ -50,5 +50,4 @@ fn main() { let mut a = Emm(Foo(Bar(0))); let _: *mut u8 = &mut ***a; //~ ERROR mismatched types - } diff --git a/src/test/ui/issues/issue-71676-1.rs b/src/test/ui/issues/issue-71676-1.rs index c09ad6dabaa9a..6e87c7174c633 100644 --- a/src/test/ui/issues/issue-71676-1.rs +++ b/src/test/ui/issues/issue-71676-1.rs @@ -50,5 +50,4 @@ fn main() { let mut a = Emm(Foo(Bar(0))); let _: *mut u8 = &mut a; //~ ERROR mismatched types - } From e4ee172ab05b03bf71e0d89e0042a89ff26a3c29 Mon Sep 17 00:00:00 2001 From: unexge Date: Sat, 2 May 2020 21:14:08 +0300 Subject: [PATCH 26/29] Add long error explanation for E0539 --- src/librustc_error_codes/error_codes.rs | 2 +- src/librustc_error_codes/error_codes/E0539.md | 42 +++++++++++++++++++ .../stability-attribute-sanity.stderr | 3 +- 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 src/librustc_error_codes/error_codes/E0539.md diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index bf4a6c52ab858..e01412bc21cfd 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -281,6 +281,7 @@ E0535: include_str!("./error_codes/E0535.md"), E0536: include_str!("./error_codes/E0536.md"), E0537: include_str!("./error_codes/E0537.md"), E0538: include_str!("./error_codes/E0538.md"), +E0539: include_str!("./error_codes/E0539.md"), E0541: include_str!("./error_codes/E0541.md"), E0550: include_str!("./error_codes/E0550.md"), E0551: include_str!("./error_codes/E0551.md"), @@ -570,7 +571,6 @@ E0753: include_str!("./error_codes/E0753.md"), E0521, // borrowed data escapes outside of closure E0523, // E0526, // shuffle indices are not constant - E0539, // incorrect meta item E0540, // multiple rustc_deprecated attributes E0542, // missing 'since' E0543, // missing 'reason' diff --git a/src/librustc_error_codes/error_codes/E0539.md b/src/librustc_error_codes/error_codes/E0539.md new file mode 100644 index 0000000000000..69555453514fe --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0539.md @@ -0,0 +1,42 @@ +An invalid meta-item was used inside an attribute. + +Erroneous code example: + +```compile_fail,E0539 +#[rustc_deprecated(reason)] // error! +#[unstable(feature = "deprecated_fn", issue = "123")] +fn deprecated() {} + +#[unstable(feature = "unstable_struct", issue)] // error! +struct Unstable; + +#[rustc_const_unstable(feature)] // error! +const fn unstable_fn() {} + +#[stable(feature = "stable_struct", since)] // error! +struct Stable; + +#[rustc_const_stable(feature)] // error! +const fn stable_fn() {} +``` + +Meta items are the key-value pairs inside of an attribute. +To fix these issues you need to give required key-value pairs. + +``` +#[rustc_deprecated(since = "1.39.0", reason = "reason")] // ok! +#[unstable(feature = "deprecated_fn", issue = "123")] +fn deprecated() {} + +#[unstable(feature = "unstable_struct", issue = "123")] // ok! +struct Unstable; + +#[rustc_const_unstable(feature = "unstable_fn", issue = "124")] // ok! +const fn unstable_fn() {} + +#[stable(feature = "stable_struct", since = "1.39.0")] // ok! +struct Stable; + +#[rustc_const_stable(feature = "stable_fn", since = "1.39.0")] // ok! +const fn stable_fn() {} +``` diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity.stderr b/src/test/ui/stability-attribute/stability-attribute-sanity.stderr index d0ca170503796..3c5da3f144035 100644 --- a/src/test/ui/stability-attribute/stability-attribute-sanity.stderr +++ b/src/test/ui/stability-attribute/stability-attribute-sanity.stderr @@ -108,4 +108,5 @@ LL | fn deprecated_without_unstable_or_stable() { } error: aborting due to 18 previous errors -For more information about this error, try `rustc --explain E0541`. +Some errors have detailed explanations: E0539, E0541. +For more information about an error, try `rustc --explain E0539`. From 95365672108a76871583dea6fc1fe1b523a47ab0 Mon Sep 17 00:00:00 2001 From: unexge Date: Sat, 2 May 2020 23:10:34 +0300 Subject: [PATCH 27/29] Add `#![feature(staged_api)]` attribute to E0539 error examples --- src/librustc_error_codes/error_codes/E0539.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustc_error_codes/error_codes/E0539.md b/src/librustc_error_codes/error_codes/E0539.md index 69555453514fe..a9224c4182190 100644 --- a/src/librustc_error_codes/error_codes/E0539.md +++ b/src/librustc_error_codes/error_codes/E0539.md @@ -3,6 +3,8 @@ An invalid meta-item was used inside an attribute. Erroneous code example: ```compile_fail,E0539 +#![feature(staged_api)] + #[rustc_deprecated(reason)] // error! #[unstable(feature = "deprecated_fn", issue = "123")] fn deprecated() {} @@ -24,6 +26,8 @@ Meta items are the key-value pairs inside of an attribute. To fix these issues you need to give required key-value pairs. ``` +#![feature(staged_api)] + #[rustc_deprecated(since = "1.39.0", reason = "reason")] // ok! #[unstable(feature = "deprecated_fn", issue = "123")] fn deprecated() {} From ef813ca95a674a19f15ce53ce432d2fb185d7fe2 Mon Sep 17 00:00:00 2001 From: unexge Date: Sun, 3 May 2020 00:25:45 +0300 Subject: [PATCH 28/29] Add stability attribute to E0539 error examples --- src/librustc_error_codes/error_codes/E0539.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc_error_codes/error_codes/E0539.md b/src/librustc_error_codes/error_codes/E0539.md index a9224c4182190..df2d7d910bb36 100644 --- a/src/librustc_error_codes/error_codes/E0539.md +++ b/src/librustc_error_codes/error_codes/E0539.md @@ -4,6 +4,7 @@ Erroneous code example: ```compile_fail,E0539 #![feature(staged_api)] +#![stable(since = "1.0.0", feature = "test")] #[rustc_deprecated(reason)] // error! #[unstable(feature = "deprecated_fn", issue = "123")] @@ -27,6 +28,7 @@ To fix these issues you need to give required key-value pairs. ``` #![feature(staged_api)] +#![stable(since = "1.0.0", feature = "test")] #[rustc_deprecated(since = "1.39.0", reason = "reason")] // ok! #[unstable(feature = "deprecated_fn", issue = "123")] From 4a79424b748338bd9635f0115c025942af2d5c3d Mon Sep 17 00:00:00 2001 From: ThinkChaos Date: Sun, 3 May 2020 12:52:23 +0200 Subject: [PATCH 29/29] Mention `RefCell::take` can panic in docs --- src/libcore/cell.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 05c9c97a6126e..0f2665eba6f22 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -1026,6 +1026,10 @@ impl RefCell { impl RefCell { /// Takes the wrapped value, leaving `Default::default()` in its place. /// + /// # Panics + /// + /// Panics if the value is currently borrowed. + /// /// # Examples /// /// ```