Skip to content

Commit 45b88af

Browse files
committed
simplify suggest_deref_ref_or_into
1 parent 1599c5a commit 45b88af

File tree

3 files changed

+47
-45
lines changed

3 files changed

+47
-45
lines changed

compiler/rustc_hir/src/hir.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1811,6 +1811,14 @@ impl Expr<'_> {
18111811
_ => false,
18121812
}
18131813
}
1814+
1815+
pub fn method_ident(&self) -> Option<Ident> {
1816+
match self.kind {
1817+
ExprKind::MethodCall(receiver_method, ..) => Some(receiver_method.ident),
1818+
ExprKind::Unary(_, expr) | ExprKind::AddrOf(.., expr) => expr.method_ident(),
1819+
_ => None,
1820+
}
1821+
}
18141822
}
18151823

18161824
/// Checks if the specified expression is a built-in range literal.

compiler/rustc_span/src/symbol.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1434,6 +1434,8 @@ symbols! {
14341434
thumb2,
14351435
thumb_mode: "thumb-mode",
14361436
tmm_reg,
1437+
to_string,
1438+
to_vec,
14371439
todo_macro,
14381440
tool_attributes,
14391441
tool_lints,

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

+37-45
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@ 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, Ident};
17+
use rustc_span::symbol::sym;
1818
use rustc_span::Span;
1919
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
2020

21-
use std::iter;
22-
2321
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2422
pub(in super::super) fn suggest_semicolon_at_end(&self, span: Span, err: &mut Diagnostic) {
2523
err.span_suggestion_short(
@@ -187,54 +185,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
187185
err.span_label(self.tcx.def_span(def_id), &format!("{} defined here", found));
188186
}
189187
} else if !self.check_for_cast(err, expr, found, expected, expected_ty_expr) {
190-
let struct_pat_shorthand_field = self.maybe_get_struct_pattern_shorthand_field(expr);
191188
let methods = self.get_conversion_methods(expr.span, expected, found, expr.hir_id);
192189
if !methods.is_empty() {
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-
}
190+
let mut suggestions = methods.iter()
191+
.filter_map(|conversion_method| {
192+
let receiver_method_ident = expr.method_ident();
193+
if let Some(method_ident) = receiver_method_ident
194+
&& method_ident.name == conversion_method.name
195+
{
196+
return None // do not suggest code that is already there (#53348)
202197
}
203-
let method_ident = method_ident(&receiver_expr);
204-
if let Some(method_ident) = method_ident
205-
&& method_ident.name == method.name
198+
199+
let method_call_list = [sym::to_vec, sym::to_string];
200+
let mut sugg = if let ExprKind::MethodCall(receiver_method, ..) = expr.kind
201+
&& receiver_method.ident.name == sym::clone
202+
&& method_call_list.contains(&conversion_method.name)
203+
// If receiver is `.clone()` and found type has one of those methods,
204+
// we guess that the user wants to convert from a slice type (`&[]` or `&str`)
205+
// to an owned type (`Vec` or `String`). These conversions clone internally,
206+
// so we remove the user's `clone` call.
206207
{
207-
None // do not suggest code that is already there (#53348)
208+
vec![(
209+
receiver_method.ident.span,
210+
conversion_method.name.to_string()
211+
)]
212+
} else if expr.precedence().order()
213+
< ExprPrecedence::MethodCall.order()
214+
{
215+
vec![
216+
(expr.span.shrink_to_lo(), "(".to_string()),
217+
(expr.span.shrink_to_hi(), format!(").{}()", conversion_method.name)),
218+
]
208219
} 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-
)]
218-
} else {
219-
if expr.precedence().order()
220-
< ExprPrecedence::MethodCall.order()
221-
{
222-
vec![
223-
(expr.span.shrink_to_lo(), "(".to_string()),
224-
(expr.span.shrink_to_hi(), format!("){}", method_call)),
225-
]
226-
} else {
227-
vec![(expr.span.shrink_to_hi(), method_call)]
228-
}
229-
};
230-
if let Some(name) = struct_pat_shorthand_field {
231-
sugg.insert(
232-
0,
233-
(expr.span.shrink_to_lo(), format!("{}: ", name)),
234-
);
235-
}
236-
Some(sugg)
220+
vec![(expr.span.shrink_to_hi(), format!(".{}()", conversion_method.name))]
221+
};
222+
let struct_pat_shorthand_field = self.maybe_get_struct_pattern_shorthand_field(expr);
223+
if let Some(name) = struct_pat_shorthand_field {
224+
sugg.insert(
225+
0,
226+
(expr.span.shrink_to_lo(), format!("{}: ", name)),
227+
);
237228
}
229+
Some(sugg)
238230
})
239231
.peekable();
240232
if suggestions.peek().is_some() {

0 commit comments

Comments
 (0)