about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/src/check/callee.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs164
-rw-r--r--src/test/ui/binop/issue-77910-1.stderr2
-rw-r--r--src/test/ui/closures/closure-bounds-subtype.stderr4
-rw-r--r--src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr2
-rw-r--r--src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr9
-rw-r--r--src/test/ui/suggestions/call-on-unimplemented-ctor.rs2
-rw-r--r--src/test/ui/suggestions/call-on-unimplemented-ctor.stderr5
-rw-r--r--src/test/ui/suggestions/call-on-unimplemented-fn-ptr.rs15
-rw-r--r--src/test/ui/suggestions/call-on-unimplemented-fn-ptr.stderr21
-rw-r--r--src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr9
13 files changed, 174 insertions, 74 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/callee.rs b/compiler/rustc_hir_analysis/src/check/callee.rs
index f0a7c910906..088de1979ba 100644
--- a/compiler/rustc_hir_analysis/src/check/callee.rs
+++ b/compiler/rustc_hir_analysis/src/check/callee.rs
@@ -1,6 +1,6 @@
 use super::method::probe::{IsSuggestion, Mode, ProbeScope};
 use super::method::MethodCallee;
-use super::{DefIdOrName, Expectation, FnCtxt, TupleArgumentsFlag};
+use super::{Expectation, FnCtxt, TupleArgumentsFlag};
 use crate::type_error_struct;
 
 use rustc_ast::util::parser::PREC_POSTFIX;
@@ -27,6 +27,7 @@ use rustc_span::Span;
 use rustc_target::spec::abi;
 use rustc_trait_selection::autoderef::Autoderef;
 use rustc_trait_selection::infer::InferCtxtExt as _;
+use rustc_trait_selection::traits::error_reporting::DefIdOrName;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 
 use std::iter;
diff --git a/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs
index 429f068c91b..8c4fe75878f 100644
--- a/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs
@@ -2,7 +2,6 @@ use super::FnCtxt;
 use crate::astconv::AstConv;
 use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel};
 
-use hir::def_id::DefId;
 use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
 use rustc_errors::{Applicability, Diagnostic, MultiSpan};
 use rustc_hir as hir;
@@ -19,6 +18,7 @@ use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_trait_selection::infer::InferCtxtExt;
+use rustc_trait_selection::traits::error_reporting::DefIdOrName;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -1209,8 +1209,3 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 }
-
-pub enum DefIdOrName {
-    DefId(DefId),
-    Name(&'static str),
-}
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 6abff0ac577..b7e6a564f39 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -2796,3 +2796,8 @@ impl<'tcx> ty::TypeVisitor<'tcx> for HasNumericInferVisitor {
         }
     }
 }
