mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 15:23:46 +00:00
parse extern consts
This commit is contained in:
parent
f8d2264463
commit
35884fe168
@ -683,6 +683,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
let ty = self.lower_ty(t, ImplTraitContext::disallowed());
|
let ty = self.lower_ty(t, ImplTraitContext::disallowed());
|
||||||
hir::ForeignItemKind::Static(ty, m)
|
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::TyAlias(..) => hir::ForeignItemKind::Type,
|
||||||
ForeignItemKind::Macro(_) => panic!("macro shouldn't exist here"),
|
ForeignItemKind::Macro(_) => panic!("macro shouldn't exist here"),
|
||||||
},
|
},
|
||||||
|
@ -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,
|
/// Reject C-varadic type unless the function is foreign,
|
||||||
/// or free and `unsafe extern "C"` semantically.
|
/// or free and `unsafe extern "C"` semantically.
|
||||||
fn check_c_varadic_type(&self, fk: FnKind<'a>) {
|
fn check_c_varadic_type(&self, fk: FnKind<'a>) {
|
||||||
@ -989,6 +1003,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
ForeignItemKind::Static(_, _, body) => {
|
ForeignItemKind::Static(_, _, body) => {
|
||||||
self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span));
|
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(..) => {}
|
ForeignItemKind::Macro(..) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,7 +400,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||||||
ast::ForeignItemKind::TyAlias(..) => {
|
ast::ForeignItemKind::TyAlias(..) => {
|
||||||
gate_feature_post!(&self, extern_types, i.span, "extern types are experimental");
|
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)
|
visit::walk_foreign_item(self, i)
|
||||||
|
@ -1023,6 +1023,9 @@ impl<'a> State<'a> {
|
|||||||
ast::ForeignItemKind::Fn(sig, gen, body) => {
|
ast::ForeignItemKind::Fn(sig, gen, body) => {
|
||||||
self.print_fn_full(sig, item.ident, gen, &item.vis, body.as_deref(), &item.attrs);
|
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) => {
|
ast::ForeignItemKind::Static(ty, mutbl, body) => {
|
||||||
self.print_item_const(item.ident, Some(*mutbl), ty, body.as_deref(), &item.vis);
|
self.print_item_const(item.ident, Some(*mutbl), ty, body.as_deref(), &item.vis);
|
||||||
}
|
}
|
||||||
|
@ -880,19 +880,12 @@ impl<'a> Parser<'a> {
|
|||||||
} else if self.is_static_global() {
|
} else if self.is_static_global() {
|
||||||
// FOREIGN STATIC ITEM
|
// FOREIGN STATIC ITEM
|
||||||
self.bump(); // `static`
|
self.bump(); // `static`
|
||||||
self.parse_item_foreign_static()?
|
let mutbl = self.parse_mutability();
|
||||||
} else if self.token.is_keyword(kw::Const) {
|
let (ident, ty, expr) = self.parse_item_const_common(Some(mutbl))?;
|
||||||
// Treat `const` as `static` for error recovery, but don't add it to expected tokens.
|
(ident, ForeignItemKind::Static(ty, mutbl, expr))
|
||||||
self.bump(); // `const`
|
} else if self.eat_keyword(kw::Const) {
|
||||||
self.struct_span_err(self.prev_span, "extern items cannot be `const`")
|
let (ident, ty, expr) = self.parse_item_const_common(None)?;
|
||||||
.span_suggestion(
|
(ident, ForeignItemKind::Const(ty, expr))
|
||||||
self.prev_span,
|
|
||||||
"try using a static value",
|
|
||||||
"static".to_owned(),
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
self.parse_item_foreign_static()?
|
|
||||||
} else if self.isnt_macro_invocation() {
|
} else if self.isnt_macro_invocation() {
|
||||||
return Err(self.missing_assoc_item_kind_err("extern", self.prev_span));
|
return Err(self.missing_assoc_item_kind_err("extern", self.prev_span));
|
||||||
} else if self.token.is_path_start() {
|
} 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)))
|
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.
|
/// Parses a type from a foreign module.
|
||||||
fn parse_item_foreign_type(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> {
|
fn parse_item_foreign_type(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> {
|
||||||
let (ident, kind) = self.parse_assoc_ty()?;
|
let (ident, kind) = self.parse_assoc_ty()?;
|
||||||
|
@ -826,7 +826,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
|||||||
ForeignItemKind::Fn(..) => {
|
ForeignItemKind::Fn(..) => {
|
||||||
(Res::Def(DefKind::Fn, self.r.definitions.local_def_id(item.id)), ValueNS)
|
(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)
|
(Res::Def(DefKind::Static, self.r.definitions.local_def_id(item.id)), ValueNS)
|
||||||
}
|
}
|
||||||
ForeignItemKind::TyAlias(..) => {
|
ForeignItemKind::TyAlias(..) => {
|
||||||
|
@ -443,7 +443,7 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
|||||||
visit::walk_foreign_item(this, foreign_item);
|
visit::walk_foreign_item(this, foreign_item);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ForeignItemKind::Static(..) => {
|
ForeignItemKind::Const(..) | ForeignItemKind::Static(..) => {
|
||||||
self.with_item_rib(HasGenericParams::No, |this| {
|
self.with_item_rib(HasGenericParams::No, |this| {
|
||||||
visit::walk_foreign_item(this, foreign_item);
|
visit::walk_foreign_item(this, foreign_item);
|
||||||
});
|
});
|
||||||
|
@ -1534,7 +1534,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
|
|||||||
self.visit_ty(&ret_ty);
|
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) {
|
if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
|
||||||
down_cast_data!(var_data, DefData, item.span);
|
down_cast_data!(var_data, DefData, item.span);
|
||||||
self.dumper.dump_def(&access, var_data);
|
self.dumper.dump_def(&access, var_data);
|
||||||
|
@ -151,7 +151,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
|
|||||||
attributes: lower_attributes(item.attrs.clone(), self),
|
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);
|
filter!(self.span_utils, item.ident.span);
|
||||||
|
|
||||||
let id = id_from_node_id(item.id, self);
|
let id = id_from_node_id(item.id, self);
|
||||||
|
@ -792,6 +792,7 @@ impl Sig for ast::ForeignItem {
|
|||||||
|
|
||||||
Ok(Signature { text: text, defs: defs, refs: vec![] })
|
Ok(Signature { text: text, defs: defs, refs: vec![] })
|
||||||
}
|
}
|
||||||
|
ast::ForeignItemKind::Const(..) => Err("foreign const"),
|
||||||
ast::ForeignItemKind::Macro(..) => Err("macro"),
|
ast::ForeignItemKind::Macro(..) => Err("macro"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2605,6 +2605,9 @@ pub type ForeignItem = Item<ForeignItemKind>;
|
|||||||
/// An item within an `extern` block.
|
/// An item within an `extern` block.
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub enum ForeignItemKind {
|
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`).
|
/// A static item (`static FOO: u8`).
|
||||||
Static(P<Ty>, Mutability, Option<P<Expr>>),
|
Static(P<Ty>, Mutability, Option<P<Expr>>),
|
||||||
/// A function.
|
/// A function.
|
||||||
@ -2619,6 +2622,7 @@ impl ForeignItemKind {
|
|||||||
pub fn descriptive_variant(&self) -> &str {
|
pub fn descriptive_variant(&self) -> &str {
|
||||||
match *self {
|
match *self {
|
||||||
ForeignItemKind::Fn(..) => "foreign function",
|
ForeignItemKind::Fn(..) => "foreign function",
|
||||||
|
ForeignItemKind::Const(..) => "foreign const item",
|
||||||
ForeignItemKind::Static(..) => "foreign static item",
|
ForeignItemKind::Static(..) => "foreign static item",
|
||||||
ForeignItemKind::TyAlias(..) => "foreign type",
|
ForeignItemKind::TyAlias(..) => "foreign type",
|
||||||
ForeignItemKind::Macro(..) => "macro in foreign module",
|
ForeignItemKind::Macro(..) => "macro in foreign module",
|
||||||
|
@ -1046,7 +1046,7 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
|
|||||||
visitor.visit_generics(generics);
|
visitor.visit_generics(generics);
|
||||||
visit_opt(body, |body| visitor.visit_block(body));
|
visit_opt(body, |body| visitor.visit_block(body));
|
||||||
}
|
}
|
||||||
ForeignItemKind::Static(ty, _, body) => {
|
ForeignItemKind::Const(ty, body) | ForeignItemKind::Static(ty, _, body) => {
|
||||||
visitor.visit_ty(ty);
|
visitor.visit_ty(ty);
|
||||||
visit_opt(body, |body| visitor.visit_expr(body));
|
visit_opt(body, |body| visitor.visit_expr(body));
|
||||||
}
|
}
|
||||||
|
@ -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());
|
let kind = FnKind::Fn(FnCtxt::Foreign, item.ident, sig, &item.vis, body.as_deref());
|
||||||
visitor.visit_fn(kind, item.span, item.id);
|
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);
|
visitor.visit_ty(typ);
|
||||||
walk_list!(visitor, visit_expr, body);
|
walk_list!(visitor, visit_expr, body);
|
||||||
}
|
}
|
||||||
|
10
src/test/ui/extern/extern-const.stderr
vendored
10
src/test/ui/extern/extern-const.stderr
vendored
@ -1,8 +1,14 @@
|
|||||||
error: extern items cannot be `const`
|
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;
|
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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
8
src/test/ui/parser/foreign-const-semantic-fail.rs
Normal file
8
src/test/ui/parser/foreign-const-semantic-fail.rs
Normal file
@ -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`
|
||||||
|
}
|
27
src/test/ui/parser/foreign-const-semantic-fail.stderr
Normal file
27
src/test/ui/parser/foreign-const-semantic-fail.stderr
Normal file
@ -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
|
||||||
|
|
11
src/test/ui/parser/foreign-const-syntactic-pass.rs
Normal file
11
src/test/ui/parser/foreign-const-syntactic-pass.rs
Normal file
@ -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;
|
||||||
|
}
|
@ -1,6 +0,0 @@
|
|||||||
extern {
|
|
||||||
const i: isize;
|
|
||||||
//~^ ERROR extern items cannot be `const`
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
@ -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
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user