Skip to content

Commit aa393b0

Browse files
petrochenkovestebank
authored andcommitted
Some cleanup to maybe_parse_struct_expr
1 parent 4c4ca60 commit aa393b0

File tree

4 files changed

+26
-54
lines changed

4 files changed

+26
-54
lines changed

src/libsyntax/parse/parser.rs

+13-18
Original file line numberDiff line numberDiff line change
@@ -2910,27 +2910,22 @@ impl<'a> Parser<'a> {
29102910
path: &ast::Path,
29112911
attrs: &ThinVec<Attribute>,
29122912
) -> Option<PResult<'a, P<Expr>>> {
2913-
// We don't want to assume it's a struct when encountering `{ <ident>: <ident> }` because
2914-
// it could be type ascription, like in `{ ident: u32 }`.
2915-
let isnt_ascription = self.look_ahead(1, |t| t.is_ident()) &&
2916-
self.look_ahead(2, |t| *t == token::Colon) && (
2917-
(self.look_ahead(3, |t| t.is_ident()) &&
2918-
self.look_ahead(4, |t| *t == token::Comma)) ||
2919-
self.look_ahead(3, |t| t.is_lit()) ||
2920-
self.look_ahead(3, |t| *t == token::BinOp(token::Minus)) &&
2921-
self.look_ahead(4, |t| t.is_lit())
2922-
);
2923-
let could_be_struct = self.look_ahead(1, |t| t.is_ident()) && (
2924-
self.look_ahead(2, |t| *t == token::Colon) && isnt_ascription
2925-
|| self.look_ahead(2, |t| *t == token::Comma)
2926-
// We could also check for `token::CloseDelim(token::Brace)`, but that would
2927-
// have false positives in the case of `if x == y { z } { a }`.
2913+
let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
2914+
let certainly_not_a_block = || self.look_ahead(1, |t| t.is_ident()) && (
2915+
// `{ ident, ` cannot start a block
2916+
self.look_ahead(2, |t| t == &token::Comma) ||
2917+
self.look_ahead(2, |t| t == &token::Colon) && (
2918+
// `{ ident: token, ` cannot start a block
2919+
self.look_ahead(4, |t| t == &token::Comma) ||
2920+
// `{ ident: ` cannot start a block unless it's a type ascription `ident: Type`
2921+
self.look_ahead(3, |t| !t.can_begin_type())
2922+
)
29282923
);
2929-
let bad_struct = self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
2930-
if !bad_struct || could_be_struct {
2924+
2925+
if struct_allowed || certainly_not_a_block() {
29312926
// This is a struct literal, but we don't can't accept them here
29322927
let expr = self.parse_struct_expr(lo, path.clone(), attrs.clone());
2933-
if let (Ok(expr), true) = (&expr, bad_struct) {
2928+
if let (Ok(expr), false) = (&expr, struct_allowed) {
29342929
let mut err = self.diagnostic().struct_span_err(
29352930
expr.span,
29362931
"struct literals are not allowed here",

src/test/ui/parser/struct-literal-in-match-discriminant.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ LL | }) {
1414
|
1515

1616
error: aborting due to previous error
17+

src/test/ui/struct-literal-variant-in-if.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ fn test_E(x: E) {
1313
if x == E::I { field1: true, field2: 42 } {}
1414
//~^ ERROR struct literals are not allowed here
1515
if x == E::V { field: false } {}
16-
//~^ ERROR expected identifier, found keyword `false`
17-
//~| ERROR expected type, found keyword `false`
18-
//~| ERROR expected value, found struct variant `E::V`
16+
//~^ ERROR struct literals are not allowed here
1917
if x == E::J { field: -42 } {}
2018
//~^ ERROR struct literals are not allowed here
2119
if x == E::K { field: "" } {}

src/test/ui/struct-literal-variant-in-if.stderr

+11-33
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,18 @@ help: surround the struct literal with parenthesis
88
LL | if x == (E::I { field1: true, field2: 42 }) {}
99
| ^ ^
1010

11-
error: expected identifier, found keyword `false`
12-
--> $DIR/struct-literal-variant-in-if.rs:15:27
13-
|
14-
LL | if x == E::V { field: false } {}
15-
| ^^^^^ expected identifier, found keyword
16-
help: you can escape reserved keywords to use them as identifiers
17-
|
18-
LL | if x == E::V { field: r#false } {}
19-
| ^^^^^^^
20-
21-
error: expected type, found keyword `false`
22-
--> $DIR/struct-literal-variant-in-if.rs:15:27
11+
error: struct literals are not allowed here
12+
--> $DIR/struct-literal-variant-in-if.rs:15:13
2313
|
2414
LL | if x == E::V { field: false } {}
25-
| ^^^^^ expecting a type here because of type ascription
26-
|
27-
= note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
28-
note: this expression expects an ascribed type after the colon
29-
--> $DIR/struct-literal-variant-in-if.rs:15:20
15+
| ^^^^^^^^^^^^^^^^^^^^^
16+
help: surround the struct literal with parenthesis
3017
|
31-
LL | if x == E::V { field: false } {}
32-
| ^^^^^
33-
= help: this might be indicative of a syntax error elsewhere
18+
LL | if x == (E::V { field: false }) {}
19+
| ^ ^
3420

3521
error: struct literals are not allowed here
36-
--> $DIR/struct-literal-variant-in-if.rs:19:13
22+
--> $DIR/struct-literal-variant-in-if.rs:17:13
3723
|
3824
LL | if x == E::J { field: -42 } {}
3925
| ^^^^^^^^^^^^^^^^^^^
@@ -43,7 +29,7 @@ LL | if x == (E::J { field: -42 }) {}
4329
| ^ ^
4430

4531
error: struct literals are not allowed here
46-
--> $DIR/struct-literal-variant-in-if.rs:21:13
32+
--> $DIR/struct-literal-variant-in-if.rs:19:13
4733
|
4834
LL | if x == E::K { field: "" } {}
4935
| ^^^^^^^^^^^^^^^^^^
@@ -60,14 +46,6 @@ LL | if x == E::V { field } {}
6046
| |
6147
| help: surround the struct literal with parenthesis: `(E::V { field })`
6248

63-
error[E0423]: expected value, found struct variant `E::V`
64-
--> $DIR/struct-literal-variant-in-if.rs:15:13
65-
|
66-
LL | if x == E::V { field: false } {}
67-
| ^^^^-----------------
68-
| |
69-
| help: surround the struct literal with parenthesis: `(E::V { field: false })`
70-
7149
error[E0308]: mismatched types
7250
--> $DIR/struct-literal-variant-in-if.rs:10:20
7351
|
@@ -81,15 +59,15 @@ LL | if x == E::V { field } {}
8159
found type `bool`
8260

8361
error[E0308]: mismatched types
84-
--> $DIR/struct-literal-variant-in-if.rs:23:20
62+
--> $DIR/struct-literal-variant-in-if.rs:21:20
8563
|
8664
LL | let y: usize = ();
8765
| ^^ expected usize, found ()
8866
|
8967
= note: expected type `usize`
9068
found type `()`
9169

92-
error: aborting due to 9 previous errors
70+
error: aborting due to 7 previous errors
9371

94-
Some errors occurred: E0308, E0423.
72+
Some errors have detailed explanations: E0308, E0423.
9573
For more information about an error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)