Skip to content

Commit 9a88364

Browse files
committed
syntactically allow visibility on trait item & enum variant
1 parent e2fa952 commit 9a88364

25 files changed

+184
-109
lines changed

src/librustc_parse/parser/diagnostics.rs

-20
Original file line numberDiff line numberDiff line change
@@ -1187,26 +1187,6 @@ impl<'a> Parser<'a> {
11871187
}
11881188
}
11891189

1190-
/// Recovers from `pub` keyword in places where it seems _reasonable_ but isn't valid.
1191-
pub(super) fn eat_bad_pub(&mut self) {
1192-
// When `unclosed_delims` is populated, it means that the code being parsed is already
1193-
// quite malformed, which might mean that, for example, a pub struct definition could be
1194-
// parsed as being a trait item, which is invalid and this error would trigger
1195-
// unconditionally, resulting in misleading diagnostics. Because of this, we only attempt
1196-
// this nice to have recovery for code that is otherwise well formed.
1197-
if self.token.is_keyword(kw::Pub) && self.unclosed_delims.is_empty() {
1198-
match self.parse_visibility(false) {
1199-
Ok(vis) => {
1200-
self.diagnostic()
1201-
.struct_span_err(vis.span, "unnecessary visibility qualifier")
1202-
.span_label(vis.span, "`pub` not permitted here")
1203-
.emit();
1204-
}
1205-
Err(mut err) => err.emit(),
1206-
}
1207-
}
1208-
}
1209-
12101190
/// Eats tokens until we can be relatively sure we reached the end of the
12111191
/// statement. This is something of a best-effort heuristic.
12121192
///

src/librustc_parse/parser/item.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{Parser, PathStyle};
1+
use super::{Parser, PathStyle, FollowedByType};
22
use super::diagnostics::{Error, dummy_arg, ConsumeClosingDelim};
33

