Skip to content

Commit bb6174c

Browse files
committed
Do not complain about type ascription on likely incorrect struct literal
1 parent a640315 commit bb6174c

File tree

4 files changed

+55
-17
lines changed

4 files changed

+55
-17
lines changed

src/librustc_resolve/lib.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3222,11 +3222,30 @@ impl<'a> Resolver<'a> {
32223222
let is_expected = &|def| source.is_expected(def);
32233223

32243224
let report_errors = |this: &mut Self, def: Option<Def>| {
3225-
let (err, candidates) = this.smart_resolve_report_errors(path, span, source, def);
3226-
let def_id = this.current_module.normal_ancestor_id;
3227-
let node_id = this.definitions.as_local_node_id(def_id).unwrap();
3228-
let better = def.is_some();
3229-
this.use_injections.push(UseError { err, candidates, node_id, better });
3225+
let mut report = true;
3226+
3227+
if let &[segment] = path {
3228+
if this.session.parse_sess.missing_ident_could_be_struct_literal
3229+
.borrow().contains(&segment.ident.span)
3230+
{
3231+
for sp in this.session.possible_struct_literal.borrow().iter() {
3232+
if sp.overlaps(segment.ident.span) {
3233+
// Ignore errors caused by likely struct literals. An error has
3234+
// already been emitted suggesting surrounding struct literal with
3235+
// `()` in a case like `if x == E::V { field: field } {}`
3236+
report = false;
3237+
break;
3238+
}
3239+
}
3240+
}
3241+
}
3242+
if report {
3243+
let (err, candidates) = this.smart_resolve_report_errors(path, span, source, def);
3244+
let def_id = this.current_module.normal_ancestor_id;
3245+
let node_id = this.definitions.as_local_node_id(def_id).unwrap();
3246+
let better = def.is_some();
3247+
this.use_injections.push(UseError { err, candidates, node_id, better });
3248+
}
32303249
err_path_resolution()
32313250
};
32323251

src/libsyntax/parse/parser.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2922,18 +2922,27 @@ impl<'a> Parser<'a> {
29222922
)
29232923
);
29242924
// could be a block but we won't know until type-checking
2925-
if self.look_ahead(1, |t| t.is_ident()) && (
2926-
// foo { bar }
2927-
self.look_ahead(2, |t| t == &token::CloseDelim(token::Brace)) ||
2928-
// foo { bar: baz }
2929-
self.look_ahead(2, |t| t == &token::Colon)
2930-
) {
2925+
// foo { bar }
2926+
if self.look_ahead(1, |t| t.is_ident()) &&
2927+
self.look_ahead(2, |t| t == &token::CloseDelim(token::Brace))
2928+
{
29312929
self.look_ahead(1, |t| {
29322930
if let token::Ident(ident, _) = t {
29332931
self.sess.missing_ident_could_be_struct_literal.borrow_mut().insert(ident.span);
29342932
}
29352933
});
29362934
}
2935+
// foo { bar: baz }
2936+
if self.look_ahead(1, |t| t.is_ident()) &&
2937+
self.look_ahead(2, |t| t == &token::Colon) &&
2938+
self.look_ahead(3, |t| t.is_ident())
2939+
{
2940+
self.look_ahead(3, |t| {
2941+
if let token::Ident(ident, _) = t {
2942+
self.sess.missing_ident_could_be_struct_literal.borrow_mut().insert(ident.span);
2943+
}
2944+
});
2945+
}
29372946

29382947
if struct_allowed || certainly_not_a_block() {
29392948
// This is a struct literal, but we don't can't accept them here

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ fn test_E(x: E) {
99
let field = true;
1010
if x == E::V { field } {}
1111
//~^ ERROR expected value, found struct variant `E::V`
12+
if x == E::V { field: field } {}
13+
//~^ ERROR expected value, found struct variant `E::V`
1214
if x == E::I { field1: true, field2: 42 } {}
1315
//~^ ERROR struct literals are not allowed here
1416
if x == E::V { field: false } {}

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

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: struct literals are not allowed here
2-
--> $DIR/struct-literal-variant-in-if.rs:12:13
2+
--> $DIR/struct-literal-variant-in-if.rs:14:13
33
|
44
LL | if x == E::I { field1: true, field2: 42 } {}
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL | if x == (E::I { field1: true, field2: 42 }) {}
99
| ^ ^
1010

1111
error: struct literals are not allowed here
12-
--> $DIR/struct-literal-variant-in-if.rs:14:13
12+
--> $DIR/struct-literal-variant-in-if.rs:16:13
1313
|
1414
LL | if x == E::V { field: false } {}
1515
| ^^^^^^^^^^^^^^^^^^^^^
@@ -19,7 +19,7 @@ LL | if x == (E::V { field: false }) {}
1919
| ^ ^
2020

2121
error: struct literals are not allowed here
22-
--> $DIR/struct-literal-variant-in-if.rs:16:13
22+
--> $DIR/struct-literal-variant-in-if.rs:18:13
2323
|
2424
LL | if x == E::J { field: -42 } {}
2525
| ^^^^^^^^^^^^^^^^^^^
@@ -29,7 +29,7 @@ LL | if x == (E::J { field: -42 }) {}
2929
| ^ ^
3030

3131
error: struct literals are not allowed here
32-
--> $DIR/struct-literal-variant-in-if.rs:18:13
32+
--> $DIR/struct-literal-variant-in-if.rs:20:13
3333
|
3434
LL | if x == E::K { field: "" } {}
3535
| ^^^^^^^^^^^^^^^^^^
@@ -46,16 +46,24 @@ LL | if x == E::V { field } {}
4646
| |
4747
| help: surround the struct literal with parenthesis: `(E::V { field })`
4848

49+
error[E0423]: expected value, found struct variant `E::V`
50+
--> $DIR/struct-literal-variant-in-if.rs:12:13
51+
|
52+
LL | if x == E::V { field: field } {}
53+
| ^^^^-----------------
54+
| |
55+
| help: surround the struct literal with parenthesis: `(E::V { field: field })`
56+
4957
error[E0308]: mismatched types
50-
--> $DIR/struct-literal-variant-in-if.rs:20:20
58+
--> $DIR/struct-literal-variant-in-if.rs:22:20
5159
|
5260
LL | let y: usize = ();
5361
| ^^ expected usize, found ()
5462
|
5563
= note: expected type `usize`
5664
found type `()`
5765

58-
error: aborting due to 6 previous errors
66+
error: aborting due to 7 previous errors
5967

6068
Some errors have detailed explanations: E0308, E0423.
6169
For more information about an error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)