about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-12-24 08:53:47 +0100
committerGitHub <noreply@github.com>2022-12-24 08:53:47 +0100
commita952b61e9413a9c0b6d16267bcfbf0cc65c4941d (patch)
tree0fd481fe14a9dd037fb6fcdbce96ca1dcab0aa56
parent9ae98804e51178a12bc8166bf469abc5283e10fd (diff)
parent3b38adf5682c153ce58e67fa346624b7bc5286b2 (diff)
downloadrust-a952b61e9413a9c0b6d16267bcfbf0cc65c4941d.tar.gz
rust-a952b61e9413a9c0b6d16267bcfbf0cc65c4941d.zip
Rollup merge of #105872 - chenyukang:yukang/fix-105494-remove-method-call, r=eholk
Suggest remove last method call when type coerce with expected  type

Fixes #105494
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs25
-rw-r--r--src/test/ui/suggestions/issue-105494.rs22
-rw-r--r--src/test/ui/suggestions/issue-105494.stderr54
4 files changed, 102 insertions, 0 deletions
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index e68bd1297c8..042ff0b46a5 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 efec0244633..9a7d753e66b 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -329,6 +329,31 @@ 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) {
+                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(
+                    span,
+                    "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 00000000000..8b409232c20
--- /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 00000000000..5aa3f2af738
--- /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`.