]> git.lizzy.rs Git - rust.git/commitdiff
Account for type params
authorEsteban Küber <esteban@kuber.com.ar>
Mon, 2 Jan 2023 03:35:53 +0000 (19:35 -0800)
committerEsteban Küber <esteban@kuber.com.ar>
Wed, 11 Jan 2023 21:38:56 +0000 (21:38 +0000)
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
tests/ui/kindck/kindck-copy.stderr
tests/ui/not-panic/not-panic-safe.rs
tests/ui/not-panic/not-panic-safe.stderr

index 553144078ee4ddd04ead9d1d2853d694ff160273..bcc8200480497732b3e6afa63ab66fce033e4b38 100644 (file)
@@ -1363,19 +1363,70 @@ fn suggest_remove_reference(
             // Remove all the hir desugaring contexts while maintaining the macro contexts.
             span.remove_mark();
         }
-        let mut suggested = false;
-
-        let mut expr_finder = super::FindExprBySpan { span, result: None };
+        let mut expr_finder = super::FindExprBySpan::new(span);
         let Some(hir::Node::Expr(body)) = self.tcx.hir().find(obligation.cause.body_id) else {
             return false;
         };
         expr_finder.visit_expr(&body);
+        let mut maybe_suggest = |suggested_ty, count, suggestions| {
+            // Remapping bound vars here
+            let trait_pred_and_suggested_ty =
+                trait_pred.map_bound(|trait_pred| (trait_pred, suggested_ty));
+
+            let new_obligation = self.mk_trait_obligation_with_new_self_ty(
+                obligation.param_env,
+                trait_pred_and_suggested_ty,
+            );
+
+            if self.predicate_may_hold(&new_obligation) {
+                let msg = if count == 1 {
+                    "consider removing the leading `&`-reference".to_string()
+                } else {
+                    format!("consider removing {count} leading `&`-references")
+                };
+
+                err.multipart_suggestion_verbose(
+                    &msg,
+                    suggestions,
+                    Applicability::MachineApplicable,
+                );
+                true
+            } else {
+                false
+            }
+        };
+
+        // Maybe suggest removal of borrows from types in type parameters, like in
+        // `src/test/ui/not-panic/not-panic-safe.rs`.
         let mut count = 0;
         let mut suggestions = vec![];
-        let Some(mut expr) = expr_finder.result else { return false; };
         // Skipping binder here, remapping below
         let mut suggested_ty = trait_pred.self_ty().skip_binder();
+        if let Some(mut hir_ty) = expr_finder.ty_result {
+            while let hir::TyKind::Ref(_, mut_ty) = &hir_ty.kind {
+                count += 1;
+                let span = hir_ty.span.until(mut_ty.ty.span);
+                suggestions.push((span, String::new()));
+
+                let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else {
+                    break;
+                };
+                suggested_ty = *inner_ty;
+
+                hir_ty = mut_ty.ty;
+
+                if maybe_suggest(suggested_ty, count, suggestions.clone()) {
+                    return true;
+                }
+            }
+        }
 
