From c54932cb12b8384060bfe132907ec42cc5c1bbd2 Mon Sep 17 00:00:00 2001 From: Jared Roesch Date: Fri, 2 Jan 2015 04:02:50 -0800 Subject: [PATCH] Fix the parsing of where-clauses for structs --- src/libsyntax/parse/parser.rs | 24 +++++++++++++++++++++--- src/test/run-pass/issue-17904.rs | 22 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 src/test/run-pass/issue-17904.rs diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 37ac86a3324..570ef67bbcc 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4875,11 +4875,26 @@ impl<'a> Parser<'a> { self.span_err(ty.span, "`virtual` structs have been removed from the language"); } - self.parse_where_clause(&mut generics); - let mut fields: Vec; let is_tuple_like; + // There is a special case worth noting here, as reported in issue #17904. + // If we are parsing a tuple struct it is the case that the where clause + // should follow the field list. Like so: + // + // struct Foo(T) where T: Copy; + // + // If we are parsing a normal record-style struct it is the case + // that the where clause comes before the body, and after the generics. + // So if we look ahead and see a brace or a where-clause we begin + // parsing a record style struct. + // + // Otherwise if we look ahead and see a paren we parse a tuple-style + // struct. + + // Will parse the where-clause if it precedes the brace. + self.parse_where_clause(&mut generics); + if self.eat(&token::OpenDelim(token::Brace)) { // It's a record-like struct. is_tuple_like = false; @@ -4916,8 +4931,11 @@ impl<'a> Parser<'a> { written as `struct {};`", token::get_ident(class_name))[]); } + self.parse_where_clause(&mut generics); self.expect(&token::Semi); - } else if self.eat(&token::Semi) { + } else if self.token.is_keyword(keywords::Where) || self.eat(&token::Semi) { + // We can find a where clause here. + self.parse_where_clause(&mut generics); // It's a unit-like struct. is_tuple_like = true; fields = Vec::new(); diff --git a/src/test/run-pass/issue-17904.rs b/src/test/run-pass/issue-17904.rs new file mode 100644 index 00000000000..c2976378dda --- /dev/null +++ b/src/test/run-pass/issue-17904.rs @@ -0,0 +1,22 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Tests that type assignability is used to search for instances when +// making method calls, but only if there aren't any matches without +// it. + +struct Foo where T: Copy; +struct Bar(T) where T: Copy; +struct Bleh(T, U) where T: Copy, U: Sized; +struct Baz where T: Copy { + field: T +} + +fn main() {}