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 17206b21af0..dafc424f1b4 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3429,26 +3429,37 @@ fn hint_missing_borrow<'tcx>( (ty, refs) } + let mut to_borrow = Vec::new(); + let mut remove_borrow = Vec::new(); + for ((found_arg, expected_arg), arg_span) in found_args.zip(expected_args).zip(arg_spans) { let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg); let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg); if found_ty == expected_ty { - let hint = if found_refs < expected_refs { - "consider borrowing the argument" - } else if found_refs == expected_refs { - continue; - } else { - "do not borrow the argument" - }; - err.span_suggestion_verbose( - arg_span, - hint, - expected_arg.to_string(), - Applicability::MaybeIncorrect, - ); + if found_refs < expected_refs { + to_borrow.push((arg_span, expected_arg.to_string())); + } else if found_refs > expected_refs { + remove_borrow.push((arg_span, expected_arg.to_string())); + } } } + + if !to_borrow.is_empty() { + err.multipart_suggestion( + "consider borrowing the argument", + to_borrow, + Applicability::MaybeIncorrect, + ); + } + + if !remove_borrow.is_empty() { + err.multipart_suggestion( + "do not borrow the argument", + remove_borrow, + Applicability::MaybeIncorrect, + ); + } } /// Collect all the returned expressions within the input expression. diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.stderr b/src/test/ui/anonymous-higher-ranked-lifetime.stderr index 2e5f7a51b6e..afb7f8fea92 100644 --- a/src/test/ui/anonymous-higher-ranked-lifetime.stderr +++ b/src/test/ui/anonymous-higher-ranked-lifetime.stderr @@ -15,12 +15,8 @@ LL | fn f1(_: F) where F: Fn(&(), &()) {} | ^^^^^^^^^^^^ required by this bound in `f1` help: consider borrowing the argument | -LL | f1(|_: &(), _: ()| {}); - | ~~~ -help: consider borrowing the argument - | -LL | f1(|_: (), _: &()| {}); - | ~~~ +LL | f1(|_: &(), _: &()| {}); + | ~~~ ~~~ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:3:5 @@ -39,12 +35,8 @@ LL | fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f2` help: consider borrowing the argument | -LL | f2(|_: &'a (), _: ()| {}); - | ~~~~~~ -help: consider borrowing the argument - | -LL | f2(|_: (), _: &()| {}); - | ~~~ +LL | f2(|_: &'a (), _: &()| {}); + | ~~~~~~ ~~~ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5 @@ -63,12 +55,8 @@ LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {} | ^^^^^^^^^^^^^^^ required by this bound in `f3` help: consider borrowing the argument | -LL | f3(|_: &(), _: ()| {}); - | ~~~ -help: consider borrowing the argument - | -LL | f3(|_: (), _: &()| {}); - | ~~~ +LL | f3(|_: &(), _: &()| {}); + | ~~~ ~~~ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:5:5 @@ -87,12 +75,8 @@ LL | fn f4(_: F) where F: for<'r> Fn(&(), &'r ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f4` help: consider borrowing the argument | -LL | f4(|_: &(), _: ()| {}); - | ~~~ -help: consider borrowing the argument - | -LL | f4(|_: (), _: &'r ()| {}); - | ~~~~~~ +LL | f4(|_: &(), _: &'r ()| {}); + | ~~~ ~~~~~~ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5 @@ -111,19 +95,17 @@ LL | fn f5(_: F) where F: for<'r> Fn(&'r (), &'r ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f5` help: consider borrowing the argument | -LL | f5(|_: &'r (), _: ()| {}); - | ~~~~~~ -help: consider borrowing the argument - | -LL | f5(|_: (), _: &'r ()| {}); - | ~~~~~~ +LL | f5(|_: &'r (), _: &'r ()| {}); + | ~~~~~~ ~~~~~~ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:7:5 | LL | g1(|_: (), _: ()| {}); - | ^^ -------------- found signature defined here - | | + | ^^ -------------- + | | | | + | | | help: consider borrowing the argument: `&()` + | | found signature defined here | expected due to this | = note: expected closure signature `for<'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _` @@ -133,17 +115,15 @@ note: required by a bound in `g1` | LL | fn g1(_: F) where F: Fn(&(), Box) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g1` -help: consider borrowing the argument - | -LL | g1(|_: &(), _: ()| {}); - | ~~~ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 | LL | g2(|_: (), _: ()| {}); - | ^^ -------------- found signature defined here - | | + | ^^ -------------- + | | | | + | | | help: consider borrowing the argument: `&()` + | | found signature defined here | expected due to this | = note: expected closure signature `for<'a> fn(&'a (), for<'a> fn(&'a ())) -> _` @@ -153,17 +133,15 @@ note: required by a bound in `g2` | LL | fn g2(_: F) where F: Fn(&(), fn(&())) {} | ^^^^^^^^^^^^^^^^ required by this bound in `g2` -help: consider borrowing the argument - | -LL | g2(|_: &(), _: ()| {}); - | ~~~ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:9:5 | LL | g3(|_: (), _: ()| {}); - | ^^ -------------- found signature defined here - | | + | ^^ -------------- + | | | | + | | | help: consider borrowing the argument: `&'s ()` + | | found signature defined here | expected due to this | = note: expected closure signature `for<'s> fn(&'s (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _` @@ -173,17 +151,15 @@ note: required by a bound in `g3` | LL | fn g3(_: F) where F: for<'s> Fn(&'s (), Box) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g3` -help: consider borrowing the argument - | -LL | g3(|_: &'s (), _: ()| {}); - | ~~~~~~ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 | LL | g4(|_: (), _: ()| {}); - | ^^ -------------- found signature defined here - | | + | ^^ -------------- + | | | | + | | | help: consider borrowing the argument: `&()` + | | found signature defined here | expected due to this | = note: expected closure signature `for<'a> fn(&'a (), for<'r> fn(&'r ())) -> _` @@ -193,10 +169,6 @@ note: required by a bound in `g4` | LL | fn g4(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g4` -help: consider borrowing the argument - | -LL | g4(|_: &(), _: ()| {}); - | ~~~ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:11:5 @@ -215,12 +187,8 @@ LL | fn h1(_: F) where F: Fn(&(), Box, &(), fn(&(), &())) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h1` help: consider borrowing the argument | -LL | h1(|_: &(), _: (), _: (), _: ()| {}); - | ~~~ -help: consider borrowing the argument - | -LL | h1(|_: (), _: (), _: &(), _: ()| {}); - | ~~~ +LL | h1(|_: &(), _: (), _: &(), _: ()| {}); + | ~~~ ~~~ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 @@ -239,12 +207,8 @@ LL | fn h2(_: F) where F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h2` help: consider borrowing the argument | -LL | h2(|_: &(), _: (), _: (), _: ()| {}); - | ~~~ -help: consider borrowing the argument - | -LL | h2(|_: (), _: (), _: &'t0 (), _: ()| {}); - | ~~~~~~~ +LL | h2(|_: &(), _: (), _: &'t0 (), _: ()| {}); + | ~~~ ~~~~~~~ error: aborting due to 11 previous errors diff --git a/src/test/ui/closures/multiple-fn-bounds.stderr b/src/test/ui/closures/multiple-fn-bounds.stderr index 32a1edb0024..da26302c9d8 100644 --- a/src/test/ui/closures/multiple-fn-bounds.stderr +++ b/src/test/ui/closures/multiple-fn-bounds.stderr @@ -2,8 +2,10 @@ error[E0631]: type mismatch in closure arguments --> $DIR/multiple-fn-bounds.rs:10:5 | LL | foo(move |x| v); - | ^^^ -------- found signature defined here - | | + | ^^^ -------- + | | | | + | | | help: do not borrow the argument: `char` + | | found signature defined here | expected due to this | = note: expected closure signature `fn(char) -> _` @@ -18,10 +20,6 @@ note: required by a bound in `foo` | LL | fn foo bool + Fn(char) -> bool>(f: F) { | ^^^^^^^^^^^^^^^^ required by this bound in `foo` -help: do not borrow the argument - | -LL | foo(move |char| v); - | ~~~~ error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index 67dff5f92aa..bfc243b68a8 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -2,8 +2,10 @@ error[E0631]: type mismatch in closure arguments --> $DIR/closure-arg-type-mismatch.rs:3:14 | LL | a.iter().map(|_: (u32, u32)| 45); - | ^^^ --------------- found signature defined here - | | + | ^^^ --------------- + | | | | + | | | help: consider borrowing the argument: `&(u32, u32)` + | | found signature defined here | expected due to this | = note: expected closure signature `fn(&(u32, u32)) -> _` diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index d66e3b38123..0f035b89dd9 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -2,8 +2,10 @@ error[E0631]: type mismatch in closure arguments --> $DIR/issue-36053-2.rs:7:32 | LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); - | ^^^^^^ --------- found signature defined here - | | + | ^^^^^^ --------- + | | | | + | | | help: consider borrowing the argument: `&&str` + | | found signature defined here | expected due to this | = note: expected closure signature `for<'a> fn(&'a &str) -> _`