diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index f13898d702454..af9700ee81e55 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -8,8 +8,7 @@ use rustc_ast_pretty::pprust; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult, StashKey}; use rustc_span::source_map::{self, Span}; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_span::BytePos; -use syntax::ast::{self, AttrKind, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID}; +use syntax::ast::{self, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID}; use syntax::ast::{AssocItem, AssocItemKind, Item, ItemKind, UseTree, UseTreeKind}; use syntax::ast::{Async, Const, Defaultness, IsAuto, PathSegment, Unsafe}; use syntax::ast::{BindingMode, Block, FnDecl, FnSig, Mac, MacArgs, MacDelimiter, Param, SelfKind}; @@ -90,18 +89,18 @@ impl<'a> Parser<'a> { } // FAILURE TO PARSE ITEM - match vis.node { - VisibilityKind::Inherited => {} - _ => { - self.struct_span_err(vis.span, "unmatched visibility `pub`") - .span_label(vis.span, "the unmatched visibility") - .help("you likely meant to define an item, e.g., `pub fn foo() {}`") - .emit(); - } + if let VisibilityKind::Inherited = vis.node { + } else { + let vs = pprust::vis_to_string(&vis); + let vs = vs.trim_end(); + self.struct_span_err(vis.span, &format!("unmatched visibility `{}`", vs)) + .span_label(vis.span, "the unmatched visibility") + .help(&format!("you likely meant to define an item, e.g., `{} fn foo() {{}}`", vs)) + .emit(); } - if !attributes_allowed && !attrs.is_empty() { - self.expected_item_err(&attrs)?; + if !attributes_allowed { + self.recover_attrs_no_item(&attrs)?; } Ok(None) } @@ -165,7 +164,7 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::Struct) { // STRUCT ITEM self.parse_item_struct()? - } else if self.is_union_item() { + } else if self.is_kw_followed_by_ident(kw::Union) { // UNION ITEM self.bump(); // `union` self.parse_item_union()? @@ -175,15 +174,12 @@ impl<'a> Parser<'a> { } else if self.is_macro_rules_item() { // MACRO_RULES ITEM self.parse_item_macro_rules(vis)? - } else if vis.node.is_pub() - && self.check_ident() - && self.look_ahead(1, |t| *t != token::Not) - { + } 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() { // MACRO INVOCATION ITEM - self.parse_item_macro(vis)? + (Ident::invalid(), ItemKind::Mac(self.parse_item_macro(vis)?)) } else { return Ok(None); }; @@ -193,12 +189,17 @@ impl<'a> Parser<'a> { /// When parsing a statement, would the start of a path be an item? pub(super) fn is_path_start_item(&mut self) -> bool { self.is_crate_vis() // no: `crate::b`, yes: `crate $item` - || self.is_union_item() // no: `union::b`, yes: `union U { .. }` + || self.is_kw_followed_by_ident(kw::Union) // no: `union::b`, yes: `union U { .. }` || self.check_auto_or_unsafe_trait_item() // no: `auto::b`, yes: `auto trait X { .. }` || self.is_async_fn() // no(2015): `async::b`, yes: `async fn` || self.is_macro_rules_item() // no: `macro_rules::b`, yes: `macro_rules! mac` } + /// Are we sure this could not possibly be a macro invocation? + fn isnt_macro_invocation(&mut self) -> bool { + self.check_ident() && self.look_ahead(1, |t| *t != token::Not && *t != token::ModSep) + } + /// Recover on encountering a struct or method definition where the user /// forgot to add the `struct` or `fn` keyword after writing `pub`: `pub S {}`. fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> { @@ -297,33 +298,33 @@ impl<'a> Parser<'a> { } /// Parses an item macro, e.g., `item!();`. - fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> { - self.complain_if_pub_macro(&vis.node, vis.span); - - // Item macro - let path = self.parse_path(PathStyle::Mod)?; - self.expect(&token::Not)?; - let args = self.parse_mac_args()?; - if args.need_semicolon() && !self.eat(&token::Semi) { - self.report_invalid_macro_expansion_item(); - } - - let mac = Mac { path, args, prior_type_ascription: self.last_type_ascription }; - Ok((Ident::invalid(), ItemKind::Mac(mac))) - } - - /// Emits an expected-item-after-attributes error. - fn expected_item_err(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> { - let message = match attrs.last() { - Some(&Attribute { kind: AttrKind::DocComment(_), .. }) => { - "expected item after doc comment" - } - _ => "expected item after attributes", + fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, Mac> { + let path = self.parse_path(PathStyle::Mod)?; // `foo::bar` + self.expect(&token::Not)?; // `!` + 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 }) + } + + /// Recover if we parsed attributes and expected an item but there was none. + fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> { + let (start, end) = match attrs { + [] => return Ok(()), + [x0] => (x0, x0), + [x0, .., xn] => (x0, xn), }; - - let mut err = self.struct_span_err(self.prev_span, message); - if attrs.last().unwrap().is_doc_comment() { - err.span_label(self.prev_span, "this doc comment doesn't document anything"); + let msg = if end.is_doc_comment() { + "expected item after doc comment" + } else { + "expected item after attributes" + }; + let mut err = self.struct_span_err(end.span, msg); + if end.is_doc_comment() { + err.span_label(end.span, "this doc comment doesn't document anything"); + } + if let [.., penultimate, _] = attrs { + err.span_label(start.span.to(penultimate.span), "other attributes here"); } Err(err) } @@ -332,38 +333,19 @@ impl<'a> Parser<'a> { self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn]) } - /// Parses a macro invocation inside a `trait`, `impl` or `extern` block. + /// Parses a macro invocation inside a `trait`, `impl`, or `extern` block. fn parse_assoc_macro_invoc( &mut self, item_kind: &str, - vis: Option<&Visibility>, + vis: &Visibility, at_end: &mut bool, ) -> PResult<'a, Option> { - if self.token.is_path_start() && !(self.is_async_fn() && self.token.span.rust_2015()) { - let prev_span = self.prev_span; - let path = self.parse_path(PathStyle::Mod)?; - - if path.segments.len() == 1 { - if !self.eat(&token::Not) { - return Err(self.missing_assoc_item_kind_err(item_kind, prev_span)); - } - } else { - self.expect(&token::Not)?; - } - - if let Some(vis) = vis { - self.complain_if_pub_macro(&vis.node, prev_span); - } - + if self.isnt_macro_invocation() { + Err(self.missing_assoc_item_kind_err(item_kind, self.prev_span)) + } else if self.token.is_path_start() { + let mac = self.parse_item_macro(vis)?; *at_end = true; - - // eat a matched-delimiter token tree: - let args = self.parse_mac_args()?; - if args.need_semicolon() { - self.expect_semi()?; - } - - Ok(Some(Mac { path, args, prior_type_ascription: self.last_type_ascription })) + Ok(Some(mac)) } else { Ok(None) } @@ -389,7 +371,7 @@ impl<'a> Parser<'a> { // | ^ missing `fn`, `type`, or `const` // pub path( // ^^ `sp` below will point to this - let sp = prev_span.between(self.prev_span); + let sp = prev_span.between(self.token.span); let mut err = self .struct_span_err(sp, &format!("{} for {}-item declaration", expected_kinds, item_type)); err.span_label(sp, expected_kinds); @@ -706,10 +688,13 @@ impl<'a> Parser<'a> { } else if self.check_fn_front_matter() { let (ident, sig, generics, body) = self.parse_fn(at_end, &mut attrs, req_name)?; (ident, AssocItemKind::Fn(sig, body), generics) - } else if let Some(mac) = self.parse_assoc_macro_invoc("associated", Some(&vis), at_end)? { + } else if self.check_keyword(kw::Const) { + self.parse_assoc_const()? + } else if let Some(mac) = self.parse_assoc_macro_invoc("associated", &vis, at_end)? { (Ident::invalid(), AssocItemKind::Macro(mac), Generics::default()) } else { - self.parse_assoc_const()? + self.recover_attrs_no_item(&attrs)?; + self.unexpected()? }; let span = lo.to(self.prev_span); @@ -813,7 +798,7 @@ impl<'a> Parser<'a> { fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> { match self.token.kind { - token::Ident(name, false) if name == kw::Underscore => { + token::Ident(name @ kw::Underscore, false) => { let span = self.token.span; self.bump(); Ok(Ident::new(name, span)) @@ -928,12 +913,10 @@ impl<'a> Parser<'a> { ) .emit(); self.parse_item_foreign_static()? - } else if let Some(mac) = self.parse_assoc_macro_invoc("extern", Some(&vis), at_end)? { + } else if let Some(mac) = self.parse_assoc_macro_invoc("extern", &vis, at_end)? { (Ident::invalid(), ForeignItemKind::Macro(mac)) } else { - if !attrs.is_empty() { - self.expected_item_err(&attrs)?; - } + self.recover_attrs_no_item(&attrs)?; self.unexpected()? }; Ok(P(self.mk_item(lo, ident, kind, vis, attrs))) @@ -1189,11 +1172,6 @@ impl<'a> Parser<'a> { Ok((class_name, ItemKind::Union(vdata, generics))) } - fn is_union_item(&self) -> bool { - self.token.is_keyword(kw::Union) - && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) - } - fn parse_record_struct_body( &mut self, ) -> PResult<'a, (Vec, /* recovered */ bool)> { @@ -1343,24 +1321,26 @@ impl<'a> Parser<'a> { /// Parses a declarative macro 2.0 definition. /// The `macro` keyword has already been parsed. + /// ``` + /// MacBody = "{" TOKEN_STREAM "}" ; + /// MacParams = "(" TOKEN_STREAM ")" ; + /// DeclMac = "macro" Ident MacParams? MacBody ; + /// ``` fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemInfo> { let ident = self.parse_ident()?; let body = if self.check(&token::OpenDelim(token::Brace)) { - self.parse_mac_args()? + self.parse_mac_args()? // `MacBody` } else if self.check(&token::OpenDelim(token::Paren)) { - let params = self.parse_token_tree(); + let params = self.parse_token_tree(); // `MacParams` let pspan = params.span(); - let body = if self.check(&token::OpenDelim(token::Brace)) { - self.parse_token_tree() - } else { + if !self.check(&token::OpenDelim(token::Brace)) { return self.unexpected(); - }; + } + let body = self.parse_token_tree(); // `MacBody` + // Convert `MacParams MacBody` into `{ MacParams => MacBody }`. let bspan = body.span(); - let tokens = TokenStream::new(vec![ - params.into(), - TokenTree::token(token::FatArrow, pspan.between(bspan)).into(), - body.into(), - ]); + let arrow = TokenTree::token(token::FatArrow, pspan.between(bspan)); // `=>` + let tokens = TokenStream::new(vec![params.into(), arrow.into(), body.into()]); let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi()); P(MacArgs::Delimited(dspan, MacDelimiter::Brace, tokens)) } else { @@ -1380,65 +1360,68 @@ impl<'a> Parser<'a> { /// Parses a legacy `macro_rules! foo { ... }` declarative macro. fn parse_item_macro_rules(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> { - self.complain_if_pub_macro(&vis.node, vis.span); self.expect_keyword(sym::macro_rules)?; // `macro_rules` self.expect(&token::Not)?; // `!` let ident = self.parse_ident()?; let body = self.parse_mac_args()?; - if body.need_semicolon() && !self.eat(&token::Semi) { - self.report_invalid_macro_expansion_item(); - } + self.eat_semi_for_macro_if_needed(&body); + self.complain_if_pub_macro(vis, true); Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: true }))) } - fn complain_if_pub_macro(&self, vis: &VisibilityKind, sp: Span) { - match *vis { - VisibilityKind::Inherited => {} - _ => { - let mut err = if self.token.is_keyword(sym::macro_rules) { - let mut err = - self.struct_span_err(sp, "can't qualify macro_rules invocation with `pub`"); - err.span_suggestion( - sp, - "try exporting the macro", - "#[macro_export]".to_owned(), - Applicability::MaybeIncorrect, // speculative - ); - err - } else { - let mut err = - self.struct_span_err(sp, "can't qualify macro invocation with `pub`"); - err.help("try adjusting the macro to put `pub` inside the invocation"); - err - }; - err.emit(); - } + /// Item macro invocations or `macro_rules!` definitions need inherited visibility. + /// If that's not the case, emit an error. + fn complain_if_pub_macro(&self, vis: &Visibility, macro_rules: bool) { + if let VisibilityKind::Inherited = vis.node { + return; + } + + let vstr = pprust::vis_to_string(vis); + let vstr = vstr.trim_end(); + if macro_rules { + let msg = format!("can't qualify macro_rules invocation with `{}`", vstr); + self.struct_span_err(vis.span, &msg) + .span_suggestion( + vis.span, + "try exporting the macro", + "#[macro_export]".to_owned(), + Applicability::MaybeIncorrect, // speculative + ) + .emit(); + } else { + self.struct_span_err(vis.span, "can't qualify macro invocation with `pub`") + .span_suggestion( + vis.span, + "remove the visibility", + String::new(), + Applicability::MachineApplicable, + ) + .help(&format!("try adjusting the macro to put `{}` inside the invocation", vstr)) + .emit(); } } - fn report_invalid_macro_expansion_item(&self) { - let has_close_delim = self - .sess - .source_map() - .span_to_snippet(self.prev_span) - .map(|s| s.ends_with(")") || s.ends_with("]")) - .unwrap_or(false); + fn eat_semi_for_macro_if_needed(&mut self, args: &MacArgs) { + if args.need_semicolon() && !self.eat(&token::Semi) { + self.report_invalid_macro_expansion_item(args); + } + } + fn report_invalid_macro_expansion_item(&self, args: &MacArgs) { let mut err = self.struct_span_err( self.prev_span, "macros that expand to items must be delimited with braces or followed by a semicolon", ); - - // To avoid ICE, we shouldn't emit actual suggestions when it hasn't closing delims - if has_close_delim { + if self.unclosed_delims.is_empty() { + let DelimSpan { open, close } = match args { + MacArgs::Empty | MacArgs::Eq(..) => unreachable!(), + MacArgs::Delimited(dspan, ..) => *dspan, + }; err.multipart_suggestion( "change the delimiters to curly braces", - vec![ - (self.prev_span.with_hi(self.prev_span.lo() + BytePos(1)), '{'.to_string()), - (self.prev_span.with_lo(self.prev_span.hi() - BytePos(1)), '}'.to_string()), - ], + vec![(open, "{".to_string()), (close, '}'.to_string())], Applicability::MaybeIncorrect, ); } else { @@ -1449,14 +1432,13 @@ impl<'a> Parser<'a> { Applicability::HasPlaceholders, ); } - err.span_suggestion( self.prev_span.shrink_to_hi(), "add a semicolon", ';'.to_string(), Applicability::MaybeIncorrect, - ) - .emit(); + ); + err.emit(); } /// Checks if current token is one of tokens which cannot be nested like `kw::Enum`. In case diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 4716d722778a6..79944dc35e523 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -572,6 +572,11 @@ impl<'a> Parser<'a> { if !self.eat_keyword(kw) { self.unexpected() } else { Ok(()) } } + /// Is the given keyword `kw` followed by a non-reserved identifier? + fn is_kw_followed_by_ident(&self, kw: Symbol) -> bool { + self.token.is_keyword(kw) && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) + } + fn check_or_expected(&mut self, ok: bool, typ: TokenType) -> bool { if ok { true diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index 439d0368d0961..742fc4802fd9d 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -8,7 +8,7 @@ use crate::DirectoryOwnership; use rustc_errors::{Applicability, PResult}; use rustc_span::source_map::{BytePos, Span}; -use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::symbol::{kw, sym}; use syntax::ast; use syntax::ast::{AttrStyle, AttrVec, Attribute, Mac, MacStmtStyle}; use syntax::ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKind, DUMMY_NODE_ID}; @@ -55,13 +55,11 @@ impl<'a> Parser<'a> { return self.recover_stmt_local(lo, attrs.into(), msg, "let"); } - // Starts like a simple path, being careful to avoid contextual keywords - // such as a union items, item with `crate` visibility or auto trait items. - // Our goal here is to parse an arbitrary path `a::b::c` but not something that starts - // like a path (1 token), but it fact not a path. - if self.token.is_path_start() - && !self.token.is_qpath_start() - && !self.is_path_start_item() // Confirm we don't steal syntax from `parse_item_`. + // Starts like a simple path, being careful to avoid contextual keywords, + // e.g., `union`, items with `crate` visibility, or `auto trait` items. + // We aim to parse an arbitrary path `a::b` but not something that starts like a path + // (1 token), but it fact not a path. Also, we avoid stealing syntax from `parse_item_`. + if self.token.is_path_start() && !self.token.is_qpath_start() && !self.is_path_start_item() { let path = self.parse_path(PathStyle::Expr)?; @@ -191,10 +189,6 @@ impl<'a> Parser<'a> { } } - fn is_kw_followed_by_ident(&self, kw: Symbol) -> bool { - self.token.is_keyword(kw) && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) - } - fn recover_stmt_local( &mut self, lo: Span, diff --git a/src/test/ui/issues/issue-58856-2.stderr b/src/test/ui/issues/issue-58856-2.stderr index 01d70d861e2c9..6221b90b31dd7 100644 --- a/src/test/ui/issues/issue-58856-2.stderr +++ b/src/test/ui/issues/issue-58856-2.stderr @@ -7,11 +7,11 @@ LL | fn how_are_you(&self -> Empty { | | help: `)` may belong here | unclosed delimiter -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `)` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, `}`, or identifier, found `)` --> $DIR/issue-58856-2.rs:11:1 | LL | } - | - expected one of 10 possible tokens + | - expected one of 11 possible tokens LL | } | ^ unexpected token diff --git a/src/test/ui/issues/issue-60075.stderr b/src/test/ui/issues/issue-60075.stderr index 60eb99b46b79f..b2beb73503bb0 100644 --- a/src/test/ui/issues/issue-60075.stderr +++ b/src/test/ui/issues/issue-60075.stderr @@ -4,7 +4,7 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `}` LL | }); | ^ expected one of `.`, `;`, `?`, `else`, or an operator -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `;` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, `}`, or identifier, found `;` --> $DIR/issue-60075.rs:6:11 | LL | fn qux() -> Option { diff --git a/src/test/ui/macros/issue-54441.rs b/src/test/ui/macros/issue-54441.rs index afdf76b7b580f..a70163df1cb93 100644 --- a/src/test/ui/macros/issue-54441.rs +++ b/src/test/ui/macros/issue-54441.rs @@ -1,6 +1,7 @@ macro_rules! m { + //~^ ERROR missing `fn`, `type`, or `static` for extern-item declaration () => { - let //~ ERROR expected + let }; } diff --git a/src/test/ui/macros/issue-54441.stderr b/src/test/ui/macros/issue-54441.stderr index c94355f47161c..761e7aec7235a 100644 --- a/src/test/ui/macros/issue-54441.stderr +++ b/src/test/ui/macros/issue-54441.stderr @@ -1,13 +1,11 @@ -error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `static`, `type`, or `unsafe`, found keyword `let` - --> $DIR/issue-54441.rs:3:9 +error: missing `fn`, `type`, or `static` for extern-item declaration + --> $DIR/issue-54441.rs:1:1 | -LL | let - | ^^^ expected one of 9 possible tokens -... -LL | m!(); - | ----- in this macro invocation - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) +LL | / macro_rules! m { +LL | | +LL | | () => { +LL | | let + | |________^ missing `fn`, `type`, or `static` error: aborting due to previous error diff --git a/src/test/ui/parser/attr-before-eof.stderr b/src/test/ui/parser/attr-before-eof.stderr index eb5daf849811c..a2acb94372b8c 100644 --- a/src/test/ui/parser/attr-before-eof.stderr +++ b/src/test/ui/parser/attr-before-eof.stderr @@ -1,8 +1,8 @@ error: expected item after attributes - --> $DIR/attr-before-eof.rs:3:16 + --> $DIR/attr-before-eof.rs:3:1 | LL | #[derive(Debug)] - | ^ + | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/attr-dangling-in-mod.stderr b/src/test/ui/parser/attr-dangling-in-mod.stderr index d896b61ce49c4..1c892eac08f3b 100644 --- a/src/test/ui/parser/attr-dangling-in-mod.stderr +++ b/src/test/ui/parser/attr-dangling-in-mod.stderr @@ -1,8 +1,8 @@ error: expected item after attributes - --> $DIR/attr-dangling-in-mod.rs:6:14 + --> $DIR/attr-dangling-in-mod.rs:6:1 | LL | #[foo = "bar"] - | ^ + | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/attrs-after-extern-mod.stderr b/src/test/ui/parser/attrs-after-extern-mod.stderr index a02e738a2c38e..6060f3afe1e95 100644 --- a/src/test/ui/parser/attrs-after-extern-mod.stderr +++ b/src/test/ui/parser/attrs-after-extern-mod.stderr @@ -1,8 +1,8 @@ error: expected item after attributes - --> $DIR/attrs-after-extern-mod.rs:6:19 + --> $DIR/attrs-after-extern-mod.rs:6:5 | LL | #[cfg(stage37)] - | ^ + | ^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/default.rs b/src/test/ui/parser/default.rs index 17cd06864bf1d..65ecb1ebbe919 100644 --- a/src/test/ui/parser/default.rs +++ b/src/test/ui/parser/default.rs @@ -19,7 +19,8 @@ impl Foo for u16 { } impl Foo for u32 { //~ ERROR not all trait items implemented, missing: `foo` - default pub fn foo() -> T { T::default() } //~ ERROR expected one of + default pub fn foo() -> T { T::default() } + //~^ ERROR missing `fn`, `type`, or `const` for associated-item declaration } fn main() {} diff --git a/src/test/ui/parser/default.stderr b/src/test/ui/parser/default.stderr index dde36cf8ddeed..ede9e47151863 100644 --- a/src/test/ui/parser/default.stderr +++ b/src/test/ui/parser/default.stderr @@ -1,8 +1,8 @@ -error: expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found keyword `pub` - --> $DIR/default.rs:22:13 +error: missing `fn`, `type`, or `const` for associated-item declaration + --> $DIR/default.rs:22:12 | LL | default pub fn foo() -> T { T::default() } - | ^^^ expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe` + | ^ missing `fn`, `type`, or `const` error[E0449]: unnecessary visibility qualifier --> $DIR/default.rs:16:5 diff --git a/src/test/ui/parser/doc-before-attr.stderr b/src/test/ui/parser/doc-before-attr.stderr index 0fae44ce5c806..14fd01af2f98a 100644 --- a/src/test/ui/parser/doc-before-attr.stderr +++ b/src/test/ui/parser/doc-before-attr.stderr @@ -1,8 +1,10 @@ error: expected item after attributes - --> $DIR/doc-before-attr.rs:4:16 + --> $DIR/doc-before-attr.rs:4:1 | +LL | /// hi + | ------ other attributes here LL | #[derive(Debug)] - | ^ + | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs index edbf508ecdb76..1d271fa64b0ec 100644 --- a/src/test/ui/parser/duplicate-visibility.rs +++ b/src/test/ui/parser/duplicate-visibility.rs @@ -1,7 +1,6 @@ -// error-pattern: expected one of `(`, `async`, `const`, `extern`, `fn` - fn main() {} extern { pub pub fn foo(); + //~^ ERROR missing `fn`, `type`, or `static` for extern-item declaration } diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr index 92cf348796943..36a3a1ed5a0cc 100644 --- a/src/test/ui/parser/duplicate-visibility.stderr +++ b/src/test/ui/parser/duplicate-visibility.stderr @@ -1,8 +1,8 @@ -error: expected one of `(`, `async`, `const`, `extern`, `fn`, `static`, `type`, or `unsafe`, found keyword `pub` - --> $DIR/duplicate-visibility.rs:6:9 +error: missing `fn`, `type`, or `static` for extern-item declaration + --> $DIR/duplicate-visibility.rs:4:8 | LL | pub pub fn foo(); - | ^^^ expected one of 8 possible tokens + | ^ missing `fn`, `type`, or `static` error: aborting due to previous error diff --git a/src/test/ui/parser/issue-19398.rs b/src/test/ui/parser/issue-19398.rs index 2158a2fd6c11c..982a6be23ac5f 100644 --- a/src/test/ui/parser/issue-19398.rs +++ b/src/test/ui/parser/issue-19398.rs @@ -1,5 +1,6 @@ trait T { - extern "Rust" unsafe fn foo(); //~ ERROR expected one of `async`, `const` + //~^ ERROR missing `fn`, `type`, or `const` for associated-item declaration + extern "Rust" unsafe fn foo(); } fn main() {} diff --git a/src/test/ui/parser/issue-19398.stderr b/src/test/ui/parser/issue-19398.stderr index 201a6b2d66a7c..2bd6ac3a4b3a4 100644 --- a/src/test/ui/parser/issue-19398.stderr +++ b/src/test/ui/parser/issue-19398.stderr @@ -1,10 +1,11 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found keyword `extern` - --> $DIR/issue-19398.rs:2:5 +error: missing `fn`, `type`, or `const` for associated-item declaration + --> $DIR/issue-19398.rs:1:10 | -LL | trait T { - | - expected one of 10 possible tokens -LL | extern "Rust" unsafe fn foo(); - | ^^^^^^ unexpected token +LL | trait T { + | __________^ +LL | | +LL | | extern "Rust" unsafe fn foo(); + | |____^ missing `fn`, `type`, or `const` error: aborting due to previous error diff --git a/src/test/ui/parser/issue-20711-2.rs b/src/test/ui/parser/issue-20711-2.rs index 0063a334182f4..168c7e76162bc 100644 --- a/src/test/ui/parser/issue-20711-2.rs +++ b/src/test/ui/parser/issue-20711-2.rs @@ -4,6 +4,7 @@ impl Foo { fn foo() {} #[stable(feature = "rust1", since = "1.0.0")] -} //~ ERROR expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or + //~^ ERROR expected item after attributes +} fn main() {} diff --git a/src/test/ui/parser/issue-20711-2.stderr b/src/test/ui/parser/issue-20711-2.stderr index ee484890fada8..10ef31584dec1 100644 --- a/src/test/ui/parser/issue-20711-2.stderr +++ b/src/test/ui/parser/issue-20711-2.stderr @@ -1,10 +1,8 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `}` - --> $DIR/issue-20711-2.rs:7:1 +error: expected item after attributes + --> $DIR/issue-20711-2.rs:6:5 | LL | #[stable(feature = "rust1", since = "1.0.0")] - | - expected one of 9 possible tokens -LL | } - | ^ unexpected token + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/issue-20711.rs b/src/test/ui/parser/issue-20711.rs index dc216167b8a4f..020bb79d6e74e 100644 --- a/src/test/ui/parser/issue-20711.rs +++ b/src/test/ui/parser/issue-20711.rs @@ -2,6 +2,7 @@ struct Foo; impl Foo { #[stable(feature = "rust1", since = "1.0.0")] -} //~ ERROR expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or + //~^ ERROR expected item after attributes +} fn main() {} diff --git a/src/test/ui/parser/issue-20711.stderr b/src/test/ui/parser/issue-20711.stderr index 152c9f1c68975..66768de569418 100644 --- a/src/test/ui/parser/issue-20711.stderr +++ b/src/test/ui/parser/issue-20711.stderr @@ -1,10 +1,8 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `}` - --> $DIR/issue-20711.rs:5:1 +error: expected item after attributes + --> $DIR/issue-20711.rs:4:5 | LL | #[stable(feature = "rust1", since = "1.0.0")] - | - expected one of 9 possible tokens -LL | } - | ^ unexpected token + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/issue-32446.stderr b/src/test/ui/parser/issue-32446.stderr index 1a97f54160b24..25c1efe35ae11 100644 --- a/src/test/ui/parser/issue-32446.stderr +++ b/src/test/ui/parser/issue-32446.stderr @@ -1,8 +1,8 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `...` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, `}`, or identifier, found `...` --> $DIR/issue-32446.rs:4:11 | LL | trait T { ... } - | ^^^ expected one of 10 possible tokens + | ^^^ expected one of 11 possible tokens error: aborting due to previous error diff --git a/src/test/ui/parser/issue-41155.stderr b/src/test/ui/parser/issue-41155.stderr index 0e191eb7e0a04..327bc65818fa9 100644 --- a/src/test/ui/parser/issue-41155.stderr +++ b/src/test/ui/parser/issue-41155.stderr @@ -1,8 +1,8 @@ -error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `type`, or `unsafe`, found `}` +error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `type`, `unsafe`, or identifier, found `}` --> $DIR/issue-41155.rs:5:1 | LL | pub - | - expected one of 8 possible tokens + | - expected one of 9 possible tokens LL | } | ^ unexpected token diff --git a/src/test/ui/parser/issue-58094-missing-right-square-bracket.stderr b/src/test/ui/parser/issue-58094-missing-right-square-bracket.stderr index 00f6652b311da..8a44ee761ed67 100644 --- a/src/test/ui/parser/issue-58094-missing-right-square-bracket.stderr +++ b/src/test/ui/parser/issue-58094-missing-right-square-bracket.stderr @@ -7,10 +7,10 @@ LL | #[Ѕ | unclosed delimiter error: expected item after attributes - --> $DIR/issue-58094-missing-right-square-bracket.rs:4:4 + --> $DIR/issue-58094-missing-right-square-bracket.rs:4:1 | LL | #[Ѕ - | ^ + | ^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/macro/pub-item-macro.rs b/src/test/ui/parser/macro/pub-item-macro.rs index bae90227c62f4..f5f8a01e6a440 100644 --- a/src/test/ui/parser/macro/pub-item-macro.rs +++ b/src/test/ui/parser/macro/pub-item-macro.rs @@ -1,12 +1,15 @@ // Issue #14660 -macro_rules! priv_x { () => { - static x: u32 = 0; -}} +macro_rules! priv_x { + () => { + static x: u32 = 0; + }; +} macro_rules! pub_x { () => { pub priv_x!(); //~ ERROR can't qualify macro invocation with `pub` - //~^ HELP try adjusting the macro to put `pub` inside the invocation + //~^ HELP remove the visibility + //~| HELP try adjusting the macro to put `pub` inside the invocation }} mod foo { diff --git a/src/test/ui/parser/macro/pub-item-macro.stderr b/src/test/ui/parser/macro/pub-item-macro.stderr index 49644cf6a0e64..4ff96532e03a8 100644 --- a/src/test/ui/parser/macro/pub-item-macro.stderr +++ b/src/test/ui/parser/macro/pub-item-macro.stderr @@ -1,8 +1,8 @@ error: can't qualify macro invocation with `pub` - --> $DIR/pub-item-macro.rs:8:5 + --> $DIR/pub-item-macro.rs:10:5 | LL | pub priv_x!(); - | ^^^ + | ^^^ help: remove the visibility ... LL | pub_x!(); | --------- in this macro invocation @@ -11,16 +11,16 @@ LL | pub_x!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0603]: static `x` is private - --> $DIR/pub-item-macro.rs:17:23 + --> $DIR/pub-item-macro.rs:20:23 | LL | let y: u32 = foo::x; | ^ this static is private | note: the static `x` is defined here - --> $DIR/pub-item-macro.rs:4:5 + --> $DIR/pub-item-macro.rs:5:9 | -LL | static x: u32 = 0; - | ^^^^^^^^^^^^^^^^^^ +LL | static x: u32 = 0; + | ^^^^^^^^^^^^^^^^^^ ... LL | pub_x!(); | --------- in this macro invocation diff --git a/src/test/ui/parser/macro/trait-non-item-macros.stderr b/src/test/ui/parser/macro/trait-non-item-macros.stderr index 5a89b5b936f5b..9d05e85bcc00e 100644 --- a/src/test/ui/parser/macro/trait-non-item-macros.stderr +++ b/src/test/ui/parser/macro/trait-non-item-macros.stderr @@ -1,8 +1,8 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `2` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or identifier, found `2` --> $DIR/trait-non-item-macros.rs:2:19 | LL | ($a:expr) => ($a) - | ^^ expected one of 9 possible tokens + | ^^ expected one of 10 possible tokens ... LL | bah!(2); | -------- in this macro invocation diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs index 9f02a7a997bf2..592215030f552 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs @@ -1,12 +1,14 @@ +fn main() {} + impl T for () { //~ ERROR cannot find trait `T` in this scope fn foo(&self) {} +//~^ ERROR missing `fn`, `type`, or `const` -trait T { //~ ERROR expected one of +trait T { fn foo(&self); } pub(crate) struct Bar(); -fn main() {} //~ ERROR this file contains an unclosed delimiter diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr index a23cfeac58f84..1ec54525105f6 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/missing-close-brace-in-impl-trait.rs:12:52 + --> $DIR/missing-close-brace-in-impl-trait.rs:14:52 | LL | impl T for () { | - unclosed delimiter @@ -7,23 +7,18 @@ LL | impl T for () { LL | | ^ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found keyword `trait` - --> $DIR/missing-close-brace-in-impl-trait.rs:5:1 +error: missing `fn`, `type`, or `const` for associated-item declaration + --> $DIR/missing-close-brace-in-impl-trait.rs:5:17 | -LL | impl T for () { - | - unclosed delimiter -LL | -LL | fn foo(&self) {} - | - - | | - | expected one of 10 possible tokens - | help: `}` may belong here -LL | -LL | trait T { - | ^^^^^ unexpected token +LL | fn foo(&self) {} + | _________________^ +LL | | +LL | | +LL | | trait T { + | |_ missing `fn`, `type`, or `const` error[E0405]: cannot find trait `T` in this scope - --> $DIR/missing-close-brace-in-impl-trait.rs:1:6 + --> $DIR/missing-close-brace-in-impl-trait.rs:3:6 | LL | impl T for () { | ^ not found in this scope diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs index 5ec5d45bbe7b2..077e334719427 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs @@ -3,7 +3,7 @@ trait T { fn foo(&self); pub(crate) struct Bar(); -//~^ ERROR expected one of +//~^ ERROR missing `fn`, `type`, or `const` impl T for Bar { fn foo(&self) {} diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr index 213640127829c..1bb153c461d90 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr @@ -7,11 +7,11 @@ LL | trait T { LL | fn main() {} | ^ -error: expected one of `async`, `const`, `default`, `extern`, `fn`, `type`, or `unsafe`, found keyword `struct` - --> $DIR/missing-close-brace-in-trait.rs:5:12 +error: missing `fn`, `type`, or `const` for associated-item declaration + --> $DIR/missing-close-brace-in-trait.rs:5:11 | LL | pub(crate) struct Bar(); - | ^^^^^^ expected one of 7 possible tokens + | ^ missing `fn`, `type`, or `const` error[E0601]: `main` function not found in crate `missing_close_brace_in_trait` --> $DIR/missing-close-brace-in-trait.rs:1:1 diff --git a/src/test/ui/parser/pub-method-macro.rs b/src/test/ui/parser/pub-method-macro.rs index f04af1a0d65ff..0183bdcf6220b 100644 --- a/src/test/ui/parser/pub-method-macro.rs +++ b/src/test/ui/parser/pub-method-macro.rs @@ -15,7 +15,8 @@ mod bleh { impl S { pub defn!(f); //~ ERROR can't qualify macro invocation with `pub` - //~^ HELP try adjusting the macro to put `pub` inside the invocation + //~^ HELP remove the visibility + //~| HELP try adjusting the macro to put `pub` inside the invocation } } diff --git a/src/test/ui/parser/pub-method-macro.stderr b/src/test/ui/parser/pub-method-macro.stderr index 7b0fe4934610d..7c7a909267a1c 100644 --- a/src/test/ui/parser/pub-method-macro.stderr +++ b/src/test/ui/parser/pub-method-macro.stderr @@ -2,7 +2,7 @@ error: can't qualify macro invocation with `pub` --> $DIR/pub-method-macro.rs:17:9 | LL | pub defn!(f); - | ^^^ + | ^^^ help: remove the visibility | = help: try adjusting the macro to put `pub` inside the invocation diff --git a/src/test/ui/parser/removed-syntax-static-fn.rs b/src/test/ui/parser/removed-syntax-static-fn.rs index 0caddb9855d83..9e12222f3fd8b 100644 --- a/src/test/ui/parser/removed-syntax-static-fn.rs +++ b/src/test/ui/parser/removed-syntax-static-fn.rs @@ -1,8 +1,8 @@ struct S; impl S { + //~^ ERROR missing `fn`, `type`, or `const` for associated-item declaration static fn f() {} - //~^ ERROR expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, } fn main() {} diff --git a/src/test/ui/parser/removed-syntax-static-fn.stderr b/src/test/ui/parser/removed-syntax-static-fn.stderr index dfadefee23c15..5edf88026fbec 100644 --- a/src/test/ui/parser/removed-syntax-static-fn.stderr +++ b/src/test/ui/parser/removed-syntax-static-fn.stderr @@ -1,10 +1,11 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found keyword `static` - --> $DIR/removed-syntax-static-fn.rs:4:5 +error: missing `fn`, `type`, or `const` for associated-item declaration + --> $DIR/removed-syntax-static-fn.rs:3:9 | -LL | impl S { - | - expected one of 10 possible tokens -LL | static fn f() {} - | ^^^^^^ unexpected token +LL | impl S { + | _________^ +LL | | +LL | | static fn f() {} + | |____^ missing `fn`, `type`, or `const` error: aborting due to previous error diff --git a/src/test/ui/pub/pub-restricted-error-fn.stderr b/src/test/ui/pub/pub-restricted-error-fn.stderr index c5acb92dcd436..c0168b02da607 100644 --- a/src/test/ui/pub/pub-restricted-error-fn.stderr +++ b/src/test/ui/pub/pub-restricted-error-fn.stderr @@ -1,10 +1,10 @@ -error: unmatched visibility `pub` +error: unmatched visibility `pub(crate)` --> $DIR/pub-restricted-error-fn.rs:1:1 | LL | pub(crate) () fn foo() {} | ^^^^^^^^^^ the unmatched visibility | - = help: you likely meant to define an item, e.g., `pub fn foo() {}` + = help: you likely meant to define an item, e.g., `pub(crate) fn foo() {}` error: expected item, found `(` --> $DIR/pub-restricted-error-fn.rs:1:12