ast/parser: fuse static
& const
grammars in all contexts.
This commit is contained in:
parent
f3e9763543
commit
1c2906ead3
18 changed files with 205 additions and 125 deletions
|
@ -679,7 +679,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
|
|
||||||
hir::ForeignItemKind::Fn(fn_dec, fn_args, generics)
|
hir::ForeignItemKind::Fn(fn_dec, fn_args, generics)
|
||||||
}
|
}
|
||||||
ForeignItemKind::Static(ref t, m) => {
|
ForeignItemKind::Static(ref t, m, _) => {
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -464,19 +464,22 @@ impl<'a> AstValidator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_foreign_ty_bodyless(&self, ident: Ident, body: Option<&Ty>) {
|
fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body: Option<Span>) {
|
||||||
let body = match body {
|
let body = match body {
|
||||||
None => return,
|
None => return,
|
||||||
Some(body) => body,
|
Some(body) => body,
|
||||||
};
|
};
|
||||||
self.err_handler()
|
self.err_handler()
|
||||||
.struct_span_err(ident.span, "incorrect `type` inside `extern` block")
|
.struct_span_err(ident.span, &format!("incorrect `{}` inside `extern` block", kind))
|
||||||
.span_label(ident.span, "cannot have a body")
|
.span_label(ident.span, "cannot have a body")
|
||||||
.span_label(body.span, "the invalid body")
|
.span_label(body, "the invalid body")
|
||||||
.span_label(
|
.span_label(
|
||||||
self.current_extern_span(),
|
self.current_extern_span(),
|
||||||
"`extern` blocks define existing foreign types and types \
|
format!(
|
||||||
inside of them cannot have a body",
|
"`extern` blocks define existing foreign {0}s and {0}s \
|
||||||
|
inside of them cannot have a body",
|
||||||
|
kind
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.note(MORE_EXTERN)
|
.note(MORE_EXTERN)
|
||||||
.emit();
|
.emit();
|
||||||
|
@ -579,6 +582,16 @@ impl<'a> AstValidator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_item_named(&self, ident: Ident, kind: &str) {
|
||||||
|
if ident.name != kw::Underscore {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.err_handler()
|
||||||
|
.struct_span_err(ident.span, &format!("`{}` items in this context need a name", kind))
|
||||||
|
.span_label(ident.span, format!("`_` is not a valid name for this `{}` item", kind))
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum GenericPosition {
|
enum GenericPosition {
|
||||||
|
@ -969,11 +982,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
|
self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
|
||||||
}
|
}
|
||||||
ForeignItemKind::TyAlias(generics, bounds, body) => {
|
ForeignItemKind::TyAlias(generics, bounds, body) => {
|
||||||
self.check_foreign_ty_bodyless(fi.ident, body.as_deref());
|
self.check_foreign_kind_bodyless(fi.ident, "type", body.as_ref().map(|b| b.span));
|
||||||
self.check_type_no_bounds(bounds, "`extern` blocks");
|
self.check_type_no_bounds(bounds, "`extern` blocks");
|
||||||
self.check_foreign_ty_genericless(generics);
|
self.check_foreign_ty_genericless(generics);
|
||||||
}
|
}
|
||||||
ForeignItemKind::Static(..) | ForeignItemKind::Macro(..) => {}
|
ForeignItemKind::Static(_, _, body) => {
|
||||||
|
self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span));
|
||||||
|
}
|
||||||
|
ForeignItemKind::Macro(..) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
visit::walk_foreign_item(self, fi)
|
visit::walk_foreign_item(self, fi)
|
||||||
|
@ -1234,6 +1250,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let AssocItemKind::Const(..) = item.kind {
|
||||||
|
self.check_item_named(item.ident, "const");
|
||||||
|
}
|
||||||
|
|
||||||
self.with_in_trait_impl(false, |this| visit::walk_assoc_item(this, item, ctxt));
|
self.with_in_trait_impl(false, |this| visit::walk_assoc_item(this, item, ctxt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1023,17 +1023,8 @@ 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::Static(t, m) => {
|
ast::ForeignItemKind::Static(ty, mutbl, body) => {
|
||||||
self.head(visibility_qualified(&item.vis, "static"));
|
self.print_item_const(item.ident, Some(*mutbl), ty, body.as_deref(), &item.vis);
|
||||||
if *m == ast::Mutability::Mut {
|
|
||||||
self.word_space("mut");
|
|
||||||
}
|
|
||||||
self.print_ident(item.ident);
|
|
||||||
self.word_space(":");
|
|
||||||
self.print_type(t);
|
|
||||||
self.s.word(";");
|
|
||||||
self.end(); // end the head-ibox
|
|
||||||
self.end(); // end the outer cbox
|
|
||||||
}
|
}
|
||||||
ast::ForeignItemKind::TyAlias(generics, bounds, ty) => {
|
ast::ForeignItemKind::TyAlias(generics, bounds, ty) => {
|
||||||
self.print_associated_type(item.ident, generics, bounds, ty.as_deref());
|
self.print_associated_type(item.ident, generics, bounds, ty.as_deref());
|
||||||
|
@ -1047,24 +1038,31 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_associated_const(
|
fn print_item_const(
|
||||||
&mut self,
|
&mut self,
|
||||||
ident: ast::Ident,
|
ident: ast::Ident,
|
||||||
|
mutbl: Option<ast::Mutability>,
|
||||||
ty: &ast::Ty,
|
ty: &ast::Ty,
|
||||||
default: Option<&ast::Expr>,
|
body: Option<&ast::Expr>,
|
||||||
vis: &ast::Visibility,
|
vis: &ast::Visibility,
|
||||||
) {
|
) {
|
||||||
self.s.word(visibility_qualified(vis, ""));
|
let leading = match mutbl {
|
||||||
self.word_space("const");
|
None => "const ",
|
||||||
|
Some(ast::Mutability::Not) => "static ",
|
||||||
|
Some(ast::Mutability::Mut) => "static mut ",
|
||||||
|
};
|
||||||
|
self.head(visibility_qualified(vis, leading));
|
||||||
self.print_ident(ident);
|
self.print_ident(ident);
|
||||||
self.word_space(":");
|
self.word_space(":");
|
||||||
self.print_type(ty);
|
self.print_type(ty);
|
||||||
if let Some(expr) = default {
|
self.s.space();
|
||||||
self.s.space();
|
self.end(); // end the head-ibox
|
||||||
|
if let Some(body) = body {
|
||||||
self.word_space("=");
|
self.word_space("=");
|
||||||
self.print_expr(expr);
|
self.print_expr(body);
|
||||||
}
|
}
|
||||||
self.s.word(";")
|
self.s.word(";");
|
||||||
|
self.end(); // end the outer cbox
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_associated_type(
|
fn print_associated_type(
|
||||||
|
@ -1114,36 +1112,11 @@ impl<'a> State<'a> {
|
||||||
self.end(); // end inner head-block
|
self.end(); // end inner head-block
|
||||||
self.end(); // end outer head-block
|
self.end(); // end outer head-block
|
||||||
}
|
}
|
||||||
ast::ItemKind::Static(ref ty, m, ref expr) => {
|
ast::ItemKind::Static(ref ty, mutbl, ref body) => {
|
||||||
self.head(visibility_qualified(&item.vis, "static"));
|
self.print_item_const(item.ident, Some(mutbl), ty, body.as_deref(), &item.vis);
|
||||||
if m == ast::Mutability::Mut {
|
|
||||||
self.word_space("mut");
|
|
||||||
}
|
|
||||||
self.print_ident(item.ident);
|
|
||||||
self.word_space(":");
|
|
||||||
self.print_type(ty);
|
|
||||||
self.s.space();
|
|
||||||
self.end(); // end the head-ibox
|
|
||||||
if let Some(expr) = expr {
|
|
||||||
self.word_space("=");
|
|
||||||
self.print_expr(expr);
|
|
||||||
}
|
|
||||||
self.s.word(";");
|
|
||||||
self.end(); // end the outer cbox
|
|
||||||
}
|
}
|
||||||
ast::ItemKind::Const(ref ty, ref expr) => {
|
ast::ItemKind::Const(ref ty, ref body) => {
|
||||||
self.head(visibility_qualified(&item.vis, "const"));
|
self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis);
|
||||||
self.print_ident(item.ident);
|
|
||||||
self.word_space(":");
|
|
||||||
self.print_type(ty);
|
|
||||||
self.s.space();
|
|
||||||
self.end(); // end the head-ibox
|
|
||||||
if let Some(expr) = expr {
|
|
||||||
self.word_space("=");
|
|
||||||
self.print_expr(expr);
|
|
||||||
}
|
|
||||||
self.s.word(";");
|
|
||||||
self.end(); // end the outer cbox
|
|
||||||
}
|
}
|
||||||
ast::ItemKind::Fn(ref sig, ref gen, ref body) => {
|
ast::ItemKind::Fn(ref sig, ref gen, ref 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);
|
||||||
|
@ -1469,7 +1442,7 @@ impl<'a> State<'a> {
|
||||||
self.print_defaultness(item.defaultness);
|
self.print_defaultness(item.defaultness);
|
||||||
match &item.kind {
|
match &item.kind {
|
||||||
ast::AssocItemKind::Const(ty, expr) => {
|
ast::AssocItemKind::Const(ty, expr) => {
|
||||||
self.print_associated_const(item.ident, ty, expr.as_deref(), &item.vis);
|
self.print_item_const(item.ident, None, ty, expr.as_deref(), &item.vis);
|
||||||
}
|
}
|
||||||
ast::AssocItemKind::Fn(sig, generics, body) => {
|
ast::AssocItemKind::Fn(sig, generics, body) => {
|
||||||
let body = body.as_deref();
|
let body = body.as_deref();
|
||||||
|
|
|
@ -670,7 +670,7 @@ impl<'a> Parser<'a> {
|
||||||
} else if self.check_fn_front_matter() {
|
} else if self.check_fn_front_matter() {
|
||||||
let (ident, sig, generics, body) = self.parse_fn(at_end, &mut attrs, req_name)?;
|
let (ident, sig, generics, body) = self.parse_fn(at_end, &mut attrs, req_name)?;
|
||||||
(ident, AssocItemKind::Fn(sig, generics, body))
|
(ident, AssocItemKind::Fn(sig, generics, body))
|
||||||
} else if self.check_keyword(kw::Const) {
|
} else if self.eat_keyword(kw::Const) {
|
||||||
self.parse_assoc_const()?
|
self.parse_assoc_const()?
|
||||||
} else if self.isnt_macro_invocation() {
|
} else if self.isnt_macro_invocation() {
|
||||||
return Err(self.missing_assoc_item_kind_err("associated", self.prev_span));
|
return Err(self.missing_assoc_item_kind_err("associated", self.prev_span));
|
||||||
|
@ -693,11 +693,7 @@ impl<'a> Parser<'a> {
|
||||||
/// AssocConst = "const" Ident ":" Ty "=" Expr ";"
|
/// AssocConst = "const" Ident ":" Ty "=" Expr ";"
|
||||||
fn parse_assoc_const(&mut self) -> PResult<'a, (Ident, AssocItemKind)> {
|
fn parse_assoc_const(&mut self) -> PResult<'a, (Ident, AssocItemKind)> {
|
||||||
self.expect_keyword(kw::Const)?;
|
self.expect_keyword(kw::Const)?;
|
||||||
let ident = self.parse_ident()?;
|
let (ident, ty, expr) = self.parse_item_const_common(None)?;
|
||||||
self.expect(&token::Colon)?;
|
|
||||||
let ty = self.parse_ty()?;
|
|
||||||
let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None };
|
|
||||||
self.expect_semi()?;
|
|
||||||
Ok((ident, AssocItemKind::Const(ty, expr)))
|
Ok((ident, AssocItemKind::Const(ty, expr)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -916,11 +912,8 @@ impl<'a> Parser<'a> {
|
||||||
/// Assumes that the `static` keyword is already parsed.
|
/// Assumes that the `static` keyword is already parsed.
|
||||||
fn parse_item_foreign_static(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> {
|
fn parse_item_foreign_static(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> {
|
||||||
let mutbl = self.parse_mutability();
|
let mutbl = self.parse_mutability();
|
||||||
let ident = self.parse_ident()?;
|
let (ident, ty, expr) = self.parse_item_const_common(Some(mutbl))?;
|
||||||
self.expect(&token::Colon)?;
|
Ok((ident, ForeignItemKind::Static(ty, mutbl, expr)))
|
||||||
let ty = self.parse_ty()?;
|
|
||||||
self.expect_semi()?;
|
|
||||||
Ok((ident, ForeignItemKind::Static(ty, mutbl)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a type from a foreign module.
|
/// Parses a type from a foreign module.
|
||||||
|
@ -971,6 +964,22 @@ impl<'a> Parser<'a> {
|
||||||
///
|
///
|
||||||
/// When `m` is `"const"`, `$ident` may also be `"_"`.
|
/// When `m` is `"const"`, `$ident` may also be `"_"`.
|
||||||
fn parse_item_const(&mut self, m: Option<Mutability>) -> PResult<'a, ItemInfo> {
|
fn parse_item_const(&mut self, m: Option<Mutability>) -> PResult<'a, ItemInfo> {
|
||||||
|
let (id, ty, expr) = self.parse_item_const_common(m)?;
|
||||||
|
let item = match m {
|
||||||
|
Some(m) => ItemKind::Static(ty, m, expr),
|
||||||
|
None => ItemKind::Const(ty, expr),
|
||||||
|
};
|
||||||
|
Ok((id, item))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse `["const" | ("static" "mut"?)] $ident ":" $ty (= $expr)?` with
|
||||||
|
/// `["const" | ("static" "mut"?)]` already parsed and stored in `m`.
|
||||||
|
///
|
||||||
|
/// When `m` is `"const"`, `$ident` may also be `"_"`.
|
||||||
|
fn parse_item_const_common(
|
||||||
|
&mut self,
|
||||||
|
m: Option<Mutability>,
|
||||||
|
) -> PResult<'a, (Ident, P<Ty>, Option<P<ast::Expr>>)> {
|
||||||
let id = if m.is_none() { self.parse_ident_or_underscore() } else { self.parse_ident() }?;
|
let id = if m.is_none() { self.parse_ident_or_underscore() } else { self.parse_ident() }?;
|
||||||
|
|
||||||
// Parse the type of a `const` or `static mut?` item.
|
// Parse the type of a `const` or `static mut?` item.
|
||||||
|
@ -983,11 +992,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None };
|
let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None };
|
||||||
self.expect_semi()?;
|
self.expect_semi()?;
|
||||||
let item = match m {
|
Ok((id, ty, expr))
|
||||||
Some(m) => ItemKind::Static(ty, m, expr),
|
|
||||||
None => ItemKind::Const(ty, expr),
|
|
||||||
};
|
|
||||||
Ok((id, item))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// We were supposed to parse `:` but the `:` was missing.
|
/// We were supposed to parse `:` but the `:` was missing.
|
||||||
|
|
|
@ -1532,7 +1532,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::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::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);
|
||||||
|
|
|
@ -760,7 +760,7 @@ impl Sig for ast::ForeignItem {
|
||||||
|
|
||||||
Ok(sig)
|
Ok(sig)
|
||||||
}
|
}
|
||||||
ast::ForeignItemKind::Static(ref ty, m) => {
|
ast::ForeignItemKind::Static(ref ty, m, _) => {
|
||||||
let mut text = "static ".to_owned();
|
let mut text = "static ".to_owned();
|
||||||
if m == ast::Mutability::Mut {
|
if m == ast::Mutability::Mut {
|
||||||
text.push_str("mut ");
|
text.push_str("mut ");
|
||||||
|
|
|
@ -2606,7 +2606,7 @@ pub type ForeignItem = Item<ForeignItemKind>;
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub enum ForeignItemKind {
|
pub enum ForeignItemKind {
|
||||||
/// A static item (`static FOO: u8`).
|
/// A static item (`static FOO: u8`).
|
||||||
Static(P<Ty>, Mutability),
|
Static(P<Ty>, Mutability, Option<P<Expr>>),
|
||||||
/// A function.
|
/// A function.
|
||||||
Fn(FnSig, Generics, Option<P<Block>>),
|
Fn(FnSig, Generics, Option<P<Block>>),
|
||||||
/// A type.
|
/// A type.
|
||||||
|
|
|
@ -1046,7 +1046,10 @@ 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(t, _m) => visitor.visit_ty(t),
|
ForeignItemKind::Static(ty, _, body) => {
|
||||||
|
visitor.visit_ty(ty);
|
||||||
|
visit_opt(body, |body| visitor.visit_expr(body));
|
||||||
|
}
|
||||||
ForeignItemKind::TyAlias(generics, bounds, ty) => {
|
ForeignItemKind::TyAlias(generics, bounds, ty) => {
|
||||||
visitor.visit_generics(generics);
|
visitor.visit_generics(generics);
|
||||||
visit_bounds(bounds, visitor);
|
visit_bounds(bounds, visitor);
|
||||||
|
|
|
@ -534,7 +534,10 @@ 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, _) => visitor.visit_ty(typ),
|
ForeignItemKind::Static(ref typ, _, ref body) => {
|
||||||
|
visitor.visit_ty(typ);
|
||||||
|
walk_list!(visitor, visit_expr, body);
|
||||||
|
}
|
||||||
ForeignItemKind::TyAlias(ref generics, ref bounds, ref ty) => {
|
ForeignItemKind::TyAlias(ref generics, ref bounds, ref ty) => {
|
||||||
visitor.visit_generics(generics);
|
visitor.visit_generics(generics);
|
||||||
walk_list!(visitor, visit_param_bound, bounds);
|
walk_list!(visitor, visit_param_bound, bounds);
|
||||||
|
|
17
src/test/ui/parser/assoc-const-underscore-semantic-fail.rs
Normal file
17
src/test/ui/parser/assoc-const-underscore-semantic-fail.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// Semantically, an associated constant cannot use `_` as a name.
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
|
||||||
|
const _: () = {
|
||||||
|
pub trait A {
|
||||||
|
const _: () = (); //~ ERROR `const` items in this context need a name
|
||||||
|
}
|
||||||
|
impl A for () {
|
||||||
|
const _: () = (); //~ ERROR `const` items in this context need a name
|
||||||
|
//~^ ERROR const `_` is not a member of trait `A`
|
||||||
|
}
|
||||||
|
struct B;
|
||||||
|
impl B {
|
||||||
|
const _: () = (); //~ ERROR `const` items in this context need a name
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,27 @@
|
||||||
|
error: `const` items in this context need a name
|
||||||
|
--> $DIR/assoc-const-underscore-semantic-fail.rs:7:15
|
||||||
|
|
|
||||||
|
LL | const _: () = ();
|
||||||
|
| ^ `_` is not a valid name for this `const` item
|
||||||
|
|
||||||
|
error: `const` items in this context need a name
|
||||||
|
--> $DIR/assoc-const-underscore-semantic-fail.rs:10:15
|
||||||
|
|
|
||||||
|
LL | const _: () = ();
|
||||||
|
| ^ `_` is not a valid name for this `const` item
|
||||||
|
|
||||||
|
error: `const` items in this context need a name
|
||||||
|
--> $DIR/assoc-const-underscore-semantic-fail.rs:15:15
|
||||||
|
|
|
||||||
|
LL | const _: () = ();
|
||||||
|
| ^ `_` is not a valid name for this `const` item
|
||||||
|
|
||||||
|
error[E0438]: const `_` is not a member of trait `A`
|
||||||
|
--> $DIR/assoc-const-underscore-semantic-fail.rs:10:9
|
||||||
|
|
|
||||||
|
LL | const _: () = ();
|
||||||
|
| ^^^^^^^^^^^^^^^^^ not a member of trait `A`
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0438`.
|
18
src/test/ui/parser/assoc-const-underscore-syntactic-pass.rs
Normal file
18
src/test/ui/parser/assoc-const-underscore-syntactic-pass.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// All constant items (associated or otherwise) may syntactically use `_` as a name.
|
||||||
|
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
|
||||||
|
#[cfg(FALSE)]
|
||||||
|
const _: () = {
|
||||||
|
pub trait A {
|
||||||
|
const _: () = ();
|
||||||
|
}
|
||||||
|
impl A for () {
|
||||||
|
const _: () = ();
|
||||||
|
}
|
||||||
|
impl dyn A {
|
||||||
|
const _: () = ();
|
||||||
|
}
|
||||||
|
};
|
8
src/test/ui/parser/foreign-static-semantic-fail.rs
Normal file
8
src/test/ui/parser/foreign-static-semantic-fail.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
// Syntactically, a foreign static may not have a body.
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
|
||||||
|
extern {
|
||||||
|
static X: u8 = 0; //~ ERROR incorrect `static` inside `extern` block
|
||||||
|
static mut Y: u8 = 0; //~ ERROR incorrect `static` inside `extern` block
|
||||||
|
}
|
27
src/test/ui/parser/foreign-static-semantic-fail.stderr
Normal file
27
src/test/ui/parser/foreign-static-semantic-fail.stderr
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
error: incorrect `static` inside `extern` block
|
||||||
|
--> $DIR/foreign-static-semantic-fail.rs:6:12
|
||||||
|
|
|
||||||
|
LL | extern {
|
||||||
|
| ------ `extern` blocks define existing foreign statics and statics inside of them cannot have a body
|
||||||
|
LL | static X: u8 = 0;
|
||||||
|
| ^ - the invalid body
|
||||||
|
| |
|
||||||
|
| cannot have a body
|
||||||
|
|
|
||||||
|
= note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
|
||||||
|
|
||||||
|
error: incorrect `static` inside `extern` block
|
||||||
|
--> $DIR/foreign-static-semantic-fail.rs:7:16
|
||||||
|
|
|
||||||
|
LL | extern {
|
||||||
|
| ------ `extern` blocks define existing foreign statics and statics inside of them cannot have a body
|
||||||
|
LL | static X: u8 = 0;
|
||||||
|
LL | static mut Y: u8 = 0;
|
||||||
|
| ^ - the invalid body
|
||||||
|
| |
|
||||||
|
| cannot have a body
|
||||||
|
|
|
||||||
|
= 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-static-syntactic-pass.rs
Normal file
11
src/test/ui/parser/foreign-static-syntactic-pass.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// Syntactically, a foreign static may have a body.
|
||||||
|
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
|
||||||
|
#[cfg(FALSE)]
|
||||||
|
extern {
|
||||||
|
static X: u8 = 0;
|
||||||
|
static mut Y: u8 = 0;
|
||||||
|
}
|
|
@ -1,18 +1,4 @@
|
||||||
// Test that various non-const items and associated consts do not permit `_` as a name.
|
// Test that various non-const items do not syntactically permit `_` as a name.
|
||||||
|
|
||||||
// Associated `const`s:
|
|
||||||
|
|
||||||
pub trait A {
|
|
||||||
const _: () = (); //~ ERROR expected identifier, found reserved identifier `_`
|
|
||||||
}
|
|
||||||
impl A for () {
|
|
||||||
const _: () = (); //~ ERROR expected identifier, found reserved identifier `_`
|
|
||||||
}
|
|
||||||
impl dyn A {
|
|
||||||
const _: () = (); //~ ERROR expected identifier, found reserved identifier `_`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Other kinds of items:
|
|
||||||
|
|
||||||
static _: () = (); //~ ERROR expected identifier, found reserved identifier `_`
|
static _: () = (); //~ ERROR expected identifier, found reserved identifier `_`
|
||||||
struct _(); //~ ERROR expected identifier, found reserved identifier `_`
|
struct _(); //~ ERROR expected identifier, found reserved identifier `_`
|
||||||
|
|
|
@ -1,92 +1,74 @@
|
||||||
error: expected identifier, found reserved identifier `_`
|
error: expected identifier, found reserved identifier `_`
|
||||||
--> $DIR/underscore_item_not_const.rs:6:11
|
--> $DIR/underscore_item_not_const.rs:3:8
|
||||||
|
|
|
||||||
LL | const _: () = ();
|
|
||||||
| ^ expected identifier, found reserved identifier
|
|
||||||
|
|
||||||
error: expected identifier, found reserved identifier `_`
|
|
||||||
--> $DIR/underscore_item_not_const.rs:9:11
|
|
||||||
|
|
|
||||||
LL | const _: () = ();
|
|
||||||
| ^ expected identifier, found reserved identifier
|
|
||||||
|
|
||||||
error: expected identifier, found reserved identifier `_`
|
|
||||||
--> $DIR/underscore_item_not_const.rs:12:11
|
|
||||||
|
|
|
||||||
LL | const _: () = ();
|
|
||||||
| ^ expected identifier, found reserved identifier
|
|
||||||
|
|
||||||
error: expected identifier, found reserved identifier `_`
|
|
||||||
--> $DIR/underscore_item_not_const.rs:17:8
|
|
||||||
|
|
|
|
||||||
LL | static _: () = ();
|
LL | static _: () = ();
|
||||||
| ^ expected identifier, found reserved identifier
|
| ^ expected identifier, found reserved identifier
|
||||||
|
|
||||||
error: expected identifier, found reserved identifier `_`
|
error: expected identifier, found reserved identifier `_`
|
||||||
--> $DIR/underscore_item_not_const.rs:18:8
|
--> $DIR/underscore_item_not_const.rs:4:8
|
||||||
|
|
|
|
||||||
LL | struct _();
|
LL | struct _();
|
||||||
| ^ expected identifier, found reserved identifier
|
| ^ expected identifier, found reserved identifier
|
||||||
|
|
||||||
error: expected identifier, found reserved identifier `_`
|
error: expected identifier, found reserved identifier `_`
|
||||||
--> $DIR/underscore_item_not_const.rs:19:6
|
--> $DIR/underscore_item_not_const.rs:5:6
|
||||||
|
|
|
|
||||||
LL | enum _ {}
|
LL | enum _ {}
|
||||||
| ^ expected identifier, found reserved identifier
|
| ^ expected identifier, found reserved identifier
|
||||||
|
|
||||||
error: expected identifier, found reserved identifier `_`
|
error: expected identifier, found reserved identifier `_`
|
||||||
--> $DIR/underscore_item_not_const.rs:20:4
|
--> $DIR/underscore_item_not_const.rs:6:4
|
||||||
|
|
|
|
||||||
LL | fn _() {}
|
LL | fn _() {}
|
||||||
| ^ expected identifier, found reserved identifier
|
| ^ expected identifier, found reserved identifier
|
||||||
|
|
||||||
error: expected identifier, found reserved identifier `_`
|
error: expected identifier, found reserved identifier `_`
|
||||||
--> $DIR/underscore_item_not_const.rs:21:5
|
--> $DIR/underscore_item_not_const.rs:7:5
|
||||||
|
|
|
|
||||||
LL | mod _ {}
|
LL | mod _ {}
|
||||||
| ^ expected identifier, found reserved identifier
|
| ^ expected identifier, found reserved identifier
|
||||||
|
|
||||||
error: expected identifier, found reserved identifier `_`
|
error: expected identifier, found reserved identifier `_`
|
||||||
--> $DIR/underscore_item_not_const.rs:22:6
|
--> $DIR/underscore_item_not_const.rs:8:6
|
||||||
|
|
|
|
||||||
LL | type _ = ();
|
LL | type _ = ();
|
||||||
| ^ expected identifier, found reserved identifier
|
| ^ expected identifier, found reserved identifier
|
||||||
|
|
||||||
error: expected identifier, found reserved identifier `_`
|
error: expected identifier, found reserved identifier `_`
|
||||||
--> $DIR/underscore_item_not_const.rs:23:5
|
--> $DIR/underscore_item_not_const.rs:9:5
|
||||||
|
|
|
|
||||||
LL | use _;
|
LL | use _;
|
||||||
| ^ expected identifier, found reserved identifier
|
| ^ expected identifier, found reserved identifier
|
||||||
|
|
||||||
error: expected identifier, found reserved identifier `_`
|
error: expected identifier, found reserved identifier `_`
|
||||||
--> $DIR/underscore_item_not_const.rs:24:5
|
--> $DIR/underscore_item_not_const.rs:10:5
|
||||||
|
|
|
|
||||||
LL | use _ as g;
|
LL | use _ as g;
|
||||||
| ^ expected identifier, found reserved identifier
|
| ^ expected identifier, found reserved identifier
|
||||||
|
|
||||||
error: expected identifier, found reserved identifier `_`
|
error: expected identifier, found reserved identifier `_`
|
||||||
--> $DIR/underscore_item_not_const.rs:25:7
|
--> $DIR/underscore_item_not_const.rs:11:7
|
||||||
|
|
|
|
||||||
LL | trait _ {}
|
LL | trait _ {}
|
||||||
| ^ expected identifier, found reserved identifier
|
| ^ expected identifier, found reserved identifier
|
||||||
|
|
||||||
error: expected identifier, found reserved identifier `_`
|
error: expected identifier, found reserved identifier `_`
|
||||||
--> $DIR/underscore_item_not_const.rs:26:7
|
--> $DIR/underscore_item_not_const.rs:12:7
|
||||||
|
|
|
|
||||||
LL | trait _ = Copy;
|
LL | trait _ = Copy;
|
||||||
| ^ expected identifier, found reserved identifier
|
| ^ expected identifier, found reserved identifier
|
||||||
|
|
||||||
error: expected identifier, found reserved identifier `_`
|
error: expected identifier, found reserved identifier `_`
|
||||||
--> $DIR/underscore_item_not_const.rs:27:14
|
--> $DIR/underscore_item_not_const.rs:13:14
|
||||||
|
|
|
|
||||||
LL | macro_rules! _ { () => {} }
|
LL | macro_rules! _ { () => {} }
|
||||||
| ^ expected identifier, found reserved identifier
|
| ^ expected identifier, found reserved identifier
|
||||||
|
|
||||||
error: expected one of `!` or `::`, found reserved identifier `_`
|
error: expected one of `!` or `::`, found reserved identifier `_`
|
||||||
--> $DIR/underscore_item_not_const.rs:28:7
|
--> $DIR/underscore_item_not_const.rs:14:7
|
||||||
|
|
|
|
||||||
LL | union _ { f: u8 }
|
LL | union _ { f: u8 }
|
||||||
| ^ expected one of `!` or `::`
|
| ^ expected one of `!` or `::`
|
||||||
|
|
||||||
error: aborting due to 15 previous errors
|
error: aborting due to 12 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue