Rollup merge of #106891 - estebank:issue-45727, r=petrochenkov
Tweak "borrow closure argument" suggestion Fix #45727.
This commit is contained in:
commit
5f2ad80e18
9 changed files with 127 additions and 47 deletions
|
@ -1350,6 +1350,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
expected_trait_ref,
|
||||
obligation.cause.code(),
|
||||
found_node,
|
||||
obligation.param_env,
|
||||
)
|
||||
} else {
|
||||
let (closure_span, closure_arg_span, found) = found_did
|
||||
|
|
|
@ -283,6 +283,7 @@ pub trait TypeErrCtxtExt<'tcx> {
|
|||
expected: ty::PolyTraitRef<'tcx>,
|
||||
cause: &ObligationCauseCode<'tcx>,
|
||||
found_node: Option<Node<'_>>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
|
||||
|
||||
fn note_conflicting_closure_bounds(
|
||||
|
@ -1978,6 +1979,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
expected: ty::PolyTraitRef<'tcx>,
|
||||
cause: &ObligationCauseCode<'tcx>,
|
||||
found_node: Option<Node<'_>>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
pub(crate) fn build_fn_sig_ty<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
|
@ -2040,7 +2042,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
self.note_conflicting_closure_bounds(cause, &mut err);
|
||||
|
||||
if let Some(found_node) = found_node {
|
||||
hint_missing_borrow(span, found, expected, found_node, &mut err);
|
||||
hint_missing_borrow(self, param_env, span, found, expected, found_node, &mut err);
|
||||
}
|
||||
|
||||
err
|
||||
|
@ -3747,6 +3749,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
|
||||
/// Add a hint to add a missing borrow or remove an unnecessary one.
|
||||
fn hint_missing_borrow<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
span: Span,
|
||||
found: Ty<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
|
@ -3769,7 +3773,7 @@ fn hint_missing_borrow<'tcx>(
|
|||
// This could be a variant constructor, for example.
|
||||
let Some(fn_decl) = found_node.fn_decl() else { return; };
|
||||
|
||||
let arg_spans = fn_decl.inputs.iter().map(|ty| ty.span);
|
||||
let args = fn_decl.inputs.iter().map(|ty| ty);
|
||||
|
||||
fn get_deref_type_and_refs(mut ty: Ty<'_>) -> (Ty<'_>, usize) {
|
||||
let mut refs = 0;
|
||||
|
@ -3785,21 +3789,34 @@ fn hint_missing_borrow<'tcx>(
|
|||
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) {
|
||||
for ((found_arg, expected_arg), arg) in found_args.zip(expected_args).zip(args) {
|
||||
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 {
|
||||
if infcx.can_eq(param_env, found_ty, expected_ty).is_ok() {
|
||||
if found_refs < expected_refs {
|
||||
to_borrow.push((arg_span, expected_arg.to_string()));
|
||||
to_borrow.push((arg.span.shrink_to_lo(), "&".repeat(expected_refs - found_refs)));
|
||||
} else if found_refs > expected_refs {
|
||||
remove_borrow.push((arg_span, expected_arg.to_string()));
|
||||
let mut span = arg.span.shrink_to_lo();
|
||||
let mut left = found_refs - expected_refs;
|
||||
let mut ty = arg;
|
||||
while let hir::TyKind::Ref(_, mut_ty) = &ty.kind && left > 0 {
|
||||
span = span.with_hi(mut_ty.ty.span.lo());
|
||||
ty = mut_ty.ty;
|
||||
left -= 1;
|
||||
}
|
||||
let sugg = if left == 0 {
|
||||
(span, String::new())
|
||||
} else {
|
||||
(arg.span, expected_arg.to_string())
|
||||
};
|
||||
remove_borrow.push(sugg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !to_borrow.is_empty() {
|
||||
err.multipart_suggestion(
|
||||
err.multipart_suggestion_verbose(
|
||||
"consider borrowing the argument",
|
||||
to_borrow,
|
||||
Applicability::MaybeIncorrect,
|
||||
|
@ -3807,7 +3824,7 @@ fn hint_missing_borrow<'tcx>(
|
|||
}
|
||||
|
||||
if !remove_borrow.is_empty() {
|
||||
err.multipart_suggestion(
|
||||
err.multipart_suggestion_verbose(
|
||||
"do not borrow the argument",
|
||||
remove_borrow,
|
||||
Applicability::MaybeIncorrect,
|
||||
|
|
|
@ -16,7 +16,7 @@ LL | fn f1<F>(_: F) where F: Fn(&(), &()) {}
|
|||
help: consider borrowing the argument
|
||||
|
|
||||
LL | f1(|_: &(), _: &()| {});
|
||||
| ~~~ ~~~
|
||||
| + +
|
||||
|
||||
error[E0631]: type mismatch in closure arguments
|
||||
--> $DIR/anonymous-higher-ranked-lifetime.rs:3:5
|
||||
|
@ -35,8 +35,8 @@ LL | fn f2<F>(_: F) where F: for<'a> Fn(&'a (), &()) {}
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f2`
|
||||
help: consider borrowing the argument
|
||||
|
|
||||
LL | f2(|_: &'a (), _: &()| {});
|
||||
| ~~~~~~ ~~~
|
||||
LL | f2(|_: &(), _: &()| {});
|
||||
| + +
|
||||
|
||||
error[E0631]: type mismatch in closure arguments
|
||||
--> $DIR/anonymous-higher-ranked-lifetime.rs:4:5
|
||||
|
@ -56,7 +56,7 @@ LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {}
|
|||
help: consider borrowing the argument
|
||||
|
|
||||
LL | f3(|_: &(), _: &()| {});
|
||||
| ~~~ ~~~
|
||||
| + +
|
||||
|
||||
error[E0631]: type mismatch in closure arguments
|
||||
--> $DIR/anonymous-higher-ranked-lifetime.rs:5:5
|
||||
|
@ -75,8 +75,8 @@ LL | fn f4<F>(_: F) where F: for<'r> Fn(&(), &'r ()) {}
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f4`
|
||||
help: consider borrowing the argument
|
||||
|
|
||||
LL | f4(|_: &(), _: &'r ()| {});
|
||||
| ~~~ ~~~~~~
|
||||
LL | f4(|_: &(), _: &()| {});
|
||||
| + +
|
||||
|
||||
error[E0631]: type mismatch in closure arguments
|
||||
--> $DIR/anonymous-higher-ranked-lifetime.rs:6:5
|
||||
|
@ -95,17 +95,15 @@ LL | fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {}
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f5`
|
||||
help: consider borrowing the argument
|
||||
|
|
||||
LL | f5(|_: &'r (), _: &'r ()| {});
|
||||
| ~~~~~~ ~~~~~~
|
||||
LL | f5(|_: &(), _: &()| {});
|
||||
| + +
|
||||
|
||||
error[E0631]: type mismatch in closure arguments
|
||||
--> $DIR/anonymous-higher-ranked-lifetime.rs:7:5
|
||||
|
|
||||
LL | g1(|_: (), _: ()| {});
|
||||
| ^^ --------------
|
||||
| | | |
|
||||
| | | help: consider borrowing the argument: `&()`
|
||||
| | found signature defined here
|
||||
| ^^ -------------- found signature defined here
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected closure signature `for<'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
|
||||
|
@ -115,15 +113,17 @@ note: required by a bound in `g1`
|
|||
|
|
||||
LL | fn g1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ 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(|_: (), _: ()| {});
|
||||
| ^^ --------------
|
||||
| | | |
|
||||
| | | help: consider borrowing the argument: `&()`
|
||||
| | found signature defined here
|
||||
| ^^ -------------- found signature defined here
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected closure signature `for<'a> fn(&'a (), for<'a> fn(&'a ())) -> _`
|
||||
|
@ -133,15 +133,17 @@ note: required by a bound in `g2`
|
|||
|
|
||||
LL | fn g2<F>(_: 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(|_: (), _: ()| {});
|
||||
| ^^ --------------
|
||||
| | | |
|
||||
| | | help: consider borrowing the argument: `&'s ()`
|
||||
| | found signature defined here
|
||||
| ^^ -------------- found signature defined here
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected closure signature `for<'s> fn(&'s (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
|
||||
|
@ -151,15 +153,17 @@ note: required by a bound in `g3`
|
|||
|
|
||||
LL | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<dyn Fn(&())>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g3`
|
||||
help: consider borrowing the argument
|
||||
|
|
||||
LL | g3(|_: &(), _: ()| {});
|
||||
| +
|
||||
|
||||
error[E0631]: type mismatch in closure arguments
|
||||
--> $DIR/anonymous-higher-ranked-lifetime.rs:10:5
|
||||
|
|
||||
LL | g4(|_: (), _: ()| {});
|
||||
| ^^ --------------
|
||||
| | | |
|
||||
| | | help: consider borrowing the argument: `&()`
|
||||
| | found signature defined here
|
||||
| ^^ -------------- found signature defined here
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected closure signature `for<'a> fn(&'a (), for<'r> fn(&'r ())) -> _`
|
||||
|
@ -169,6 +173,10 @@ note: required by a bound in `g4`
|
|||
|
|
||||
LL | fn g4<F>(_: 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
|
||||
|
@ -188,7 +196,7 @@ LL | fn h1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>, &(), fn(&(), &())) {}
|
|||
help: consider borrowing the argument
|
||||
|
|
||||
LL | h1(|_: &(), _: (), _: &(), _: ()| {});
|
||||
| ~~~ ~~~
|
||||
| + +
|
||||
|
||||
error[E0631]: type mismatch in closure arguments
|
||||
--> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
|
||||
|
@ -207,8 +215,8 @@ LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<dyn Fn(&())>, &'t0 (), fn(&(),
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h2`
|
||||
help: consider borrowing the argument
|
||||
|
|
||||
LL | h2(|_: &(), _: (), _: &'t0 (), _: ()| {});
|
||||
| ~~~ ~~~~~~~
|
||||
LL | h2(|_: &(), _: (), _: &(), _: ()| {});
|
||||
| + +
|
||||
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
|
|
|
@ -2,10 +2,8 @@ error[E0631]: type mismatch in closure arguments
|
|||
--> $DIR/multiple-fn-bounds.rs:10:5
|
||||
|
|
||||
LL | foo(move |x| v);
|
||||
| ^^^ --------
|
||||
| | | |
|
||||
| | | help: do not borrow the argument: `char`
|
||||
| | found signature defined here
|
||||
| ^^^ -------- found signature defined here
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected closure signature `fn(char) -> _`
|
||||
|
@ -20,6 +18,10 @@ note: required by a bound in `foo`
|
|||
|
|
||||
LL | fn foo<F: Fn(&char) -> 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
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
// run-rustfix
|
||||
fn main() {
|
||||
let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments
|
||||
let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
// run-rustfix
|
||||
fn main() {
|
||||
let _ = (-10..=10).find(|x: i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments
|
||||
let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
error[E0631]: type mismatch in closure arguments
|
||||
--> $DIR/closure-arg-type-mismatch-issue-45727.rs:3:24
|
||||
|
|
||||
LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0);
|
||||
| ^^^^ -------- found signature defined here
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected closure signature `for<'a> fn(&'a {integer}) -> _`
|
||||
found closure signature `fn(i32) -> _`
|
||||
note: required by a bound in `find`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
help: consider borrowing the argument
|
||||
|
|
||||
LL | let _ = (-10..=10).find(|x: &i32| x.signum() == 0);
|
||||
| +
|
||||
|
||||
error[E0631]: type mismatch in closure arguments
|
||||
--> $DIR/closure-arg-type-mismatch-issue-45727.rs:4:24
|
||||
|
|
||||
LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
|
||||
| ^^^^ ----------- found signature defined here
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected closure signature `for<'a> fn(&'a {integer}) -> _`
|
||||
found closure signature `for<'a, 'b, 'c> fn(&'a &'b &'c i32) -> _`
|
||||
note: required by a bound in `find`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
help: do not borrow the argument
|
||||
|
|
||||
LL - let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
|
||||
LL + let _ = (-10..=10).find(|x: &i32| x.signum() == 0);
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0631`.
|
|
@ -2,16 +2,18 @@ error[E0631]: type mismatch in closure arguments
|
|||
--> $DIR/closure-arg-type-mismatch.rs:3:14
|
||||
|
|
||||
LL | a.iter().map(|_: (u32, u32)| 45);
|
||||
| ^^^ ---------------
|
||||
| | | |
|
||||
| | | help: consider borrowing the argument: `&(u32, u32)`
|
||||
| | found signature defined here
|
||||
| ^^^ --------------- found signature defined here
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected closure signature `fn(&(u32, u32)) -> _`
|
||||
found closure signature `fn((u32, u32)) -> _`
|
||||
note: required by a bound in `map`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
help: consider borrowing the argument
|
||||
|
|
||||
LL | a.iter().map(|_: &(u32, u32)| 45);
|
||||
| +
|
||||
|
||||
error[E0631]: type mismatch in closure arguments
|
||||
--> $DIR/closure-arg-type-mismatch.rs:4:14
|
||||
|
|
|
@ -2,16 +2,18 @@ error[E0631]: type mismatch in closure arguments
|
|||
--> $DIR/issue-36053-2.rs:7:32
|
||||
|
|
||||
LL | once::<&str>("str").fuse().filter(|a: &str| true).count();
|
||||
| ^^^^^^ ---------
|
||||
| | | |
|
||||
| | | help: consider borrowing the argument: `&&str`
|
||||
| | found signature defined here
|
||||
| ^^^^^^ --------- found signature defined here
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected closure signature `for<'a> fn(&'a &str) -> _`
|
||||
found closure signature `for<'a> fn(&'a str) -> _`
|
||||
note: required by a bound in `filter`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
help: consider borrowing the argument
|
||||
|
|
||||
LL | once::<&str>("str").fuse().filter(|a: &&str| true).count();
|
||||
| +
|
||||
|
||||
error[E0599]: the method `count` exists for struct `Filter<Fuse<Once<&str>>, [closure@issue-36053-2.rs:7:39]>`, but its trait bounds were not satisfied
|
||||
--> $DIR/issue-36053-2.rs:7:55
|
||||
|
|
Loading…
Reference in a new issue