From 9a88364525a4660dbd6f6a371b3b25199f5bbe4a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 7 Nov 2019 11:26:36 +0100 Subject: [PATCH] syntactically allow visibility on trait item & enum variant --- src/librustc_parse/parser/diagnostics.rs | 20 ------ src/librustc_parse/parser/item.rs | 18 +++--- src/librustc_parse/parser/mod.rs | 8 ++- src/librustc_passes/ast_validation.rs | 6 ++ src/libsyntax/ast.rs | 62 +++++++++++-------- src/libsyntax/mut_visit.rs | 46 +++++++------- src/libsyntax/print/pprust/tests.rs | 1 + src/libsyntax/visit.rs | 2 + src/libsyntax_expand/build.rs | 4 +- src/libsyntax_expand/mbe/macro_parser.rs | 4 +- src/libsyntax_expand/placeholders.rs | 3 +- src/test/ui/ast-json/ast-json-output.stdout | 2 +- src/test/ui/issues/issue-28433.stderr | 9 +-- src/test/ui/issues/issue-60075.rs | 2 +- src/test/ui/issues/issue-60075.stderr | 2 +- src/test/ui/parser/issue-32446.stderr | 4 +- .../issue-65041-empty-vis-matcher-in-enum.rs | 28 +++++++++ .../issue-65041-empty-vis-matcher-in-trait.rs | 28 +++++++++ .../ui/parser/macro/trait-non-item-macros.rs | 2 +- .../parser/macro/trait-non-item-macros.stderr | 4 +- .../missing-close-brace-in-trait.rs | 4 +- .../missing-close-brace-in-trait.stderr | 31 ++++++---- .../ui/parser/trait-pub-assoc-const.stderr | 5 +- src/test/ui/parser/trait-pub-assoc-ty.stderr | 5 +- src/test/ui/parser/trait-pub-method.stderr | 5 +- 25 files changed, 190 insertions(+), 115 deletions(-) create mode 100644 src/test/ui/parser/issue-65041-empty-vis-matcher-in-enum.rs create mode 100644 src/test/ui/parser/issue-65041-empty-vis-matcher-in-trait.rs diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 38eae008537..1b465f326c0 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -1187,26 +1187,6 @@ impl<'a> Parser<'a> { } } - /// Recovers from `pub` keyword in places where it seems _reasonable_ but isn't valid. - pub(super) fn eat_bad_pub(&mut self) { - // When `unclosed_delims` is populated, it means that the code being parsed is already - // quite malformed, which might mean that, for example, a pub struct definition could be - // parsed as being a trait item, which is invalid and this error would trigger - // unconditionally, resulting in misleading diagnostics. Because of this, we only attempt - // this nice to have recovery for code that is otherwise well formed. - if self.token.is_keyword(kw::Pub) && self.unclosed_delims.is_empty() { - match self.parse_visibility(false) { - Ok(vis) => { - self.diagnostic() - .struct_span_err(vis.span, "unnecessary visibility qualifier") - .span_label(vis.span, "`pub` not permitted here") - .emit(); - } - Err(mut err) => err.emit(), - } - } - } - /// Eats tokens until we can be relatively sure we reached the end of the /// statement. This is something of a best-effort heuristic. /// diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 3e21436d313..f183b6c8fbc 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1,4 +1,4 @@ -use super::{Parser, PathStyle}; +use super::{Parser, PathStyle, FollowedByType}; use super::diagnostics::{Error, dummy_arg, ConsumeClosingDelim}; use crate::maybe_whole; @@ -93,7 +93,7 @@ impl<'a> Parser<'a> { let lo = self.token.span; - let vis = self.parse_visibility(false)?; + let vis = self.parse_visibility(FollowedByType::No)?; if self.eat_keyword(kw::Use) { // USE ITEM @@ -706,7 +706,7 @@ impl<'a> Parser<'a> { mut attrs: Vec, ) -> PResult<'a, ImplItem> { let lo = self.token.span; - let vis = self.parse_visibility(false)?; + let vis = self.parse_visibility(FollowedByType::No)?; let defaultness = self.parse_defaultness(); let (name, kind, generics) = if let Some(type_) = self.eat_type() { let (name, alias, generics) = type_?; @@ -896,7 +896,7 @@ impl<'a> Parser<'a> { mut attrs: Vec, ) -> PResult<'a, TraitItem> { let lo = self.token.span; - self.eat_bad_pub(); + let vis = self.parse_visibility(FollowedByType::No)?; let (name, kind, generics) = if self.eat_keyword(kw::Type) { self.parse_trait_item_assoc_ty()? } else if self.is_const_item() { @@ -912,6 +912,7 @@ impl<'a> Parser<'a> { id: DUMMY_NODE_ID, ident: name, attrs, + vis, generics, kind, span: lo.to(self.prev_span), @@ -1142,7 +1143,7 @@ impl<'a> Parser<'a> { let attrs = self.parse_outer_attributes()?; let lo = self.token.span; - let visibility = self.parse_visibility(false)?; + let visibility = self.parse_visibility(FollowedByType::No)?; // FOREIGN STATIC ITEM // Treat `const` as `static` for error recovery, but don't add it to expected tokens. @@ -1370,7 +1371,7 @@ impl<'a> Parser<'a> { let variant_attrs = self.parse_outer_attributes()?; let vlo = self.token.span; - self.eat_bad_pub(); + let vis = self.parse_visibility(FollowedByType::No)?; let ident = self.parse_ident()?; let struct_def = if self.check(&token::OpenDelim(token::Brace)) { @@ -1397,6 +1398,7 @@ impl<'a> Parser<'a> { let vr = ast::Variant { ident, + vis, id: DUMMY_NODE_ID, attrs: variant_attrs, data: struct_def, @@ -1550,7 +1552,7 @@ impl<'a> Parser<'a> { self.parse_paren_comma_seq(|p| { let attrs = p.parse_outer_attributes()?; let lo = p.token.span; - let vis = p.parse_visibility(true)?; + let vis = p.parse_visibility(FollowedByType::Yes)?; let ty = p.parse_ty()?; Ok(StructField { span: lo.to(ty.span), @@ -1568,7 +1570,7 @@ impl<'a> Parser<'a> { fn parse_struct_decl_field(&mut self) -> PResult<'a, StructField> { let attrs = self.parse_outer_attributes()?; let lo = self.token.span; - let vis = self.parse_visibility(false)?; + let vis = self.parse_visibility(FollowedByType::No)?; self.parse_single_struct_field(lo, vis, attrs) } diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index a491d91e20f..29536146a9b 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -346,6 +346,8 @@ impl SeqSep { } } +pub enum FollowedByType { Yes, No } + impl<'a> Parser<'a> { pub fn new( sess: &'a ParseSess, @@ -1116,7 +1118,7 @@ impl<'a> Parser<'a> { /// If the following element can't be a tuple (i.e., it's a function definition), then /// it's not a tuple struct field), and the contents within the parentheses isn't valid, /// so emit a proper diagnostic. - pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibility> { + pub fn parse_visibility(&mut self, fbt: FollowedByType) -> PResult<'a, Visibility> { maybe_whole!(self, NtVis, |x| x); self.expected_tokens.push(TokenType::Keyword(kw::Crate)); @@ -1171,7 +1173,9 @@ impl<'a> Parser<'a> { id: ast::DUMMY_NODE_ID, }; return Ok(respan(lo.to(self.prev_span), vis)); - } else if !can_take_tuple { // Provide this diagnostic if this is not a tuple struct. + } else if let FollowedByType::No = fbt { + // Provide this diagnostic if a type cannot follow; + // in particular, if this is not a tuple struct. self.recover_incorrect_vis_restriction()?; // Emit diagnostic, but continue with public visibility. } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index ec5572914d8..e43212a8f29 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -524,6 +524,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } ItemKind::Enum(ref def, _) => { for variant in &def.variants { + self.invalid_visibility(&variant.vis, None); for field in variant.data.fields() { self.invalid_visibility(&field.vis, None); } @@ -754,6 +755,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } visit::walk_impl_item(self, ii); } + + fn visit_trait_item(&mut self, ti: &'a TraitItem) { + self.invalid_visibility(&ti.vis, None); + visit::walk_trait_item(self, ti); + } } pub fn check_crate(session: &Session, krate: &Crate, lints: &mut lint::LintBuffer) -> bool { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 170d089d4bb..550520790b5 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -961,12 +961,12 @@ pub struct Arm { /// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct field. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Field { - pub ident: Ident, - pub expr: P, - pub span: Span, - pub is_shorthand: bool, pub attrs: ThinVec, pub id: NodeId, + pub span: Span, + pub ident: Ident, + pub expr: P, + pub is_shorthand: bool, pub is_placeholder: bool, } @@ -1515,12 +1515,14 @@ pub struct FnSig { /// signature) or provided (meaning it has a default implementation). #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct TraitItem { - pub id: NodeId, - pub ident: Ident, pub attrs: Vec, + pub id: NodeId, + pub span: Span, + pub vis: Visibility, + pub ident: Ident, + pub generics: Generics, pub kind: TraitItemKind, - pub span: Span, /// See `Item::tokens` for what this is. pub tokens: Option, } @@ -1536,14 +1538,15 @@ pub enum TraitItemKind { /// Represents anything within an `impl` block. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct ImplItem { - pub id: NodeId, - pub ident: Ident, - pub vis: Visibility, - pub defaultness: Defaultness, pub attrs: Vec, + pub id: NodeId, + pub span: Span, + pub vis: Visibility, + pub ident: Ident, + + pub defaultness: Defaultness, pub generics: Generics, pub kind: ImplItemKind, - pub span: Span, /// See `Item::tokens` for what this is. pub tokens: Option, } @@ -2101,22 +2104,24 @@ pub struct GlobalAsm { pub struct EnumDef { pub variants: Vec, } - /// Enum variant. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Variant { - /// Name of the variant. - pub ident: Ident, /// Attributes of the variant. pub attrs: Vec, /// Id of the variant (not the constructor, see `VariantData::ctor_id()`). pub id: NodeId, + /// Span + pub span: Span, + /// The visibility of the variant. Syntactically accepted but not semantically. + pub vis: Visibility, + /// Name of the variant. + pub ident: Ident, + /// Fields and constructor id of the variant. pub data: VariantData, /// Explicit discriminant, e.g., `Foo = 1`. pub disr_expr: Option, - /// Span - pub span: Span, /// Is a macro placeholder pub is_placeholder: bool, } @@ -2295,12 +2300,13 @@ impl VisibilityKind { /// E.g., `bar: usize` as in `struct Foo { bar: usize }`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct StructField { - pub span: Span, - pub ident: Option, - pub vis: Visibility, - pub id: NodeId, - pub ty: P, pub attrs: Vec, + pub id: NodeId, + pub span: Span, + pub vis: Visibility, + pub ident: Option, + + pub ty: P, pub is_placeholder: bool, } @@ -2344,12 +2350,13 @@ impl VariantData { /// The name might be a dummy name in case of anonymous items. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Item { - pub ident: Ident, pub attrs: Vec, pub id: NodeId, - pub kind: ItemKind, - pub vis: Visibility, pub span: Span, + pub vis: Visibility, + pub ident: Ident, + + pub kind: ItemKind, /// Original tokens this item was parsed from. This isn't necessarily /// available for all items, although over time more and more items should @@ -2518,12 +2525,13 @@ impl ItemKind { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct ForeignItem { - pub ident: Ident, pub attrs: Vec, - pub kind: ForeignItemKind, pub id: NodeId, pub span: Span, pub vis: Visibility, + pub ident: Ident, + + pub kind: ForeignItemKind, } /// An item within an `extern` block. diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 376323a83ea..d79571ccf26 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -472,16 +472,17 @@ pub fn noop_visit_foreign_mod(foreign_mod: &mut ForeignMod, vis: items.flat_map_in_place(|item| vis.flat_map_foreign_item(item)); } -pub fn noop_flat_map_variant(mut variant: Variant, vis: &mut T) +pub fn noop_flat_map_variant(mut variant: Variant, visitor: &mut T) -> SmallVec<[Variant; 1]> { - let Variant { ident, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant; - vis.visit_ident(ident); - visit_attrs(attrs, vis); - vis.visit_id(id); - vis.visit_variant_data(data); - visit_opt(disr_expr, |disr_expr| vis.visit_anon_const(disr_expr)); - vis.visit_span(span); + let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant; + visitor.visit_ident(ident); + visitor.visit_vis(vis); + visit_attrs(attrs, visitor); + visitor.visit_id(id); + visitor.visit_variant_data(data); + visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr)); + visitor.visit_span(span); smallvec![variant] } @@ -920,32 +921,33 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { } } -pub fn noop_flat_map_trait_item(mut item: TraitItem, vis: &mut T) +pub fn noop_flat_map_trait_item(mut item: TraitItem, visitor: &mut T) -> SmallVec<[TraitItem; 1]> { - let TraitItem { id, ident, attrs, generics, kind, span, tokens: _ } = &mut item; - vis.visit_id(id); - vis.visit_ident(ident); - visit_attrs(attrs, vis); - vis.visit_generics(generics); + let TraitItem { id, ident, vis, attrs, generics, kind, span, tokens: _ } = &mut item; + visitor.visit_id(id); + visitor.visit_ident(ident); + visitor.visit_vis(vis); + visit_attrs(attrs, visitor); + visitor.visit_generics(generics); match kind { TraitItemKind::Const(ty, default) => { - vis.visit_ty(ty); - visit_opt(default, |default| vis.visit_expr(default)); + visitor.visit_ty(ty); + visit_opt(default, |default| visitor.visit_expr(default)); } TraitItemKind::Method(sig, body) => { - visit_fn_sig(sig, vis); - visit_opt(body, |body| vis.visit_block(body)); + visit_fn_sig(sig, visitor); + visit_opt(body, |body| visitor.visit_block(body)); } TraitItemKind::Type(bounds, default) => { - visit_bounds(bounds, vis); - visit_opt(default, |default| vis.visit_ty(default)); + visit_bounds(bounds, visitor); + visit_opt(default, |default| visitor.visit_ty(default)); } TraitItemKind::Macro(mac) => { - vis.visit_mac(mac); + visitor.visit_mac(mac); } } - vis.visit_span(span); + visitor.visit_span(span); smallvec![item] } diff --git a/src/libsyntax/print/pprust/tests.rs b/src/libsyntax/print/pprust/tests.rs index 2c6dd0fb1c6..d7725acb5d4 100644 --- a/src/libsyntax/print/pprust/tests.rs +++ b/src/libsyntax/print/pprust/tests.rs @@ -50,6 +50,7 @@ fn test_variant_to_string() { let var = ast::Variant { ident, + vis: source_map::respan(syntax_pos::DUMMY_SP, ast::VisibilityKind::Inherited), attrs: Vec::new(), id: ast::DUMMY_NODE_ID, data: ast::VariantData::Unit(ast::DUMMY_NODE_ID), diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index ea2dc357e6e..1fad6af0f5b 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -314,6 +314,7 @@ pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant) where V: Visitor<'a>, { visitor.visit_ident(variant.ident); + visitor.visit_vis(&variant.vis); visitor.visit_variant_data(&variant.data); walk_list!(visitor, visit_anon_const, &variant.disr_expr); walk_list!(visitor, visit_attribute, &variant.attrs); @@ -585,6 +586,7 @@ pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl } pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a TraitItem) { + visitor.visit_vis(&trait_item.vis); visitor.visit_ident(trait_item.ident); walk_list!(visitor, visit_attribute, &trait_item.attrs); visitor.visit_generics(&trait_item.generics); diff --git a/src/libsyntax_expand/build.rs b/src/libsyntax_expand/build.rs index 105ffe3ee8a..7fe37f377a8 100644 --- a/src/libsyntax_expand/build.rs +++ b/src/libsyntax_expand/build.rs @@ -582,12 +582,13 @@ impl<'a> ExtCtxt<'a> { } pub fn variant(&self, span: Span, ident: Ident, tys: Vec> ) -> ast::Variant { + let vis_span = span.shrink_to_lo(); let fields: Vec<_> = tys.into_iter().map(|ty| { ast::StructField { span: ty.span, ty, ident: None, - vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited), + vis: respan(vis_span, ast::VisibilityKind::Inherited), attrs: Vec::new(), id: ast::DUMMY_NODE_ID, is_placeholder: false, @@ -606,6 +607,7 @@ impl<'a> ExtCtxt<'a> { disr_expr: None, id: ast::DUMMY_NODE_ID, ident, + vis: respan(vis_span, ast::VisibilityKind::Inherited), span, is_placeholder: false, } diff --git a/src/libsyntax_expand/mbe/macro_parser.rs b/src/libsyntax_expand/mbe/macro_parser.rs index 0dcb2c39fdc..bf7960f9066 100644 --- a/src/libsyntax_expand/mbe/macro_parser.rs +++ b/src/libsyntax_expand/mbe/macro_parser.rs @@ -77,7 +77,7 @@ use TokenTreeOrTokenTreeSlice::*; use crate::mbe::{self, TokenTree}; use rustc_parse::Directory; -use rustc_parse::parser::{Parser, PathStyle}; +use rustc_parse::parser::{Parser, PathStyle, FollowedByType}; use syntax::ast::{Ident, Name}; use syntax::print::pprust; use syntax::sess::ParseSess; @@ -933,7 +933,7 @@ fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a, } sym::path => token::NtPath(p.parse_path(PathStyle::Type)?), sym::meta => token::NtMeta(p.parse_attr_item()?), - sym::vis => token::NtVis(p.parse_visibility(true)?), + sym::vis => token::NtVis(p.parse_visibility(FollowedByType::Yes)?), sym::lifetime => if p.check_lifetime() { token::NtLifetime(p.expect_lifetime().ident) } else { diff --git a/src/libsyntax_expand/placeholders.rs b/src/libsyntax_expand/placeholders.rs index e595888dae7..36a09700076 100644 --- a/src/libsyntax_expand/placeholders.rs +++ b/src/libsyntax_expand/placeholders.rs @@ -53,7 +53,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { tokens: None, })]), AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![ast::TraitItem { - id, span, ident, attrs, generics, + id, span, ident, vis, attrs, generics, kind: ast::TraitItemKind::Macro(mac_placeholder()), tokens: None, }]), @@ -150,6 +150,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { id, ident, span, + vis, is_placeholder: true, } ]) diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout index 64c9f693115..b299fc55841 100644 --- a/src/test/ui/ast-json/ast-json-output.stdout +++ b/src/test/ui/ast-json/ast-json-output.stdout @@ -1 +1 @@ -{"module":{"inner":{"lo":0,"hi":0},"items":[{"ident":{"name":"core","span":{"lo":0,"hi":0}},"attrs":[],"id":0,"kind":{"variant":"ExternCrate","fields":[null]},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"span":{"lo":0,"hi":0},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0}} +{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0}} diff --git a/src/test/ui/issues/issue-28433.stderr b/src/test/ui/issues/issue-28433.stderr index 851bc5dfbdd..9f5f6333602 100644 --- a/src/test/ui/issues/issue-28433.stderr +++ b/src/test/ui/issues/issue-28433.stderr @@ -1,14 +1,15 @@ -error: unnecessary visibility qualifier +error[E0449]: unnecessary visibility qualifier --> $DIR/issue-28433.rs:2:5 | LL | pub Duck, - | ^^^ `pub` not permitted here + | ^^^ `pub` not permitted here because it's implied -error: unnecessary visibility qualifier +error[E0449]: unnecessary visibility qualifier --> $DIR/issue-28433.rs:5:5 | LL | pub(crate) Dove - | ^^^^^^^^^^ `pub` not permitted here + | ^^^^^^^^^^ error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0449`. diff --git a/src/test/ui/issues/issue-60075.rs b/src/test/ui/issues/issue-60075.rs index 1f53a927932..7d3fc83786e 100644 --- a/src/test/ui/issues/issue-60075.rs +++ b/src/test/ui/issues/issue-60075.rs @@ -4,7 +4,7 @@ trait T { fn qux() -> Option { let _ = if true { }); -//~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `;` +//~^ ERROR expected one of `async` //~| ERROR expected one of `.`, `;`, `?`, `else`, or an operator, found `}` //~| ERROR expected identifier, found `;` Some(4) diff --git a/src/test/ui/issues/issue-60075.stderr b/src/test/ui/issues/issue-60075.stderr index 39e3ad7b6b4..e0b15130c33 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`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `;` +error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `;` --> $DIR/issue-60075.rs:6:11 | LL | fn qux() -> Option { diff --git a/src/test/ui/parser/issue-32446.stderr b/src/test/ui/parser/issue-32446.stderr index ab37dd7c39d..70256a59231 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`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `...` +error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `...` --> $DIR/issue-32446.rs:4:11 | LL | trait T { ... } - | ^^^ expected one of 7 possible tokens + | ^^^ expected one of 9 possible tokens error: aborting due to previous error diff --git a/src/test/ui/parser/issue-65041-empty-vis-matcher-in-enum.rs b/src/test/ui/parser/issue-65041-empty-vis-matcher-in-enum.rs new file mode 100644 index 00000000000..ef89e31d842 --- /dev/null +++ b/src/test/ui/parser/issue-65041-empty-vis-matcher-in-enum.rs @@ -0,0 +1,28 @@ +// check-pass + +// Here we check that a `:vis` macro matcher subsititued for the empty visibility +// (`VisibilityKind::Inherited`) is accepted when used before an enum variant. + +fn main() {} + +macro_rules! mac_variant { + ($vis:vis MARKER) => { + enum Enum { + $vis Unit, + + $vis Tuple(u8, u16), + + $vis Struct { f: u8 }, + } + } +} + +mac_variant!(MARKER); + +// We also accept visibilities on variants syntactically but not semantically. +#[cfg(FALSE)] +enum E { + pub U, + pub(crate) T(u8), + pub(super) T { f: String } +} diff --git a/src/test/ui/parser/issue-65041-empty-vis-matcher-in-trait.rs b/src/test/ui/parser/issue-65041-empty-vis-matcher-in-trait.rs new file mode 100644 index 00000000000..b08767b210b --- /dev/null +++ b/src/test/ui/parser/issue-65041-empty-vis-matcher-in-trait.rs @@ -0,0 +1,28 @@ +// check-pass + +// Here we check that a `:vis` macro matcher subsititued for the empty visibility +// (`VisibilityKind::Inherited`) is accepted when used before an item in a trait. + +fn main() {} + +macro_rules! mac_in_trait { + ($vis:vis MARKER) => { + $vis fn beta() {} + + $vis const GAMMA: u8; + + $vis type Delta; + } +} + +trait Alpha { + mac_in_trait!(MARKER); +} + +// We also accept visibilities on items in traits syntactically but not semantically. +#[cfg(FALSE)] +trait Foo { + pub fn bar(); + pub(crate) type baz; + pub(super) const QUUX: u8; +} diff --git a/src/test/ui/parser/macro/trait-non-item-macros.rs b/src/test/ui/parser/macro/trait-non-item-macros.rs index 958c90b7c0a..5021886bf98 100644 --- a/src/test/ui/parser/macro/trait-non-item-macros.rs +++ b/src/test/ui/parser/macro/trait-non-item-macros.rs @@ -1,6 +1,6 @@ macro_rules! bah { ($a:expr) => ($a) - //~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found `2` + //~^ ERROR expected one of `async` } trait bar { 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 dd97a3afa99..0a433ab278e 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`, `extern`, `fn`, `type`, or `unsafe`, found `2` +error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `2` --> $DIR/trait-non-item-macros.rs:2:19 | LL | ($a:expr) => ($a) - | ^^ expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe` + | ^^ expected one of 8 possible tokens ... LL | bah!(2); | -------- in this macro invocation 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 79547195411..9f3d78d584d 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 @@ -1,7 +1,9 @@ trait T { +//~^ ERROR `main` function not found in crate `missing_close_brace_in_trait` fn foo(&self); -pub(crate) struct Bar(); //~ ERROR expected one of +pub(crate) struct Bar(); +//~^ ERROR expected one of 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 1bd8e445fad..cbaf9315e85 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 @@ -1,5 +1,5 @@ error: this file contains an un-closed delimiter - --> $DIR/missing-close-brace-in-trait.rs:10:66 + --> $DIR/missing-close-brace-in-trait.rs:12:66 | LL | trait T { | - un-closed delimiter @@ -7,19 +7,24 @@ LL | trait T { LL | fn main() {} | ^ -error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found keyword `pub` - --> $DIR/missing-close-brace-in-trait.rs:4:1 +error: expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found keyword `struct` + --> $DIR/missing-close-brace-in-trait.rs:5:12 | -LL | trait T { - | - unclosed delimiter -LL | fn foo(&self); - | - - | | - | expected one of 7 possible tokens - | help: `}` may belong here -LL | LL | pub(crate) struct Bar(); - | ^^^ unexpected token + | ^^^^^^ expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe` -error: aborting due to 2 previous errors +error[E0601]: `main` function not found in crate `missing_close_brace_in_trait` + --> $DIR/missing-close-brace-in-trait.rs:1:1 + | +LL | / trait T { +LL | | +LL | | fn foo(&self); +LL | | +... | +LL | | +LL | | fn main() {} + | |_________________________________________________________________^ consider adding a `main` function to `$DIR/missing-close-brace-in-trait.rs` +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/parser/trait-pub-assoc-const.stderr b/src/test/ui/parser/trait-pub-assoc-const.stderr index 817692cc82c..efd09a0364e 100644 --- a/src/test/ui/parser/trait-pub-assoc-const.stderr +++ b/src/test/ui/parser/trait-pub-assoc-const.stderr @@ -1,8 +1,9 @@ -error: unnecessary visibility qualifier +error[E0449]: unnecessary visibility qualifier --> $DIR/trait-pub-assoc-const.rs:2:5 | LL | pub const Foo: u32; - | ^^^ `pub` not permitted here + | ^^^ `pub` not permitted here because it's implied error: aborting due to previous error +For more information about this error, try `rustc --explain E0449`. diff --git a/src/test/ui/parser/trait-pub-assoc-ty.stderr b/src/test/ui/parser/trait-pub-assoc-ty.stderr index 400be6af22a..e76373f5c5f 100644 --- a/src/test/ui/parser/trait-pub-assoc-ty.stderr +++ b/src/test/ui/parser/trait-pub-assoc-ty.stderr @@ -1,8 +1,9 @@ -error: unnecessary visibility qualifier +error[E0449]: unnecessary visibility qualifier --> $DIR/trait-pub-assoc-ty.rs:2:5 | LL | pub type Foo; - | ^^^ `pub` not permitted here + | ^^^ `pub` not permitted here because it's implied error: aborting due to previous error +For more information about this error, try `rustc --explain E0449`. diff --git a/src/test/ui/parser/trait-pub-method.stderr b/src/test/ui/parser/trait-pub-method.stderr index b3617a4aa9b..0e3fe027cb5 100644 --- a/src/test/ui/parser/trait-pub-method.stderr +++ b/src/test/ui/parser/trait-pub-method.stderr @@ -1,8 +1,9 @@ -error: unnecessary visibility qualifier +error[E0449]: unnecessary visibility qualifier --> $DIR/trait-pub-method.rs:2:5 | LL | pub fn foo(); - | ^^^ `pub` not permitted here + | ^^^ `pub` not permitted here because it's implied error: aborting due to previous error +For more information about this error, try `rustc --explain E0449`.