+
+pub enum DefIdOrName {
+    DefId(DefId),
+    Name(&'static str),
+}
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 316afe28a0a..98e32e2ce85 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1,11 +1,13 @@
 use super::{
-    Obligation, ObligationCause, ObligationCauseCode, PredicateObligation, SelectionContext,
+    DefIdOrName, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation,
+    SelectionContext,
 };
 
 use crate::autoderef::Autoderef;
 use crate::infer::InferCtxt;
 use crate::traits::normalize_to;
 
+use hir::def::CtorOf;
 use hir::HirId;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -812,28 +814,87 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         err: &mut Diagnostic,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
-        // Skipping binder here, remapping below
-        let self_ty = trait_pred.self_ty().skip_binder();
+        if let ty::PredicateKind::Trait(trait_pred) = obligation.predicate.kind().skip_binder()
+            && Some(trait_pred.def_id()) == self.tcx.lang_items().sized_trait()
+        {
+            // Don't suggest calling to turn an unsized type into a sized type
+            return false;
+        }
 
-        let (def_id, inputs, output, kind) = match *self_ty.kind() {
-            ty::Closure(def_id, substs) => {
-                let sig = substs.as_closure().sig();
-                (def_id, sig.inputs().map_bound(|inputs| &inputs[1..]), sig.output(), "closure")
+        // This is duplicated from `extract_callable_info` in typeck, which
+        // relies on autoderef, so we can't use it here.
+        let found = trait_pred.self_ty().skip_binder().peel_refs();
+        let Some((def_id_or_name, output, inputs)) = (match *found.kind()
+        {
+            ty::FnPtr(fn_sig) => {
+                Some((DefIdOrName::Name("function pointer"), fn_sig.output(), fn_sig.inputs()))
             }
             ty::FnDef(def_id, _) => {
-                let sig = self_ty.fn_sig(self.tcx);
-                (
-                    def_id,
-                    sig.inputs(),
-                    sig.output(),
-                    match self.tcx.def_kind(def_id) {
-                        DefKind::Ctor(..) => "constructor",
-                        _ => "function",
-                    },
-                )
+                let fn_sig = found.fn_sig(self.tcx);
+                Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs()))
             }
-            _ => return false,
-        };
+            ty::Closure(def_id, substs) => {
+                let fn_sig = substs.as_closure().sig();
+                Some((
+                    DefIdOrName::DefId(def_id),
+                    fn_sig.output(),
+                    fn_sig.inputs().map_bound(|inputs| &inputs[1..]),
+                ))
+            }
+            ty::Opaque(def_id, substs) => {
+                self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| {
+                    if let ty::PredicateKind::Projection(proj) = pred.kind().skip_binder()
+                    && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+                    // args tuple will always be substs[1]
+                    && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
+                    {
+                        Some((
+                            DefIdOrName::DefId(def_id),
+                            pred.kind().rebind(proj.term.ty().unwrap()),
+                            pred.kind().rebind(args.as_slice()),
+                        ))
+                    } else {
+                        None
+                    }
+                })
+            }
+            ty::Dynamic(data, _, ty::Dyn) => {
+                data.iter().find_map(|pred| {
+                    if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
+                    && Some(proj.item_def_id) == self.tcx.lang_items().fn_once_output()
+                    // for existential projection, substs are shifted over by 1
+                    && let ty::Tuple(args) = proj.substs.type_at(0).kind()
+                    {
+                        Some((
+                            DefIdOrName::Name("trait object"),
+                            pred.rebind(proj.term.ty().unwrap()),
+                            pred.rebind(args.as_slice()),
+                        ))
+                    } else {
+                        None
+                    }
+                })
+            }
+            ty::Param(_) => {
+                obligation.param_env.caller_bounds().iter().find_map(|pred| {
+                    if let ty::PredicateKind::Projection(proj) = pred.kind().skip_binder()
+                    && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+                    && proj.projection_ty.self_ty() == found
+                    // args tuple will always be substs[1]
+                    && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
+                    {
+                        Some((
+                            DefIdOrName::Name("type parameter"),
+                            pred.kind().rebind(proj.term.ty().unwrap()),
+                            pred.kind().rebind(args.as_slice()),
+                        ))
+                    } else {
+                        None
+                    }
+                })
+            }
+            _ => None,
+        }) else { return false; };
         let output = self.replace_bound_vars_with_fresh_vars(
             obligation.cause.span,
             LateBoundRegionConversionTime::FnCall,
@@ -859,7 +920,18 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         // Get the name of the callable and the arguments to be used in the suggestion.
         let hir = self.tcx.hir();
 
-        let msg = format!("use parentheses to call the {}", kind);
+        let msg = match def_id_or_name {
+            DefIdOrName::DefId(def_id) => match self.tcx.def_kind(def_id) {
+                DefKind::Ctor(CtorOf::Struct, _) => {
+                    "use parentheses to instantiate this tuple struct".to_string()
+                }
+                DefKind::Ctor(CtorOf::Variant, _) => {
+                    "use parentheses to instantiate this tuple variant".to_string()
+                }
+                kind => format!("use parentheses to call this {}", kind.descr(def_id)),
+            },
+            DefIdOrName::Name(name) => format!("use parentheses to call this {name}"),
+        };
 
         let args = inputs
             .map(|ty| {
@@ -872,31 +944,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             .collect::<Vec<_>>()
             .join(", ");
 
-        let name = match hir.get_if_local(def_id) {
-            Some(hir::Node::Expr(hir::Expr {
-                kind: hir::ExprKind::Closure(hir::Closure { fn_decl_span, .. }),
-                ..
-            })) => {
-                err.span_label(*fn_decl_span, "consider calling this closure");
-                let Some(name) = self.get_closure_name(def_id, err, &msg) else {
-                    return false;
-                };
-                name.to_string()
-            }
-            Some(hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(..), .. })) => {
-                err.span_label(ident.span, "consider calling this function");
-                ident.to_string()
-            }
-            Some(hir::Node::Ctor(..)) => {
-                let name = self.tcx.def_path_str(def_id);
-                err.span_label(
-                    self.tcx.def_span(def_id),
-                    format!("consider calling the constructor for `{}`", name),
-                );
-                name
-            }
-            _ => return false,
-        };
         if matches!(obligation.cause.code(), ObligationCauseCode::FunctionArgumentObligation { .. })
             && obligation.cause.span.can_be_used_for_suggestions()
         {
@@ -910,7 +957,32 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 format!("({args})"),
                 Applicability::HasPlaceholders,
             );
-        } else {
+        } else if let DefIdOrName::DefId(def_id) = def_id_or_name {
+            let name = match hir.get_if_local(def_id) {
+                Some(hir::Node::Expr(hir::Expr {
+                    kind: hir::ExprKind::Closure(hir::Closure { fn_decl_span, .. }),
+                    ..
+                })) => {
+                    err.span_label(*fn_decl_span, "consider calling this closure");
+                    let Some(name) = self.get_closure_name(def_id, err, &msg) else {
+                        return false;
+                    };
+                    name.to_string()
+                }
+                Some(hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(..), .. })) => {
+                    err.span_label(ident.span, "consider calling this function");
+                    ident.to_string()
+                }
+                Some(hir::Node::Ctor(..)) => {
+                    let name = self.tcx.def_path_str(def_id);
+                    err.span_label(
+                        self.tcx.def_span(def_id),
+                        format!("consider calling the constructor for `{}`", name),
+                    );
+                    name
+                }
+                _ => return false,
+            };
             err.help(&format!("{msg}: `{name}({args})`"));
         }
         true
