@@ -4875,9 +4875,6 @@ impl<'a> Parser<'a> {
4875
4875
self . span_err ( ty. span , "`virtual` structs have been removed from the language" ) ;
4876
4876
}
4877
4877
4878
- let mut fields: Vec < StructField > ;
4879
- let is_tuple_like;
4880
-
4881
4878
// There is a special case worth noting here, as reported in issue #17904.
4882
4879
// If we are parsing a tuple struct it is the case that the where clause
4883
4880
// should follow the field list. Like so:
@@ -4892,68 +4889,102 @@ impl<'a> Parser<'a> {
4892
4889
// Otherwise if we look ahead and see a paren we parse a tuple-style
4893
4890
// struct.
4894
4891
4895
- // Will parse the where-clause if it precedes the brace.
4896
- self . parse_where_clause ( & mut generics) ;
4892
+ let ( fields, ctor_id) = if self . token . is_keyword ( keywords:: Where ) {
4893
+ self . parse_where_clause ( & mut generics) ;
4894
+ if self . eat ( & token:: Semi ) {
4895
+ // If we see a: `struct Foo<T> where T: Copy;` style decl.
4896
+ ( Vec :: new ( ) , Some ( ast:: DUMMY_NODE_ID ) )
4897
+ } else {
4898
+ // If we see: `struct Foo<T> where T: Copy { ... }`
4899
+ ( self . parse_record_struct_body ( & class_name) , None )
4900
+ }
4901
+ // No `where` so: `struct Foo<T>;`
4902
+ } else if self . eat ( & token:: Semi ) {
4903
+ ( Vec :: new ( ) , Some ( ast:: DUMMY_NODE_ID ) )
4904
+ // Record-style struct definition
4905
+ } else if self . token == token:: OpenDelim ( token:: Brace ) {
4906
+ let fields = self . parse_record_struct_body ( & class_name) ;
4907
+ ( fields, None )
4908
+ // Tuple-style struct definition with optional where-clause.
4909
+ } else {
4910
+ let fields = self . parse_tuple_struct_body ( & class_name, & mut generics) ;
4911
+ ( fields, Some ( ast:: DUMMY_NODE_ID ) )
4912
+ } ;
4897
4913
4914
+ ( class_name,
4915
+ ItemStruct ( P ( ast:: StructDef {
4916
+ fields : fields,
4917
+ ctor_id : ctor_id,
4918
+ } ) , generics) ,
4919
+ None )
4920
+ }
4921
+
4922
+ pub fn parse_record_struct_body ( & mut self , class_name : & ast:: Ident ) -> Vec < StructField > {
4923
+ let mut fields = Vec :: new ( ) ;
4898
4924
if self . eat ( & token:: OpenDelim ( token:: Brace ) ) {
4899
- // It's a record-like struct.
4900
- is_tuple_like = false ;
4901
- fields = Vec :: new ( ) ;
4902
4925
while self . token != token:: CloseDelim ( token:: Brace ) {
4903
4926
fields. push ( self . parse_struct_decl_field ( true ) ) ;
4904
4927
}
4928
+
4905
4929
if fields. len ( ) == 0 {
4906
4930
self . fatal ( format ! ( "unit-like struct definition should be \
4907
- written as `struct {};`",
4908
- token:: get_ident( class_name) ) [ ] ) ;
4931
+ written as `struct {};`",
4932
+ token:: get_ident( class_name. clone ( ) ) ) [ ] ) ;
4909
4933
}
4934
+
4910
4935
self . bump ( ) ;
4911
- } else if self . check ( & token:: OpenDelim ( token:: Paren ) ) {
4912
- // It's a tuple-like struct.
4913
- is_tuple_like = true ;
4914
- fields = self . parse_unspanned_seq (
4936
+ } else {
4937
+ let token_str = self . this_token_to_string ( ) ;
4938
+ self . fatal ( format ! ( "expected `where`, or `{}` after struct \
4939
+ name, found `{}`", "{" ,
4940
+ token_str) [ ] ) ;
4941
+ }
4942
+
4943
+ fields
4944
+ }
4945
+
4946
+ pub fn parse_tuple_struct_body ( & mut self ,
4947
+ class_name : & ast:: Ident ,
4948
+ generics : & mut ast:: Generics )
4949
+ -> Vec < StructField > {
4950
+ // This is the case where we find `struct Foo<T>(T) where T: Copy;`
4951
+ if self . check ( & token:: OpenDelim ( token:: Paren ) ) {
4952
+ let fields = self . parse_unspanned_seq (
4915
4953
& token:: OpenDelim ( token:: Paren ) ,
4916
4954
& token:: CloseDelim ( token:: Paren ) ,
4917
4955
seq_sep_trailing_allowed ( token:: Comma ) ,
4918
4956
|p| {
4919
- let attrs = p. parse_outer_attributes ( ) ;
4920
- let lo = p. span . lo ;
4921
- let struct_field_ = ast:: StructField_ {
4922
- kind : UnnamedField ( p. parse_visibility ( ) ) ,
4923
- id : ast:: DUMMY_NODE_ID ,
4924
- ty : p. parse_ty_sum ( ) ,
4925
- attrs : attrs,
4926
- } ;
4927
- spanned ( lo, p. span . hi , struct_field_)
4928
- } ) ;
4957
+ let attrs = p. parse_outer_attributes ( ) ;
4958
+ let lo = p. span . lo ;
4959
+ let struct_field_ = ast:: StructField_ {
4960
+ kind : UnnamedField ( p. parse_visibility ( ) ) ,
4961
+ id : ast:: DUMMY_NODE_ID ,
4962
+ ty : p. parse_ty_sum ( ) ,
4963
+ attrs : attrs,
4964
+ } ;
4965
+ spanned ( lo, p. span . hi , struct_field_)
4966
+ } ) ;
4967
+
4929
4968
if fields. len ( ) == 0 {
4930
4969
self . fatal ( format ! ( "unit-like struct definition should be \
4931
- written as `struct {};`",
4932
- token:: get_ident( class_name) ) [ ] ) ;
4970
+ written as `struct {};`",
4971
+ token:: get_ident( class_name. clone ( ) ) ) [ ] ) ;
4933
4972
}
4934
- self . parse_where_clause ( & mut generics) ;
4973
+
4974
+ self . parse_where_clause ( generics) ;
4935
4975
self . expect ( & token:: Semi ) ;
4936
- } else if self . token . is_keyword ( keywords:: Where ) || self . eat ( & token:: Semi ) {
4937
- // We can find a where clause here.
4938
- self . parse_where_clause ( & mut generics) ;
4939
- // It's a unit-like struct.
4940
- is_tuple_like = true ;
4941
- fields = Vec :: new ( ) ;
4976
+ fields
4977
+ // This is the case where we just see struct Foo<T> where T: Copy;
4978
+ } else if self . token . is_keyword ( keywords:: Where ) {
4979
+ self . parse_where_clause ( generics) ;
4980
+ self . expect ( & token:: Semi ) ;
4981
+ Vec :: new ( )
4982
+ // This case is where we see: `struct Foo<T>;`
4942
4983
} else {
4943
4984
let token_str = self . this_token_to_string ( ) ;
4944
- self . fatal ( format ! ( "expected `{}`, `(`, or `;` after struct \
4945
- name, found `{}`", "{" ,
4946
- token_str) [ ] )
4985
+ self . fatal ( format ! ( "expected `where`, `{}`, `(`, or `;` after struct \
4986
+ name, found `{}`", "{" , token_str) [ ] ) ;
4947
4987
}
4948
-
4949
- let _ = ast:: DUMMY_NODE_ID ; // FIXME: Workaround for crazy bug.
4950
- let new_id = ast:: DUMMY_NODE_ID ;
4951
- ( class_name,
4952
- ItemStruct ( P ( ast:: StructDef {
4953
- fields : fields,
4954
- ctor_id : if is_tuple_like { Some ( new_id) } else { None } ,
4955
- } ) , generics) ,
4956
- None )
4957
4988
}
4958
4989
4959
4990
/// Parse a structure field declaration
0 commit comments