+        // Maybe suggest removal of borrows from expressions, like in `for i in &&&foo {}`.
+        let Some(mut expr) = expr_finder.result else { return false; };
+        let mut count = 0;
+        let mut suggestions = vec![];
+        // Skipping binder here, remapping below
+        let mut suggested_ty = trait_pred.self_ty().skip_binder();
         'outer: loop {
             while let hir::ExprKind::AddrOf(_, _, borrowed) = expr.kind {
                 count += 1;
@@ -1387,35 +1438,14 @@ fn suggest_remove_reference(
                 suggestions.push((span, String::new()));
 
                 let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else {
-                    break;
+                    break 'outer;
                 };
                 suggested_ty = *inner_ty;
 
                 expr = borrowed;
 
-                // Remapping bound vars here
-                let trait_pred_and_suggested_ty =
-                    trait_pred.map_bound(|trait_pred| (trait_pred, suggested_ty));
-
-                let new_obligation = self.mk_trait_obligation_with_new_self_ty(
-                    obligation.param_env,
-                    trait_pred_and_suggested_ty,
-                );
-
-                if self.predicate_may_hold(&new_obligation) {
-                    let msg = if count == 1 {
-                        "consider removing the leading `&`-reference".to_string()
-                    } else {
-                        format!("consider removing {count} leading `&`-references")
-                    };
-
-                    err.multipart_suggestion_verbose(
-                        &msg,
-                        suggestions,
-                        Applicability::MachineApplicable,
-                    );
-                    suggested = true;
-                    break 'outer;
+                if maybe_suggest(suggested_ty, count, suggestions.clone()) {
+                    return true;
                 }
             }
             if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
@@ -1431,7 +1461,7 @@ fn suggest_remove_reference(
                 break 'outer;
             }
         }
-        suggested
+        false
     }
 
     fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic) {
index 9af89159a8cfcec0f98cf91bcbbff4f358b7e34d..aee2aa98a60c20a5e75257313d5e2e35e67089e1 100644 (file)
@@ -4,12 +4,16 @@ error[E0277]: the trait bound `&'static mut isize: Copy` is not satisfied
 LL |     assert_copy::<&'static mut isize>();
    |                   ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'static mut isize`
    |
-   = help: the trait `Copy` is implemented for `isize`
 note: required by a bound in `assert_copy`
   --> $DIR/kindck-copy.rs:5:18
    |
 LL | fn assert_copy<T:Copy>() { }
    |                  ^^^^ required by this bound in `assert_copy`
+help: consider removing the leading `&`-reference
+   |
+LL -     assert_copy::<&'static mut isize>();
+LL +     assert_copy::<isize>();
+   |
 
 error[E0277]: the trait bound `&'a mut isize: Copy` is not satisfied
   --> $DIR/kindck-copy.rs:28:19
@@ -17,12 +21,16 @@ error[E0277]: the trait bound `&'a mut isize: Copy` is not satisfied
 LL |     assert_copy::<&'a mut isize>();
    |                   ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'a mut isize`
    |
-   = help: the trait `Copy` is implemented for `isize`
 note: required by a bound in `assert_copy`
   --> $DIR/kindck-copy.rs:5:18
    |
 LL | fn assert_copy<T:Copy>() { }
    |                  ^^^^ required by this bound in `assert_copy`
+help: consider removing the leading `&`-reference
+   |
+LL -     assert_copy::<&'a mut isize>();
+LL +     assert_copy::<isize>();
+   |
 
 error[E0277]: the trait bound `Box<isize>: Copy` is not satisfied
   --> $DIR/kindck-copy.rs:31:19
index 4165c5dc13aaae07bdc05a6ed1c4cd75d78d56df..1b3c6482ce94fab0607258c3e24d96aa8caf48dc 100644 (file)
@@ -5,6 +5,6 @@
 fn assert<T: UnwindSafe + ?Sized>() {}
 
 fn main() {
-    assert::<&mut i32>();
-    //~^ ERROR the type `&mut i32` may not be safely transferred across an unwind boundary
+    assert::<&mut &mut &i32>();
+    //~^ ERROR the type `&mut &mut &i32` may not be safely transferred across an unwind boundary
 }
index 013c5ee704458c8d9435d670debb2c191e892551..37a6aee390669c70536d0791887bf53921bc4f55 100644 (file)
@@ -1,16 +1,21 @@
-error[E0277]: the type `&mut i32` may not be safely transferred across an unwind boundary
+error[E0277]: the type `&mut &mut &i32` may not be safely transferred across an unwind boundary
   --> $DIR/not-panic-safe.rs:8:14
    |
-LL |     assert::<&mut i32>();
-   |              ^^^^^^^^ `&mut i32` may not be safely transferred across an unwind boundary
+LL |     assert::<&mut &mut &i32>();
+   |              ^^^^^^^^^^^^^^ `&mut &mut &i32` may not be safely transferred across an unwind boundary
    |
-   = help: the trait `UnwindSafe` is not implemented for `&mut i32`
-   = note: `UnwindSafe` is implemented for `&i32`, but not for `&mut i32`
+   = help: the trait `UnwindSafe` is not implemented for `&mut &mut &i32`
+   = note: `UnwindSafe` is implemented for `&&mut &i32`, but not for `&mut &mut &i32`
 note: required by a bound in `assert`
   --> $DIR/not-panic-safe.rs:5:14
    |
 LL | fn assert<T: UnwindSafe + ?Sized>() {}
    |              ^^^^^^^^^^ required by this bound in `assert`
+help: consider removing 2 leading `&`-references
+   |
+LL -     assert::<&mut &mut &i32>();
+LL +     assert::<&i32>();
+   |
 
 error: aborting due to previous error