Skip to content

Commit 1c2906e

Browse files
committed
ast/parser: fuse static & const grammars in all contexts.
1 parent f3e9763 commit 1c2906e

18 files changed

+205
-125
lines changed

src/librustc_ast_lowering/item.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
679679

680680
hir::ForeignItemKind::Fn(fn_dec, fn_args, generics)
681681
}
682-
ForeignItemKind::Static(ref t, m) => {
682+
ForeignItemKind::Static(ref t, m, _) => {
683683
let ty = self.lower_ty(t, ImplTraitContext::disallowed());
684684
hir::ForeignItemKind::Static(ty, m)
685685
}

src/librustc_ast_passes/ast_validation.rs

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -464,19 +464,22 @@ impl<'a> AstValidator<'a> {
464464
}
465465
}
466466

467-
fn check_foreign_ty_bodyless(&self, ident: Ident, body: Option<&Ty>) {
467+
fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body: Option<Span>) {
468468
let body = match body {
469469
None => return,
470470
Some(body) => body,
471471
};
472472
self.err_handler()
473-
.struct_span_err(ident.span, "incorrect `type` inside `extern` block")
473+
.struct_span_err(ident.span, &format!("incorrect `{}` inside `extern` block", kind))
474474
.span_label(ident.span, "cannot have a body")
475-
.span_label(body.span, "the invalid body")
475+
.span_label(body, "the invalid body")
476476
.span_label(
477477
self.current_extern_span(),
478-
"`extern` blocks define existing foreign types and types \
479-
inside of them cannot have a body",
478+
format!(
479+
"`extern` blocks define existing foreign {0}s and {0}s \
480+
inside of them cannot have a body",
481+
kind
482+
),
480483
)
481484
.note(MORE_EXTERN)
482485
.emit();
@@ -579,6 +582,16 @@ impl<'a> AstValidator<'a> {
579582
}
580583
}
581584
}
585+
586+
fn check_item_named(&self, ident: Ident, kind: &str) {
587+
if ident.name != kw::Underscore {
588+
return;
589+
}
590+
self.err_handler()
591+
.struct_span_err(ident.span, &format!("`{}` items in this context need a name", kind))
592+
.span_label(ident.span, format!("`_` is not a valid name for this `{}` item", kind))
593+
.emit();
594+
}
582595
}
583596

584597
enum GenericPosition {
@@ -969,11 +982,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
969982
self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
970983
}
971984
ForeignItemKind::TyAlias(generics, bounds, body) => {
972-
self.check_foreign_ty_bodyless(fi.ident, body.as_deref());
985+
self.check_foreign_kind_bodyless(fi.ident, "type", body.as_ref().map(|b| b.span));
973986
self.check_type_no_bounds(bounds, "`extern` blocks");
974987
self.check_foreign_ty_genericless(generics);
975988
}
976-
ForeignItemKind::Static(..) | ForeignItemKind::Macro(..) => {}
989+
ForeignItemKind::Static(_, _, body) => {
990+
self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span));
991+
}
992+
ForeignItemKind::Macro(..) => {}
977993
}
978994

979995
visit::walk_foreign_item(self, fi)
@@ -1234,6 +1250,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
12341250
}
12351251
}
12361252

1253+
if let AssocItemKind::Const(..) = item.kind {
1254+
self.check_item_named(item.ident, "const");
1255+
}
1256+
12371257
self.with_in_trait_impl(false, |this| visit::walk_assoc_item(this, item, ctxt));
12381258
}
12391259
}

src/librustc_ast_pretty/pprust.rs

