From 459b234e6ace06854a383aae02c656b3410ec344 Mon Sep 17 00:00:00 2001 From: yukang Date: Sun, 18 Dec 2022 02:56:56 +0800 Subject: [PATCH 1/2] fix #105494, Suggest remove last method call when type coerce with expected --- compiler/rustc_hir_typeck/src/demand.rs | 1 + .../src/fn_ctxt/suggestions.rs | 20 +++++++ src/test/ui/suggestions/issue-105494.rs | 22 ++++++++ src/test/ui/suggestions/issue-105494.stderr | 54 +++++++++++++++++++ 4 files changed, 97 insertions(+) create mode 100644 src/test/ui/suggestions/issue-105494.rs create mode 100644 src/test/ui/suggestions/issue-105494.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index e68bd1297c878..042ff0b46a5af 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -38,6 +38,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Use `||` to give these suggestions a precedence let _ = self.suggest_missing_parentheses(err, expr) + || self.suggest_remove_last_method_call(err, expr, expected) || self.suggest_associated_const(err, expr, expected) || self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr) || self.suggest_option_to_bool(err, expr, expr_ty, expected) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index efec024463334..720fbd1ad147b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -329,6 +329,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + pub fn suggest_remove_last_method_call( + &self, + err: &mut Diagnostic, + expr: &hir::Expr<'tcx>, + expected: Ty<'tcx>, + ) -> bool { + if let hir::ExprKind::MethodCall(hir::PathSegment { ident: method, .. }, recv_expr, &[], _) = expr.kind && + let Some(recv_ty) = self.typeck_results.borrow().expr_ty_opt(recv_expr) && + self.can_coerce(recv_ty, expected) { + err.span_suggestion_verbose( + expr.span.with_lo(method.span.lo() - rustc_span::BytePos(1)), + "try removing the method call", + "", + Applicability::MachineApplicable, + ); + return true; + } + false + } + pub fn suggest_deref_ref_or_into( &self, err: &mut Diagnostic, diff --git a/src/test/ui/suggestions/issue-105494.rs b/src/test/ui/suggestions/issue-105494.rs new file mode 100644 index 0000000000000..8b409232c202c --- /dev/null +++ b/src/test/ui/suggestions/issue-105494.rs @@ -0,0 +1,22 @@ +fn test1() { + let _v: i32 = (1 as i32).to_string(); //~ ERROR mismatched types + + // won't suggestion + let _v: i32 = (1 as i128).to_string(); //~ ERROR mismatched types + + let _v: &str = "foo".to_string(); //~ ERROR mismatched types +} + +fn test2() { + let mut path: String = "/usr".to_string(); + let folder: String = "lib".to_string(); + + path = format!("{}/{}", path, folder).as_str(); //~ ERROR mismatched types + + println!("{}", &path); +} + +fn main() { + test1(); + test2(); +} diff --git a/src/test/ui/suggestions/issue-105494.stderr b/src/test/ui/suggestions/issue-105494.stderr new file mode 100644 index 0000000000000..5aa3f2af738f4 --- /dev/null +++ b/src/test/ui/suggestions/issue-105494.stderr @@ -0,0 +1,54 @@ +error[E0308]: mismatched types + --> $DIR/issue-105494.rs:2:19 + | +LL | let _v: i32 = (1 as i32).to_string(); + | --- ^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String` + | | + | expected due to this + | +help: try removing the method call + | +LL - let _v: i32 = (1 as i32).to_string(); +LL + let _v: i32 = (1 as i32); + | + +error[E0308]: mismatched types + --> $DIR/issue-105494.rs:5:19 + | +LL | let _v: i32 = (1 as i128).to_string(); + | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/issue-105494.rs:7:20 + | +LL | let _v: &str = "foo".to_string(); + | ---- ^^^^^^^^^^^^^^^^^ expected `&str`, found struct `String` + | | + | expected due to this + | +help: try removing the method call + | +LL - let _v: &str = "foo".to_string(); +LL + let _v: &str = "foo"; + | + +error[E0308]: mismatched types + --> $DIR/issue-105494.rs:14:12 + | +LL | let mut path: String = "/usr".to_string(); + | ------ expected due to this type +... +LL | path = format!("{}/{}", path, folder).as_str(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&str` + | +help: try removing the method call + | +LL - path = format!("{}/{}", path, folder).as_str(); +LL + path = format!("{}/{}", path, folder); + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. From 3b38adf5682c153ce58e67fa346624b7bc5286b2 Mon Sep 17 00:00:00 2001 From: yukang Date: Sun, 18 Dec 2022 17:38:01 +0800 Subject: [PATCH 2/2] fix suggest span for #105494 --- compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 720fbd1ad147b..9a7d753e66b8e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -338,8 +338,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let hir::ExprKind::MethodCall(hir::PathSegment { ident: method, .. }, recv_expr, &[], _) = expr.kind && let Some(recv_ty) = self.typeck_results.borrow().expr_ty_opt(recv_expr) && self.can_coerce(recv_ty, expected) { + let span = if let Some(recv_span) = recv_expr.span.find_ancestor_inside(expr.span) { + expr.span.with_lo(recv_span.hi()) + } else { + expr.span.with_lo(method.span.lo() - rustc_span::BytePos(1)) + }; err.span_suggestion_verbose( - expr.span.with_lo(method.span.lo() - rustc_span::BytePos(1)), + span, "try removing the method call", "", Applicability::MachineApplicable,