diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index d6932094dddb6..d2fe099e433f2 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -3,7 +3,7 @@ use super::{FnCtxt, Needs}; use super::method::MethodCallee; use rustc::ty::{self, Ty, TypeFoldable}; -use rustc::ty::TyKind::{Ref, Adt, Str, Uint, Never, Tuple, Char, Array}; +use rustc::ty::TyKind::{Ref, Adt, FnDef, Str, Uint, Never, Tuple, Char, Array}; use rustc::ty::adjustment::{Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::infer::type_variable::TypeVariableOrigin; use errors::{self,Applicability}; @@ -333,8 +333,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { lhs_ty); if !lhs_expr.span.eq(&rhs_expr.span) { - err.span_label(lhs_expr.span, lhs_ty.to_string()); - err.span_label(rhs_expr.span, rhs_ty.to_string()); + 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; @@ -415,6 +429,62 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { (lhs_ty, rhs_ty, return_ty) } + fn add_type_neq_err_label( + &self, + 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(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); + } + } + }; + + let other_ty = if let FnDef(def_id, _) = other_ty.sty { + let hir_id = &self.tcx.hir().as_local_hir_id(def_id).unwrap(); + match self.tcx.typeck_tables_of(def_id).liberated_fn_sigs().get(*hir_id) { + Some(f) => f.clone().output(), + None => { + bug!("No fn-sig entry for def_id={:?}", def_id); + } + } + } else { + other_ty + }; + + if self.lookup_op_method(fn_sig.output(), + &[other_ty], + Op::Binary(op, is_assign)) + .is_ok() { + let (variable_snippet, applicability) = if fn_sig.inputs().len() > 0 { + (format!("{}( /* arguments */ )", source_map.span_to_snippet(span).unwrap()), + Applicability::HasPlaceholders) + } else { + (format!("{}()", source_map.span_to_snippet(span).unwrap()), + Applicability::MaybeIncorrect) + }; + + err.span_suggestion( + span, + "you might have forgotten to call this function", + variable_snippet, + applicability, + ); + } + } + } + fn check_str_addition( &self, expr: &'gcx hir::Expr, diff --git a/src/test/ui/fn/fn-compare-mismatch.stderr b/src/test/ui/fn/fn-compare-mismatch.stderr index 07b93d9aae7ed..74fb00f8ac383 100644 --- a/src/test/ui/fn/fn-compare-mismatch.stderr +++ b/src/test/ui/fn/fn-compare-mismatch.stderr @@ -7,6 +7,14 @@ LL | let x = f == g; | fn() {main::f} | = note: an implementation of `std::cmp::PartialEq` might be missing for `fn() {main::f}` +help: you might have forgotten to call this function + | +LL | let x = f() == g; + | ^^^ +help: you might have forgotten to call this function + | +LL | let x = f == g(); + | ^^^ error[E0308]: mismatched types --> $DIR/fn-compare-mismatch.rs:4:18 diff --git a/src/test/ui/issues/issue-59488.rs b/src/test/ui/issues/issue-59488.rs new file mode 100644 index 0000000000000..27cf16a821ffc --- /dev/null +++ b/src/test/ui/issues/issue-59488.rs @@ -0,0 +1,26 @@ +// ignore-tidy-linelength + +fn foo() -> i32 { + 42 +} + +fn bar(a: i64) -> i64 { + 43 +} + +fn main() { + foo > 12; + //~^ 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] + + foo > foo; + //~^ ERROR 20:9: 20:10: binary operation `>` cannot be applied to type `fn() -> i32 {foo}` [E0369] + + foo > bar; + //~^ ERROR 23:9: 23:10: binary operation `>` cannot be applied to type `fn() -> i32 {foo}` [E0369] + //~| ERROR 23:11: 23:14: mismatched types [E0308] +} diff --git a/src/test/ui/issues/issue-59488.stderr b/src/test/ui/issues/issue-59488.stderr new file mode 100644 index 0000000000000..b49f5e35f4226 --- /dev/null +++ b/src/test/ui/issues/issue-59488.stderr @@ -0,0 +1,81 @@ +error[E0369]: binary operation `>` cannot be applied to type `fn() -> i32 {foo}` + --> $DIR/issue-59488.rs:12:9 + | +LL | foo > 12; + | --- ^ -- {integer} + | | + | fn() -> i32 {foo} + | help: you might have forgotten to call this function: `foo()` + | + = note: an implementation of `std::cmp::PartialOrd` might be missing for `fn() -> i32 {foo}` + +error[E0308]: mismatched types + --> $DIR/issue-59488.rs:12:11 + | +LL | foo > 12; + | ^^ expected fn item, found integer + | + = note: expected type `fn() -> i32 {foo}` + found type `i32` + +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: you might have forgotten to call this function: `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[E0369]: binary operation `>` cannot be applied to type `fn() -> i32 {foo}` + --> $DIR/issue-59488.rs:20:9 + | +LL | foo > foo; + | --- ^ --- fn() -> i32 {foo} + | | + | fn() -> i32 {foo} + | + = note: an implementation of `std::cmp::PartialOrd` might be missing for `fn() -> i32 {foo}` +help: you might have forgotten to call this function + | +LL | foo() > foo; + | ^^^^^ +help: you might have forgotten to call this function + | +LL | foo > foo(); + | ^^^^^ + +error[E0369]: binary operation `>` cannot be applied to type `fn() -> i32 {foo}` + --> $DIR/issue-59488.rs:23:9 + | +LL | foo > bar; + | --- ^ --- fn(i64) -> i64 {bar} + | | + | fn() -> i32 {foo} + | + = note: an implementation of `std::cmp::PartialOrd` might be missing for `fn() -> i32 {foo}` + +error[E0308]: mismatched types + --> $DIR/issue-59488.rs:23:11 + | +LL | foo > bar; + | ^^^ expected fn item, found a different fn item + | + = note: expected type `fn() -> i32 {foo}` + found type `fn(i64) -> i64 {bar}` + +error: aborting due to 7 previous errors + +Some errors occurred: E0308, E0369. +For more information about an error, try `rustc --explain E0308`.