diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index b1fa818d0a8cf..75938470b6fca 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -1269,6 +1269,7 @@ impl<'a> State<'a> { self.print_where_clause(&generics.where_clause); self.s.word(" "); self.bopen(); + self.print_inner_attributes(&item.attrs); for trait_item in trait_items { self.print_assoc_item(trait_item); } diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 90692fe1ec9dd..0968e92c20314 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -867,7 +867,7 @@ pub fn parse_ast_fragment<'a>( AstFragmentKind::ForeignItems => { let mut items = SmallVec::new(); while this.token != token::Eof { - items.push(this.parse_foreign_item()?); + items.push(this.parse_foreign_item(&mut false)?); } AstFragment::ForeignItems(items) } diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs index 8dec64c579e88..1c479295af3ed 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_parse/config.rs @@ -562,14 +562,9 @@ fn is_cfg(attr: &Attribute) -> bool { /// Process the potential `cfg` attributes on a module. /// Also determine if the module should be included in this configuration. -pub fn process_configure_mod( - sess: &ParseSess, - cfg_mods: bool, - attrs: &[Attribute], -) -> (bool, Vec) { +pub fn process_configure_mod(sess: &ParseSess, cfg_mods: bool, attrs: &mut Vec) -> bool { // Don't perform gated feature checking. let mut strip_unconfigured = StripUnconfigured { sess, features: None }; - let mut attrs = attrs.to_owned(); - strip_unconfigured.process_cfg_attrs(&mut attrs); - (!cfg_mods || strip_unconfigured.in_cfg(&attrs), attrs) + strip_unconfigured.process_cfg_attrs(attrs); + !cfg_mods || strip_unconfigured.in_cfg(&attrs) } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index ccd55c5c08a70..500aaaf43b92a 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -8,10 +8,9 @@ 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, StrLit, Unsafe}; +use syntax::ast::{Async, Const, Defaultness, IsAuto, PathSegment, Unsafe}; use syntax::ast::{BindingMode, Block, FnDecl, FnSig, Mac, MacArgs, MacDelimiter, Param, SelfKind}; use syntax::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData}; use syntax::ast::{FnHeader, ForeignItem, ForeignItemKind, Mutability, Visibility, VisibilityKind}; @@ -22,7 +21,7 @@ use syntax::tokenstream::{DelimSpan, TokenStream, TokenTree}; use log::debug; use std::mem; -pub(super) type ItemInfo = (Ident, ItemKind, Option>); +pub(super) type ItemInfo = (Ident, ItemKind); impl<'a> Parser<'a> { pub fn parse_item(&mut self) -> PResult<'a, Option>> { @@ -83,71 +82,67 @@ impl<'a> Parser<'a> { }); let lo = self.token.span; - let vis = self.parse_visibility(FollowedByType::No)?; - if self.eat_keyword(kw::Use) { - // USE ITEM - let item_ = ItemKind::Use(P(self.parse_use_tree()?)); - self.expect_semi()?; + if let Some((ident, kind)) = self.parse_item_kind(&mut attrs, macros_allowed, lo, &vis)? { + return Ok(Some(P(self.mk_item(lo, ident, kind, vis, attrs)))); + } - let span = lo.to(self.prev_span); - let item = self.mk_item(span, Ident::invalid(), item_, vis, attrs); - return Ok(Some(item)); + // FAILURE TO PARSE ITEM + 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 self.check_fn_front_matter() { - // FUNCTION ITEM - let (ident, sig, generics, body) = self.parse_fn(&mut false, &mut attrs, |_| true)?; - let kind = ItemKind::Fn(sig, generics, body); - return self.mk_item_with_info(attrs, lo, vis, (ident, kind, None)); + if !attributes_allowed { + self.recover_attrs_no_item(&attrs)?; } + Ok(None) + } - if self.eat_keyword(kw::Extern) { + /// Parses one of the items allowed by the flags. + fn parse_item_kind( + &mut self, + attrs: &mut Vec, + macros_allowed: bool, + lo: Span, + vis: &Visibility, + ) -> PResult<'a, Option> { + let info = if self.eat_keyword(kw::Use) { + // USE ITEM + let tree = self.parse_use_tree()?; + self.expect_semi()?; + (Ident::invalid(), ItemKind::Use(P(tree))) + } else if self.check_fn_front_matter() { + // FUNCTION ITEM + let (ident, sig, generics, body) = self.parse_fn(&mut false, attrs, |_| true)?; + (ident, ItemKind::Fn(sig, generics, body)) + } else if self.eat_keyword(kw::Extern) { if self.eat_keyword(kw::Crate) { // EXTERN CRATE - return Ok(Some(self.parse_item_extern_crate(lo, vis, attrs)?)); + self.parse_item_extern_crate()? + } else { + // EXTERN BLOCK + self.parse_item_foreign_mod(attrs)? } - // EXTERN BLOCK - let abi = self.parse_abi(); - return Ok(Some(self.parse_item_foreign_mod(lo, abi, vis, attrs)?)); - } - - if self.is_static_global() { + } else if self.is_static_global() { // STATIC ITEM - self.bump(); + self.bump(); // `static` let m = self.parse_mutability(); - let info = self.parse_item_const(Some(m))?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if let Const::Yes(const_span) = self.parse_constness() { + self.parse_item_const(Some(m))? + } else if let Const::Yes(const_span) = self.parse_constness() { // CONST ITEM - if self.eat_keyword(kw::Mut) { - let prev_span = self.prev_span; - self.struct_span_err(prev_span, "const globals cannot be mutable") - .span_label(prev_span, "cannot be mutable") - .span_suggestion( - const_span, - "you might want to declare a static instead", - "static".to_owned(), - Applicability::MaybeIncorrect, - ) - .emit(); - } - - let info = self.parse_item_const(None)?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Trait, kw::Auto]) { - // UNSAFE TRAIT ITEM - let unsafety = self.parse_unsafety(); - let info = self.parse_item_trait(lo, unsafety)?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.check_keyword(kw::Impl) + self.recover_const_mut(const_span); + self.parse_item_const(None)? + } else if self.check_keyword(kw::Trait) || self.check_auto_or_unsafe_trait_item() { + // TRAIT ITEM + self.parse_item_trait(attrs, lo)? + } else if self.check_keyword(kw::Impl) || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Impl]) || self.check_keyword(kw::Default) && self.is_keyword_ahead(1, &[kw::Impl, kw::Unsafe]) { @@ -155,273 +150,189 @@ impl<'a> Parser<'a> { let defaultness = self.parse_defaultness(); let unsafety = self.parse_unsafety(); self.expect_keyword(kw::Impl)?; - let info = self.parse_item_impl(unsafety, defaultness)?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.eat_keyword(kw::Mod) { + self.parse_item_impl(attrs, unsafety, defaultness)? + } else if self.eat_keyword(kw::Mod) { // MODULE ITEM - let info = self.parse_item_mod(&attrs[..])?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.eat_keyword(kw::Type) { + self.parse_item_mod(attrs)? + } else if self.eat_keyword(kw::Type) { // TYPE ITEM let (ident, ty, generics) = self.parse_type_alias()?; - let kind = ItemKind::TyAlias(ty, generics); - return self.mk_item_with_info(attrs, lo, vis, (ident, kind, None)); - } - - if self.eat_keyword(kw::Enum) { + (ident, ItemKind::TyAlias(ty, generics)) + } else if self.eat_keyword(kw::Enum) { // ENUM ITEM - let info = self.parse_item_enum()?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.check_keyword(kw::Trait) - || (self.check_keyword(kw::Auto) && self.is_keyword_ahead(1, &[kw::Trait])) - { - // TRAIT ITEM - let info = self.parse_item_trait(lo, Unsafe::No)?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.eat_keyword(kw::Struct) { + self.parse_item_enum()? + } else if self.eat_keyword(kw::Struct) { // STRUCT ITEM - let info = self.parse_item_struct()?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.is_union_item() { + self.parse_item_struct()? + } else if self.is_kw_followed_by_ident(kw::Union) { // UNION ITEM - self.bump(); - let info = self.parse_item_union()?; - return self.mk_item_with_info(attrs, lo, vis, info); - } + self.bump(); // `union` + self.parse_item_union()? + } else if self.eat_keyword(kw::Macro) { + // MACROS 2.0 ITEM + self.parse_item_decl_macro(lo)? + } else if self.is_macro_rules_item() { + // MACRO_RULES ITEM + self.parse_item_macro_rules(vis)? + } 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 + (Ident::invalid(), ItemKind::Mac(self.parse_item_macro(vis)?)) + } else { + return Ok(None); + }; + Ok(Some(info)) + } - if let Some(macro_def) = self.eat_macro_def(&attrs, &vis, lo)? { - return Ok(Some(macro_def)); - } + /// 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_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` + } - // Verify whether we have encountered a struct or method definition where the user forgot to - // add the `struct` or `fn` keyword after writing `pub`: `pub S {}` - if vis.node.is_pub() && self.check_ident() && self.look_ahead(1, |t| *t != token::Not) { - // Space between `pub` keyword and the identifier - // - // pub S {} - // ^^^ `sp` points here - let sp = self.prev_span.between(self.token.span); - let full_sp = self.prev_span.to(self.token.span); - let ident_sp = self.token.span; - if self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) { - // possible public struct definition where `struct` was forgotten - let ident = self.parse_ident().unwrap(); - let msg = format!("add `struct` here to parse `{}` as a public struct", ident); - let mut err = self.struct_span_err(sp, "missing `struct` for struct definition"); + /// 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, ()> { + // Space between `pub` keyword and the identifier + // + // pub S {} + // ^^^ `sp` points here + let sp = self.prev_span.between(self.token.span); + let full_sp = self.prev_span.to(self.token.span); + let ident_sp = self.token.span; + if self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) { + // possible public struct definition where `struct` was forgotten + let ident = self.parse_ident().unwrap(); + let msg = format!("add `struct` here to parse `{}` as a public struct", ident); + let mut err = self.struct_span_err(sp, "missing `struct` for struct definition"); + err.span_suggestion_short( + sp, + &msg, + " struct ".into(), + Applicability::MaybeIncorrect, // speculative + ); + return Err(err); + } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) { + let ident = self.parse_ident().unwrap(); + self.bump(); // `(` + let kw_name = self.recover_first_param(); + self.consume_block(token::Paren, ConsumeClosingDelim::Yes); + let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) { + self.eat_to_tokens(&[&token::OpenDelim(token::Brace)]); + self.bump(); // `{` + ("fn", kw_name, false) + } else if self.check(&token::OpenDelim(token::Brace)) { + self.bump(); // `{` + ("fn", kw_name, false) + } else if self.check(&token::Colon) { + let kw = "struct"; + (kw, kw, false) + } else { + ("fn` or `struct", "function or struct", true) + }; + + let msg = format!("missing `{}` for {} definition", kw, kw_name); + let mut err = self.struct_span_err(sp, &msg); + if !ambiguous { + self.consume_block(token::Brace, ConsumeClosingDelim::Yes); + let suggestion = + format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name); err.span_suggestion_short( sp, - &msg, - " struct ".into(), - Applicability::MaybeIncorrect, // speculative + &suggestion, + format!(" {} ", kw), + Applicability::MachineApplicable, ); - return Err(err); - } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) { - let ident = self.parse_ident().unwrap(); - self.bump(); // `(` - let kw_name = self.recover_first_param(); - self.consume_block(token::Paren, ConsumeClosingDelim::Yes); - let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) { - self.eat_to_tokens(&[&token::OpenDelim(token::Brace)]); - self.bump(); // `{` - ("fn", kw_name, false) - } else if self.check(&token::OpenDelim(token::Brace)) { - self.bump(); // `{` - ("fn", kw_name, false) - } else if self.check(&token::Colon) { - let kw = "struct"; - (kw, kw, false) - } else { - ("fn` or `struct", "function or struct", true) - }; - - let msg = format!("missing `{}` for {} definition", kw, kw_name); - let mut err = self.struct_span_err(sp, &msg); - if !ambiguous { - self.consume_block(token::Brace, ConsumeClosingDelim::Yes); - let suggestion = - format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name); - err.span_suggestion_short( - sp, - &suggestion, - format!(" {} ", kw), - Applicability::MachineApplicable, + } else { + if let Ok(snippet) = self.span_to_snippet(ident_sp) { + err.span_suggestion( + full_sp, + "if you meant to call a macro, try", + format!("{}!", snippet), + // this is the `ambiguous` conditional branch + Applicability::MaybeIncorrect, ); } else { - if let Ok(snippet) = self.span_to_snippet(ident_sp) { - err.span_suggestion( - full_sp, - "if you meant to call a macro, try", - format!("{}!", snippet), - // this is the `ambiguous` conditional branch - Applicability::MaybeIncorrect, - ); - } else { - err.help( - "if you meant to call a macro, remove the `pub` \ + err.help( + "if you meant to call a macro, remove the `pub` \ and add a trailing `!` after the identifier", - ); - } - } - return Err(err); - } else if self.look_ahead(1, |t| *t == token::Lt) { - let ident = self.parse_ident().unwrap(); - self.eat_to_tokens(&[&token::Gt]); - self.bump(); // `>` - let (kw, kw_name, ambiguous) = if self.eat(&token::OpenDelim(token::Paren)) { - ("fn", self.recover_first_param(), false) - } else if self.check(&token::OpenDelim(token::Brace)) { - ("struct", "struct", false) - } else { - ("fn` or `struct", "function or struct", true) - }; - let msg = format!("missing `{}` for {} definition", kw, kw_name); - let mut err = self.struct_span_err(sp, &msg); - if !ambiguous { - err.span_suggestion_short( - sp, - &format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name), - format!(" {} ", kw), - Applicability::MachineApplicable, ); } - return Err(err); } - } - self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, vis) - } - - pub(super) fn mk_item_with_info( - &self, - attrs: Vec, - lo: Span, - vis: Visibility, - info: ItemInfo, - ) -> PResult<'a, Option>> { - let (ident, item, extra_attrs) = info; - let span = lo.to(self.prev_span); - let attrs = Self::maybe_append(attrs, extra_attrs); - Ok(Some(self.mk_item(span, ident, item, vis, attrs))) - } - - fn maybe_append(mut lhs: Vec, mut rhs: Option>) -> Vec { - if let Some(ref mut rhs) = rhs { - lhs.append(rhs); - } - lhs - } - - /// This is the fall-through for parsing items. - fn parse_macro_use_or_failure( - &mut self, - attrs: Vec, - macros_allowed: bool, - attributes_allowed: bool, - lo: Span, - visibility: Visibility, - ) -> PResult<'a, Option>> { - if macros_allowed - && self.token.is_path_start() - && !(self.is_async_fn() && self.token.span.rust_2015()) - { - // MACRO INVOCATION ITEM - - let prev_span = self.prev_span; - self.complain_if_pub_macro(&visibility.node, prev_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(); + return Err(err); + } else if self.look_ahead(1, |t| *t == token::Lt) { + let ident = self.parse_ident().unwrap(); + self.eat_to_tokens(&[&token::Gt]); + self.bump(); // `>` + let (kw, kw_name, ambiguous) = if self.eat(&token::OpenDelim(token::Paren)) { + ("fn", self.recover_first_param(), false) + } else if self.check(&token::OpenDelim(token::Brace)) { + ("struct", "struct", false) + } else { + ("fn` or `struct", "function or struct", true) + }; + let msg = format!("missing `{}` for {} definition", kw, kw_name); + let mut err = self.struct_span_err(sp, &msg); + if !ambiguous { + err.span_suggestion_short( + sp, + &format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name), + format!(" {} ", kw), + Applicability::MachineApplicable, + ); } - - let hi = self.prev_span; - let mac = Mac { path, args, prior_type_ascription: self.last_type_ascription }; - let item = - self.mk_item(lo.to(hi), Ident::invalid(), ItemKind::Mac(mac), visibility, attrs); - return Ok(Some(item)); - } - - // FAILURE TO PARSE ITEM - match visibility.node { - VisibilityKind::Inherited => {} - _ => return Err(self.struct_span_err(self.prev_span, "unmatched visibility `pub`")), + return Err(err); + } else { + Ok(()) } + } - if !attributes_allowed && !attrs.is_empty() { - self.expected_item_err(&attrs)?; - } - Ok(None) + /// 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)?; // `!` + 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 }) } - /// 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", + /// 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) } - pub(super) fn is_async_fn(&self) -> bool { + fn is_async_fn(&self) -> bool { self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn]) } - /// Parses a macro invocation inside a `trait`, `impl` or `extern` block. - fn parse_assoc_macro_invoc( - &mut self, - item_kind: &str, - vis: Option<&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); - } - - *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 })) - } else { - Ok(None) - } - } - fn missing_assoc_item_kind_err( &self, item_type: &str, @@ -442,7 +353,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); @@ -451,16 +362,21 @@ impl<'a> Parser<'a> { /// Parses an implementation item, `impl` keyword is already parsed. /// - /// impl<'a, T> TYPE { /* impl items */ } - /// impl<'a, T> TRAIT for TYPE { /* impl items */ } - /// impl<'a, T> !TRAIT for TYPE { /* impl items */ } - /// impl<'a, T> const TRAIT for TYPE { /* impl items */ } + /// ``` + /// impl<'a, T> TYPE { /* impl items */ } + /// impl<'a, T> TRAIT for TYPE { /* impl items */ } + /// impl<'a, T> !TRAIT for TYPE { /* impl items */ } + /// impl<'a, T> const TRAIT for TYPE { /* impl items */ } + /// ``` /// /// We actually parse slightly more relaxed grammar for better error reporting and recovery. - /// `impl` GENERICS `const`? `!`? TYPE `for`? (TYPE | `..`) (`where` PREDICATES)? `{` BODY `}` - /// `impl` GENERICS `const`? `!`? TYPE (`where` PREDICATES)? `{` BODY `}` + /// ``` + /// "impl" GENERICS "const"? "!"? TYPE "for"? (TYPE | "..") ("where" PREDICATES)? "{" BODY "}" + /// "impl" GENERICS "const"? "!"? TYPE ("where" PREDICATES)? "{" BODY "}" + /// ``` fn parse_item_impl( &mut self, + attrs: &mut Vec, unsafety: Unsafe, defaultness: Defaultness, ) -> PResult<'a, ItemInfo> { @@ -515,7 +431,7 @@ impl<'a> Parser<'a> { generics.where_clause = self.parse_where_clause()?; - let (impl_items, attrs) = self.parse_impl_body()?; + let impl_items = self.parse_item_list(attrs, |p, at_end| p.parse_impl_item(at_end))?; let item_kind = match ty_second { Some(ty_second) => { @@ -568,18 +484,25 @@ impl<'a> Parser<'a> { } }; - Ok((Ident::invalid(), item_kind, Some(attrs))) + Ok((Ident::invalid(), item_kind)) } - fn parse_impl_body(&mut self) -> PResult<'a, (Vec>, Vec)> { + fn parse_item_list( + &mut self, + attrs: &mut Vec, + mut parse_item: impl FnMut(&mut Parser<'a>, &mut bool) -> PResult<'a, T>, + ) -> PResult<'a, Vec> { self.expect(&token::OpenDelim(token::Brace))?; - let attrs = self.parse_inner_attributes()?; + attrs.append(&mut self.parse_inner_attributes()?); - let mut impl_items = Vec::new(); + let mut items = Vec::new(); while !self.eat(&token::CloseDelim(token::Brace)) { + if self.recover_doc_comment_before_brace() { + continue; + } let mut at_end = false; - match self.parse_impl_item(&mut at_end) { - Ok(impl_item) => impl_items.push(impl_item), + match parse_item(self, &mut at_end) { + Ok(item) => items.push(item), Err(mut err) => { err.emit(); if !at_end { @@ -589,7 +512,30 @@ impl<'a> Parser<'a> { } } } - Ok((impl_items, attrs)) + Ok(items) + } + + /// Recover on a doc comment before `}`. + fn recover_doc_comment_before_brace(&mut self) -> bool { + if let token::DocComment(_) = self.token.kind { + if self.look_ahead(1, |tok| tok == &token::CloseDelim(token::Brace)) { + struct_span_err!( + self.diagnostic(), + self.token.span, + E0584, + "found a documentation comment that doesn't document anything", + ) + .span_label(self.token.span, "this doc comment doesn't document anything") + .help( + "doc comments must come before what they document, maybe a \ + comment was intended with `//`?", + ) + .emit(); + self.bump(); + return true; + } + } + false } /// Parses defaultness (i.e., `default` or nothing). @@ -617,8 +563,17 @@ impl<'a> Parser<'a> { } } - /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`. - fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafe) -> PResult<'a, ItemInfo> { + /// Is this an `(unsafe auto? | auto) trait` item? + fn check_auto_or_unsafe_trait_item(&mut self) -> bool { + // auto trait + self.check_keyword(kw::Auto) && self.is_keyword_ahead(1, &[kw::Trait]) + // unsafe auto trait + || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Trait, kw::Auto]) + } + + /// Parses `unsafe? auto? trait Foo { ... }` or `trait Foo = Bar;`. + fn parse_item_trait(&mut self, attrs: &mut Vec, lo: Span) -> PResult<'a, ItemInfo> { + let unsafety = self.parse_unsafety(); // Parse optional `auto` prefix. let is_auto = if self.eat_keyword(kw::Auto) { IsAuto::Yes } else { IsAuto::No }; @@ -656,43 +611,12 @@ impl<'a> Parser<'a> { self.sess.gated_spans.gate(sym::trait_alias, whole_span); - Ok((ident, ItemKind::TraitAlias(tps, bounds), None)) + Ok((ident, ItemKind::TraitAlias(tps, bounds))) } else { // It's a normal trait. tps.where_clause = self.parse_where_clause()?; - self.expect(&token::OpenDelim(token::Brace))?; - let mut trait_items = vec![]; - while !self.eat(&token::CloseDelim(token::Brace)) { - if let token::DocComment(_) = self.token.kind { - if self.look_ahead(1, |tok| tok == &token::CloseDelim(token::Brace)) { - struct_span_err!( - self.diagnostic(), - self.token.span, - E0584, - "found a documentation comment that doesn't document anything", - ) - .help( - "doc comments must come before what they document, maybe a \ - comment was intended with `//`?", - ) - .emit(); - self.bump(); - continue; - } - } - let mut at_end = false; - match self.parse_trait_item(&mut at_end) { - Ok(item) => trait_items.push(item), - Err(mut e) => { - e.emit(); - if !at_end { - self.consume_block(token::Brace, ConsumeClosingDelim::Yes); - break; - } - } - } - } - Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, trait_items), None)) + let items = self.parse_item_list(attrs, |p, at_end| p.parse_trait_item(at_end))?; + Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, items))) } } @@ -740,28 +664,28 @@ impl<'a> Parser<'a> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; let defaultness = self.parse_defaultness(); - let (name, kind, generics) = if self.eat_keyword(kw::Type) { + + let (ident, kind, generics) = if self.eat_keyword(kw::Type) { self.parse_assoc_ty()? } 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 self.isnt_macro_invocation() { + return Err(self.missing_assoc_item_kind_err("associated", self.prev_span)); + } else if self.token.is_path_start() { + let mac = self.parse_item_macro(&vis)?; + *at_end = true; (Ident::invalid(), AssocItemKind::Macro(mac), Generics::default()) } else { - self.parse_assoc_const()? + self.recover_attrs_no_item(&attrs)?; + self.unexpected()? }; - Ok(AssocItem { - id: DUMMY_NODE_ID, - span: lo.to(self.prev_span), - ident: name, - attrs, - vis, - defaultness, - generics, - kind, - tokens: None, - }) + let span = lo.to(self.prev_span); + let id = DUMMY_NODE_ID; + Ok(AssocItem { id, span, ident, attrs, vis, defaultness, generics, kind, tokens: None }) } /// This parses the grammar: @@ -860,7 +784,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)) @@ -877,12 +801,7 @@ impl<'a> Parser<'a> { /// extern crate foo; /// extern crate bar as foo; /// ``` - fn parse_item_extern_crate( - &mut self, - lo: Span, - visibility: Visibility, - attrs: Vec, - ) -> PResult<'a, P> { + fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemInfo> { // Accept `extern crate name-like-this` for better diagnostics let orig_name = self.parse_crate_name_with_dashes()?; let (item_name, orig_name) = if let Some(rename) = self.parse_rename()? { @@ -891,9 +810,7 @@ impl<'a> Parser<'a> { (orig_name, None) }; self.expect_semi()?; - - let span = lo.to(self.prev_span); - Ok(self.mk_item(span, item_name, ItemKind::ExternCrate(orig_name), visibility, attrs)) + Ok((item_name, ItemKind::ExternCrate(orig_name))) } fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, ast::Ident> { @@ -936,8 +853,7 @@ impl<'a> Parser<'a> { /// Parses `extern` for foreign ABIs modules. /// - /// `extern` is expected to have been - /// consumed before calling this method. + /// `extern` is expected to have been consumed before calling this method. /// /// # Examples /// @@ -945,57 +861,32 @@ impl<'a> Parser<'a> { /// extern "C" {} /// extern {} /// ``` - fn parse_item_foreign_mod( - &mut self, - lo: Span, - abi: Option, - visibility: Visibility, - mut attrs: Vec, - ) -> PResult<'a, P> { - self.expect(&token::OpenDelim(token::Brace))?; - - attrs.extend(self.parse_inner_attributes()?); - - let mut foreign_items = vec![]; - while !self.eat(&token::CloseDelim(token::Brace)) { - foreign_items.push(self.parse_foreign_item()?); - } - - let prev_span = self.prev_span; - let m = ast::ForeignMod { abi, items: foreign_items }; - let invalid = Ident::invalid(); - Ok(self.mk_item(lo.to(prev_span), invalid, ItemKind::ForeignMod(m), visibility, attrs)) + fn parse_item_foreign_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { + let abi = self.parse_abi(); // ABI? + let items = self.parse_item_list(attrs, |p, at_end| p.parse_foreign_item(at_end))?; + let module = ast::ForeignMod { abi, items }; + Ok((Ident::invalid(), ItemKind::ForeignMod(module))) } - /// Parses a foreign item. - pub fn parse_foreign_item(&mut self) -> PResult<'a, P> { + /// Parses a foreign item (one in an `extern { ... }` block). + pub fn parse_foreign_item(&mut self, at_end: &mut bool) -> PResult<'a, P> { maybe_whole!(self, NtForeignItem, |ni| ni); let mut attrs = self.parse_outer_attributes()?; let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; - if self.check_keyword(kw::Type) { + let (ident, kind) = if self.check_keyword(kw::Type) { // FOREIGN TYPE ITEM - self.parse_item_foreign_type(vis, lo, attrs) + self.parse_item_foreign_type()? } else if self.check_fn_front_matter() { // FOREIGN FUNCTION ITEM - let (ident, sig, generics, body) = self.parse_fn(&mut false, &mut attrs, |_| true)?; - let kind = ForeignItemKind::Fn(sig, generics, body); - let span = lo.to(self.prev_span); - Ok(P(ast::ForeignItem { - ident, - attrs, - kind, - id: DUMMY_NODE_ID, - span, - vis, - tokens: None, - })) + let (ident, sig, generics, body) = self.parse_fn(at_end, &mut attrs, |_| true)?; + (ident, ForeignItemKind::Fn(sig, generics, body)) } else if self.is_static_global() { // FOREIGN STATIC ITEM self.bump(); // `static` - self.parse_item_foreign_static(vis, lo, attrs) + self.parse_item_foreign_static()? } else if self.token.is_keyword(kw::Const) { // Treat `const` as `static` for error recovery, but don't add it to expected tokens. self.bump(); // `const` @@ -1007,66 +898,37 @@ impl<'a> Parser<'a> { Applicability::MachineApplicable, ) .emit(); - self.parse_item_foreign_static(vis, lo, attrs) - } else if let Some(mac) = self.parse_assoc_macro_invoc("extern", Some(&vis), &mut false)? { - let kind = ForeignItemKind::Macro(mac); - let span = lo.to(self.prev_span); - let ident = Ident::invalid(); - Ok(P(ForeignItem { ident, span, id: DUMMY_NODE_ID, attrs, vis, kind, tokens: None })) + self.parse_item_foreign_static()? + } else if self.isnt_macro_invocation() { + return Err(self.missing_assoc_item_kind_err("extern", self.prev_span)); + } else if self.token.is_path_start() { + let mac = self.parse_item_macro(&vis)?; + *at_end = true; + (Ident::invalid(), ForeignItemKind::Macro(mac)) } else { - if !attrs.is_empty() { - self.expected_item_err(&attrs)?; - } - self.unexpected() - } + self.recover_attrs_no_item(&attrs)?; + self.unexpected()? + }; + Ok(P(self.mk_item(lo, ident, kind, vis, attrs))) } /// Parses a static item from a foreign module. /// Assumes that the `static` keyword is already parsed. - fn parse_item_foreign_static( - &mut self, - vis: ast::Visibility, - lo: Span, - attrs: Vec, - ) -> PResult<'a, P> { + fn parse_item_foreign_static(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> { let mutbl = self.parse_mutability(); let ident = self.parse_ident()?; self.expect(&token::Colon)?; let ty = self.parse_ty()?; - let hi = self.token.span; self.expect_semi()?; - Ok(P(ForeignItem { - ident, - attrs, - kind: ForeignItemKind::Static(ty, mutbl), - id: DUMMY_NODE_ID, - span: lo.to(hi), - vis, - tokens: None, - })) + Ok((ident, ForeignItemKind::Static(ty, mutbl))) } /// Parses a type from a foreign module. - fn parse_item_foreign_type( - &mut self, - vis: ast::Visibility, - lo: Span, - attrs: Vec, - ) -> PResult<'a, P> { + fn parse_item_foreign_type(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> { self.expect_keyword(kw::Type)?; - let ident = self.parse_ident()?; - let hi = self.token.span; self.expect_semi()?; - Ok(P(ast::ForeignItem { - ident, - attrs, - kind: ForeignItemKind::Ty, - id: DUMMY_NODE_ID, - span: lo.to(hi), - vis, - tokens: None, - })) + Ok((ident, ForeignItemKind::Ty)) } fn is_static_global(&mut self) -> bool { @@ -1086,6 +948,22 @@ impl<'a> Parser<'a> { } } + /// Recover on `const mut` with `const` already eaten. + fn recover_const_mut(&mut self, const_span: Span) { + if self.eat_keyword(kw::Mut) { + let span = self.prev_span; + self.struct_span_err(span, "const globals cannot be mutable") + .span_label(span, "cannot be mutable") + .span_suggestion( + const_span, + "you might want to declare a static instead", + "static".to_owned(), + Applicability::MaybeIncorrect, + ) + .emit(); + } + } + /// Parse `["const" | ("static" "mut"?)] $ident ":" $ty = $expr` with /// `["const" | ("static" "mut"?)]` already parsed and stored in `m`. /// @@ -1110,7 +988,7 @@ impl<'a> Parser<'a> { Some(m) => ItemKind::Static(ty, m, e), None => ItemKind::Const(ty, e), }; - Ok((id, item, None)) + Ok((id, item)) } /// We were supposed to parse `:` but instead, we're already at `=`. @@ -1163,7 +1041,7 @@ impl<'a> Parser<'a> { let enum_definition = EnumDef { variants: variants.into_iter().filter_map(|v| v).collect() }; - Ok((id, ItemKind::Enum(enum_definition, generics), None)) + Ok((id, ItemKind::Enum(enum_definition, generics))) } fn parse_enum_variant(&mut self) -> PResult<'a, Option> { @@ -1257,7 +1135,7 @@ impl<'a> Parser<'a> { return Err(err); }; - Ok((class_name, ItemKind::Struct(vdata, generics), None)) + Ok((class_name, ItemKind::Struct(vdata, generics))) } /// Parses `union Foo { ... }`. @@ -1281,12 +1159,7 @@ impl<'a> Parser<'a> { return Err(err); }; - Ok((class_name, ItemKind::Union(vdata, generics), None)) - } - - pub(super) fn is_union_item(&self) -> bool { - self.token.is_keyword(kw::Union) - && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) + Ok((class_name, ItemKind::Union(vdata, generics))) } fn parse_record_struct_body( @@ -1436,112 +1309,109 @@ impl<'a> Parser<'a> { }) } - pub(super) fn eat_macro_def( - &mut self, - attrs: &[Attribute], - vis: &Visibility, - lo: Span, - ) -> PResult<'a, Option>> { - let (ident, def) = if self.eat_keyword(kw::Macro) { - let ident = self.parse_ident()?; - let body = if self.check(&token::OpenDelim(token::Brace)) { - self.parse_mac_args()? - } else if self.check(&token::OpenDelim(token::Paren)) { - let params = self.parse_token_tree(); - let pspan = params.span(); - let body = if self.check(&token::OpenDelim(token::Brace)) { - self.parse_token_tree() - } else { - return self.unexpected(); - }; - let bspan = body.span(); - let tokens = TokenStream::new(vec![ - params.into(), - TokenTree::token(token::FatArrow, pspan.between(bspan)).into(), - body.into(), - ]); - let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi()); - P(MacArgs::Delimited(dspan, MacDelimiter::Brace, tokens)) - } else { + /// 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()? // `MacBody` + } else if self.check(&token::OpenDelim(token::Paren)) { + let params = self.parse_token_tree(); // `MacParams` + let pspan = params.span(); + 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 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 { + return self.unexpected(); + }; + + self.sess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_span)); + Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: false }))) + } - (ident, ast::MacroDef { body, legacy: false }) - } else if self.check_keyword(sym::macro_rules) + /// Is this unambiguously the start of a `macro_rules! foo` item defnition? + fn is_macro_rules_item(&mut self) -> bool { + self.check_keyword(sym::macro_rules) && self.look_ahead(1, |t| *t == token::Not) && self.look_ahead(2, |t| t.is_ident()) - { - let prev_span = self.prev_span; - self.complain_if_pub_macro(&vis.node, prev_span); - self.bump(); - self.bump(); - - 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(); - } + } - (ident, ast::MacroDef { body, legacy: true }) - } else { - return Ok(None); - }; + /// Parses a legacy `macro_rules! foo { ... }` declarative macro. + fn parse_item_macro_rules(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> { + self.expect_keyword(sym::macro_rules)?; // `macro_rules` + self.expect(&token::Not)?; // `!` - let span = lo.to(self.prev_span); + let ident = self.parse_ident()?; + let body = self.parse_mac_args()?; + self.eat_semi_for_macro_if_needed(&body); + self.complain_if_pub_macro(vis, true); + + Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: true }))) + } - if !def.legacy { - self.sess.gated_spans.gate(sym::decl_macro, span); + /// 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; } - Ok(Some(self.mk_item(span, ident, ItemKind::MacroDef(def), vis.clone(), attrs.to_vec()))) + 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 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(); - } + 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) { - 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 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 { @@ -1552,14 +1422,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 @@ -1591,15 +1460,16 @@ impl<'a> Parser<'a> { Ok(true) } - fn mk_item( + fn mk_item( &self, - span: Span, + lo: Span, ident: Ident, - kind: ItemKind, + kind: K, vis: Visibility, attrs: Vec, - ) -> P { - P(Item { ident, attrs, id: DUMMY_NODE_ID, kind, vis, span, tokens: None }) + ) -> Item { + let span = lo.to(self.prev_span); + Item { ident, attrs, id: DUMMY_NODE_ID, kind, vis, span, tokens: None } } } 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/module.rs b/src/librustc_parse/parser/module.rs index 0c8fad03d8690..754923ae55e29 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -40,36 +40,34 @@ impl<'a> Parser<'a> { } /// Parses a `mod { ... }` or `mod ;` item. - pub(super) fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo> { - let (in_cfg, outer_attrs) = - crate::config::process_configure_mod(self.sess, self.cfg_mods, outer_attrs); + pub(super) fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { + let in_cfg = crate::config::process_configure_mod(self.sess, self.cfg_mods, attrs); let id_span = self.token.span; let id = self.parse_ident()?; - if self.eat(&token::Semi) { + let (module, mut inner_attrs) = if self.eat(&token::Semi) { if in_cfg && self.recurse_into_file_modules { // This mod is in an external file. Let's go get it! let ModulePathSuccess { path, directory_ownership } = - self.submod_path(id, &outer_attrs, id_span)?; - let (module, attrs) = - self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?; - Ok((id, ItemKind::Mod(module), Some(attrs))) + self.submod_path(id, &attrs, id_span)?; + self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)? } else { - let placeholder = ast::Mod { inner: DUMMY_SP, items: Vec::new(), inline: false }; - Ok((id, ItemKind::Mod(placeholder), None)) + (ast::Mod { inner: DUMMY_SP, items: Vec::new(), inline: false }, Vec::new()) } } else { let old_directory = self.directory.clone(); - self.push_directory(id, &outer_attrs); + self.push_directory(id, &attrs); self.expect(&token::OpenDelim(token::Brace))?; let mod_inner_lo = self.token.span; - let attrs = self.parse_inner_attributes()?; + let inner_attrs = self.parse_inner_attributes()?; let module = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?; self.directory = old_directory; - Ok((id, ItemKind::Mod(module), Some(attrs))) - } + (module, inner_attrs) + }; + attrs.append(&mut inner_attrs); + Ok((id, ItemKind::Mod(module))) } /// Given a termination token, parses all of the items in a module. diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index e97af0dc00c69..742fc4802fd9d 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -7,10 +7,10 @@ use crate::maybe_whole; use crate::DirectoryOwnership; use rustc_errors::{Applicability, PResult}; -use rustc_span::source_map::{respan, BytePos, Span}; -use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::source_map::{BytePos, Span}; +use rustc_span::symbol::{kw, sym}; use syntax::ast; -use syntax::ast::{AttrStyle, AttrVec, Attribute, Mac, MacStmtStyle, VisibilityKind}; +use syntax::ast::{AttrStyle, AttrVec, Attribute, Mac, MacStmtStyle}; use syntax::ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKind, DUMMY_NODE_ID}; use syntax::ptr::P; use syntax::token::{self, TokenKind}; @@ -55,21 +55,11 @@ impl<'a> Parser<'a> { return self.recover_stmt_local(lo, attrs.into(), msg, "let"); } - let mac_vis = respan(lo, VisibilityKind::Inherited); - if let Some(macro_def) = self.eat_macro_def(&attrs, &mac_vis, lo)? { - return Ok(Some(self.mk_stmt(lo.to(self.prev_span), StmtKind::Item(macro_def)))); - } - - // 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_union_item() // `union::b::c` - path, `union U { ... }` - not a path. - && !self.is_crate_vis() // `crate::b::c` - path, `crate struct S;` - not a path. - && !self.is_auto_trait_item() - && !self.is_async_fn() + // 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)?; @@ -199,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, @@ -299,16 +285,6 @@ impl<'a> Parser<'a> { } } - fn is_auto_trait_item(&self) -> bool { - // auto trait - (self.token.is_keyword(kw::Auto) && - self.is_keyword_ahead(1, &[kw::Trait])) - || // unsafe auto trait - (self.token.is_keyword(kw::Unsafe) && - self.is_keyword_ahead(1, &[kw::Auto]) && - self.is_keyword_ahead(2, &[kw::Trait])) - } - /// Parses a block. No inner attributes are allowed. pub fn parse_block(&mut self) -> PResult<'a, P> { maybe_whole!(self, NtBlock, |x| x); diff --git a/src/test/pretty/trait-inner-attr.rs b/src/test/pretty/trait-inner-attr.rs new file mode 100644 index 0000000000000..bb4fb1459bd64 --- /dev/null +++ b/src/test/pretty/trait-inner-attr.rs @@ -0,0 +1,7 @@ +// pp-exact + +trait Foo { + #![allow(bar)] +} + +fn main() { } 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.rs b/src/test/ui/parser/attrs-after-extern-mod.rs index 4bdd16471cd80..ea899dca7b221 100644 --- a/src/test/ui/parser/attrs-after-extern-mod.rs +++ b/src/test/ui/parser/attrs-after-extern-mod.rs @@ -1,13 +1,7 @@ -// Constants (static variables) can be used to match in patterns, but mutable -// statics cannot. This ensures that there's some form of error if this is -// attempted. +// Make sure there's an error when given `extern { ... #[attr] }`. -extern crate libc; +fn main() {} extern { - static mut rust_dbg_static_mut: libc::c_int; - pub fn rust_dbg_static_mut_check_four(); #[cfg(stage37)] //~ ERROR expected item after attributes } - -pub fn main() {} diff --git a/src/test/ui/parser/attrs-after-extern-mod.stderr b/src/test/ui/parser/attrs-after-extern-mod.stderr index cecdab4d63197..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:10: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/doc-before-extern-rbrace.rs b/src/test/ui/parser/doc-before-extern-rbrace.rs index 695d4da1dca60..040206b80ffd0 100644 --- a/src/test/ui/parser/doc-before-extern-rbrace.rs +++ b/src/test/ui/parser/doc-before-extern-rbrace.rs @@ -1,4 +1,6 @@ +fn main() {} + extern { /// hi - //~^ ERROR expected item after doc comment + //~^ ERROR found a documentation comment that doesn't document anything } diff --git a/src/test/ui/parser/doc-before-extern-rbrace.stderr b/src/test/ui/parser/doc-before-extern-rbrace.stderr index 8cc9c916a7afd..0edceb268a7f5 100644 --- a/src/test/ui/parser/doc-before-extern-rbrace.stderr +++ b/src/test/ui/parser/doc-before-extern-rbrace.stderr @@ -1,8 +1,11 @@ -error: expected item after doc comment - --> $DIR/doc-before-extern-rbrace.rs:2:5 +error[E0584]: found a documentation comment that doesn't document anything + --> $DIR/doc-before-extern-rbrace.rs:4:5 | LL | /// hi | ^^^^^^ this doc comment doesn't document anything + | + = help: doc comments must come before what they document, maybe a comment was intended with `//`? error: aborting due to previous error +For more information about this error, try `rustc --explain E0584`. diff --git a/src/test/ui/parser/doc-inside-trait-item.stderr b/src/test/ui/parser/doc-inside-trait-item.stderr index 261e27b6e0d18..246255a0a4675 100644 --- a/src/test/ui/parser/doc-inside-trait-item.stderr +++ b/src/test/ui/parser/doc-inside-trait-item.stderr @@ -2,7 +2,7 @@ error[E0584]: found a documentation comment that doesn't document anything --> $DIR/doc-inside-trait-item.rs:3:5 | LL | /// empty doc - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ this doc comment doesn't document anything | = help: doc comments must come before what they document, maybe a comment was intended with `//`? diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs index a8f0b7d61b985..1d271fa64b0ec 100644 --- a/src/test/ui/parser/duplicate-visibility.rs +++ b/src/test/ui/parser/duplicate-visibility.rs @@ -1,4 +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 cba4058e48255..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:3: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/inner-attr-in-trait-def.rs b/src/test/ui/parser/inner-attr-in-trait-def.rs new file mode 100644 index 0000000000000..8dba6b362cdfa --- /dev/null +++ b/src/test/ui/parser/inner-attr-in-trait-def.rs @@ -0,0 +1,9 @@ +// check-pass + +#![deny(non_camel_case_types)] + +fn main() {} + +trait foo_bar { + #![allow(non_camel_case_types)] +} 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.rs b/src/test/ui/pub/pub-restricted-error-fn.rs index 56ee02f517c7b..3f8904fbe79d8 100644 --- a/src/test/ui/pub/pub-restricted-error-fn.rs +++ b/src/test/ui/pub/pub-restricted-error-fn.rs @@ -1,3 +1,2 @@ -#![feature(pub_restricted)] - pub(crate) () fn foo() {} //~ unmatched visibility +//~^ ERROR expected item, found `(` diff --git a/src/test/ui/pub/pub-restricted-error-fn.stderr b/src/test/ui/pub/pub-restricted-error-fn.stderr index fcff5334890eb..c0168b02da607 100644 --- a/src/test/ui/pub/pub-restricted-error-fn.stderr +++ b/src/test/ui/pub/pub-restricted-error-fn.stderr @@ -1,8 +1,16 @@ -error: unmatched visibility `pub` - --> $DIR/pub-restricted-error-fn.rs:3:10 +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(crate) fn foo() {}` + +error: expected item, found `(` + --> $DIR/pub-restricted-error-fn.rs:1:12 + | +LL | pub(crate) () fn foo() {} + | ^ expected item -error: aborting due to previous error +error: aborting due to 2 previous errors