Rollup merge of #51360 - estebank:braces-around-literal-structs, r=nikomatsakis
Suggest parentheses when a struct literal needs them When writing a struct literal in an expression that expects a block to be started afterwards (like an `if` statement), do not suggest using the same struct literal: ``` did you mean `S { /* fields * /}`? ``` Instead, suggest surrounding the expression with parentheses: ``` did you mean `(S { /* fields * /})`? ``` Fix #47360, #50090. Leaving #42982 open to come back to this problem with a better solution.
This commit is contained in:
commit
4b176b2ce2
@ -2934,8 +2934,38 @@ impl<'a> Resolver<'a> {
|
|||||||
here due to private fields"));
|
here due to private fields"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?",
|
// HACK(estebank): find a better way to figure out that this was a
|
||||||
path_str));
|
// parser issue where a struct literal is being used on an expression
|
||||||
|
// where a brace being opened means a block is being started. Look
|
||||||
|
// ahead for the next text to see if `span` is followed by a `{`.
|
||||||
|
let cm = this.session.codemap();
|
||||||
|
let mut sp = span;
|
||||||
|
loop {
|
||||||
|
sp = cm.next_point(sp);
|
||||||
|
match cm.span_to_snippet(sp) {
|
||||||
|
Ok(ref snippet) => {
|
||||||
|
if snippet.chars().any(|c| { !c.is_whitespace() }) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let followed_by_brace = match cm.span_to_snippet(sp) {
|
||||||
|
Ok(ref snippet) if snippet == "{" => true,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
if let (PathSource::Expr(None), true) = (source, followed_by_brace) {
|
||||||
|
err.span_label(
|
||||||
|
span,
|
||||||
|
format!("did you mean `({} {{ /* fields */ }})`?", path_str),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
err.span_label(
|
||||||
|
span,
|
||||||
|
format!("did you mean `{} {{ /* fields */ }}`?", path_str),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return (err, candidates);
|
return (err, candidates);
|
||||||
}
|
}
|
||||||
|
@ -13,3 +13,22 @@ fn main () {
|
|||||||
|
|
||||||
let f = Foo(); //~ ERROR E0423
|
let f = Foo(); //~ ERROR E0423
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bar() {
|
||||||
|
struct S { x: i32, y: i32 }
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
struct T {}
|
||||||
|
|
||||||
|
if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
|
||||||
|
//~^ ERROR E0423
|
||||||
|
//~| expected type, found `1`
|
||||||
|
if T {} == T {} { println!("Ok"); }
|
||||||
|
//~^ ERROR E0423
|
||||||
|
//~| ERROR expected expression, found `==`
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo() {
|
||||||
|
for _ in std::ops::Range { start: 0, end: 10 } {}
|
||||||
|
//~^ ERROR E0423
|
||||||
|
//~| ERROR expected type, found `0`
|
||||||
|
}
|
||||||
|
@ -1,9 +1,48 @@
|
|||||||
|
error: expected type, found `1`
|
||||||
|
--> $DIR/E0423.rs:22:39
|
||||||
|
|
|
||||||
|
LL | if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
|
||||||
|
| ^ expecting a type here because of type ascription
|
||||||
|
|
||||||
|
error: expected expression, found `==`
|
||||||
|
--> $DIR/E0423.rs:25:13
|
||||||
|
|
|
||||||
|
LL | if T {} == T {} { println!("Ok"); }
|
||||||
|
| ^^ expected expression
|
||||||
|
|
||||||
|
error: expected type, found `0`
|
||||||
|
--> $DIR/E0423.rs:31:39
|
||||||
|
|
|
||||||
|
LL | for _ in std::ops::Range { start: 0, end: 10 } {}
|
||||||
|
| ^ expecting a type here because of type ascription
|
||||||
|
|
||||||
error[E0423]: expected function, found struct `Foo`
|
error[E0423]: expected function, found struct `Foo`
|
||||||
--> $DIR/E0423.rs:14:13
|
--> $DIR/E0423.rs:14:13
|
||||||
|
|
|
|
||||||
LL | let f = Foo(); //~ ERROR E0423
|
LL | let f = Foo(); //~ ERROR E0423
|
||||||
| ^^^ did you mean `Foo { /* fields */ }`?
|
| ^^^
|
||||||
|
| |
|
||||||
|
| did you mean `foo`?
|
||||||
|
| did you mean `Foo { /* fields */ }`?
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0423]: expected value, found struct `S`
|
||||||
|
--> $DIR/E0423.rs:22:32
|
||||||
|
|
|
||||||
|
LL | if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
|
||||||
|
| ^ did you mean `(S { /* fields */ })`?
|
||||||
|
|
||||||
|
error[E0423]: expected value, found struct `T`
|
||||||
|
--> $DIR/E0423.rs:25:8
|
||||||
|
|
|
||||||
|
LL | if T {} == T {} { println!("Ok"); }
|
||||||
|
| ^ did you mean `(T { /* fields */ })`?
|
||||||
|
|
||||||
|
error[E0423]: expected value, found struct `std::ops::Range`
|
||||||
|
--> $DIR/E0423.rs:31:14
|
||||||
|
|
|
||||||
|
LL | for _ in std::ops::Range { start: 0, end: 10 } {}
|
||||||
|
| ^^^^^^^^^^^^^^^ did you mean `(std::ops::Range { /* fields */ })`?
|
||||||
|
|
||||||
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0423`.
|
For more information about this error, try `rustc --explain E0423`.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user