1
Fork 0

Suggest if let x = y when encountering if x = y

Detect potential cases where `if let` was meant but `let` was left out.

Fix #44990.
This commit is contained in:
Esteban Küber 2020-08-25 20:28:25 -07:00
parent 85fbf49ce0
commit 07112ca62d
11 changed files with 268 additions and 102 deletions

View file

@ -378,6 +378,9 @@ struct DiagnosticMetadata<'ast> {
/// Only used for better errors on `let <pat>: <expr, not type>;`.
current_let_binding: Option<(Span, Option<Span>, Option<Span>)>,
/// Used to detect possible `if let` written without `let` and to provide structured suggestion.
in_if_condition: Option<&'ast Expr>,
}
struct LateResolutionVisitor<'a, 'b, 'ast> {
@ -403,7 +406,7 @@ struct LateResolutionVisitor<'a, 'b, 'ast> {
///
/// In particular, rustdoc uses this to avoid giving errors for `cfg()` items.
/// In most cases this will be `None`, in which case errors will always be reported.
/// If it is `Some(_)`, then it will be updated when entering a nested function or trait body.
/// If it is `true`, then it will be updated when entering a nested function or trait body.
in_func_body: bool,
}
@ -2199,7 +2202,9 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
ExprKind::If(ref cond, ref then, ref opt_else) => {
self.with_rib(ValueNS, NormalRibKind, |this| {
let old = this.diagnostic_metadata.in_if_condition.replace(cond);
this.visit_expr(cond);
this.diagnostic_metadata.in_if_condition = old;
this.visit_block(then);
});
if let Some(expr) = opt_else {

View file

@ -176,6 +176,19 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
let code = source.error_code(res.is_some());
let mut err = self.r.session.struct_span_err_with_code(base_span, &base_msg, code);
match (source, self.diagnostic_metadata.in_if_condition) {
(PathSource::Expr(_), Some(Expr { span, kind: ExprKind::Assign(..), .. })) => {
err.span_suggestion_verbose(
span.shrink_to_lo(),
"you might have meant to use pattern matching",
"let ".to_string(),
Applicability::MaybeIncorrect,
);
self.r.session.if_let_suggestions.borrow_mut().insert(*span);
}
_ => {}
}
let is_assoc_fn = self.self_type_is_available(span);
// Emit help message for fake-self from other languages (e.g., `this` in Javascript).
if ["this", "my"].contains(&&*item_str.as_str()) && is_assoc_fn {