diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index e4a2aaff86aed..f6887c18075a4 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -1,13 +1,14 @@ use std::fmt; use rustc_data_structures::intern::Interned; -use rustc_errors::{Diag, IntoDiagArg}; +use rustc_errors::{Applicability, Diag, IntoDiagArg}; +use rustc_hir as hir; use rustc_hir::def::Namespace; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_middle::bug; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::print::{FmtPrinter, Print, PrintTraitRefExt as _, RegionHighlightMode}; -use rustc_middle::ty::{self, GenericArgsRef, RePlaceholder, Region, TyCtxt}; +use rustc_middle::ty::{self, GenericArgsRef, IsSuggestable, RePlaceholder, Region, TyCtxt}; use tracing::{debug, instrument}; use crate::diagnostics::{ @@ -379,6 +380,50 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { } } + // When the mismatched trait is an Fn-trait and the self type is a closure with + // unannotated parameters, suggest adding explicit type annotations. This turns + // the confusing lifetime-generality error into an actionable hint, e.g.: + // |buf| → |buf: &mut [u8]| + if self.tcx().is_fn_trait(trait_def_id) { + let actual_self_ty = self.cx.resolve_vars_if_possible( + ty::TraitRef::new_from_args(self.cx.tcx, trait_def_id, actual_args).self_ty(), + ); + if let ty::Closure(closure_def_id, _) = *actual_self_ty.kind() + && let Some(local_def_id) = closure_def_id.as_local() + && let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) = + self.tcx().hir_node_by_def_id(local_def_id) + { + let body = self.tcx().hir_body(closure.body); + // For Fn traits, args[1] is the tupled input types (e.g. `(&mut [u8],)`). + let expected_input_tys = expected_args.type_at(1); + if let ty::Tuple(input_tys) = *expected_input_tys.kind() { + let suggestions: Vec<_> = body + .params + .iter() + .zip(input_tys.iter()) + .filter_map(|(param, ty)| { + // ty_span == pat.span means no explicit type annotation was written. + if param.ty_span == param.pat.span + && ty.is_suggestable(self.tcx(), false) + { + Some((param.pat.span.shrink_to_hi(), format!(": {ty}"))) + } else { + None + } + }) + .collect(); + if !suggestions.is_empty() { + let msg = if suggestions.len() == 1 { + "consider adding an explicit type annotation to the closure's argument" + } else { + "consider adding explicit type annotations to the closure's arguments" + }; + err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect); + } + } + } + } + err } diff --git a/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr index b4f3570d9f2da..461b065d55ad3 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr @@ -6,6 +6,10 @@ LL | require_send(future); | = note: closure with signature `fn(&'0 Vec) -> std::slice::Iter<'_, i32>` must implement `FnOnce<(&'1 Vec,)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `FnOnce<(&Vec,)>` +help: consider adding an explicit type annotation to the closure's argument + | +LL | for _ in things.iter().map(|n: &Vec| n.iter()).flatten() { + | +++++++++++ error: implementation of `FnOnce` is not general enough --> $DIR/higher-ranked-auto-trait-15.rs:20:5 @@ -16,6 +20,10 @@ LL | require_send(future); = note: closure with signature `fn(&'0 Vec) -> std::slice::Iter<'_, i32>` must implement `FnOnce<(&'1 Vec,)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `FnOnce<(&Vec,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit type annotation to the closure's argument + | +LL | for _ in things.iter().map(|n: &Vec| n.iter()).flatten() { + | +++++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/closures/hrtb-closure-suggest-type-annotation.fixed b/tests/ui/closures/hrtb-closure-suggest-type-annotation.fixed new file mode 100644 index 0000000000000..e4a948eb9f7bd --- /dev/null +++ b/tests/ui/closures/hrtb-closure-suggest-type-annotation.fixed @@ -0,0 +1,44 @@ +//@ run-rustfix +// When a closure is passed where a higher-ranked `FnOnce` is expected, but the closure +// parameter has no explicit type annotation, the compiler should suggest adding one. +// See . + +fn inner(buf: &mut [u8], func: F) -> usize +where + F: FnOnce(&mut [u8]) -> Result, +{ + match func(buf) { + Ok(n) => n, + Err(e) => e as usize, + } +} + +fn outer(buf: &mut [u8], func: F) -> usize +where + F: FnOnce(&mut [u8]) -> Result, +{ + let outer_closure = |buf: &mut [u8]| { + match func(buf) { + Ok(n) => { + println!("OK: {n}"); + Ok(n) + } + Err(e) => { + println!("ERR: {e}"); + Err(e) + } + } + }; + + inner(buf, outer_closure) + //~^ ERROR implementation of `FnOnce` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough +} + +fn main() { + let mut x = [0u8; 16]; + let res = outer(&mut x, |buf| { + if buf.len() % 2 == 0 { Ok(buf.len()) } else { Err(buf.len() as isize) } + }); + println!("{res:?}"); +} diff --git a/tests/ui/closures/hrtb-closure-suggest-type-annotation.rs b/tests/ui/closures/hrtb-closure-suggest-type-annotation.rs new file mode 100644 index 0000000000000..080874d8e236a --- /dev/null +++ b/tests/ui/closures/hrtb-closure-suggest-type-annotation.rs @@ -0,0 +1,44 @@ +//@ run-rustfix +// When a closure is passed where a higher-ranked `FnOnce` is expected, but the closure +// parameter has no explicit type annotation, the compiler should suggest adding one. +// See . + +fn inner(buf: &mut [u8], func: F) -> usize +where + F: FnOnce(&mut [u8]) -> Result, +{ + match func(buf) { + Ok(n) => n, + Err(e) => e as usize, + } +} + +fn outer(buf: &mut [u8], func: F) -> usize +where + F: FnOnce(&mut [u8]) -> Result, +{ + let outer_closure = |buf| { + match func(buf) { + Ok(n) => { + println!("OK: {n}"); + Ok(n) + } + Err(e) => { + println!("ERR: {e}"); + Err(e) + } + } + }; + + inner(buf, outer_closure) + //~^ ERROR implementation of `FnOnce` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough +} + +fn main() { + let mut x = [0u8; 16]; + let res = outer(&mut x, |buf| { + if buf.len() % 2 == 0 { Ok(buf.len()) } else { Err(buf.len() as isize) } + }); + println!("{res:?}"); +} diff --git a/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr b/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr new file mode 100644 index 0000000000000..51691c35f795b --- /dev/null +++ b/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr @@ -0,0 +1,29 @@ +error: implementation of `FnOnce` is not general enough + --> $DIR/hrtb-closure-suggest-type-annotation.rs:33:5 + | +LL | inner(buf, outer_closure) + | ^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 mut [u8]) -> Result` must implement `FnOnce<(&'1 mut [u8],)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 mut [u8],)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | let outer_closure = |buf: &mut [u8]| { + | +++++++++++ + +error: implementation of `FnOnce` is not general enough + --> $DIR/hrtb-closure-suggest-type-annotation.rs:33:5 + | +LL | inner(buf, outer_closure) + | ^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 mut [u8]) -> Result` must implement `FnOnce<(&'1 mut [u8],)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 mut [u8],)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit type annotation to the closure's argument + | +LL | let outer_closure = |buf: &mut [u8]| { + | +++++++++++ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr index b2bb417a8f01b..3c6aab12bf137 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr @@ -6,6 +6,10 @@ LL | foo(bar, "string", |s| s.len() == 5); | = note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | foo(bar, "string", |s: &&str| s.len() == 5); + | +++++++ error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:45:5 @@ -16,6 +20,10 @@ LL | foo(bar, "string", |s| s.len() == 5); = note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit type annotation to the closure's argument + | +LL | foo(bar, "string", |s: &&str| s.len() == 5); + | +++++++ error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:48:5 @@ -25,6 +33,10 @@ LL | foo(baz, "string", |s| s.0.len() == 5); | = note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | foo(baz, "string", |s: &Wrapper<'_>| s.0.len() == 5); + | ++++++++++++++ error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:48:5 @@ -35,6 +47,10 @@ LL | foo(baz, "string", |s| s.0.len() == 5); = note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit type annotation to the closure's argument + | +LL | foo(baz, "string", |s: &Wrapper<'_>| s.0.len() == 5); + | ++++++++++++++ error: aborting due to 4 previous errors diff --git a/tests/ui/lifetimes/issue-105675.stderr b/tests/ui/lifetimes/issue-105675.stderr index 4b3d0e8ac5efc..db623761b268e 100644 --- a/tests/ui/lifetimes/issue-105675.stderr +++ b/tests/ui/lifetimes/issue-105675.stderr @@ -6,6 +6,10 @@ LL | thing(f); | = note: closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` +help: consider adding explicit type annotations to the closure's arguments + | +LL | let f = | _: &u32 , y: &u32 , z: u32 | (); + | ++++++ +++++ error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:5:5 @@ -16,6 +20,10 @@ LL | thing(f); = note: closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding explicit type annotations to the closure's arguments + | +LL | let f = | _: &u32 , y: &u32 , z: u32 | (); + | ++++++ +++++ error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:9:5 @@ -25,6 +33,10 @@ LL | thing(f); | = note: closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | let f = | x: &u32, y: _ , z: u32 | (); + | ++++++ error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:9:5 @@ -34,6 +46,10 @@ LL | thing(f); | = note: closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&u32, &'2 u32, u32)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | let f = | x: &u32, y: _ , z: u32 | (); + | ++++++ error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:9:5 @@ -44,6 +60,10 @@ LL | thing(f); = note: closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit type annotation to the closure's argument + | +LL | let f = | x: &u32, y: _ , z: u32 | (); + | ++++++ error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:9:5 @@ -54,6 +74,10 @@ LL | thing(f); = note: closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&u32, &'2 u32, u32)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit type annotation to the closure's argument + | +LL | let f = | x: &u32, y: _ , z: u32 | (); + | ++++++ error: aborting due to 6 previous errors diff --git a/tests/ui/lifetimes/issue-79187-2.stderr b/tests/ui/lifetimes/issue-79187-2.stderr index 78f6ce882dfab..2731d0972d2bc 100644 --- a/tests/ui/lifetimes/issue-79187-2.stderr +++ b/tests/ui/lifetimes/issue-79187-2.stderr @@ -24,6 +24,10 @@ LL | take_foo(|a| a); | = note: closure with signature `fn(&'2 i32) -> &i32` must implement `FnOnce<(&'1 i32,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 i32,)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | take_foo(|a: &i32| a); + | ++++++ error: implementation of `Fn` is not general enough --> $DIR/issue-79187-2.rs:8:5 @@ -33,6 +37,10 @@ LL | take_foo(|a| a); | = note: closure with signature `fn(&'2 i32) -> &i32` must implement `Fn<(&'1 i32,)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(&'2 i32,)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | take_foo(|a: &i32| a); + | ++++++ error[E0308]: mismatched types --> $DIR/issue-79187-2.rs:11:5 diff --git a/tests/ui/lifetimes/issue-79187.stderr b/tests/ui/lifetimes/issue-79187.stderr index 8adde8d6dfbf3..e08400481e470 100644 --- a/tests/ui/lifetimes/issue-79187.stderr +++ b/tests/ui/lifetimes/issue-79187.stderr @@ -6,6 +6,10 @@ LL | thing(f); | = note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | let f = |_: &u32| (); + | ++++++ error: implementation of `FnOnce` is not general enough --> $DIR/issue-79187.rs:5:5 @@ -16,6 +20,10 @@ LL | thing(f); = note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit type annotation to the closure's argument + | +LL | let f = |_: &u32| (); + | ++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/mismatched_types/closure-mismatch.current.stderr b/tests/ui/mismatched_types/closure-mismatch.current.stderr index 378fe83ea89bd..82e3e4b0f78f2 100644 --- a/tests/ui/mismatched_types/closure-mismatch.current.stderr +++ b/tests/ui/mismatched_types/closure-mismatch.current.stderr @@ -6,6 +6,10 @@ LL | baz(|_| ()); | = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | baz(|_: &()| ()); + | +++++ error: implementation of `Fn` is not general enough --> $DIR/closure-mismatch.rs:12:5 @@ -15,6 +19,10 @@ LL | baz(|_| ()); | = note: closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | baz(|_: &()| ()); + | +++++ error: implementation of `FnOnce` is not general enough --> $DIR/closure-mismatch.rs:16:5 @@ -24,6 +32,10 @@ LL | baz(|x| ()); | = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | baz(|x: &()| ()); + | +++++ error: implementation of `Fn` is not general enough --> $DIR/closure-mismatch.rs:16:5 @@ -33,6 +45,10 @@ LL | baz(|x| ()); | = note: closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | baz(|x: &()| ()); + | +++++ error: aborting due to 4 previous errors diff --git a/tests/ui/nll/ice-106874.stderr b/tests/ui/nll/ice-106874.stderr index 629570b602ed6..45dd1557dd027 100644 --- a/tests/ui/nll/ice-106874.stderr +++ b/tests/ui/nll/ice-106874.stderr @@ -6,6 +6,10 @@ LL | A(B(C::new(D::new(move |st| f(st))))) | = note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`... = note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1` +help: consider adding an explicit type annotation to the closure's argument + | +LL | A(B(C::new(D::new(move |st: &mut V| f(st))))) + | ++++++++ error: implementation of `FnOnce` is not general enough --> $DIR/ice-106874.rs:8:5 @@ -16,6 +20,10 @@ LL | A(B(C::new(D::new(move |st| f(st))))) = note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`... = note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit type annotation to the closure's argument + | +LL | A(B(C::new(D::new(move |st: &mut V| f(st))))) + | ++++++++ error: higher-ranked subtype error --> $DIR/ice-106874.rs:8:5 @@ -39,6 +47,10 @@ LL | A(B(C::new(D::new(move |st| f(st))))) | = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | A(B(C::new(D::new(move |st: &mut V| f(st))))) + | ++++++++ error: implementation of `Fn` is not general enough --> $DIR/ice-106874.rs:8:7 @@ -48,6 +60,10 @@ LL | A(B(C::new(D::new(move |st| f(st))))) | = note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | A(B(C::new(D::new(move |st: &mut V| f(st))))) + | ++++++++ error: implementation of `FnOnce` is not general enough --> $DIR/ice-106874.rs:8:7 @@ -58,6 +74,10 @@ LL | A(B(C::new(D::new(move |st| f(st))))) = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit type annotation to the closure's argument + | +LL | A(B(C::new(D::new(move |st: &mut V| f(st))))) + | ++++++++ error: implementation of `Fn` is not general enough --> $DIR/ice-106874.rs:8:7 @@ -68,6 +88,10 @@ LL | A(B(C::new(D::new(move |st| f(st))))) = note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit type annotation to the closure's argument + | +LL | A(B(C::new(D::new(move |st: &mut V| f(st))))) + | ++++++++ error: implementation of `FnOnce` is not general enough --> $DIR/ice-106874.rs:8:7 @@ -78,6 +102,10 @@ LL | A(B(C::new(D::new(move |st| f(st))))) = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit type annotation to the closure's argument + | +LL | A(B(C::new(D::new(move |st: &mut V| f(st))))) + | ++++++++ error: implementation of `Fn` is not general enough --> $DIR/ice-106874.rs:8:7 @@ -88,6 +116,10 @@ LL | A(B(C::new(D::new(move |st| f(st))))) = note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit type annotation to the closure's argument + | +LL | A(B(C::new(D::new(move |st: &mut V| f(st))))) + | ++++++++ error: aborting due to 10 previous errors diff --git a/tests/ui/nll/issue-57843.stderr b/tests/ui/nll/issue-57843.stderr index eed511460cac7..386f952c0541d 100644 --- a/tests/ui/nll/issue-57843.stderr +++ b/tests/ui/nll/issue-57843.stderr @@ -6,6 +6,10 @@ LL | Foo(Box::new(|_| ())); | = note: closure with signature `fn(&'2 bool)` must implement `FnOnce<(&'1 bool,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 bool,)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | Foo(Box::new(|_: &'a bool| ())); + | ++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/nll/missing-universe-cause-issue-114907.stderr b/tests/ui/nll/missing-universe-cause-issue-114907.stderr index c2e91edd13872..d8922ef80e813 100644 --- a/tests/ui/nll/missing-universe-cause-issue-114907.stderr +++ b/tests/ui/nll/missing-universe-cause-issue-114907.stderr @@ -6,6 +6,10 @@ LL | accept(callback); | = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | let callback = |_: &()| {}; + | +++++ error: implementation of `FnOnce` is not general enough --> $DIR/missing-universe-cause-issue-114907.rs:33:5 @@ -16,6 +20,10 @@ LL | accept(callback); = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit type annotation to the closure's argument + | +LL | let callback = |_: &()| {}; + | +++++ error: implementation of `FnOnce` is not general enough --> $DIR/missing-universe-cause-issue-114907.rs:33:5 @@ -26,6 +34,10 @@ LL | accept(callback); = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit type annotation to the closure's argument + | +LL | let callback = |_: &()| {}; + | +++++ error: implementation of `FnOnce` is not general enough --> $DIR/missing-universe-cause-issue-114907.rs:33:5 @@ -36,6 +48,10 @@ LL | accept(callback); = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit type annotation to the closure's argument + | +LL | let callback = |_: &()| {}; + | +++++ error: higher-ranked subtype error --> $DIR/missing-universe-cause-issue-114907.rs:33:5 diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr index 804b3f00a2642..0734eba1496d7 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr @@ -32,6 +32,10 @@ LL | bad(&b); | = note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | let b = |_: &()| &a; + | +++++ error: implementation of `FnOnce` is not general enough --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 @@ -41,6 +45,10 @@ LL | bad(&b); | = note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | let b = |_: &()| &a; + | +++++ error: aborting due to 3 previous errors diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr index 804b3f00a2642..0734eba1496d7 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr @@ -32,6 +32,10 @@ LL | bad(&b); | = note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | let b = |_: &()| &a; + | +++++ error: implementation of `FnOnce` is not general enough --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 @@ -41,6 +45,10 @@ LL | bad(&b); | = note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | let b = |_: &()| &a; + | +++++ error: aborting due to 3 previous errors