diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2020-02-15 02:23:10 +0100 |
|---|---|---|
| committer | Mazdak Farrokhzad <twingoow@gmail.com> | 2020-02-15 20:57:12 +0100 |
| commit | 35884fe16889b39d4be43cf8effc3bdf843c6f12 (patch) | |
| tree | c9d96a9b030337918d88626ee48bb3c7bebb3060 | |
| parent | f8d2264463162291f5cb3391c98d7bc95ec17d87 (diff) | |
| download | rust-35884fe16889b39d4be43cf8effc3bdf843c6f12.tar.gz rust-35884fe16889b39d4be43cf8effc3bdf843c6f12.zip | |
parse extern consts
| -rw-r--r-- | src/librustc_ast_lowering/item.rs | 5 | ||||
| -rw-r--r-- | src/librustc_ast_passes/ast_validation.rs | 17 | ||||
| -rw-r--r-- | src/librustc_ast_passes/feature_gate.rs | 2 | ||||
| -rw-r--r-- | src/librustc_ast_pretty/pprust.rs | 3 | ||||
| -rw-r--r-- | src/librustc_parse/parser/item.rs | 27 | ||||
| -rw-r--r-- | src/librustc_resolve/build_reduced_graph.rs | 2 | ||||
| -rw-r--r-- | src/librustc_resolve/late.rs | 2 | ||||
| -rw-r--r-- | src/librustc_save_analysis/dump_visitor.rs | 2 | ||||
| -rw-r--r-- | src/librustc_save_analysis/lib.rs | 2 | ||||
| -rw-r--r-- | src/librustc_save_analysis/sig.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/ast.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/mut_visit.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 3 | ||||
| -rw-r--r-- | src/test/ui/extern/extern-const.stderr | 10 | ||||
| -rw-r--r-- | src/test/ui/parser/foreign-const-semantic-fail.rs | 8 | ||||
| -rw-r--r-- | src/test/ui/parser/foreign-const-semantic-fail.stderr | 27 | ||||
| -rw-r--r-- | src/test/ui/parser/foreign-const-syntactic-pass.rs | 11 | ||||
| -rw-r--r-- | src/test/ui/parser/removed-syntax-extern-const.rs | 6 | ||||
| -rw-r--r-- | src/test/ui/parser/removed-syntax-extern-const.stderr | 8 |
19 files changed, 98 insertions, 44 deletions
diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index b465fd79c8f..e0db8606bc2 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -683,6 +683,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let ty = self.lower_ty(t, ImplTraitContext::disallowed()); hir::ForeignItemKind::Static(ty, m) } + ForeignItemKind::Const(ref t, _) => { + // For recovery purposes. + let ty = self.lower_ty(t, ImplTraitContext::disallowed()); + hir::ForeignItemKind::Static(ty, Mutability::Not) + } ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, ForeignItemKind::Macro(_) => panic!("macro shouldn't exist here"), }, diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 72cffdd750a..8efd50ad098 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -533,6 +533,20 @@ impl<'a> AstValidator<'a> { } } + fn error_foreign_const(&self, ident: Ident, span: Span) { + self.err_handler() + .struct_span_err(ident.span, "extern items cannot be `const`") + .span_suggestion( + span.with_hi(ident.span.lo()), + "try using a static value", + "static ".to_string(), + Applicability::MachineApplicable, + ) + .span_label(self.current_extern_span(), "in this `extern` block") + .note(MORE_EXTERN) + .emit(); + } + /// Reject C-varadic type unless the function is foreign, /// or free and `unsafe extern "C"` semantically. fn check_c_varadic_type(&self, fk: FnKind<'a>) { @@ -989,6 +1003,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ForeignItemKind::Static(_, _, body) => { self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span)); } + ForeignItemKind::Const(..) => { + self.error_foreign_const(fi.ident, fi.span); + } ForeignItemKind::Macro(..) => {} } diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index c543f7095b9..d4de2c93758 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -400,7 +400,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ForeignItemKind::TyAlias(..) => { gate_feature_post!(&self, extern_types, i.span, "extern types are experimental"); } - ast::ForeignItemKind::Macro(..) => {} + ast::ForeignItemKind::Macro(..) | ast::ForeignItemKind::Const(..) => {} } visit::walk_foreign_item(self, i) diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index ee1a829da1a..410600e4957 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -1023,6 +1023,9 @@ impl<'a> State<'a> { ast::ForeignItemKind::Fn(sig, gen, body) => { self.print_fn_full(sig, item.ident, gen, &item.vis, body.as_deref(), &item.attrs); } + ast::ForeignItemKind::Const(ty, body) => { + self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis); + } ast::ForeignItemKind::Static(ty, mutbl, body) => { self.print_item_const(item.ident, Some(*mutbl), ty, body.as_deref(), &item.vis); } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 9b7728f27d0..5fcd72090ec 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -880,19 +880,12 @@ impl<'a> Parser<'a> { } else if self.is_static_global() { // FOREIGN STATIC ITEM self.bump(); // `static` - 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` - self.struct_span_err(self.prev_span, "extern items cannot be `const`") - .span_suggestion( - self.prev_span, - "try using a static value", - "static".to_owned(), - Applicability::MachineApplicable, - ) - .emit(); - self.parse_item_foreign_static()? + let mutbl = self.parse_mutability(); + let (ident, ty, expr) = self.parse_item_const_common(Some(mutbl))?; + (ident, ForeignItemKind::Static(ty, mutbl, expr)) + } else if self.eat_keyword(kw::Const) { + let (ident, ty, expr) = self.parse_item_const_common(None)?; + (ident, ForeignItemKind::Const(ty, expr)) } 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() { @@ -906,14 +899,6 @@ impl<'a> Parser<'a> { 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) -> PResult<'a, (Ident, ForeignItemKind)> { - let mutbl = self.parse_mutability(); - let (ident, ty, expr) = self.parse_item_const_common(Some(mutbl))?; - Ok((ident, ForeignItemKind::Static(ty, mutbl, expr))) - } - /// Parses a type from a foreign module. fn parse_item_foreign_type(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> { let (ident, kind) = self.parse_assoc_ty()?; diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 7c541928e6f..1f622b80e8e 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -826,7 +826,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { ForeignItemKind::Fn(..) => { (Res::Def(DefKind::Fn, self.r.definitions.local_def_id(item.id)), ValueNS) } - ForeignItemKind::Static(..) => { + ForeignItemKind::Static(..) | ForeignItemKind::Const(..) => { (Res::Def(DefKind::Static, self.r.definitions.local_def_id(item.id)), ValueNS) } ForeignItemKind::TyAlias(..) => { diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 7b445fcc035..68559c0446a 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -443,7 +443,7 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { visit::walk_foreign_item(this, foreign_item); }); } - ForeignItemKind::Static(..) => { + ForeignItemKind::Const(..) | ForeignItemKind::Static(..) => { self.with_item_rib(HasGenericParams::No, |this| { visit::walk_foreign_item(this, foreign_item); }); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 001f2f09854..6a3abf4fbf5 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1534,7 +1534,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { self.visit_ty(&ret_ty); } } - ast::ForeignItemKind::Static(ref ty, _, _) => { + ast::ForeignItemKind::Const(ref ty, _) | ast::ForeignItemKind::Static(ref ty, _, _) => { if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) { down_cast_data!(var_data, DefData, item.span); self.dumper.dump_def(&access, var_data); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 6bb2bf4c1e9..d244370ae2c 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -151,7 +151,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { attributes: lower_attributes(item.attrs.clone(), self), })) } - ast::ForeignItemKind::Static(ref ty, _, _) => { + ast::ForeignItemKind::Const(ref ty, _) | ast::ForeignItemKind::Static(ref ty, _, _) => { filter!(self.span_utils, item.ident.span); let id = id_from_node_id(item.id, self); diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 8fba3109f21..3c68124ad40 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -792,6 +792,7 @@ impl Sig for ast::ForeignItem { Ok(Signature { text: text, defs: defs, refs: vec![] }) } + ast::ForeignItemKind::Const(..) => Err("foreign const"), ast::ForeignItemKind::Macro(..) => Err("macro"), } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index ca39fbd6c5d..5041d43b16c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2605,6 +2605,9 @@ pub type ForeignItem = Item<ForeignItemKind>; /// An item within an `extern` block. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum ForeignItemKind { + /// A constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`. + /// If `def` is parsed, then the constant is provided, and otherwise required. + Const(P<Ty>, Option<P<Expr>>), /// A static item (`static FOO: u8`). Static(P<Ty>, Mutability, Option<P<Expr>>), /// A function. @@ -2619,6 +2622,7 @@ impl ForeignItemKind { pub fn descriptive_variant(&self) -> &str { match *self { ForeignItemKind::Fn(..) => "foreign function", + ForeignItemKind::Const(..) => "foreign const item", ForeignItemKind::Static(..) => "foreign static item", ForeignItemKind::TyAlias(..) => "foreign type", ForeignItemKind::Macro(..) => "macro in foreign module", diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 91db6158689..ffc42340dba 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -1046,7 +1046,7 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>( visitor.visit_generics(generics); visit_opt(body, |body| visitor.visit_block(body)); } - ForeignItemKind::Static(ty, _, body) => { + ForeignItemKind::Const(ty, body) | ForeignItemKind::Static(ty, _, body) => { visitor.visit_ty(ty); visit_opt(body, |body| visitor.visit_expr(body)); } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index f5763ecf573..5a21eb55528 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -534,7 +534,8 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI let kind = FnKind::Fn(FnCtxt::Foreign, item.ident, sig, &item.vis, body.as_deref()); visitor.visit_fn(kind, item.span, item.id); } - ForeignItemKind::Static(ref typ, _, ref body) => { + ForeignItemKind::Const(ref typ, ref body) + | ForeignItemKind::Static(ref typ, _, ref body) => { visitor.visit_ty(typ); walk_list!(visitor, visit_expr, body); } diff --git a/src/test/ui/extern/extern-const.stderr b/src/test/ui/extern/extern-const.stderr index 258202b6903..97e11381c6f 100644 --- a/src/test/ui/extern/extern-const.stderr +++ b/src/test/ui/extern/extern-const.stderr @@ -1,8 +1,14 @@ error: extern items cannot be `const` - --> $DIR/extern-const.rs:16:5 + --> $DIR/extern-const.rs:16:11 | +LL | extern "C" { + | ---------- in this `extern` block LL | const rust_dbg_static_mut: libc::c_int; - | ^^^^^ help: try using a static value: `static` + | ------^^^^^^^^^^^^^^^^^^^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html error: aborting due to previous error diff --git a/src/test/ui/parser/foreign-const-semantic-fail.rs b/src/test/ui/parser/foreign-const-semantic-fail.rs new file mode 100644 index 00000000000..d28b6414282 --- /dev/null +++ b/src/test/ui/parser/foreign-const-semantic-fail.rs @@ -0,0 +1,8 @@ +fn main() {} + +extern { + const A: isize; + //~^ ERROR extern items cannot be `const` + const B: isize = 42; + //~^ ERROR extern items cannot be `const` +} diff --git a/src/test/ui/parser/foreign-const-semantic-fail.stderr b/src/test/ui/parser/foreign-const-semantic-fail.stderr new file mode 100644 index 00000000000..799a795c593 --- /dev/null +++ b/src/test/ui/parser/foreign-const-semantic-fail.stderr @@ -0,0 +1,27 @@ +error: extern items cannot be `const` + --> $DIR/foreign-const-semantic-fail.rs:4:11 + | +LL | extern { + | ------ in this `extern` block +LL | const A: isize; + | ------^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: extern items cannot be `const` + --> $DIR/foreign-const-semantic-fail.rs:6:11 + | +LL | extern { + | ------ in this `extern` block +... +LL | const B: isize = 42; + | ------^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/parser/foreign-const-syntactic-pass.rs b/src/test/ui/parser/foreign-const-syntactic-pass.rs new file mode 100644 index 00000000000..bacef8e71d6 --- /dev/null +++ b/src/test/ui/parser/foreign-const-syntactic-pass.rs @@ -0,0 +1,11 @@ +// Syntactically, a `const` item inside an `extern { ... }` block is allowed. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +extern { + const A: isize; + const B: isize = 42; +} diff --git a/src/test/ui/parser/removed-syntax-extern-const.rs b/src/test/ui/parser/removed-syntax-extern-const.rs deleted file mode 100644 index 71c22e62f8e..00000000000 --- a/src/test/ui/parser/removed-syntax-extern-const.rs +++ /dev/null @@ -1,6 +0,0 @@ -extern { - const i: isize; - //~^ ERROR extern items cannot be `const` -} - -fn main() {} diff --git a/src/test/ui/parser/removed-syntax-extern-const.stderr b/src/test/ui/parser/removed-syntax-extern-const.stderr deleted file mode 100644 index 2bccbd91452..00000000000 --- a/src/test/ui/parser/removed-syntax-extern-const.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: extern items cannot be `const` - --> $DIR/removed-syntax-extern-const.rs:2:5 - | -LL | const i: isize; - | ^^^^^ help: try using a static value: `static` - -error: aborting due to previous error - |
