Skip to content

Commit 56e00bf

Browse files
committed
---
yaml --- r: 169371 b: refs/heads/master c: c02fac4 h: refs/heads/master i: 169369: 3ff68f4 169367: 4f2bc2d v: v3
1 parent f35b8c9 commit 56e00bf

File tree

6 files changed

+97
-52
lines changed

6 files changed

+97
-52
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: c54932cb12b8384060bfe132907ec42cc5c1bbd2
2+
refs/heads/master: c02fac471a9126e971617449a55930b0d69058c0
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 5b3cd3900ceda838f5798c30ab96ceb41f962534
55
refs/heads/try: 5204084bd2e46af7cc6e0147430e44dd0d657bbb

trunk/src/libsyntax/parse/parser.rs

Lines changed: 76 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4875,9 +4875,6 @@ impl<'a> Parser<'a> {
48754875
self.span_err(ty.span, "`virtual` structs have been removed from the language");
48764876
}
48774877

4878-
let mut fields: Vec<StructField>;
4879-
let is_tuple_like;
4880-
48814878
// There is a special case worth noting here, as reported in issue #17904.
48824879
// If we are parsing a tuple struct it is the case that the where clause
48834880
// should follow the field list. Like so:
@@ -4892,68 +4889,102 @@ impl<'a> Parser<'a> {
48924889
// Otherwise if we look ahead and see a paren we parse a tuple-style
48934890
// struct.
48944891

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+
};
48974913

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();
48984924
if self.eat(&token::OpenDelim(token::Brace)) {
4899-
// It's a record-like struct.
4900-
is_tuple_like = false;
4901-
fields = Vec::new();
49024925
while self.token != token::CloseDelim(token::Brace) {
49034926
fields.push(self.parse_struct_decl_field(true));
49044927
}
4928+
49054929
if fields.len() == 0 {
49064930
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()))[]);
49094933
}
4934+
49104935
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(
49154953
&token::OpenDelim(token::Paren),
49164954
&token::CloseDelim(token::Paren),
49174955
seq_sep_trailing_allowed(token::Comma),
49184956
|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+
49294968
if fields.len() == 0 {
49304969
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()))[]);
49334972
}
4934-
self.parse_where_clause(&mut generics);
4973+
4974+
self.parse_where_clause(generics);
49354975
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>;`
49424983
} else {
49434984
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)[]);
49474987
}
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)
49574988
}
49584989

49594990
/// Parse a structure field declaration

trunk/src/libsyntax/print/pprust.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1067,7 +1067,6 @@ impl<'a> State<'a> {
10671067
span: codemap::Span) -> IoResult<()> {
10681068
try!(self.print_ident(ident));
10691069
try!(self.print_generics(generics));
1070-
try!(self.print_where_clause(generics));
10711070
if ast_util::struct_def_is_tuple_like(struct_def) {
10721071
if !struct_def.fields.is_empty() {
10731072
try!(self.popen());
@@ -1086,10 +1085,12 @@ impl<'a> State<'a> {
10861085
));
10871086
try!(self.pclose());
10881087
}
1088+
try!(self.print_where_clause(generics));
10891089
try!(word(&mut self.s, ";"));
10901090
try!(self.end());
10911091
self.end() // close the outer-box
10921092
} else {
1093+
try!(self.print_where_clause(generics));
10931094
try!(self.nbsp());
10941095
try!(self.bopen());
10951096
try!(self.hardbreak_if_not_bol());
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
struct Baz<U> where U: Eq(U); //This is parsed as the new Fn* style parenthesis syntax.
12+
struct Baz<U> where U: Eq(U) -> R; // Notice this parses as well.
13+
struct Baz<U>(U) where U: Eq; // This rightfully signals no error as well.
14+
struct Foo<T> where T: Copy, (T); //~ ERROR unexpected token in `where` clause
15+
struct Bar<T> { x: T } where T: Copy //~ ERROR expected item, found `where`
16+
17+
fn main() {}

trunk/src/test/compile-fail/unsized.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
// Test syntax checks for `type` keyword.
1212

13-
struct S1 for type; //~ ERROR expected `{`, `(`, or `;` after struct name, found `for`
13+
struct S1 for type; //~ ERROR expected `where`, `{`, `(`, or `;` after struct name, found `for`
1414

1515
pub fn main() {
1616
}

trunk/src/test/run-pass/issue-17904.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// Tests that type assignability is used to search for instances when
12-
// making method calls, but only if there aren't any matches without
13-
// it.
14-
1511
struct Foo<T> where T: Copy;
1612
struct Bar<T>(T) where T: Copy;
1713
struct Bleh<T, U>(T, U) where T: Copy, U: Sized;

0 commit comments

Comments
 (0)