diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 501d117db70c..2daa4fd27ce5 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -333,8 +333,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { lhs_ty); if !lhs_expr.span.eq(&rhs_expr.span) { - self.add_type_neq_err_label(&mut err, lhs_expr.span, lhs_ty); - self.add_type_neq_err_label(&mut err, rhs_expr.span, rhs_ty); + self.add_type_neq_err_label(&mut err, + lhs_expr.span, + lhs_ty, + rhs_ty, + op, + is_assign); + self.add_type_neq_err_label(&mut err, + rhs_expr.span, + rhs_ty, + lhs_ty, + op, + is_assign); } let mut suggested_deref = false; @@ -420,10 +430,40 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { err: &mut errors::DiagnosticBuilder<'_>, span: Span, ty: Ty<'tcx>, + other_ty: Ty<'tcx>, + op: hir::BinOp, + is_assign: IsAssign, ) { err.span_label(span, ty.to_string()); - if let FnDef(..) = ty.sty { - err.span_label(span, "did you forget `()`?"); + if let FnDef(def_id, _) = ty.sty { + let source_map = self.tcx.sess.source_map(); + let hir_id = &self.tcx.hir().as_local_hir_id(def_id).unwrap(); + let fn_sig = { + match self.tcx.typeck_tables_of(def_id).liberated_fn_sigs().get(*hir_id) { + Some(f) => f.clone(), + None => { + bug!("No fn-sig entry for def_id={:?}", def_id); + } + } + }; + + if self.lookup_op_method(fn_sig.output(), + &[other_ty], + Op::Binary(op, is_assign)) + .is_ok() { + let variable_snippet = if fn_sig.inputs().len() > 0 { + format!("{}( /* arguments */ )", source_map.span_to_snippet(span).unwrap()) + } else { + format!("{}()", source_map.span_to_snippet(span).unwrap()) + }; + + err.span_suggestion( + span, + "did you forget", + variable_snippet, + Applicability::MachineApplicable, + ); + } } } diff --git a/src/test/ui/fn/fn-compare-mismatch.stderr b/src/test/ui/fn/fn-compare-mismatch.stderr index 6f1155d597e6..07b93d9aae7e 100644 --- a/src/test/ui/fn/fn-compare-mismatch.stderr +++ b/src/test/ui/fn/fn-compare-mismatch.stderr @@ -2,12 +2,9 @@ error[E0369]: binary operation `==` cannot be applied to type `fn() {main::f}` --> $DIR/fn-compare-mismatch.rs:4:15 | LL | let x = f == g; - | - ^^ - - | | | - | | fn() {main::g} - | | did you forget `()`? + | - ^^ - fn() {main::g} + | | | fn() {main::f} - | did you forget `()`? | = note: an implementation of `std::cmp::PartialEq` might be missing for `fn() {main::f}` diff --git a/src/test/ui/issues/issue-59488.rs b/src/test/ui/issues/issue-59488.rs index 937eb72fa22c..ab501a2c8ec7 100644 --- a/src/test/ui/issues/issue-59488.rs +++ b/src/test/ui/issues/issue-59488.rs @@ -1,9 +1,19 @@ +// ignore-tidy-linelength + fn foo() -> i32 { 42 } +fn bar(a: i64) -> i64 { + 43 +} + fn main() { foo > 12; - //~^ ERROR 6:9: 6:10: binary operation `>` cannot be applied to type `fn() -> i32 {foo}` [E0369] - //~| ERROR 6:11: 6:13: mismatched types [E0308] + //~^ ERROR 12:9: 12:10: binary operation `>` cannot be applied to type `fn() -> i32 {foo}` [E0369] + //~| ERROR 12:11: 12:13: mismatched types [E0308] + + bar > 13; + //~^ ERROR 16:9: 16:10: binary operation `>` cannot be applied to type `fn(i64) -> i64 {bar}` [E0369] + //~| ERROR 16:11: 16:13: mismatched types [E0308] } diff --git a/src/test/ui/issues/issue-59488.stderr b/src/test/ui/issues/issue-59488.stderr index 7bd7700026cc..2eaf4220a42c 100644 --- a/src/test/ui/issues/issue-59488.stderr +++ b/src/test/ui/issues/issue-59488.stderr @@ -1,24 +1,44 @@ error[E0369]: binary operation `>` cannot be applied to type `fn() -> i32 {foo}` - --> $DIR/issue-59488.rs:6:9 + --> $DIR/issue-59488.rs:12:9 | LL | foo > 12; | --- ^ -- {integer} | | | fn() -> i32 {foo} - | did you forget `()`? + | help: did you forget: `foo()` | = note: an implementation of `std::cmp::PartialOrd` might be missing for `fn() -> i32 {foo}` error[E0308]: mismatched types - --> $DIR/issue-59488.rs:6:11 + --> $DIR/issue-59488.rs:12:11 | LL | foo > 12; | ^^ expected fn item, found integer | = note: expected type `fn() -> i32 {foo}` - found type `{integer}` + found type `i32` -error: aborting due to 2 previous errors +error[E0369]: binary operation `>` cannot be applied to type `fn(i64) -> i64 {bar}` + --> $DIR/issue-59488.rs:16:9 + | +LL | bar > 13; + | --- ^ -- {integer} + | | + | fn(i64) -> i64 {bar} + | help: did you forget: `bar( /* arguments */ )` + | + = note: an implementation of `std::cmp::PartialOrd` might be missing for `fn(i64) -> i64 {bar}` + +error[E0308]: mismatched types + --> $DIR/issue-59488.rs:16:11 + | +LL | bar > 13; + | ^^ expected fn item, found integer + | + = note: expected type `fn(i64) -> i64 {bar}` + found type `i64` + +error: aborting due to 4 previous errors Some errors occurred: E0308, E0369. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr index d44e2242cc23..8899b0d43cd8 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr +++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr @@ -44,7 +44,6 @@ LL | f(); | -^- X | | | fn() {f::<_>} - | did you forget `()`? | = note: an implementation of `std::cmp::PartialOrd` might be missing for `fn() {f::<_>}`