From a701ff981d8768e2b81a053bf9189ff67a2bb7ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 19 Jan 2021 17:51:48 -0800 Subject: [PATCH] Suggest `'a` when given `a` only when appropriate When encountering a name `a` that isn't resolved, but a label `'a` is found in the current ribs, only suggest `'a` if this name is the value expression of a `break` statement. Solve FIXME. --- compiler/rustc_resolve/src/late.rs | 6 +++ .../rustc_resolve/src/late/diagnostics.rs | 22 ++++++---- src/test/ui/label/label_misspelled.stderr | 44 ++++++++++--------- src/test/ui/loops/loop-break-value.stderr | 4 +- 4 files changed, 46 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index fff14747e572..a3a630e14906 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2266,6 +2266,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { visit::walk_expr(self, expr); } + ExprKind::Break(None, Some(ref e)) => { + // We use this instead of `visit::walk_expr` to keep the parent expr around for + // better + self.resolve_expr(e, Some(&expr)); + } + ExprKind::Let(ref pat, ref scrutinee) => { self.visit_expr(scrutinee); self.resolve_pattern_top(pat, PatternSource::Let); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 3945afb4724a..f8f81c912877 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -547,15 +547,19 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { for label_rib in &self.label_ribs { for (label_ident, _) in &label_rib.bindings { if format!("'{}", ident) == label_ident.to_string() { - let msg = "a label with a similar name exists"; - // FIXME: consider only emitting this suggestion if a label would be valid here - // which is pretty much only the case for `break` expressions. - err.span_suggestion( - span, - &msg, - label_ident.name.to_string(), - Applicability::MaybeIncorrect, - ); + err.span_label(label_ident.span, "a label with a similar name exists"); + if let PathSource::Expr(Some(Expr { + kind: ExprKind::Break(None, Some(_)), + .. + })) = source + { + err.span_suggestion( + span, + "use the similarly named label", + label_ident.name.to_string(), + Applicability::MaybeIncorrect, + ); + } } } } diff --git a/src/test/ui/label/label_misspelled.stderr b/src/test/ui/label/label_misspelled.stderr index 8282d3ada32f..7cfb6e8147dd 100644 --- a/src/test/ui/label/label_misspelled.stderr +++ b/src/test/ui/label/label_misspelled.stderr @@ -1,74 +1,78 @@ error[E0425]: cannot find value `LOOP` in this scope --> $DIR/label_misspelled.rs:3:9 | +LL | 'LOOP: loop { + | ----- a label with a similar name exists LL | LOOP; - | ^^^^ - | | - | not found in this scope - | help: a label with a similar name exists: `'LOOP` + | ^^^^ not found in this scope error[E0425]: cannot find value `while_loop` in this scope --> $DIR/label_misspelled.rs:7:9 | +LL | 'while_loop: while true { + | ----------- a label with a similar name exists LL | while_loop; - | ^^^^^^^^^^ - | | - | not found in this scope - | help: a label with a similar name exists: `'while_loop` + | ^^^^^^^^^^ not found in this scope error[E0425]: cannot find value `while_let` in this scope --> $DIR/label_misspelled.rs:11:9 | +LL | 'while_let: while let Some(_) = Some(()) { + | ---------- a label with a similar name exists LL | while_let; - | ^^^^^^^^^ - | | - | not found in this scope - | help: a label with a similar name exists: `'while_let` + | ^^^^^^^^^ not found in this scope error[E0425]: cannot find value `for_loop` in this scope --> $DIR/label_misspelled.rs:15:9 | +LL | 'for_loop: for _ in 0..3 { + | --------- a label with a similar name exists LL | for_loop; - | ^^^^^^^^ - | | - | not found in this scope - | help: a label with a similar name exists: `'for_loop` + | ^^^^^^^^ not found in this scope error[E0425]: cannot find value `LOOP` in this scope --> $DIR/label_misspelled.rs:22:15 | +LL | 'LOOP: loop { + | ----- a label with a similar name exists LL | break LOOP; | ^^^^ | | | not found in this scope - | help: a label with a similar name exists: `'LOOP` + | help: use the similarly named label: `'LOOP` error[E0425]: cannot find value `while_loop` in this scope --> $DIR/label_misspelled.rs:26:15 | +LL | 'while_loop: while true { + | ----------- a label with a similar name exists LL | break while_loop; | ^^^^^^^^^^ | | | not found in this scope - | help: a label with a similar name exists: `'while_loop` + | help: use the similarly named label: `'while_loop` error[E0425]: cannot find value `while_let` in this scope --> $DIR/label_misspelled.rs:31:15 | +LL | 'while_let: while let Some(_) = Some(()) { + | ---------- a label with a similar name exists LL | break while_let; | ^^^^^^^^^ | | | not found in this scope - | help: a label with a similar name exists: `'while_let` + | help: use the similarly named label: `'while_let` error[E0425]: cannot find value `for_loop` in this scope --> $DIR/label_misspelled.rs:36:15 | +LL | 'for_loop: for _ in 0..3 { + | --------- a label with a similar name exists LL | break for_loop; | ^^^^^^^^ | | | not found in this scope - | help: a label with a similar name exists: `'for_loop` + | help: use the similarly named label: `'for_loop` warning: denote infinite loops with `loop { ... }` --> $DIR/label_misspelled.rs:6:5 diff --git a/src/test/ui/loops/loop-break-value.stderr b/src/test/ui/loops/loop-break-value.stderr index 0237435c8b46..27104118a63a 100644 --- a/src/test/ui/loops/loop-break-value.stderr +++ b/src/test/ui/loops/loop-break-value.stderr @@ -1,11 +1,13 @@ error[E0425]: cannot find value `LOOP` in this scope --> $DIR/loop-break-value.rs:95:15 | +LL | 'LOOP: for _ in 0 .. 9 { + | ----- a label with a similar name exists LL | break LOOP; | ^^^^ | | | not found in this scope - | help: a label with a similar name exists: `'LOOP` + | help: use the similarly named label: `'LOOP` warning: denote infinite loops with `loop { ... }` --> $DIR/loop-break-value.rs:26:5