44
use crate::maybe_whole;
@@ -93,7 +93,7 @@ impl<'a> Parser<'a> {
9393

9494
let lo = self.token.span;
9595

96-
let vis = self.parse_visibility(false)?;
96+
let vis = self.parse_visibility(FollowedByType::No)?;
9797

9898
if self.eat_keyword(kw::Use) {
9999
// USE ITEM
@@ -706,7 +706,7 @@ impl<'a> Parser<'a> {
706706
mut attrs: Vec<Attribute>,
707707
) -> PResult<'a, ImplItem> {
708708
let lo = self.token.span;
709-
let vis = self.parse_visibility(false)?;
709+
let vis = self.parse_visibility(FollowedByType::No)?;
710710
let defaultness = self.parse_defaultness();
711711
let (name, kind, generics) = if let Some(type_) = self.eat_type() {
712712
let (name, alias, generics) = type_?;
@@ -896,7 +896,7 @@ impl<'a> Parser<'a> {
896896
mut attrs: Vec<Attribute>,
897897
) -> PResult<'a, TraitItem> {
898898
let lo = self.token.span;
899-
self.eat_bad_pub();
899+
let vis = self.parse_visibility(FollowedByType::No)?;
900900
let (name, kind, generics) = if self.eat_keyword(kw::Type) {
901901
self.parse_trait_item_assoc_ty()?
902902
} else if self.is_const_item() {
@@ -912,6 +912,7 @@ impl<'a> Parser<'a> {
912912
id: DUMMY_NODE_ID,
913913
ident: name,
914914
attrs,
915+
vis,
915916
generics,
916917
kind,
917918
span: lo.to(self.prev_span),
@@ -1142,7 +1143,7 @@ impl<'a> Parser<'a> {
11421143

11431144
let attrs = self.parse_outer_attributes()?;
11441145
let lo = self.token.span;
1145-
let visibility = self.parse_visibility(false)?;
1146+
let visibility = self.parse_visibility(FollowedByType::No)?;
11461147

11471148
// FOREIGN STATIC ITEM
11481149
// Treat `const` as `static` for error recovery, but don't add it to expected tokens.
@@ -1370,7 +1371,7 @@ impl<'a> Parser<'a> {
13701371
let variant_attrs = self.parse_outer_attributes()?;
13711372
let vlo = self.token.span;
13721373

1373-
self.eat_bad_pub();
1374+
let vis = self.parse_visibility(FollowedByType::No)?;
13741375
let ident = self.parse_ident()?;
13751376

13761377
let struct_def = if self.check(&token::OpenDelim(token::Brace)) {
@@ -1397,6 +1398,7 @@ impl<'a> Parser<'a> {
13971398

13981399
let vr = ast::Variant {
13991400
ident,
1401+
vis,
14001402
id: DUMMY_NODE_ID,
14011403
attrs: variant_attrs,
14021404
data: struct_def,
@@ -1550,7 +1552,7 @@ impl<'a> Parser<'a> {
15501552
self.parse_paren_comma_seq(|p| {
15511553
let attrs = p.parse_outer_attributes()?;
15521554
let lo = p.token.span;
1553-
let vis = p.parse_visibility(true)?;
1555+
let vis = p.parse_visibility(FollowedByType::Yes)?;
15541556
let ty = p.parse_ty()?;
15551557
Ok(StructField {
15561558
span: lo.to(ty.span),
@@ -1568,7 +1570,7 @@ impl<'a> Parser<'a> {
15681570
fn parse_struct_decl_field(&mut self) -> PResult<'a, StructField> {
15691571
let attrs = self.parse_outer_attributes()?;
15701572
let lo = self.token.span;
1571-
let vis = self.parse_visibility(false)?;
1573+
let vis = self.parse_visibility(FollowedByType::No)?;
15721574
self.parse_single_struct_field(lo, vis, attrs)
15731575
}
15741576

src/librustc_parse/parser/mod.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,8 @@ impl SeqSep {
346346
}
347347
}
348348

349+
pub enum FollowedByType { Yes, No }
350+
349351
impl<'a> Parser<'a> {
350352
pub fn new(
351353
sess: &'a ParseSess,
@@ -1116,7 +1118,7 @@ impl<'a> Parser<'a> {
11161118
/// If the following element can't be a tuple (i.e., it's a function definition), then
11171119
/// it's not a tuple struct field), and the contents within the parentheses isn't valid,
11181120
/// so emit a proper diagnostic.
1119-
pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibility> {
1121+
pub fn parse_visibility(&mut self, fbt: FollowedByType) -> PResult<'a, Visibility> {
11201122
maybe_whole!(self, NtVis, |x| x);
11211123

11221124
self.expected_tokens.push(TokenType::Keyword(kw::Crate));
@@ -1171,7 +1173,9 @@ impl<'a> Parser<'a> {
11711173
id: ast::DUMMY_NODE_ID,
11721174
};
11731175
return Ok(respan(lo.to(self.prev_span), vis));
1174-
} else if !can_take_tuple { // Provide this diagnostic if this is not a tuple struct.
1176+
} else if let FollowedByType::No = fbt {
1177+
// Provide this diagnostic if a type cannot follow;
1178+
// in particular, if this is not a tuple struct.
11751179
self.recover_incorrect_vis_restriction()?;
11761180
// Emit diagnostic, but continue with public visibility.
11771181
}

src/librustc_passes/ast_validation.rs

+6
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
524524
}
525525
ItemKind::Enum(ref def, _) => {
526526
for variant in &def.variants {
527+
self.invalid_visibility(&variant.vis, None);
527528
for field in variant.data.fields() {
528529
self.invalid_visibility(&field.vis, None);
529530
}
@@ -754,6 +755,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
754755
}
755756
visit::walk_impl_item(self, ii);
756757
}
758+
759+
fn visit_trait_item(&mut self, ti: &'a TraitItem) {
760+
self.invalid_visibility(&ti.vis, None);
761+
visit::walk_trait_item(self, ti);
762+
}
757763
}
758764

759765
pub fn check_crate(session: &Session, krate: &Crate, lints: &mut lint::LintBuffer) -> bool {

src/libsyntax/ast.rs

+29-21
Original file line numberDiff line numberDiff line change
@@ -961,12 +961,12 @@ pub struct Arm {
961961
/// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct field.
962962
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
963963
pub struct Field {
964+
pub attrs: ThinVec<Attribute>,
965+
pub id: NodeId,
966+
pub span: Span,
964967
pub ident: Ident,
965968
pub expr: P<Expr>,
966-
pub span: Span,
967969
pub is_shorthand: bool,
968-
pub attrs: ThinVec<Attribute>,
969-
pub id: NodeId,
970970
pub is_placeholder: bool,
971971
}
972972

@@ -1515,12 +1515,14 @@ pub struct FnSig {
15151515
/// signature) or provided (meaning it has a default implementation).
15161516
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
15171517
pub struct TraitItem {
1518+
pub attrs: Vec<Attribute>,
15181519
pub id: NodeId,
1520+
pub span: Span,
1521+
pub vis: Visibility,
15191522
pub ident: Ident,
1520-
pub attrs: Vec<Attribute>,
1523+
15211524
pub generics: Generics,
15221525
pub kind: TraitItemKind,
1523-
pub span: Span,
15241526
/// See `Item::tokens` for what this is.
15251527
pub tokens: Option<TokenStream>,
15261528
}
@@ -1536,14 +1538,15 @@ pub enum TraitItemKind {
15361538
/// Represents anything within an `impl` block.
15371539
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
15381540
pub struct ImplItem {
1541+
pub attrs: Vec<Attribute>,
15391542
pub id: NodeId,
1540-
pub ident: Ident,
1543+
pub span: Span,
15411544
pub vis: Visibility,
1545+
pub ident: Ident,
1546+
15421547
pub defaultness: Defaultness,
1543-
pub attrs: Vec<Attribute>,
15441548
pub generics: Generics,
15451549
pub kind: ImplItemKind,
1546-
pub span: Span,
15471550
/// See `Item::tokens` for what this is.
15481551
pub tokens: Option<TokenStream>,
15491552
}
@@ -2101,22 +2104,24 @@ pub struct GlobalAsm {
21012104
pub struct EnumDef {
21022105
pub variants: Vec<Variant>,
21032106
}
2104-
21052107
/// Enum variant.
21062108
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
21072109
pub struct Variant {
2108-
/// Name of the variant.
2109-
pub ident: Ident,
21102110
/// Attributes of the variant.
21112111
pub attrs: Vec<Attribute>,
21122112
/// Id of the variant (not the constructor, see `VariantData::ctor_id()`).
21132113
pub id: NodeId,
2114+
/// Span
2115+
pub span: Span,
2116+
/// The visibility of the variant. Syntactically accepted but not semantically.
2117+
pub vis: Visibility,
2118+
/// Name of the variant.
2119+
pub ident: Ident,
2120+
21142121
/// Fields and constructor id of the variant.
21152122
pub data: VariantData,
21162123
/// Explicit discriminant, e.g., `Foo = 1`.
21172124
pub disr_expr: Option<AnonConst>,
2118-
/// Span
2119-
pub span: Span,
21202125
/// Is a macro placeholder
21212126
pub is_placeholder: bool,
21222127
}
@@ -2295,12 +2300,13 @@ impl VisibilityKind {
22952300
/// E.g., `bar: usize` as in `struct Foo { bar: usize }`.
22962301
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
22972302
pub struct StructField {
2303+
pub attrs: Vec<Attribute>,
2304+
pub id: NodeId,
22982305
pub span: Span,
2299-
pub ident: Option<Ident>,
23002306
pub vis: Visibility,
2301-
pub id: NodeId,
2307+
pub ident: Option<Ident>,
2308+
23022309
pub ty: P<Ty>,
2303-
pub attrs: Vec<Attribute>,
23042310
pub is_placeholder: bool,
23052311
}
23062312

@@ -2344,12 +2350,13 @@ impl VariantData {
23442350
/// The name might be a dummy name in case of anonymous items.
23452351
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
23462352
pub struct Item {
2347-
pub ident: Ident,
23482353
pub attrs: Vec<Attribute>,
23492354
pub id: NodeId,
2350-
pub kind: ItemKind,
2351-
pub vis: Visibility,
23522355
pub span: Span,
2356+
pub vis: Visibility,
2357+
pub ident: Ident,
2358+
2359+
pub kind: ItemKind,
23532360

23542361
/// Original tokens this item was parsed from. This isn't necessarily
23552362
/// available for all items, although over time more and more items should
@@ -2518,12 +2525,13 @@ impl ItemKind {
25182525

25192526
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
25202527
pub struct ForeignItem {
2521-
pub ident: Ident,
25222528
pub attrs: Vec<Attribute>,
2523-
pub kind: ForeignItemKind,
25242529
pub id: NodeId,
25252530
pub span: Span,
25262531
pub vis: Visibility,
2532+
pub ident: Ident,
2533+
2534+
pub kind: ForeignItemKind,
25272535
}
25282536

25292537
/// An item within an `extern` block.

src/libsyntax/mut_visit.rs

+24-22
Original file line numberDiff line numberDiff line change
@@ -472,16 +472,17 @@ pub fn noop_visit_foreign_mod<T: MutVisitor>(foreign_mod: &mut ForeignMod, vis:
472472
items.flat_map_in_place(|item| vis.flat_map_foreign_item(item));
473473
}
474474

475-
pub fn noop_flat_map_variant<T: MutVisitor>(mut variant: Variant, vis: &mut T)
475+
pub fn noop_flat_map_variant<T: MutVisitor>(mut variant: Variant, visitor: &mut T)
476476
-> SmallVec<[Variant; 1]>
477477
{
478-
let Variant { ident, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant;
479-
vis.visit_ident(ident);
480-
visit_attrs(attrs, vis);
481-
vis.visit_id(id);
482-
vis.visit_variant_data(data);
483-
visit_opt(disr_expr, |disr_expr| vis.visit_anon_const(disr_expr));
484-
vis.visit_span(span);
478+
let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant;
479+
visitor.visit_ident(ident);
480+
visitor.visit_vis(vis);
481+
visit_attrs(attrs, visitor);
482+
visitor.visit_id(id);
483+
visitor.visit_variant_data(data);
484+
visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr));
485+
visitor.visit_span(span);
485486
smallvec![variant]
486487
}
487488

@@ -920,32 +921,33 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
920921
}
921922
}
922923

923-
pub fn noop_flat_map_trait_item<T: MutVisitor>(mut item: TraitItem, vis: &mut T)
924+
pub fn noop_flat_map_trait_item<T: MutVisitor>(mut item: TraitItem, visitor: &mut T)
924925
-> SmallVec<[TraitItem; 1]>
925926
{
926-
let TraitItem { id, ident, attrs, generics, kind, span, tokens: _ } = &mut item;
927-
vis.visit_id(id);
928-
vis.visit_ident(ident);
929-
visit_attrs(attrs, vis);
930-
vis.visit_generics(generics);
927+
let TraitItem { id, ident, vis, attrs, generics, kind, span, tokens: _ } = &mut item;
928+
visitor.visit_id(id);
929+
visitor.visit_ident(ident);
930+
visitor.visit_vis(vis);
931+
visit_attrs(attrs, visitor);
932+
visitor.visit_generics(generics);
931933
match kind {
932934
TraitItemKind::Const(ty, default) => {
933-
vis.visit_ty(ty);
934-
visit_opt(default, |default| vis.visit_expr(default));
935+
visitor.visit_ty(ty);
936+
visit_opt(default, |default| visitor.visit_expr(default));
935937
}
936938
TraitItemKind::Method(sig, body) => {
937-
visit_fn_sig(sig, vis);
938-
visit_opt(body, |body| vis.visit_block(body));
939+
visit_fn_sig(sig, visitor);
940+
visit_opt(body, |body| visitor.visit_block(body));
939941
}
940942
TraitItemKind::Type(bounds, default) => {
941-
visit_bounds(bounds, vis);
942-
visit_opt(default, |default| vis.visit_ty(default));
943+
visit_bounds(bounds, visitor);
944+
visit_opt(default, |default| visitor.visit_ty(default));
943945
}
944946
TraitItemKind::Macro(mac) => {
945-
vis.visit_mac(mac);
947+
visitor.visit_mac(mac);
946948
}
947949
}
948-
vis.visit_span(span);
950+
visitor.visit_span(span);
949951

950952
smallvec![item]
951953
}

src/libsyntax/print/pprust/tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ fn test_variant_to_string() {
5050

5151
let var = ast::Variant {
5252
ident,
53+
vis: source_map::respan(syntax_pos::DUMMY_SP, ast::VisibilityKind::Inherited),
5354
attrs: Vec::new(),
5455
id: ast::DUMMY_NODE_ID,
5556
data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),

src/libsyntax/visit.rs

+2
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant)
314314
where V: Visitor<'a>,
315315
{
316316
visitor.visit_ident(variant.ident);
317+
visitor.visit_vis(&variant.vis);
317318
visitor.visit_variant_data(&variant.data);
318319
walk_list!(visitor, visit_anon_const, &variant.disr_expr);
319320
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
585586
}
586587

587588
pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a TraitItem) {
589+
visitor.visit_vis(&trait_item.vis);
588590
visitor.visit_ident(trait_item.ident);
589591
walk_list!(visitor, visit_attribute, &trait_item.attrs);
590592
visitor.visit_generics(&trait_item.generics);

0 commit comments

Comments
 (0)