about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-01-18 22:56:48 +0100
committerGitHub <noreply@github.com>2019-01-18 22:56:48 +0100
commit2a830e47e11ad46f1df86c10b58aea17e7d273d0 (patch)
treeef53985ae377e166b1bb6f55079ecb2376bb36bb
parent42accf06dc1e9ed65f2a9651202d5d7eacc1ddc5 (diff)
parentec3c5b0199045b3ae3959631998451543bd99518 (diff)
downloadrust-2a830e47e11ad46f1df86c10b58aea17e7d273d0.tar.gz
rust-2a830e47e11ad46f1df86c10b58aea17e7d273d0.zip
Rollup merge of #57725 - estebank:parens, r=michaelwoerister
Use structured suggestion to surround struct literal with parenthesis
-rw-r--r--src/librustc_resolve/lib.rs42
-rw-r--r--src/test/ui/error-codes/E0423.stderr12
2 files changed, 46 insertions, 8 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index c11a2cd01c1..a58d63e1ca2 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -3401,6 +3401,29 @@ impl<'a> Resolver<'a> {
                                 Ok(ref snippet) if snippet == "{" => true,
                                 _ => false,
                             };
+                            // In case this could be a struct literal that needs to be surrounded
+                            // by parenthesis, find the appropriate span.
+                            let mut i = 0;
+                            let mut closing_brace = None;
+                            loop {
+                                sp = sm.next_point(sp);
+                                match sm.span_to_snippet(sp) {
+                                    Ok(ref snippet) => {
+                                        if snippet == "}" {
+                                            let sp = span.to(sp);
+                                            if let Ok(snippet) = sm.span_to_snippet(sp) {
+                                                closing_brace = Some((sp, snippet));
+                                            }
+                                            break;
+                                        }
+                                    }
+                                    _ => break,
+                                }
+                                i += 1;
+                                if i > 100 { // The bigger the span the more likely we're
+                                    break;   // incorrect. Bound it to 100 chars long.
+                                }
+                            }
                             match source {
                                 PathSource::Expr(Some(parent)) => {
                                     match parent.node {
@@ -3427,11 +3450,20 @@ impl<'a> Resolver<'a> {
                                     }
                                 },
                                 PathSource::Expr(None) if followed_by_brace == true => {
-                                    err.span_label(
-                                        span,
-                                        format!("did you mean `({} {{ /* fields */ }})`?",
-                                                path_str),
-                                    );
+                                    if let Some((sp, snippet)) = closing_brace {
+                                        err.span_suggestion_with_applicability(
+                                            sp,
+                                            "surround the struct literal with parenthesis",
+                                            format!("({})", snippet),
+                                            Applicability::MaybeIncorrect,
+                                        );
+                                    } else {
+                                        err.span_label(
+                                            span,
+                                            format!("did you mean `({} {{ /* fields */ }})`?",
+                                                    path_str),
+                                        );
+                                    }
                                     return (err, candidates);
                                 },
                                 _ => {
diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr
index c422a1e7957..d0deb8ce7ea 100644
--- a/src/test/ui/error-codes/E0423.stderr
+++ b/src/test/ui/error-codes/E0423.stderr
@@ -29,19 +29,25 @@ error[E0423]: expected value, found struct `S`
   --> $DIR/E0423.rs:12:32
    |
 LL |     if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
-   |                                ^ did you mean `(S { /* fields */ })`?
+   |                                ^---------------
+   |                                |
+   |                                help: surround the struct literal with parenthesis: `(S { x: 1, y: 2 })`
 
 error[E0423]: expected value, found struct `T`
   --> $DIR/E0423.rs:15:8
    |
 LL |     if T {} == T {} { println!("Ok"); }
-   |        ^ did you mean `(T { /* fields */ })`?
+   |        ^---
+   |        |
+   |        help: surround the struct literal with parenthesis: `(T {})`
 
 error[E0423]: expected value, found struct `std::ops::Range`
   --> $DIR/E0423.rs:21:14
    |
 LL |     for _ in std::ops::Range { start: 0, end: 10 } {}
-   |              ^^^^^^^^^^^^^^^ did you mean `(std::ops::Range { /* fields */ })`?
+   |              ^^^^^^^^^^^^^^^----------------------
+   |              |
+   |              help: surround the struct literal with parenthesis: `(std::ops::Range { start: 0, end: 10 })`
 
 error: aborting due to 7 previous errors