From 89eac91e0576bbf81af4e10a8be47b935592a922 Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Sun, 7 Apr 2019 22:51:33 +0900 Subject: [PATCH 1/4] Improvement for comparision against fn --- src/librustc_typeck/check/op.rs | 10 +++++++- src/test/ui/fn/fn-compare-mismatch.stderr | 7 ++++-- src/test/ui/issues/issue-59488.rs | 9 +++++++ src/test/ui/issues/issue-59488.stderr | 24 +++++++++++++++++++ ...quire-parens-for-chained-comparison.stderr | 1 + 5 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/issues/issue-59488.rs create mode 100644 src/test/ui/issues/issue-59488.stderr diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index d6932094dddb6..70c9d9ddee3d4 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}; @@ -334,9 +334,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if !lhs_expr.span.eq(&rhs_expr.span) { err.span_label(lhs_expr.span, lhs_ty.to_string()); + if let FnDef(..) = lhs_ty.sty { + err.span_label(lhs_expr.span, "did you forget `()`?"); + } + err.span_label(rhs_expr.span, rhs_ty.to_string()); + if let FnDef(..) = rhs_ty.sty { + err.span_label(rhs_expr.span, "did you forget `()`?"); + } } + let mut suggested_deref = false; if let Ref(_, mut rty, _) = lhs_ty.sty { if { diff --git a/src/test/ui/fn/fn-compare-mismatch.stderr b/src/test/ui/fn/fn-compare-mismatch.stderr index 07b93d9aae7ed..6f1155d597e62 100644 --- a/src/test/ui/fn/fn-compare-mismatch.stderr +++ b/src/test/ui/fn/fn-compare-mismatch.stderr @@ -2,9 +2,12 @@ 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} - | | + | - ^^ - + | | | + | | fn() {main::g} + | | did you forget `()`? | 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 new file mode 100644 index 0000000000000..937eb72fa22cc --- /dev/null +++ b/src/test/ui/issues/issue-59488.rs @@ -0,0 +1,9 @@ +fn foo() -> i32 { + 42 +} + +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] +} diff --git a/src/test/ui/issues/issue-59488.stderr b/src/test/ui/issues/issue-59488.stderr new file mode 100644 index 0000000000000..7bd7700026cc7 --- /dev/null +++ b/src/test/ui/issues/issue-59488.stderr @@ -0,0 +1,24 @@ +error[E0369]: binary operation `>` cannot be applied to type `fn() -> i32 {foo}` + --> $DIR/issue-59488.rs:6:9 + | +LL | foo > 12; + | --- ^ -- {integer} + | | + | fn() -> i32 {foo} + | did you forget `()`? + | + = note: an implementation of `std::cmp::PartialOrd` might be missing for `fn() -> i32 {foo}` + +error[E0308]: mismatched types + --> $DIR/issue-59488.rs:6:11 + | +LL | foo > 12; + | ^^ expected fn item, found integer + | + = note: expected type `fn() -> i32 {foo}` + found type `{integer}` + +error: aborting due to 2 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 8899b0d43cd8b..d44e2242cc23f 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr +++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr @@ -44,6 +44,7 @@ LL | f(); | -^- X | | | fn() {f::<_>} + | did you forget `()`? | = note: an implementation of `std::cmp::PartialOrd` might be missing for `fn() {f::<_>}` From cbcbd2c3bb52cd6c53c45a6a2476d510c892d2cc Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Tue, 9 Apr 2019 20:49:17 +0900 Subject: [PATCH 2/4] create add_type_neq_err_label --- src/librustc_typeck/check/op.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 70c9d9ddee3d4..501d117db70cd 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -333,18 +333,10 @@ 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()); - if let FnDef(..) = lhs_ty.sty { - err.span_label(lhs_expr.span, "did you forget `()`?"); - } - - err.span_label(rhs_expr.span, rhs_ty.to_string()); - if let FnDef(..) = rhs_ty.sty { - err.span_label(rhs_expr.span, "did you forget `()`?"); - } + 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); } - let mut suggested_deref = false; if let Ref(_, mut rty, _) = lhs_ty.sty { if { @@ -423,6 +415,18 @@ 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>, + ) { + err.span_label(span, ty.to_string()); + if let FnDef(..) = ty.sty { + err.span_label(span, "did you forget `()`?"); + } + } + fn check_str_addition( &self, expr: &'gcx hir::Expr, From 199b0bad3c233ba5bec8895efe6c8888c9ce5bee Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Fri, 12 Apr 2019 00:00:27 +0900 Subject: [PATCH 3/4] improve error messages --- src/librustc_typeck/check/op.rs | 48 +++++++++++++++++-- src/test/ui/fn/fn-compare-mismatch.stderr | 7 +-- src/test/ui/issues/issue-59488.rs | 14 +++++- src/test/ui/issues/issue-59488.stderr | 30 ++++++++++-- ...quire-parens-for-chained-comparison.stderr | 1 - 5 files changed, 83 insertions(+), 17 deletions(-) diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 501d117db70cd..2daa4fd27ce56 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 6f1155d597e62..07b93d9aae7ed 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 937eb72fa22cc..ab501a2c8ec7c 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 7bd7700026cc7..2eaf4220a42c5 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 d44e2242cc23f..8899b0d43cd8b 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::<_>}` From d01ac0d61e31ffdff0a85a76de6f4449935b5a6b Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Fri, 12 Apr 2019 22:59:30 +0900 Subject: [PATCH 4/4] add the logic for when other_ty is FnDef --- src/librustc_typeck/check/op.rs | 52 +++++++++++++++-------- src/test/ui/fn/fn-compare-mismatch.stderr | 8 ++++ src/test/ui/issues/issue-59488.rs | 7 +++ src/test/ui/issues/issue-59488.stderr | 43 +++++++++++++++++-- 4 files changed, 90 insertions(+), 20 deletions(-) diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 2daa4fd27ce56..d2fe099e433f2 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -333,18 +333,22 @@ 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, - rhs_ty, - op, - is_assign); - self.add_type_neq_err_label(&mut err, - rhs_expr.span, - rhs_ty, - lhs_ty, - op, - is_assign); + 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; @@ -447,21 +451,35 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }; + 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 = if fn_sig.inputs().len() > 0 { - format!("{}( /* arguments */ )", source_map.span_to_snippet(span).unwrap()) + 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()) + (format!("{}()", source_map.span_to_snippet(span).unwrap()), + Applicability::MaybeIncorrect) }; err.span_suggestion( span, - "did you forget", + "you might have forgotten to call this function", variable_snippet, - Applicability::MachineApplicable, + applicability, ); } } 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 index ab501a2c8ec7c..27cf16a821ffc 100644 --- a/src/test/ui/issues/issue-59488.rs +++ b/src/test/ui/issues/issue-59488.rs @@ -16,4 +16,11 @@ fn main() { 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 index 2eaf4220a42c5..b49f5e35f4226 100644 --- a/src/test/ui/issues/issue-59488.stderr +++ b/src/test/ui/issues/issue-59488.stderr @@ -5,7 +5,7 @@ LL | foo > 12; | --- ^ -- {integer} | | | fn() -> i32 {foo} - | help: did you forget: `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}` @@ -25,7 +25,7 @@ LL | bar > 13; | --- ^ -- {integer} | | | fn(i64) -> i64 {bar} - | help: did you forget: `bar( /* arguments */ )` + | 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}` @@ -38,7 +38,44 @@ LL | bar > 13; = note: expected type `fn(i64) -> i64 {bar}` found type `i64` -error: aborting due to 4 previous errors +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`.