From fedafa2b506c813be761441040d33bb86e795a41 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 25 Feb 2020 00:08:30 +0100 Subject: [PATCH] parse: backtrack to avoid stealing e.g. `x.f()` at mod level. --- src/librustc_parse/parser/item.rs | 51 ++++++++++++--- src/librustc_parse/parser/module.rs | 5 +- src/librustc_parse/parser/stmt.rs | 2 +- src/test/ui/did_you_mean/issue-40006.rs | 14 ++--- src/test/ui/did_you_mean/issue-40006.stderr | 63 +++++++++---------- .../feature-gate-extern_prelude.rs | 2 +- .../feature-gate-extern_prelude.stderr | 6 +- src/test/ui/issues/issue-21146.rs | 2 +- src/test/ui/issues/issue-21146.stderr | 4 +- .../parser/class-implements-bad-trait.stderr | 38 +++++++++-- src/test/ui/parser/extern-no-fn.rs | 2 +- src/test/ui/parser/extern-no-fn.stderr | 10 +-- src/test/ui/parser/issue-21153.rs | 2 +- src/test/ui/parser/issue-21153.stderr | 10 +-- .../parser/module-statement-recovery/main.rs | 6 ++ .../module-statement-recovery/main.stderr | 18 +++++- .../recover-statements-not-main.rs | 2 +- .../recover-statements-not-main.stderr | 16 ++++- .../ui/parser/underscore_item_not_const.rs | 4 +- .../parser/underscore_item_not_const.stderr | 19 +++++- 20 files changed, 191 insertions(+), 85 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index d7d6fcd05b795..a0cbd67e3d441 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -30,7 +30,7 @@ impl<'a> Parser<'a> { fn parse_item_(&mut self, req_name: ReqName) -> PResult<'a, Option> { let attrs = self.parse_outer_attributes()?; - self.parse_item_common(attrs, true, false, req_name) + self.parse_item_common(attrs, true, false, req_name, true) } pub(super) fn parse_item_common( @@ -39,6 +39,7 @@ impl<'a> Parser<'a> { mac_allowed: bool, attrs_allowed: bool, req_name: ReqName, + mod_stmt: bool, ) -> PResult<'a, Option> { maybe_whole!(self, NtItem, |item| { let mut item = item; @@ -49,9 +50,9 @@ impl<'a> Parser<'a> { let mut unclosed_delims = vec![]; let (mut item, tokens) = self.collect_tokens(|this| { - let item = this.parse_item_common_(attrs, mac_allowed, attrs_allowed, req_name); + let i = this.parse_item_common_(attrs, mac_allowed, attrs_allowed, req_name, mod_stmt); unclosed_delims.append(&mut this.unclosed_delims); - item + i })?; self.unclosed_delims.append(&mut unclosed_delims); @@ -83,11 +84,13 @@ impl<'a> Parser<'a> { mac_allowed: bool, attrs_allowed: bool, req_name: ReqName, + mod_stmt: bool, ) -> PResult<'a, Option> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; let mut def = self.parse_defaultness(); - let kind = self.parse_item_kind(&mut attrs, mac_allowed, lo, &vis, &mut def, req_name)?; + let kind = + self.parse_item_kind(&mut attrs, mac_allowed, lo, &vis, &mut def, req_name, mod_stmt)?; if let Some((ident, kind)) = kind { self.error_on_unconsumed_default(def, &kind); let span = lo.to(self.prev_span); @@ -148,6 +151,7 @@ impl<'a> Parser<'a> { vis: &Visibility, def: &mut Defaultness, req_name: ReqName, + mod_stmt: bool, ) -> PResult<'a, Option> { let mut def = || mem::replace(def, Defaultness::Final); @@ -212,9 +216,13 @@ impl<'a> Parser<'a> { } else if vis.node.is_pub() && self.isnt_macro_invocation() { self.recover_missing_kw_before_item()?; return Ok(None); - } else if macros_allowed && self.token.is_path_start() { + } else if let Some(kind) = if macros_allowed && self.token.is_path_start() { + self.parse_item_macro(vis, mod_stmt)? + } else { + None + } { // MACRO INVOCATION ITEM - (Ident::invalid(), ItemKind::Mac(self.parse_item_macro(vis)?)) + (Ident::invalid(), ItemKind::Mac(kind)) } else { return Ok(None); }; @@ -333,13 +341,36 @@ impl<'a> Parser<'a> { } /// Parses an item macro, e.g., `item!();`. - fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, Mac> { - let path = self.parse_path(PathStyle::Mod)?; // `foo::bar` - self.expect(&token::Not)?; // `!` + fn parse_item_macro(&mut self, vis: &Visibility, mod_stmt: bool) -> PResult<'a, Option> { + let parse_prefix = |p: &mut Self| -> PResult<'a, ast::Path> { + let path = p.parse_path(PathStyle::Mod)?; // `foo::bar` + p.expect(&token::Not)?; // `!` + Ok(path) + }; + let path = if mod_stmt { + // We're in statement-as-module-item recovery mode. + // To avoid "stealing" syntax from e.g. `x.f()` as a module-level statement, + // we backtrack if we failed to parse `$path!`; after we have, we commit firmly. + // This is only done when `mod_stmt` holds to avoid backtracking inside functions. + let snapshot = self.clone(); + match parse_prefix(self) { + Ok(path) => path, + Err(mut err) => { + // Assert that this is only for diagnostics! + // This is a safeguard against breaking LL(k) accidentally in the spec, + // assuming no one has gated the syntax with something like `#[cfg(FALSE)]`. + err.delay_as_bug(); + *self = snapshot; + return Ok(None); + } + } + } else { + parse_prefix(self)? + }; let args = self.parse_mac_args()?; // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`. self.eat_semi_for_macro_if_needed(&args); self.complain_if_pub_macro(vis, false); - Ok(Mac { path, args, prior_type_ascription: self.last_type_ascription }) + Ok(Some(Mac { path, args, prior_type_ascription: self.last_type_ascription })) } /// Recover if we parsed attributes and expected an item but there was none. diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 209e8d811e899..918c3d32be6d1 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -195,7 +195,9 @@ impl<'a> Parser<'a> { // Construct the return type; either default, `-> _`, or `-> Result<_, _>`. let output = match (has_ret_unit, has_ret_expr, has_try_expr) { + // `-> ()`; We either had `return;`, so return type is unit, or nothing was returned. (true, _, _) | (false, false, false) => FnRetTy::Default(span), + // `-> Result<_, _>`; We had `?` somewhere so `-> Result<_, _>` is a good bet. (_, _, true) => { let arg = GenericArg::Type(self.mk_ty(span, TyKind::Infer)); let args = [arg.clone(), arg].to_vec(); @@ -204,10 +206,11 @@ impl<'a> Parser<'a> { path.segments[0].args = Some(P(GenericArgs::AngleBracketed(args))); FnRetTy::Ty(self.mk_ty(span, TyKind::Path(None, path))) } + // `-> _`; We had `return $expr;` so it's probably not `()` as return type. (_, true, _) => FnRetTy::Ty(self.mk_ty(span, TyKind::Infer)), }; - // Finalize the AST for the function item. + // Finalize the AST for the function item: `fn $ident() $output { $stmts }`. let sig = FnSig { header: FnHeader::default(), decl: P(FnDecl { inputs: vec![], output }) }; let body = self.mk_block(stmts, BlockCheckMode::Default, span); let kind = ItemKind::Fn(Defaultness::Final, sig, Generics::default(), Some(body)); diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index 9aa6c054ec5ff..47f6e5b7b6d06 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -92,7 +92,7 @@ impl<'a> Parser<'a> { fn parse_stmt_item(&mut self, attrs: Vec) -> PResult<'a, Option> { let old = mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock); - let item = self.parse_item_common(attrs.clone(), false, true, |_| true)?; + let item = self.parse_item_common(attrs.clone(), false, true, |_| true, false)?; self.directory.ownership = old; Ok(item) } diff --git a/src/test/ui/did_you_mean/issue-40006.rs b/src/test/ui/did_you_mean/issue-40006.rs index 74f304d81a0f1..813c9a1dcf388 100644 --- a/src/test/ui/did_you_mean/issue-40006.rs +++ b/src/test/ui/did_you_mean/issue-40006.rs @@ -1,11 +1,11 @@ impl dyn A { - Y -} //~ ERROR expected one of `!` or `::`, found `}` + Y //~ ERROR non-item in item list +} struct S; trait X { - X() {} //~ ERROR expected one of `!` or `::`, found `(` + X() {} //~ ERROR non-item in item list fn xxx() { ### } L = M; Z = { 2 + 3 }; @@ -13,19 +13,19 @@ trait X { } trait A { - X() {} //~ ERROR expected one of `!` or `::`, found `(` + X() {} //~ ERROR non-item in item list } trait B { fn xxx() { ### } //~ ERROR expected } trait C { - L = M; //~ ERROR expected one of `!` or `::`, found `=` + L = M; //~ ERROR non-item in item list } trait D { - Z = { 2 + 3 }; //~ ERROR expected one of `!` or `::`, found `=` + Z = { 2 + 3 }; //~ ERROR non-item in item list } trait E { - ::Y (); //~ ERROR expected one of + ::Y (); //~ ERROR non-item in item list } impl S { diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index 613d7eee59480..787fb2e57e6c6 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -1,36 +1,33 @@ -error: expected one of `!` or `::`, found `}` - --> $DIR/issue-40006.rs:3:1 +error: non-item in item list + --> $DIR/issue-40006.rs:2:5 | LL | impl dyn A { - | - while parsing this item list starting here + | - item list starts here LL | Y - | - expected one of `!` or `::` + | ^ non-item starts here LL | } - | ^ - | | - | unexpected token - | the item list ends here + | - item list ends here -error: expected one of `!` or `::`, found `(` - --> $DIR/issue-40006.rs:8:6 +error: non-item in item list + --> $DIR/issue-40006.rs:8:5 | LL | trait X { - | - while parsing this item list starting here + | - item list starts here LL | X() {} - | ^ expected one of `!` or `::` + | ^ non-item starts here ... LL | } - | - the item list ends here + | - item list ends here -error: expected one of `!` or `::`, found `(` - --> $DIR/issue-40006.rs:16:6 +error: non-item in item list + --> $DIR/issue-40006.rs:16:5 | LL | trait A { - | - while parsing this item list starting here + | - item list starts here LL | X() {} - | ^ expected one of `!` or `::` + | ^ non-item starts here LL | } - | - the item list ends here + | - item list ends here error: expected `[`, found `#` --> $DIR/issue-40006.rs:19:17 @@ -38,35 +35,35 @@ error: expected `[`, found `#` LL | fn xxx() { ### } | ^ expected `[` -error: expected one of `!` or `::`, found `=` - --> $DIR/issue-40006.rs:22:7 +error: non-item in item list + --> $DIR/issue-40006.rs:22:5 | LL | trait C { - | - while parsing this item list starting here + | - item list starts here LL | L = M; - | ^ expected one of `!` or `::` + | ^ non-item starts here LL | } - | - the item list ends here + | - item list ends here -error: expected one of `!` or `::`, found `=` - --> $DIR/issue-40006.rs:25:7 +error: non-item in item list + --> $DIR/issue-40006.rs:25:5 | LL | trait D { - | - while parsing this item list starting here + | - item list starts here LL | Z = { 2 + 3 }; - | ^ expected one of `!` or `::` + | ^ non-item starts here LL | } - | - the item list ends here + | - item list ends here -error: expected one of `!` or `::`, found `(` - --> $DIR/issue-40006.rs:28:9 +error: non-item in item list + --> $DIR/issue-40006.rs:28:5 | LL | trait E { - | - while parsing this item list starting here + | - item list starts here LL | ::Y (); - | ^ expected one of `!` or `::` + | ^^ non-item starts here LL | } - | - the item list ends here + | - item list ends here error: missing `fn` for method definition --> $DIR/issue-40006.rs:32:8 diff --git a/src/test/ui/feature-gates/feature-gate-extern_prelude.rs b/src/test/ui/feature-gates/feature-gate-extern_prelude.rs index 237099e790107..ba9dc4a7c7d0f 100644 --- a/src/test/ui/feature-gates/feature-gate-extern_prelude.rs +++ b/src/test/ui/feature-gates/feature-gate-extern_prelude.rs @@ -1 +1 @@ -can-only-test-this-in-run-make-fulldeps //~ ERROR expected one of `!` or `::`, found `-` +can-only-test-this-in-run-make-fulldeps //~ ERROR expected item, found `can` diff --git a/src/test/ui/feature-gates/feature-gate-extern_prelude.stderr b/src/test/ui/feature-gates/feature-gate-extern_prelude.stderr index d72e47e9ed8ff..22e335e5aed3c 100644 --- a/src/test/ui/feature-gates/feature-gate-extern_prelude.stderr +++ b/src/test/ui/feature-gates/feature-gate-extern_prelude.stderr @@ -1,8 +1,8 @@ -error: expected one of `!` or `::`, found `-` - --> $DIR/feature-gate-extern_prelude.rs:1:4 +error: expected item, found `can` + --> $DIR/feature-gate-extern_prelude.rs:1:1 | LL | can-only-test-this-in-run-make-fulldeps - | ^ expected one of `!` or `::` + | ^^^ expected item error: aborting due to previous error diff --git a/src/test/ui/issues/issue-21146.rs b/src/test/ui/issues/issue-21146.rs index 19eaffc3edd4a..32987fcf53cdf 100644 --- a/src/test/ui/issues/issue-21146.rs +++ b/src/test/ui/issues/issue-21146.rs @@ -1,3 +1,3 @@ -// error-pattern: expected one of `!` or `::`, found `` +// error-pattern: expected item, found `parse_error` include!("auxiliary/issue-21146-inc.rs"); fn main() {} diff --git a/src/test/ui/issues/issue-21146.stderr b/src/test/ui/issues/issue-21146.stderr index c71fda3d63fe9..f2667ce406f5c 100644 --- a/src/test/ui/issues/issue-21146.stderr +++ b/src/test/ui/issues/issue-21146.stderr @@ -1,8 +1,8 @@ -error: expected one of `!` or `::`, found `` +error: expected item, found `parse_error` --> $DIR/auxiliary/issue-21146-inc.rs:3:1 | LL | parse_error - | ^^^^^^^^^^^ expected one of `!` or `::` + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/class-implements-bad-trait.stderr b/src/test/ui/parser/class-implements-bad-trait.stderr index 3a4dea95d5ddc..cb27722a65b2b 100644 --- a/src/test/ui/parser/class-implements-bad-trait.stderr +++ b/src/test/ui/parser/class-implements-bad-trait.stderr @@ -1,8 +1,36 @@ -error: expected one of `!` or `::`, found `cat` - --> $DIR/class-implements-bad-trait.rs:2:7 +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{` + --> $DIR/class-implements-bad-trait.rs:4:21 | -LL | class cat : nonexistent { - | ^^^ expected one of `!` or `::` +LL | new(in_x : usize) { self.meows = in_x; } + | ^ expected one of `.`, `;`, `?`, `}`, or an operator -error: aborting due to previous error +error: statements cannot reside in modules + --> $DIR/class-implements-bad-trait.rs:2:1 + | +LL | class cat : nonexistent { + | _^^^^^___________________^ +LL | | let meows: usize; +LL | | new(in_x : usize) { self.meows = in_x; } +LL | | } + | |_^ + | + = note: the program entry point starts in `fn main() { ... }`, defined in `main.rs` + = note: for more on functions and how to structure your program, see https://doc.rust-lang.org/book/ch03-03-how-functions-work.html +help: consider moving the statements into a function + | +LL | fn my_function() -> _ { +LL | class; +LL | cat: nonexistent; +LL | { let meows: usize; (/*ERROR*/) } +LL | } + | + +error[E0425]: cannot find function `cat` in this scope + --> $DIR/class-implements-bad-trait.rs:8:14 + | +LL | let nyan = cat(0); + | ^^^ not found in this scope + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/parser/extern-no-fn.rs b/src/test/ui/parser/extern-no-fn.rs index d9f35e0eb5cfc..2a87950250cb8 100644 --- a/src/test/ui/parser/extern-no-fn.rs +++ b/src/test/ui/parser/extern-no-fn.rs @@ -1,5 +1,5 @@ extern { - f(); //~ ERROR expected one of `!` or `::`, found `(` + f(); //~ ERROR non-item in item list } fn main() { diff --git a/src/test/ui/parser/extern-no-fn.stderr b/src/test/ui/parser/extern-no-fn.stderr index 0151cb4235b0d..7ac5bab3ace1a 100644 --- a/src/test/ui/parser/extern-no-fn.stderr +++ b/src/test/ui/parser/extern-no-fn.stderr @@ -1,12 +1,12 @@ -error: expected one of `!` or `::`, found `(` - --> $DIR/extern-no-fn.rs:2:6 +error: non-item in item list + --> $DIR/extern-no-fn.rs:2:5 | LL | extern { - | - while parsing this item list starting here + | - item list starts here LL | f(); - | ^ expected one of `!` or `::` + | ^ non-item starts here LL | } - | - the item list ends here + | - item list ends here error: aborting due to previous error diff --git a/src/test/ui/parser/issue-21153.rs b/src/test/ui/parser/issue-21153.rs index bf5fdb1f3c6b0..f75fce4d0796b 100644 --- a/src/test/ui/parser/issue-21153.rs +++ b/src/test/ui/parser/issue-21153.rs @@ -1,6 +1,6 @@ trait MyTrait: Iterator { Item = T; - //~^ ERROR expected one of `!` or `::`, found `=` + //~^ ERROR non-item in item list } fn main() {} diff --git a/src/test/ui/parser/issue-21153.stderr b/src/test/ui/parser/issue-21153.stderr index cbfa9ded3c393..c84d373738cd4 100644 --- a/src/test/ui/parser/issue-21153.stderr +++ b/src/test/ui/parser/issue-21153.stderr @@ -1,13 +1,13 @@ -error: expected one of `!` or `::`, found `=` - --> $DIR/issue-21153.rs:2:10 +error: non-item in item list + --> $DIR/issue-21153.rs:2:5 | LL | trait MyTrait: Iterator { - | - while parsing this item list starting here + | - item list starts here LL | Item = T; - | ^ expected one of `!` or `::` + | ^^^^ non-item starts here LL | LL | } - | - the item list ends here + | - item list ends here error: aborting due to previous error diff --git a/src/test/ui/parser/module-statement-recovery/main.rs b/src/test/ui/parser/module-statement-recovery/main.rs index 1d5fab97f6a0c..d8b49b7aa2784 100644 --- a/src/test/ui/parser/module-statement-recovery/main.rs +++ b/src/test/ui/parser/module-statement-recovery/main.rs @@ -15,3 +15,9 @@ Ok(42u16) struct X; if true {} //~ ERROR statements cannot reside in modules + +enum E {} + +x.y(); //~ ERROR statements cannot reside in modules +let x = 0; +x; diff --git a/src/test/ui/parser/module-statement-recovery/main.stderr b/src/test/ui/parser/module-statement-recovery/main.stderr index 1830c575be3a0..bb7c2650213ea 100644 --- a/src/test/ui/parser/module-statement-recovery/main.stderr +++ b/src/test/ui/parser/module-statement-recovery/main.stderr @@ -32,5 +32,21 @@ help: consider moving the statements into a function LL | fn my_function() -> _ { if true { } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: statements cannot reside in modules + --> $DIR/main.rs:21:1 + | +LL | x.y(); + | ^^^^^^ +LL | let x = 0; +LL | x; + | ^^ + | + = note: the program entry point starts in `fn main() { ... }`, defined in `main.rs` + = note: for more on functions and how to structure your program, see https://doc.rust-lang.org/book/ch03-03-how-functions-work.html +help: consider moving the statements into a function + | +LL | fn my_function() { x.y(); let x = 0; x; } + | + +error: aborting due to 3 previous errors diff --git a/src/test/ui/parser/module-statement-recovery/recover-statements-not-main.rs b/src/test/ui/parser/module-statement-recovery/recover-statements-not-main.rs index eb013da88a9a2..d8b49b7aa2784 100644 --- a/src/test/ui/parser/module-statement-recovery/recover-statements-not-main.rs +++ b/src/test/ui/parser/module-statement-recovery/recover-statements-not-main.rs @@ -18,6 +18,6 @@ if true {} //~ ERROR statements cannot reside in modules enum E {} -x.y(); +x.y(); //~ ERROR statements cannot reside in modules let x = 0; x; diff --git a/src/test/ui/parser/module-statement-recovery/recover-statements-not-main.stderr b/src/test/ui/parser/module-statement-recovery/recover-statements-not-main.stderr index 324e4310135df..b3cb7c83f1354 100644 --- a/src/test/ui/parser/module-statement-recovery/recover-statements-not-main.stderr +++ b/src/test/ui/parser/module-statement-recovery/recover-statements-not-main.stderr @@ -32,11 +32,21 @@ help: consider moving the statements into a function LL | fn my_function() -> _ { if true { } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: expected one of `!` or `::`, found `.` - --> $DIR/recover-statements-not-main.rs:21:2 +error: statements cannot reside in modules + --> $DIR/recover-statements-not-main.rs:21:1 | LL | x.y(); - | ^ expected one of `!` or `::` + | ^^^^^^ +LL | let x = 0; +LL | x; + | ^^ + | + = note: the program entry point starts in `fn main() { ... }`, defined in `main.rs` + = note: for more on functions and how to structure your program, see https://doc.rust-lang.org/book/ch03-03-how-functions-work.html +help: consider moving the statements into a function + | +LL | fn my_function() { x.y(); let x = 0; x; } + | error: aborting due to 3 previous errors diff --git a/src/test/ui/parser/underscore_item_not_const.rs b/src/test/ui/parser/underscore_item_not_const.rs index c01ac4752e075..85dccee12d978 100644 --- a/src/test/ui/parser/underscore_item_not_const.rs +++ b/src/test/ui/parser/underscore_item_not_const.rs @@ -11,6 +11,8 @@ use _ as g; //~ ERROR expected identifier, found reserved identifier `_` trait _ {} //~ ERROR expected identifier, found reserved identifier `_` trait _ = Copy; //~ ERROR expected identifier, found reserved identifier `_` macro_rules! _ { () => {} } //~ ERROR expected identifier, found reserved identifier `_` -union _ { f: u8 } //~ ERROR expected one of `!` or `::`, found reserved identifier `_` +union _ { f: u8 } +//~^ ERROR statements cannot reside in modules +//~| ERROR expected item, found reserved identifier `_` fn main() {} diff --git a/src/test/ui/parser/underscore_item_not_const.stderr b/src/test/ui/parser/underscore_item_not_const.stderr index 0bc7642dd1964..14fc5905d8e3e 100644 --- a/src/test/ui/parser/underscore_item_not_const.stderr +++ b/src/test/ui/parser/underscore_item_not_const.stderr @@ -64,11 +64,24 @@ error: expected identifier, found reserved identifier `_` LL | macro_rules! _ { () => {} } | ^ expected identifier, found reserved identifier -error: expected one of `!` or `::`, found reserved identifier `_` +error: statements cannot reside in modules + --> $DIR/underscore_item_not_const.rs:14:1 + | +LL | union _ { f: u8 } + | ^^^^^ + | + = note: the program entry point starts in `fn main() { ... }`, defined in `main.rs` + = note: for more on functions and how to structure your program, see https://doc.rust-lang.org/book/ch03-03-how-functions-work.html +help: consider moving the statements into a function + | +LL | fn my_function() -> _ { union } _ { f: u8 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected item, found reserved identifier `_` --> $DIR/underscore_item_not_const.rs:14:7 | LL | union _ { f: u8 } - | ^ expected one of `!` or `::` + | ^ expected item -error: aborting due to 12 previous errors +error: aborting due to 13 previous errors