diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 511e9e85b5f60..6df3dccca178f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -838,10 +838,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if matches!(obligation.cause.code(), ObligationCauseCode::FunctionArg { .. }) && obligation.cause.span.can_be_used_for_suggestions() { - let (span, sugg) = if let Some(snippet) = - self.tcx.sess.source_map().span_to_snippet(obligation.cause.span).ok() - && snippet.starts_with("|") + // For inline closures (including async closures), suggest wrapping the entire + // closure expression. We check for "async " and "async|" to only match inline + // async closures, avoiding variables like `async_closure` or other constructs. + let (span, sugg) = if let Ok(snippet) = + self.tcx.sess.source_map().span_to_snippet(obligation.cause.span) + && (snippet.starts_with("|") + || snippet.starts_with("async ") + || snippet.starts_with("async|")) { + // Check if this closure already has a call at the end (e.g., `|| {}()` or + // `async || {}()`). If so, suppress this suggestion as it would be redundant + // with the E0618 error. + if snippet.ends_with("()") { + return false; + } + (obligation.cause.span, format!("({snippet})({args})")) } else { (obligation.cause.span.shrink_to_hi(), format!("({args})")) diff --git a/tests/ui/suggestions/async-closure-inline-call-suggestion.rs b/tests/ui/suggestions/async-closure-inline-call-suggestion.rs new file mode 100644 index 0000000000000..80e594516d118 --- /dev/null +++ b/tests/ui/suggestions/async-closure-inline-call-suggestion.rs @@ -0,0 +1,19 @@ +//@ edition:2021 +use std::future::Future; + +async fn f(c: impl Future) { + c.await +} + +fn main() { + f(async || {}); + //~^ ERROR: not a future + //~| HELP: the trait `Future` is not implemented for + //~| HELP: use parentheses to call this closure + + f(async || {}()); + //~^ ERROR: expected function, found `()` + //~| HELP: if you meant to create this closure and immediately call it, surround the closure with parentheses + //~| ERROR: not a future + //~| HELP: the trait `Future` is not implemented for +} diff --git a/tests/ui/suggestions/async-closure-inline-call-suggestion.stderr b/tests/ui/suggestions/async-closure-inline-call-suggestion.stderr new file mode 100644 index 0000000000000..e506f4e82ab5d --- /dev/null +++ b/tests/ui/suggestions/async-closure-inline-call-suggestion.stderr @@ -0,0 +1,52 @@ +error[E0277]: `{async closure@$DIR/async-closure-inline-call-suggestion.rs:9:7: 9:15}` is not a future + --> $DIR/async-closure-inline-call-suggestion.rs:9:7 + | +LL | f(async || {}); + | - ^^^^^^^^^^^ `{async closure@$DIR/async-closure-inline-call-suggestion.rs:9:7: 9:15}` is not a future + | | + | required by a bound introduced by this call + | + = help: the trait `Future` is not implemented for `{async closure@$DIR/async-closure-inline-call-suggestion.rs:9:7: 9:15}` +note: required by a bound in `f` + --> $DIR/async-closure-inline-call-suggestion.rs:4:20 + | +LL | async fn f(c: impl Future) { + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `f` +help: use parentheses to call this closure + | +LL - f(async || {}); +LL + f((async || {})()); + | + +error[E0618]: expected function, found `()` + --> $DIR/async-closure-inline-call-suggestion.rs:14:16 + | +LL | f(async || {}()); + | ^^-- + | | + | call expression requires function + | +help: if you meant to create this closure and immediately call it, surround the closure with parentheses + | +LL | f((async || {})()); + | + + + +error[E0277]: `{async closure@$DIR/async-closure-inline-call-suggestion.rs:14:7: 14:15}` is not a future + --> $DIR/async-closure-inline-call-suggestion.rs:14:7 + | +LL | f(async || {}()); + | - ^^^^^^^^^^^^^ `{async closure@$DIR/async-closure-inline-call-suggestion.rs:14:7: 14:15}` is not a future + | | + | required by a bound introduced by this call + | + = help: the trait `Future` is not implemented for `{async closure@$DIR/async-closure-inline-call-suggestion.rs:14:7: 14:15}` +note: required by a bound in `f` + --> $DIR/async-closure-inline-call-suggestion.rs:4:20 + | +LL | async fn f(c: impl Future) { + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `f` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0618. +For more information about an error, try `rustc --explain E0277`.