about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2021-01-19 17:51:48 -0800
committerEsteban Küber <esteban@kuber.com.ar>2021-01-21 21:41:46 -0800
commita701ff981d8768e2b81a053bf9189ff67a2bb7ea (patch)
treedef4272e3fea867fd2caa9981ba19c6aa6ce485c
parent707ce2b798ad7bb6c1e0fce0da542d9caef07b56 (diff)
downloadrust-a701ff981d8768e2b81a053bf9189ff67a2bb7ea.tar.gz
rust-a701ff981d8768e2b81a053bf9189ff67a2bb7ea.zip
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.
-rw-r--r--compiler/rustc_resolve/src/late.rs6
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs22
-rw-r--r--src/test/ui/label/label_misspelled.stderr44
-rw-r--r--src/test/ui/loops/loop-break-value.stderr4
4 files changed, 46 insertions, 30 deletions
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index fff14747e57..a3a630e1490 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 3945afb4724..f8f81c91287 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 8282d3ada32..7cfb6e8147d 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 0237435c8b4..27104118a63 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