From 8b8cce16bfb74bcb06250ed3b9b3dc8c97e1ee4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 9 Jan 2023 04:43:18 +0000 Subject: [PATCH] Use the root trait predicate to determine whether to remove references Fix #84837. --- .../src/traits/error_reporting/suggestions.rs | 8 ++++ ...ypeck-default-trait-impl-precedence.stderr | 6 ++- tests/ui/not-panic/not-panic-safe-4.stderr | 10 +++++ .../suggestions/suggest-remove-refs-5.fixed | 8 ++++ tests/ui/suggestions/suggest-remove-refs-5.rs | 8 ++++ .../suggestions/suggest-remove-refs-5.stderr | 37 +++++++++++++++++++ 6 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 tests/ui/suggestions/suggest-remove-refs-5.fixed create mode 100644 tests/ui/suggestions/suggest-remove-refs-5.rs create mode 100644 tests/ui/suggestions/suggest-remove-refs-5.stderr diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 7e900fe0034..678e7b87829 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1359,6 +1359,14 @@ fn suggest_remove_reference( trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> bool { let mut span = obligation.cause.span; + let mut trait_pred = trait_pred; + let mut code = obligation.cause.code(); + while let Some((c, Some(parent_trait_pred))) = code.parent() { + // We want the root obligation, in order to detect properly handle + // `for _ in &mut &mut vec![] {}`. + code = c; + trait_pred = parent_trait_pred; + } while span.desugaring_kind().is_some() { // Remove all the hir desugaring contexts while maintaining the macro contexts. span.remove_mark(); diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr index ce7095664c1..32256ed69a7 100644 --- a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr +++ b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr @@ -4,7 +4,6 @@ error[E0277]: the trait bound `u32: Signed` is not satisfied LL | is_defaulted::<&'static u32>(); | ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32` | - = help: the trait `Signed` is implemented for `i32` note: required for `&'static u32` to implement `Defaulted` --> $DIR/typeck-default-trait-impl-precedence.rs:10:19 | @@ -15,6 +14,11 @@ note: required by a bound in `is_defaulted` | LL | fn is_defaulted() { } | ^^^^^^^^^ required by this bound in `is_defaulted` +help: consider removing the leading `&`-reference + | +LL - is_defaulted::<&'static u32>(); +LL + is_defaulted::(); + | error: aborting due to previous error diff --git a/tests/ui/not-panic/not-panic-safe-4.stderr b/tests/ui/not-panic/not-panic-safe-4.stderr index fc1c594d0d4..9428c125651 100644 --- a/tests/ui/not-panic/not-panic-safe-4.stderr +++ b/tests/ui/not-panic/not-panic-safe-4.stderr @@ -12,6 +12,11 @@ note: required by a bound in `assert` | LL | fn assert() {} | ^^^^^^^^^^ required by this bound in `assert` +help: consider removing the leading `&`-reference + | +LL - assert::<&RefCell>(); +LL + assert::>(); + | error[E0277]: the type `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> $DIR/not-panic-safe-4.rs:9:14 @@ -28,6 +33,11 @@ note: required by a bound in `assert` | LL | fn assert() {} | ^^^^^^^^^^ required by this bound in `assert` +help: consider removing the leading `&`-reference + | +LL - assert::<&RefCell>(); +LL + assert::>(); + | error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/suggest-remove-refs-5.fixed b/tests/ui/suggestions/suggest-remove-refs-5.fixed new file mode 100644 index 00000000000..9f59f9c199a --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-refs-5.fixed @@ -0,0 +1,8 @@ +// run-rustfix +fn main() { + let v = &mut Vec::::new(); + for _ in v {} //~ ERROR E0277 + + let v = &mut [1u8]; + for _ in v {} //~ ERROR E0277 +} diff --git a/tests/ui/suggestions/suggest-remove-refs-5.rs b/tests/ui/suggestions/suggest-remove-refs-5.rs new file mode 100644 index 00000000000..d56aa0c9ca4 --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-refs-5.rs @@ -0,0 +1,8 @@ +// run-rustfix +fn main() { + let v = &mut &mut Vec::::new(); + for _ in &mut &mut v {} //~ ERROR E0277 + + let v = &mut &mut [1u8]; + for _ in &mut v {} //~ ERROR E0277 +} diff --git a/tests/ui/suggestions/suggest-remove-refs-5.stderr b/tests/ui/suggestions/suggest-remove-refs-5.stderr new file mode 100644 index 00000000000..7de84d6122b --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-refs-5.stderr @@ -0,0 +1,37 @@ +error[E0277]: `Vec` is not an iterator + --> $DIR/suggest-remove-refs-5.rs:4:14 + | +LL | for _ in &mut &mut v {} + | ^^^^^^^^^^^ `Vec` is not an iterator; try calling `.into_iter()` or `.iter()` + | + = help: the trait `Iterator` is not implemented for `Vec` + = note: required for `&mut Vec` to implement `Iterator` + = note: 3 redundant requirements hidden + = note: required for `&mut &mut &mut &mut Vec` to implement `Iterator` + = note: required for `&mut &mut &mut &mut Vec` to implement `IntoIterator` +help: consider removing 3 leading `&`-references + | +LL ~ let v = &mut Vec::::new(); +LL ~ for _ in v {} + | + +error[E0277]: `[u8; 1]` is not an iterator + --> $DIR/suggest-remove-refs-5.rs:7:14 + | +LL | for _ in &mut v {} + | ^^^^^^ `[u8; 1]` is not an iterator; try calling `.into_iter()` or `.iter()` + | + = help: the trait `Iterator` is not implemented for `[u8; 1]` + = note: required for `&mut [u8; 1]` to implement `Iterator` + = note: 2 redundant requirements hidden + = note: required for `&mut &mut &mut [u8; 1]` to implement `Iterator` + = note: required for `&mut &mut &mut [u8; 1]` to implement `IntoIterator` +help: consider removing 2 leading `&`-references + | +LL ~ let v = &mut [1u8]; +LL ~ for _ in v {} + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`.