Skip to content

Commit 1599c5a

Browse files
committed
remove a string matching about methods
1 parent 17355a3 commit 1599c5a

File tree

7 files changed

+122
-74
lines changed

7 files changed

+122
-74
lines changed

compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs

+50-43
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_infer::infer::{self, TyCtxtInferExt};
1414
use rustc_infer::traits;
1515
use rustc_middle::lint::in_external_macro;
1616
use rustc_middle::ty::{self, Binder, IsSuggestable, Subst, ToPredicate, Ty};
17-
use rustc_span::symbol::sym;
17+
use rustc_span::symbol::{sym, Ident};
1818
use rustc_span::Span;
1919
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
2020

@@ -187,55 +187,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
187187
err.span_label(self.tcx.def_span(def_id), &format!("{} defined here", found));
188188
}
189189
} else if !self.check_for_cast(err, expr, found, expected, expected_ty_expr) {
190-
let is_struct_pat_shorthand_field =
191-
self.maybe_get_struct_pattern_shorthand_field(expr).is_some();
190+
let struct_pat_shorthand_field = self.maybe_get_struct_pattern_shorthand_field(expr);
192191
let methods = self.get_conversion_methods(expr.span, expected, found, expr.hir_id);
193192
if !methods.is_empty() {
194-
if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) {
195-
let mut suggestions = iter::zip(iter::repeat(&expr_text), &methods)
196-
.filter_map(|(receiver, method)| {
197-
let method_call = format!(".{}()", method.name);
198-
if receiver.ends_with(&method_call) {
199-
None // do not suggest code that is already there (#53348)
193+
let mut suggestions = iter::zip(iter::repeat(&expr), &methods)
194+
.filter_map(|(receiver_expr, method)| {
195+
let method_call = format!(".{}()", method.name);
196+
fn method_ident(expr: &hir::Expr<'_>) -> Option<Ident> {
197+
match expr.kind {
198+
ExprKind::MethodCall(receiver_method, ..) => Some(receiver_method.ident),
199+
ExprKind::Unary(_, expr) | ExprKind::AddrOf(.., expr) => method_ident(expr),
200+
_ => None
201+
}
202+
}
203+
let method_ident = method_ident(&receiver_expr);
204+
if let Some(method_ident) = method_ident
205+
&& method_ident.name == method.name
206+
{
207+
None // do not suggest code that is already there (#53348)
208+
} else {
209+
let method_call_list = [".to_vec()", ".to_string()"];
210+
let mut sugg = if let ExprKind::MethodCall(receiver_method, ..) = receiver_expr.kind
211+
&& receiver_method.ident.name == sym::clone
212+
&& method_call_list.contains(&method_call.as_str())
213+
{
214+
vec![(
215+
receiver_method.ident.span,
216+
method.name.to_string()
217+
)]
200218
} else {
201-
let method_call_list = [".to_vec()", ".to_string()"];
202-
let mut sugg = if receiver.ends_with(".clone()")
203-
&& method_call_list.contains(&method_call.as_str())
219+
if expr.precedence().order()
220+
< ExprPrecedence::MethodCall.order()
204221
{
205-
let max_len = receiver.rfind('.').unwrap();
206-
vec![(
207-
expr.span,
208-
format!("{}{}", &receiver[..max_len], method_call),
209-
)]
222+
vec![
223+
(expr.span.shrink_to_lo(), "(".to_string()),
224+
(expr.span.shrink_to_hi(), format!("){}", method_call)),
225+
]
210226
} else {
211-
if expr.precedence().order()
212-
< ExprPrecedence::MethodCall.order()
213-
{
214-
vec![
215-
(expr.span.shrink_to_lo(), "(".to_string()),
216-
(expr.span.shrink_to_hi(), format!("){}", method_call)),
217-
]
218-
} else {
219-
vec![(expr.span.shrink_to_hi(), method_call)]
220-
}
221-
};
222-
if is_struct_pat_shorthand_field {
223-
sugg.insert(
224-
0,
225-
(expr.span.shrink_to_lo(), format!("{}: ", receiver)),
226-
);
227+
vec![(expr.span.shrink_to_hi(), method_call)]
227228
}
228-
Some(sugg)
229+
};
230+
if let Some(name) = struct_pat_shorthand_field {
231+
sugg.insert(
232+
0,
233+
(expr.span.shrink_to_lo(), format!("{}: ", name)),
234+
);
229235
}
230-
})
231-
.peekable();
232-
if suggestions.peek().is_some() {
233-
err.multipart_suggestions(
234-
"try using a conversion method",
235-
suggestions,
236-
Applicability::MaybeIncorrect,
237-
);
238-
}
236+
Some(sugg)
237+
}
238+
})
239+
.peekable();
240+
if suggestions.peek().is_some() {
241+
err.multipart_suggestions(
242+
"try using a conversion method",
243+
suggestions,
244+
Applicability::MaybeIncorrect,
245+
);
239246
}
240247
} else if let ty::Adt(found_adt, found_substs) = found.kind()
241248
&& self.tcx.is_diagnostic_item(sym::Option, found_adt.did())
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// run-rustfix
2+
#![allow(dead_code)]
3+
4+
struct Bravery {
5+
guts: String,
6+
brains: String,
7+
}
8+
9+
fn main() {
10+
let guts = "mettle";
11+
let _ = Bravery {
12+
guts: guts.to_string(), //~ ERROR mismatched types
13+
brains: guts.to_string(), //~ ERROR mismatched types
14+
};
15+
}

src/test/ui/suggestions/issue-52820.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// run-rustfix
2+
#![allow(dead_code)]
3+
14
struct Bravery {
25
guts: String,
36
brains: String,

src/test/ui/suggestions/issue-52820.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0308]: mismatched types
2-
--> $DIR/issue-52820.rs:9:9
2+
--> $DIR/issue-52820.rs:12:9
33
|
44
LL | guts,
55
| ^^^^ expected struct `String`, found `&str`
@@ -10,13 +10,13 @@ LL | guts: guts.to_string(),
1010
| +++++ ++++++++++++
1111

1212
error[E0308]: mismatched types
13-
--> $DIR/issue-52820.rs:10:17
13+
--> $DIR/issue-52820.rs:13:17
1414
|
1515
LL | brains: guts.clone(),
16-
| ^^^^^^^^^^^^
17-
| |
16+
| ^^^^^-----^^
17+
| | |
18+
| | help: try using a conversion method: `to_string`
1819
| expected struct `String`, found `&str`
19-
| help: try using a conversion method: `guts.to_string()`
2020

2121
error: aborting due to 2 previous errors
2222

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// run-rustfix
2+
#![allow(unused_variables)]
3+
4+
fn main() {
5+
let items = vec![1, 2, 3];
6+
let ref_items: &[i32] = &items;
7+
let items_clone: Vec<i32> = ref_items.to_vec();
8+
//~^ ERROR mismatched types
9+
10+
// in that case no suggestion will be triggered
11+
let items_clone_2: Vec<i32> = items.clone();
12+
13+
let s = "hi";
14+
let string: String = s.to_string();
15+
//~^ ERROR mismatched types
16+
17+
// in that case no suggestion will be triggered
18+
let s2 = "hi";
19+
let string_2: String = s2.to_string();
20+
}
+15-12
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
1+
// run-rustfix
2+
#![allow(unused_variables)]
3+
14
fn main() {
2-
let items = vec![1, 2, 3];
3-
let ref_items: &[i32] = &items;
4-
let items_clone: Vec<i32> = ref_items.clone();
5-
//~^ ERROR mismatched types
5+
let items = vec![1, 2, 3];
6+
let ref_items: &[i32] = &items;
7+
let items_clone: Vec<i32> = ref_items.clone();
8+
//~^ ERROR mismatched types
69

7-
// in that case no suggestion will be triggered
8-
let items_clone_2:Vec<i32> = items.clone();
10+
// in that case no suggestion will be triggered
11+
let items_clone_2: Vec<i32> = items.clone();
912

10-
let s = "hi";
11-
let string: String = s.clone();
12-
//~^ ERROR mismatched types
13+
let s = "hi";
14+
let string: String = s.clone();
15+
//~^ ERROR mismatched types
1316

14-
// in that case no suggestion will be triggered
15-
let s2 = "hi";
16-
let string_2: String = s2.to_string();
17+
// in that case no suggestion will be triggered
18+
let s2 = "hi";
19+
let string_2: String = s2.to_string();
1720
}

src/test/ui/suggestions/issue-53692.stderr

+14-14
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
error[E0308]: mismatched types
2-
--> $DIR/issue-53692.rs:4:37
2+
--> $DIR/issue-53692.rs:7:33
33
|
4-
LL | let items_clone: Vec<i32> = ref_items.clone();
5-
| -------- ^^^^^^^^^^^^^^^^^
6-
| | |
7-
| | expected struct `Vec`, found `&[i32]`
8-
| | help: try using a conversion method: `ref_items.to_vec()`
9-
| expected due to this
4+
LL | let items_clone: Vec<i32> = ref_items.clone();
5+
| -------- ^^^^^^^^^^-----^^
6+
| | | |
7+
| | | help: try using a conversion method: `to_vec`
8+
| | expected struct `Vec`, found `&[i32]`
9+
| expected due to this
1010
|
1111
= note: expected struct `Vec<i32>`
1212
found reference `&[i32]`
1313

1414
error[E0308]: mismatched types
15-
--> $DIR/issue-53692.rs:11:30
15+
--> $DIR/issue-53692.rs:14:26
1616
|
17-
LL | let string: String = s.clone();
18-
| ------ ^^^^^^^^^
19-
| | |
20-
| | expected struct `String`, found `&str`
21-
| | help: try using a conversion method: `s.to_string()`
22-
| expected due to this
17+
LL | let string: String = s.clone();
18+
| ------ ^^-----^^
19+
| | | |
20+
| | | help: try using a conversion method: `to_string`
21+
| | expected struct `String`, found `&str`
22+
| expected due to this
2323

2424
error: aborting due to 2 previous errors
2525

0 commit comments

Comments
 (0)