@@ -4875,11 +4875,26 @@ impl<'a> Parser<'a> {
4875
4875
self . span_err ( ty. span , "`virtual` structs have been removed from the language" ) ;
4876
4876
}
4877
4877
4878
- self . parse_where_clause ( & mut generics) ;
4879
-
4880
4878
let mut fields: Vec < StructField > ;
4881
4879
let is_tuple_like;
4882
4880
4881
+ // There is a special case worth noting here, as reported in issue #17904.
4882
+ // If we are parsing a tuple struct it is the case that the where clause
4883
+ // should follow the field list. Like so:
4884
+ //
4885
+ // struct Foo<T>(T) where T: Copy;
4886
+ //
4887
+ // If we are parsing a normal record-style struct it is the case
4888
+ // that the where clause comes before the body, and after the generics.
4889
+ // So if we look ahead and see a brace or a where-clause we begin
4890
+ // parsing a record style struct.
4891
+ //
4892
+ // Otherwise if we look ahead and see a paren we parse a tuple-style
4893
+ // struct.
4894
+
4895
+ // Will parse the where-clause if it precedes the brace.
4896
+ self . parse_where_clause ( & mut generics) ;
4897
+
4883
4898
if self . eat ( & token:: OpenDelim ( token:: Brace ) ) {
4884
4899
// It's a record-like struct.
4885
4900
is_tuple_like = false ;
@@ -4916,8 +4931,11 @@ impl<'a> Parser<'a> {
4916
4931
written as `struct {};`",
4917
4932
token:: get_ident( class_name) ) [ ] ) ;
4918
4933
}
4934
+ self . parse_where_clause ( & mut generics) ;
4919
4935
self . expect ( & token:: Semi ) ;
4920
- } else if self . eat ( & 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) ;
4921
4939
// It's a unit-like struct.
4922
4940
is_tuple_like = true ;
4923
4941
fields = Vec :: new ( ) ;
0 commit comments