diff --git a/src/test/ui/binop/issue-77910-1.stderr b/src/test/ui/binop/issue-77910-1.stderr
index cacea71ac97..263a35d9829 100644
--- a/src/test/ui/binop/issue-77910-1.stderr
+++ b/src/test/ui/binop/issue-77910-1.stderr
@@ -19,7 +19,7 @@ LL |     assert_eq!(foo, y);
    |     ^^^^^^^^^^^^^^^^^^ `for<'a> fn(&'a i32) -> &'a i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
    = help: the trait `Debug` is not implemented for fn item `for<'a> fn(&'a i32) -> &'a i32 {foo}`
-   = help: use parentheses to call the function: `foo(/* &i32 */)`
+   = help: use parentheses to call this function: `foo(/* &i32 */)`
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/closures/closure-bounds-subtype.stderr b/src/test/ui/closures/closure-bounds-subtype.stderr
index 1a40326d986..8ad8273fc2b 100644
--- a/src/test/ui/closures/closure-bounds-subtype.stderr
+++ b/src/test/ui/closures/closure-bounds-subtype.stderr
@@ -11,6 +11,10 @@ note: required by a bound in `take_const_owned`
    |
 LL | fn take_const_owned<F>(_: F) where F: FnOnce() + Sync + Send {
    |                                                  ^^^^ required by this bound in `take_const_owned`
+help: use parentheses to call this type parameter
+   |
+LL |     take_const_owned(f());
+   |                       ++
 help: consider further restricting this bound
    |
 LL | fn give_owned<F>(f: F) where F: FnOnce() + Send + std::marker::Sync {
diff --git a/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr b/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr
index 7f29709ce50..b30bcfb776c 100644
--- a/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr
+++ b/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr
@@ -29,7 +29,7 @@ LL |     assert_eq!(a, 0);
    |     ^^^^^^^^^^^^^^^^ `fn() -> i32 {a}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
    = help: the trait `Debug` is not implemented for fn item `fn() -> i32 {a}`
-   = help: use parentheses to call the function: `a()`
+   = help: use parentheses to call this function: `a()`
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
index bfd506c9f6e..8ed62f854f0 100644
--- a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
+++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
@@ -1,9 +1,6 @@
 error[E0277]: `fn() -> impl Future<Output = ()> {foo}` is not a future
   --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:10:9
    |
-LL | async fn foo() {}
-   |          --- consider calling this function
-...
 LL |     bar(foo);
    |     --- ^^^ `fn() -> impl Future<Output = ()> {foo}` is not a future
    |     |
@@ -16,7 +13,7 @@ note: required by a bound in `bar`
    |
 LL | fn bar(f: impl Future<Output=()>) {}
    |                ^^^^^^^^^^^^^^^^^ required by this bound in `bar`
-help: use parentheses to call the function
+help: use parentheses to call this function
    |
 LL |     bar(foo());
    |            ++
@@ -24,8 +21,6 @@ LL |     bar(foo());
 error[E0277]: `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` is not a future
   --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:12:9
    |
-LL |     let async_closure = async || ();
-   |                         -------- consider calling this closure
 LL |     bar(async_closure);
    |     --- ^^^^^^^^^^^^^ `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` is not a future
    |     |
@@ -38,7 +33,7 @@ note: required by a bound in `bar`
    |
 LL | fn bar(f: impl Future<Output=()>) {}
    |                ^^^^^^^^^^^^^^^^^ required by this bound in `bar`
-help: use parentheses to call the closure
+help: use parentheses to call this closure
    |
 LL |     bar(async_closure());
    |                      ++
diff --git a/src/test/ui/suggestions/call-on-unimplemented-ctor.rs b/src/test/ui/suggestions/call-on-unimplemented-ctor.rs
index 28a319382e6..0e7412807b4 100644
--- a/src/test/ui/suggestions/call-on-unimplemented-ctor.rs
+++ b/src/test/ui/suggestions/call-on-unimplemented-ctor.rs
@@ -2,7 +2,7 @@ fn main() {
     insert_resource(Marker);
     insert_resource(Time);
     //~^ ERROR the trait bound `fn(u32) -> Time {Time}: Resource` is not satisfied
-    //~| HELP use parentheses to call the constructor
+    //~| HELP use parentheses to instantiate this tuple struct
 }
 
 trait Resource {}
diff --git a/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr b/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr
index 8ffdff2a4a3..48f3366596f 100644
--- a/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr
+++ b/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr
@@ -5,16 +5,13 @@ LL |     insert_resource(Time);
    |     --------------- ^^^^ the trait `Resource` is not implemented for fn item `fn(u32) -> Time {Time}`
    |     |
    |     required by a bound introduced by this call
-...
-LL | struct Time(u32);
-   | ----------- consider calling the constructor for `Time`
    |
 note: required by a bound in `insert_resource`
   --> $DIR/call-on-unimplemented-ctor.rs:10:23
    |
 LL | fn insert_resource<R: Resource>(resource: R) {}
    |                       ^^^^^^^^ required by this bound in `insert_resource`
-help: use parentheses to call the constructor
+help: use parentheses to instantiate this tuple struct
    |
 LL |     insert_resource(Time(/* u32 */));
    |                         +++++++++++
diff --git a/src/test/ui/suggestions/call-on-unimplemented-fn-ptr.rs b/src/test/ui/suggestions/call-on-unimplemented-fn-ptr.rs
new file mode 100644
index 00000000000..86490c724e0
--- /dev/null
+++ b/src/test/ui/suggestions/call-on-unimplemented-fn-ptr.rs
@@ -0,0 +1,15 @@
+struct Foo;
+
+trait Bar {}
+
+impl Bar for Foo {}
+
+fn needs_bar<T: Bar>(_: T) {}
+
+fn blah(f: fn() -> Foo) {
+    needs_bar(f);
+    //~^ ERROR the trait bound `fn() -> Foo: Bar` is not satisfied
+    //~| HELP use parentheses to call this function pointer
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/call-on-unimplemented-fn-ptr.stderr b/src/test/ui/suggestions/call-on-unimplemented-fn-ptr.stderr
new file mode 100644
index 00000000000..167f7e592a9
--- /dev/null
+++ b/src/test/ui/suggestions/call-on-unimplemented-fn-ptr.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `fn() -> Foo: Bar` is not satisfied
+  --> $DIR/call-on-unimplemented-fn-ptr.rs:10:15
+   |
+LL |     needs_bar(f);
+   |     --------- ^ the trait `Bar` is not implemented for `fn() -> Foo`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `needs_bar`
+  --> $DIR/call-on-unimplemented-fn-ptr.rs:7:17
+   |
+LL | fn needs_bar<T: Bar>(_: T) {}
+   |                 ^^^ required by this bound in `needs_bar`
+help: use parentheses to call this function pointer
+   |
+LL |     needs_bar(f());
+   |                ++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
index fe603b67575..955148315ba 100644
--- a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
+++ b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
@@ -1,9 +1,6 @@
 error[E0277]: the trait bound `fn() -> impl T<O = ()> {foo}: T` is not satisfied
   --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:17:9
    |
-LL | fn foo() -> impl T<O=()> { S }
-   |    --- consider calling this function
-...
 LL |     bar(foo);
    |     --- ^^^ the trait `T` is not implemented for fn item `fn() -> impl T<O = ()> {foo}`
    |     |
@@ -14,7 +11,7 @@ note: required by a bound in `bar`
    |
 LL | fn bar(f: impl T<O=()>) {}
    |                ^^^^^^^ required by this bound in `bar`
-help: use parentheses to call the function
+help: use parentheses to call this function
    |
 LL |     bar(foo());
    |            ++
@@ -22,8 +19,6 @@ LL |     bar(foo());
 error[E0277]: the trait bound `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]: T` is not satisfied
   --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:19:9
    |
-LL |     let closure = || S;
-   |                   -- consider calling this closure
 LL |     bar(closure);
    |     --- ^^^^^^^ the trait `T` is not implemented for closure `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]`
    |     |
@@ -34,7 +29,7 @@ note: required by a bound in `bar`
    |
 LL | fn bar(f: impl T<O=()>) {}
    |                ^^^^^^^ required by this bound in `bar`
-help: use parentheses to call the closure
+help: use parentheses to call this closure
    |
 LL |     bar(closure());
    |                ++