Also take unions and enums into account
This commit is contained in:
parent
1e642f0a61
commit
6717f81b96
3 changed files with 61 additions and 19 deletions
|
@ -1124,11 +1124,11 @@ impl<'a> Parser<'a> {
|
||||||
if !this.recover_nested_adt_item(kw::Enum)? {
|
if !this.recover_nested_adt_item(kw::Enum)? {
|
||||||
return Ok((None, TrailingToken::None));
|
return Ok((None, TrailingToken::None));
|
||||||
}
|
}
|
||||||
let ident = this.parse_ident()?;
|
let ident = this.parse_field_ident("enum", vlo)?;
|
||||||
|
|
||||||
let struct_def = if this.check(&token::OpenDelim(token::Brace)) {
|
let struct_def = if this.check(&token::OpenDelim(token::Brace)) {
|
||||||
// Parse a struct variant.
|
// Parse a struct variant.
|
||||||
let (fields, recovered) = this.parse_record_struct_body()?;
|
let (fields, recovered) = this.parse_record_struct_body("struct")?;
|
||||||
VariantData::Struct(fields, recovered)
|
VariantData::Struct(fields, recovered)
|
||||||
} else if this.check(&token::OpenDelim(token::Paren)) {
|
} else if this.check(&token::OpenDelim(token::Paren)) {
|
||||||
VariantData::Tuple(this.parse_tuple_struct_body()?, DUMMY_NODE_ID)
|
VariantData::Tuple(this.parse_tuple_struct_body()?, DUMMY_NODE_ID)
|
||||||
|
@ -1182,7 +1182,7 @@ impl<'a> Parser<'a> {
|
||||||
VariantData::Unit(DUMMY_NODE_ID)
|
VariantData::Unit(DUMMY_NODE_ID)
|
||||||
} else {
|
} else {
|
||||||
// If we see: `struct Foo<T> where T: Copy { ... }`
|
// If we see: `struct Foo<T> where T: Copy { ... }`
|
||||||
let (fields, recovered) = self.parse_record_struct_body()?;
|
let (fields, recovered) = self.parse_record_struct_body("struct")?;
|
||||||
VariantData::Struct(fields, recovered)
|
VariantData::Struct(fields, recovered)
|
||||||
}
|
}
|
||||||
// No `where` so: `struct Foo<T>;`
|
// No `where` so: `struct Foo<T>;`
|
||||||
|
@ -1190,7 +1190,7 @@ impl<'a> Parser<'a> {
|
||||||
VariantData::Unit(DUMMY_NODE_ID)
|
VariantData::Unit(DUMMY_NODE_ID)
|
||||||
// Record-style struct definition
|
// Record-style struct definition
|
||||||
} else if self.token == token::OpenDelim(token::Brace) {
|
} else if self.token == token::OpenDelim(token::Brace) {
|
||||||
let (fields, recovered) = self.parse_record_struct_body()?;
|
let (fields, recovered) = self.parse_record_struct_body("struct")?;
|
||||||
VariantData::Struct(fields, recovered)
|
VariantData::Struct(fields, recovered)
|
||||||
// Tuple-style struct definition with optional where-clause.
|
// Tuple-style struct definition with optional where-clause.
|
||||||
} else if self.token == token::OpenDelim(token::Paren) {
|
} else if self.token == token::OpenDelim(token::Paren) {
|
||||||
|
@ -1220,10 +1220,10 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let vdata = if self.token.is_keyword(kw::Where) {
|
let vdata = if self.token.is_keyword(kw::Where) {
|
||||||
generics.where_clause = self.parse_where_clause()?;
|
generics.where_clause = self.parse_where_clause()?;
|
||||||
let (fields, recovered) = self.parse_record_struct_body()?;
|
let (fields, recovered) = self.parse_record_struct_body("union")?;
|
||||||
VariantData::Struct(fields, recovered)
|
VariantData::Struct(fields, recovered)
|
||||||
} else if self.token == token::OpenDelim(token::Brace) {
|
} else if self.token == token::OpenDelim(token::Brace) {
|
||||||
let (fields, recovered) = self.parse_record_struct_body()?;
|
let (fields, recovered) = self.parse_record_struct_body("union")?;
|
||||||
VariantData::Struct(fields, recovered)
|
VariantData::Struct(fields, recovered)
|
||||||
} else {
|
} else {
|
||||||
let token_str = super::token_descr(&self.token);
|
let token_str = super::token_descr(&self.token);
|
||||||
|
@ -1236,12 +1236,15 @@ impl<'a> Parser<'a> {
|
||||||
Ok((class_name, ItemKind::Union(vdata, generics)))
|
Ok((class_name, ItemKind::Union(vdata, generics)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_record_struct_body(&mut self) -> PResult<'a, (Vec<FieldDef>, /* recovered */ bool)> {
|
fn parse_record_struct_body(
|
||||||
|
&mut self,
|
||||||
|
adt_ty: &str,
|
||||||
|
) -> PResult<'a, (Vec<FieldDef>, /* recovered */ bool)> {
|
||||||
let mut fields = Vec::new();
|
let mut fields = Vec::new();
|
||||||
let mut recovered = false;
|
let mut recovered = false;
|
||||||
if self.eat(&token::OpenDelim(token::Brace)) {
|
if self.eat(&token::OpenDelim(token::Brace)) {
|
||||||
while self.token != token::CloseDelim(token::Brace) {
|
while self.token != token::CloseDelim(token::Brace) {
|
||||||
let field = self.parse_field_def().map_err(|e| {
|
let field = self.parse_field_def(adt_ty).map_err(|e| {
|
||||||
self.consume_block(token::Brace, ConsumeClosingDelim::No);
|
self.consume_block(token::Brace, ConsumeClosingDelim::No);
|
||||||
recovered = true;
|
recovered = true;
|
||||||
e
|
e
|
||||||
|
@ -1294,24 +1297,25 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses an element of a struct declaration.
|
/// Parses an element of a struct declaration.
|
||||||
fn parse_field_def(&mut self) -> PResult<'a, FieldDef> {
|
fn parse_field_def(&mut self, adt_ty: &str) -> PResult<'a, FieldDef> {
|
||||||
let attrs = self.parse_outer_attributes()?;
|
let attrs = self.parse_outer_attributes()?;
|
||||||
self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
|
self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
|
||||||
let lo = this.token.span;
|
let lo = this.token.span;
|
||||||
let vis = this.parse_visibility(FollowedByType::No)?;
|
let vis = this.parse_visibility(FollowedByType::No)?;
|
||||||
Ok((this.parse_single_struct_field(lo, vis, attrs)?, TrailingToken::None))
|
Ok((this.parse_single_struct_field(adt_ty, lo, vis, attrs)?, TrailingToken::None))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a structure field declaration.
|
/// Parses a structure field declaration.
|
||||||
fn parse_single_struct_field(
|
fn parse_single_struct_field(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
adt_ty: &str,
|
||||||
lo: Span,
|
lo: Span,
|
||||||
vis: Visibility,
|
vis: Visibility,
|
||||||
attrs: Vec<Attribute>,
|
attrs: Vec<Attribute>,
|
||||||
) -> PResult<'a, FieldDef> {
|
) -> PResult<'a, FieldDef> {
|
||||||
let mut seen_comma: bool = false;
|
let mut seen_comma: bool = false;
|
||||||
let a_var = self.parse_name_and_ty(lo, vis, attrs)?;
|
let a_var = self.parse_name_and_ty(adt_ty, lo, vis, attrs)?;
|
||||||
if self.token == token::Comma {
|
if self.token == token::Comma {
|
||||||
seen_comma = true;
|
seen_comma = true;
|
||||||
}
|
}
|
||||||
|
@ -1398,11 +1402,12 @@ impl<'a> Parser<'a> {
|
||||||
/// Parses a structure field.
|
/// Parses a structure field.
|
||||||
fn parse_name_and_ty(
|
fn parse_name_and_ty(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
adt_ty: &str,
|
||||||
lo: Span,
|
lo: Span,
|
||||||
vis: Visibility,
|
vis: Visibility,
|
||||||
attrs: Vec<Attribute>,
|
attrs: Vec<Attribute>,
|
||||||
) -> PResult<'a, FieldDef> {
|
) -> PResult<'a, FieldDef> {
|
||||||
let name = self.parse_field_ident(lo)?;
|
let name = self.parse_field_ident(adt_ty, lo)?;
|
||||||
self.expect(&token::Colon)?;
|
self.expect(&token::Colon)?;
|
||||||
let ty = self.parse_ty()?;
|
let ty = self.parse_ty()?;
|
||||||
Ok(FieldDef {
|
Ok(FieldDef {
|
||||||
|
@ -1418,14 +1423,14 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
/// Parses a field identifier. Specialized version of `parse_ident_common`
|
/// Parses a field identifier. Specialized version of `parse_ident_common`
|
||||||
/// for better diagnostics and suggestions.
|
/// for better diagnostics and suggestions.
|
||||||
fn parse_field_ident(&mut self, lo: Span) -> PResult<'a, Ident> {
|
fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
|
||||||
let (ident, is_raw) = self.ident_or_err()?;
|
let (ident, is_raw) = self.ident_or_err()?;
|
||||||
if !is_raw && ident.is_reserved() {
|
if !is_raw && ident.is_reserved() {
|
||||||
let err = if self.check_fn_front_matter(false) {
|
let err = if self.check_fn_front_matter(false) {
|
||||||
let _ = self.parse_fn(&mut Vec::new(), |_| true, lo);
|
let _ = self.parse_fn(&mut Vec::new(), |_| true, lo);
|
||||||
let mut err = self.struct_span_err(
|
let mut err = self.struct_span_err(
|
||||||
lo.to(self.prev_token.span),
|
lo.to(self.prev_token.span),
|
||||||
"functions are not allowed in struct definitions",
|
&format!("functions are not allowed in {} definitions", adt_ty),
|
||||||
);
|
);
|
||||||
err.help("unlike in C++, Java, and C#, functions are declared in `impl` blocks");
|
err.help("unlike in C++, Java, and C#, functions are declared in `impl` blocks");
|
||||||
err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
|
err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
|
||||||
|
|
|
@ -5,10 +5,29 @@
|
||||||
|
|
||||||
struct S {
|
struct S {
|
||||||
field: usize,
|
field: usize,
|
||||||
fn do_something() {}
|
|
||||||
|
fn foo() {}
|
||||||
//~^ ERROR functions are not allowed in struct definitions
|
//~^ ERROR functions are not allowed in struct definitions
|
||||||
//~| HELP unlike in C++, Java, and C#, functions are declared in `impl` blocks
|
//~| HELP unlike in C++, Java, and C#, functions are declared in `impl` blocks
|
||||||
//~| HELP see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
|
//~| HELP see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
|
||||||
}
|
}
|
||||||
|
|
||||||
|
union U {
|
||||||
|
variant: usize,
|
||||||
|
|
||||||
|
fn foo() {}
|
||||||
|
//~^ ERROR functions are not allowed in union definitions
|
||||||
|
//~| HELP unlike in C++, Java, and C#, functions are declared in `impl` blocks
|
||||||
|
//~| HELP see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
|
||||||
|
}
|
||||||
|
|
||||||
|
enum E {
|
||||||
|
Variant,
|
||||||
|
|
||||||
|
fn foo() {}
|
||||||
|
//~^ ERROR functions are not allowed in enum definitions
|
||||||
|
//~| HELP unlike in C++, Java, and C#, functions are declared in `impl` blocks
|
||||||
|
//~| HELP see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,11 +1,29 @@
|
||||||
error: functions are not allowed in struct definitions
|
error: functions are not allowed in struct definitions
|
||||||
--> $DIR/struct-fn-in-definition.rs:5:5
|
--> $DIR/struct-fn-in-definition.rs:9:5
|
||||||
|
|
|
|
||||||
LL | fn do_something() {}
|
LL | fn foo() {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: unlike in C++, Java, and C#, functions are declared in `impl` blocks
|
= help: unlike in C++, Java, and C#, functions are declared in `impl` blocks
|
||||||
= help: see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
|
= help: see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: functions are not allowed in union definitions
|
||||||
|
--> $DIR/struct-fn-in-definition.rs:18:5
|
||||||
|
|
|
||||||
|
LL | fn foo() {}
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: unlike in C++, Java, and C#, functions are declared in `impl` blocks
|
||||||
|
= help: see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
|
||||||
|
|
||||||
|
error: functions are not allowed in enum definitions
|
||||||
|
--> $DIR/struct-fn-in-definition.rs:27:5
|
||||||
|
|
|
||||||
|
LL | fn foo() {}
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: unlike in C++, Java, and C#, functions are declared in `impl` blocks
|
||||||
|
= help: see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue