about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTakayuki Maeda <takoyaki0316@gmail.com>2022-07-11 02:19:45 +0900
committerTakayuki Maeda <takoyaki0316@gmail.com>2022-07-11 02:19:45 +0900
commit1599c5a82175485bdebbb231fba1cedcac742868 (patch)
treeb71401890f71884783c08c97f16293ffb16ef7dc
parent17355a3b9f30e16870a1890033bd13463c664f81 (diff)
downloadrust-1599c5a82175485bdebbb231fba1cedcac742868.tar.gz
rust-1599c5a82175485bdebbb231fba1cedcac742868.zip
remove a string matching about methods
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs93
-rw-r--r--src/test/ui/suggestions/issue-52820.fixed15
-rw-r--r--src/test/ui/suggestions/issue-52820.rs3
-rw-r--r--src/test/ui/suggestions/issue-52820.stderr10
-rw-r--r--src/test/ui/suggestions/issue-53692.fixed20
-rw-r--r--src/test/ui/suggestions/issue-53692.rs27
-rw-r--r--src/test/ui/suggestions/issue-53692.stderr28
7 files changed, 122 insertions, 74 deletions
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
index 863a981134f..721fc8c5681 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -14,7 +14,7 @@ use rustc_infer::infer::{self, TyCtxtInferExt};
 use rustc_infer::traits;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, Binder, IsSuggestable, Subst, ToPredicate, Ty};
-use rustc_span::symbol::sym;
+use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 
@@ -187,55 +187,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 err.span_label(self.tcx.def_span(def_id), &format!("{} defined here", found));
             }
         } else if !self.check_for_cast(err, expr, found, expected, expected_ty_expr) {
-            let is_struct_pat_shorthand_field =
-                self.maybe_get_struct_pattern_shorthand_field(expr).is_some();
+            let struct_pat_shorthand_field = self.maybe_get_struct_pattern_shorthand_field(expr);
             let methods = self.get_conversion_methods(expr.span, expected, found, expr.hir_id);
             if !methods.is_empty() {
-                if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) {
-                    let mut suggestions = iter::zip(iter::repeat(&expr_text), &methods)
-                        .filter_map(|(receiver, method)| {
-                            let method_call = format!(".{}()", method.name);
-                            if receiver.ends_with(&method_call) {
-                                None // do not suggest code that is already there (#53348)
+                let mut suggestions = iter::zip(iter::repeat(&expr), &methods)
+                    .filter_map(|(receiver_expr, method)| {
+                        let method_call = format!(".{}()", method.name);
+                        fn method_ident(expr: &hir::Expr<'_>) -> Option<Ident> {
+                            match expr.kind {
+                                ExprKind::MethodCall(receiver_method, ..) => Some(receiver_method.ident),
+                                ExprKind::Unary(_, expr) | ExprKind::AddrOf(.., expr) => method_ident(expr),
+                                _ => None
+                            }
+                        }
+                        let method_ident = method_ident(&receiver_expr);
+                        if let Some(method_ident) = method_ident
+                            && method_ident.name == method.name
+                        {
+                            None // do not suggest code that is already there (#53348)
+                        } else {
+                            let method_call_list = [".to_vec()", ".to_string()"];
+                            let mut sugg = if let ExprKind::MethodCall(receiver_method, ..) = receiver_expr.kind
+                                && receiver_method.ident.name == sym::clone
+                                && method_call_list.contains(&method_call.as_str())
+                            {
+                                vec![(
+                                    receiver_method.ident.span,
+                                    method.name.to_string()
+                                )]
                             } else {
-                                let method_call_list = [".to_vec()", ".to_string()"];
-                                let mut sugg = if receiver.ends_with(".clone()")
-                                    && method_call_list.contains(&method_call.as_str())
+                                if expr.precedence().order()
+                                    < ExprPrecedence::MethodCall.order()
                                 {
-                                    let max_len = receiver.rfind('.').unwrap();
-                                    vec![(
-                                        expr.span,
-                                        format!("{}{}", &receiver[..max_len], method_call),
-                                    )]
+                                    vec![
+                                        (expr.span.shrink_to_lo(), "(".to_string()),
+                                        (expr.span.shrink_to_hi(), format!("){}", method_call)),
+                                    ]
                                 } else {
-                                    if expr.precedence().order()
-                                        < ExprPrecedence::MethodCall.order()
-                                    {
-                                        vec![
-                                            (expr.span.shrink_to_lo(), "(".to_string()),
-                                            (expr.span.shrink_to_hi(), format!("){}", method_call)),
-                                        ]
-                                    } else {
-                                        vec![(expr.span.shrink_to_hi(), method_call)]
-                                    }
-                                };
-                                if is_struct_pat_shorthand_field {
-                                    sugg.insert(
-                                        0,
-                                        (expr.span.shrink_to_lo(), format!("{}: ", receiver)),
-                                    );
+                                    vec![(expr.span.shrink_to_hi(), method_call)]
                                 }
-                                Some(sugg)
+                            };
+                            if let Some(name) = struct_pat_shorthand_field {
+                                sugg.insert(
+                                    0,
+                                    (expr.span.shrink_to_lo(), format!("{}: ", name)),
+                                );
                             }
-                        })
-                        .peekable();
-                    if suggestions.peek().is_some() {
-                        err.multipart_suggestions(
-                            "try using a conversion method",
-                            suggestions,
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
+                            Some(sugg)
+                        }
+                    })
+                    .peekable();
+                if suggestions.peek().is_some() {
+                    err.multipart_suggestions(
+                        "try using a conversion method",
+                        suggestions,
+                        Applicability::MaybeIncorrect,
+                    );
                 }
             } else if let ty::Adt(found_adt, found_substs) = found.kind()
                 && self.tcx.is_diagnostic_item(sym::Option, found_adt.did())
diff --git a/src/test/ui/suggestions/issue-52820.fixed b/src/test/ui/suggestions/issue-52820.fixed
new file mode 100644
index 00000000000..514690de4d0
--- /dev/null
+++ b/src/test/ui/suggestions/issue-52820.fixed
@@ -0,0 +1,15 @@
+// run-rustfix
+#![allow(dead_code)]
+
+struct Bravery {
+    guts: String,
+    brains: String,
+}
+
+fn main() {
+    let guts = "mettle";
+    let _ = Bravery {
+        guts: guts.to_string(), //~ ERROR mismatched types
+        brains: guts.to_string(), //~ ERROR mismatched types
+    };
+}
diff --git a/src/test/ui/suggestions/issue-52820.rs b/src/test/ui/suggestions/issue-52820.rs
index 075b07f5652..17cd9224c57 100644
--- a/src/test/ui/suggestions/issue-52820.rs
+++ b/src/test/ui/suggestions/issue-52820.rs
@@ -1,3 +1,6 @@
+// run-rustfix
+#![allow(dead_code)]
+
 struct Bravery {
     guts: String,
     brains: String,
diff --git a/src/test/ui/suggestions/issue-52820.stderr b/src/test/ui/suggestions/issue-52820.stderr
index 7b465844501..09269ed4eee 100644
--- a/src/test/ui/suggestions/issue-52820.stderr
+++ b/src/test/ui/suggestions/issue-52820.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-52820.rs:9:9
+  --> $DIR/issue-52820.rs:12:9
    |
 LL |         guts,
    |         ^^^^ expected struct `String`, found `&str`
@@ -10,13 +10,13 @@ LL |         guts: guts.to_string(),
    |         +++++     ++++++++++++
 
 error[E0308]: mismatched types
-  --> $DIR/issue-52820.rs:10:17
+  --> $DIR/issue-52820.rs:13:17
    |
 LL |         brains: guts.clone(),
-   |                 ^^^^^^^^^^^^
-   |                 |
+   |                 ^^^^^-----^^
+   |                 |    |
+   |                 |    help: try using a conversion method: `to_string`
    |                 expected struct `String`, found `&str`
-   |                 help: try using a conversion method: `guts.to_string()`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/suggestions/issue-53692.fixed b/src/test/ui/suggestions/issue-53692.fixed
new file mode 100644
index 00000000000..35a677b4761
--- /dev/null
+++ b/src/test/ui/suggestions/issue-53692.fixed
@@ -0,0 +1,20 @@
+// run-rustfix
+#![allow(unused_variables)]
+
+fn main() {
+    let items = vec![1, 2, 3];
+    let ref_items: &[i32] = &items;
+    let items_clone: Vec<i32> = ref_items.to_vec();
+    //~^ ERROR mismatched types
+
+    // in that case no suggestion will be triggered
+    let items_clone_2: Vec<i32> = items.clone();
+
+    let s = "hi";
+    let string: String = s.to_string();
+    //~^ ERROR mismatched types
+
+    // in that case no suggestion will be triggered
+    let s2 = "hi";
+    let string_2: String = s2.to_string();
+}
diff --git a/src/test/ui/suggestions/issue-53692.rs b/src/test/ui/suggestions/issue-53692.rs
index 30f344e4282..6f6707be5f6 100644
--- a/src/test/ui/suggestions/issue-53692.rs
+++ b/src/test/ui/suggestions/issue-53692.rs
@@ -1,17 +1,20 @@
+// run-rustfix
+#![allow(unused_variables)]
+
 fn main() {
-        let items = vec![1, 2, 3];
-        let ref_items: &[i32] = &items;
-        let items_clone: Vec<i32> = ref_items.clone();
-//~^ ERROR mismatched types
+    let items = vec![1, 2, 3];
+    let ref_items: &[i32] = &items;
+    let items_clone: Vec<i32> = ref_items.clone();
+    //~^ ERROR mismatched types
 
-        // in that case no suggestion will be triggered
-        let items_clone_2:Vec<i32> = items.clone();
+    // in that case no suggestion will be triggered
+    let items_clone_2: Vec<i32> = items.clone();
 
-        let s = "hi";
-        let string: String = s.clone();
-//~^ ERROR mismatched types
+    let s = "hi";
+    let string: String = s.clone();
+    //~^ ERROR mismatched types
 
-        // in that case no suggestion will be triggered
-        let s2 = "hi";
-        let string_2: String = s2.to_string();
+    // in that case no suggestion will be triggered
+    let s2 = "hi";
+    let string_2: String = s2.to_string();
 }
diff --git a/src/test/ui/suggestions/issue-53692.stderr b/src/test/ui/suggestions/issue-53692.stderr
index 09c78da54bc..3a1b624f402 100644
--- a/src/test/ui/suggestions/issue-53692.stderr
+++ b/src/test/ui/suggestions/issue-53692.stderr
@@ -1,25 +1,25 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-53692.rs:4:37
+  --> $DIR/issue-53692.rs:7:33
    |
-LL |         let items_clone: Vec<i32> = ref_items.clone();
-   |                          --------   ^^^^^^^^^^^^^^^^^
-   |                          |          |
-   |                          |          expected struct `Vec`, found `&[i32]`
-   |                          |          help: try using a conversion method: `ref_items.to_vec()`
-   |                          expected due to this
+LL |     let items_clone: Vec<i32> = ref_items.clone();
+   |                      --------   ^^^^^^^^^^-----^^
+   |                      |          |         |
+   |                      |          |         help: try using a conversion method: `to_vec`
+   |                      |          expected struct `Vec`, found `&[i32]`
+   |                      expected due to this
    |
    = note: expected struct `Vec<i32>`
            found reference `&[i32]`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-53692.rs:11:30
+  --> $DIR/issue-53692.rs:14:26
    |
-LL |         let string: String = s.clone();
-   |                     ------   ^^^^^^^^^
-   |                     |        |
-   |                     |        expected struct `String`, found `&str`
-   |                     |        help: try using a conversion method: `s.to_string()`
-   |                     expected due to this
+LL |     let string: String = s.clone();
+   |                 ------   ^^-----^^
+   |                 |        | |
+   |                 |        | help: try using a conversion method: `to_string`
+   |                 |        expected struct `String`, found `&str`
+   |                 expected due to this
 
 error: aborting due to 2 previous errors