Lines changed: 22 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,17 +1023,8 @@ impl<'a> State<'a> {
10231023
ast::ForeignItemKind::Fn(sig, gen, body) => {
10241024
self.print_fn_full(sig, item.ident, gen, &item.vis, body.as_deref(), &item.attrs);
10251025
}
1026-
ast::ForeignItemKind::Static(t, m) => {
1027-
self.head(visibility_qualified(&item.vis, "static"));
1028-
if *m == ast::Mutability::Mut {
1029-
self.word_space("mut");
1030-
}
1031-
self.print_ident(item.ident);
1032-
self.word_space(":");
1033-
self.print_type(t);
1034-
self.s.word(";");
1035-
self.end(); // end the head-ibox
1036-
self.end(); // end the outer cbox
1026+
ast::ForeignItemKind::Static(ty, mutbl, body) => {
1027+
self.print_item_const(item.ident, Some(*mutbl), ty, body.as_deref(), &item.vis);
10371028
}
10381029
ast::ForeignItemKind::TyAlias(generics, bounds, ty) => {
10391030
self.print_associated_type(item.ident, generics, bounds, ty.as_deref());
@@ -1047,24 +1038,31 @@ impl<'a> State<'a> {
10471038
}
10481039
}
10491040

1050-
fn print_associated_const(
1041+
fn print_item_const(
10511042
&mut self,
10521043
ident: ast::Ident,
1044+
mutbl: Option<ast::Mutability>,
10531045
ty: &ast::Ty,
1054-
default: Option<&ast::Expr>,
1046+
body: Option<&ast::Expr>,
10551047
vis: &ast::Visibility,
10561048
) {
1057-
self.s.word(visibility_qualified(vis, ""));
1058-
self.word_space("const");
1049+
let leading = match mutbl {
1050+
None => "const ",
1051+
Some(ast::Mutability::Not) => "static ",
1052+
Some(ast::Mutability::Mut) => "static mut ",
1053+
};
1054+
self.head(visibility_qualified(vis, leading));
10591055
self.print_ident(ident);
10601056
self.word_space(":");
10611057
self.print_type(ty);
1062-
if let Some(expr) = default {
1063-
self.s.space();
1058+
self.s.space();
1059+
self.end(); // end the head-ibox
1060+
if let Some(body) = body {
10641061
self.word_space("=");
1065-
self.print_expr(expr);
1062+
self.print_expr(body);
10661063
}
1067-
self.s.word(";")
1064+
self.s.word(";");
1065+
self.end(); // end the outer cbox
10681066
}
10691067

10701068
fn print_associated_type(
@@ -1114,36 +1112,11 @@ impl<'a> State<'a> {
11141112
self.end(); // end inner head-block
11151113
self.end(); // end outer head-block
11161114
}
1117-
ast::ItemKind::Static(ref ty, m, ref expr) => {
1118-
self.head(visibility_qualified(&item.vis, "static"));
1119-
if m == ast::Mutability::Mut {
1120-
self.word_space("mut");
1121-
}
1122-
self.print_ident(item.ident);
1123-
self.word_space(":");
1124-
self.print_type(ty);
1125-
self.s.space();
1126-
self.end(); // end the head-ibox
1127-
if let Some(expr) = expr {
1128-
self.word_space("=");
1129-
self.print_expr(expr);
1130-
}
1131-
self.s.word(";");
1132-
self.end(); // end the outer cbox
1115+
ast::ItemKind::Static(ref ty, mutbl, ref body) => {
1116+
self.print_item_const(item.ident, Some(mutbl), ty, body.as_deref(), &item.vis);
11331117
}
1134-
ast::ItemKind::Const(ref ty, ref expr) => {
1135-
self.head(visibility_qualified(&item.vis, "const"));
1136-
self.print_ident(item.ident);
1137-
self.word_space(":");
1138-
self.print_type(ty);
1139-
self.s.space();
1140-
self.end(); // end the head-ibox
1141-
if let Some(expr) = expr {
1142-
self.word_space("=");
1143-
self.print_expr(expr);
1144-
}
1145-
self.s.word(";");
1146-
self.end(); // end the outer cbox
1118+
ast::ItemKind::Const(ref ty, ref body) => {
1119+
self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis);
11471120
}
11481121
ast::ItemKind::Fn(ref sig, ref gen, ref body) => {
11491122
self.print_fn_full(sig, item.ident, gen, &item.vis, body.as_deref(), &item.attrs);
@@ -1469,7 +1442,7 @@ impl<'a> State<'a> {
14691442
self.print_defaultness(item.defaultness);
14701443
match &item.kind {
14711444
ast::AssocItemKind::Const(ty, expr) => {
1472-
self.print_associated_const(item.ident, ty, expr.as_deref(), &item.vis);
1445+
self.print_item_const(item.ident, None, ty, expr.as_deref(), &item.vis);
14731446
}
14741447
ast::AssocItemKind::Fn(sig, generics, body) => {
14751448
let body = body.as_deref();

src/librustc_parse/parser/item.rs

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ impl<'a> Parser<'a> {
670670
} else if self.check_fn_front_matter() {
671671
let (ident, sig, generics, body) = self.parse_fn(at_end, &mut attrs, req_name)?;
672672
(ident, AssocItemKind::Fn(sig, generics, body))
673-
} else if self.check_keyword(kw::Const) {
673+
} else if self.eat_keyword(kw::Const) {
674674
self.parse_assoc_const()?
675675
} else if self.isnt_macro_invocation() {
676676
return Err(self.missing_assoc_item_kind_err("associated", self.prev_span));
@@ -693,11 +693,7 @@ impl<'a> Parser<'a> {
693693
/// AssocConst = "const" Ident ":" Ty "=" Expr ";"
694694
fn parse_assoc_const(&mut self) -> PResult<'a, (Ident, AssocItemKind)> {
695695
self.expect_keyword(kw::Const)?;
696-
let ident = self.parse_ident()?;
697-
self.expect(&token::Colon)?;
698-
let ty = self.parse_ty()?;
699-
let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None };
700-
self.expect_semi()?;
696+
let (ident, ty, expr) = self.parse_item_const_common(None)?;
701697
Ok((ident, AssocItemKind::Const(ty, expr)))
702698
}
703699

@@ -916,11 +912,8 @@ impl<'a> Parser<'a> {
916912
/// Assumes that the `static` keyword is already parsed.
917913
fn parse_item_foreign_static(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> {
918914
let mutbl = self.parse_mutability();
919-
let ident = self.parse_ident()?;
920-
self.expect(&token::Colon)?;
921-
let ty = self.parse_ty()?;
922-
self.expect_semi()?;
923-
Ok((ident, ForeignItemKind::Static(ty, mutbl)))
915+
let (ident, ty, expr) = self.parse_item_const_common(Some(mutbl))?;
916+
Ok((ident, ForeignItemKind::Static(ty, mutbl, expr)))
924917
}
925918

926919
/// Parses a type from a foreign module.
@@ -971,6 +964,22 @@ impl<'a> Parser<'a> {
971964
///
972965
/// When `m` is `"const"`, `$ident` may also be `"_"`.
973966
fn parse_item_const(&mut self, m: Option<Mutability>) -> PResult<'a, ItemInfo> {
967+
let (id, ty, expr) = self.parse_item_const_common(m)?;
968+
let item = match m {
969+
Some(m) => ItemKind::Static(ty, m, expr),
970+
None => ItemKind::Const(ty, expr),
971+
};
972+
Ok((id, item))
973+
}
974+
975+
/// Parse `["const" | ("static" "mut"?)] $ident ":" $ty (= $expr)?` with
976+
/// `["const" | ("static" "mut"?)]` already parsed and stored in `m`.
977+
///
978+
/// When `m` is `"const"`, `$ident` may also be `"_"`.
979+
fn parse_item_const_common(
980+
&mut self,
981+
m: Option<Mutability>,
982+
) -> PResult<'a, (Ident, P<Ty>, Option<P<ast::Expr>>)> {
974983
let id = if m.is_none() { self.parse_ident_or_underscore() } else { self.parse_ident() }?;
975984

976985
// Parse the type of a `const` or `static mut?` item.
@@ -983,11 +992,7 @@ impl<'a> Parser<'a> {
983992

984993
let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None };
985994
self.expect_semi()?;
986-
let item = match m {
987-
Some(m) => ItemKind::Static(ty, m, expr),
988-
None => ItemKind::Const(ty, expr),
989-
};
990-
Ok((id, item))
995+
Ok((id, ty, expr))
991996
}
992997

993998
/// We were supposed to parse `:` but the `:` was missing.

src/librustc_save_analysis/dump_visitor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1532,7 +1532,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
15321532
self.visit_ty(&ret_ty);
15331533
}
15341534
}
1535-
ast::ForeignItemKind::Static(ref ty, _) => {
1535+
ast::ForeignItemKind::Static(ref ty, _, _) => {
15361536
if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
15371537
down_cast_data!(var_data, DefData, item.span);
15381538
self.dumper.dump_def(&access, var_data);

src/librustc_save_analysis/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
151151
attributes: lower_attributes(item.attrs.clone(), self),
152152
}))
153153
}
154-
ast::ForeignItemKind::Static(ref ty, _) => {
154+
ast::ForeignItemKind::Static(ref ty, _, _) => {
155155
filter!(self.span_utils, item.ident.span);
156156

157157
let id = id_from_node_id(item.id, self);

src/librustc_save_analysis/sig.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,7 @@ impl Sig for ast::ForeignItem {
760760

761761
Ok(sig)
762762
}
763-
ast::ForeignItemKind::Static(ref ty, m) => {
763+
ast::ForeignItemKind::Static(ref ty, m, _) => {
764764
let mut text = "static ".to_owned();
765765
if m == ast::Mutability::Mut {
766766
text.push_str("mut ");

src/libsyntax/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2606,7 +2606,7 @@ pub type ForeignItem = Item<ForeignItemKind>;
26062606
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
26072607
pub enum ForeignItemKind {
26082608
/// A static item (`static FOO: u8`).
2609-
Static(P<Ty>, Mutability),
2609+
Static(P<Ty>, Mutability, Option<P<Expr>>),
26102610
/// A function.
26112611
Fn(FnSig, Generics, Option<P<Block>>),
26122612
/// A type.

src/libsyntax/mut_visit.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1046,7 +1046,10 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
10461046
visitor.visit_generics(generics);
10471047
visit_opt(body, |body| visitor.visit_block(body));
10481048
}
1049-
ForeignItemKind::Static(t, _m) => visitor.visit_ty(t),
1049+
ForeignItemKind::Static(ty, _, body) => {
1050+
visitor.visit_ty(ty);
1051+
visit_opt(body, |body| visitor.visit_expr(body));
1052+
}
10501053
ForeignItemKind::TyAlias(generics, bounds, ty) => {
10511054
visitor.visit_generics(generics);
10521055
visit_bounds(bounds, visitor);

src/libsyntax/visit.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,10 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI
534534
let kind = FnKind::Fn(FnCtxt::Foreign, item.ident, sig, &item.vis, body.as_deref());
535535
visitor.visit_fn(kind, item.span, item.id);
536536
}
537-
ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ),
537+
ForeignItemKind::Static(ref typ, _, ref body) => {
538+
visitor.visit_ty(typ);
539+
walk_list!(visitor, visit_expr, body);
540+
}
538541
ForeignItemKind::TyAlias(ref generics, ref bounds, ref ty) => {
539542
visitor.visit_generics(generics);
540543
walk_list!(visitor, visit_param_bound, bounds);

0 commit comments

Comments
 (0)