From b795abeb1dc0f6d27e49d980a48936b687754b28 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 17 Jan 2017 21:18:29 +0300 Subject: Refactor parsing of generic arguments/parameters and where clauses --- src/test/parse-fail/generic-non-trailing-defaults.rs | 19 ------------------- src/test/parse-fail/issue-14303-path.rs | 1 - src/test/parse-fail/issue-17904-2.rs | 15 +++++++++++++++ src/test/parse-fail/issue-17904.rs | 3 +-- src/test/parse-fail/issue-32214.rs | 5 ++--- src/test/parse-fail/lifetime-semicolon.rs | 3 +-- .../where-clauses-no-bounds-or-predicates.rs | 4 ++-- 7 files changed, 21 insertions(+), 29 deletions(-) delete mode 100644 src/test/parse-fail/generic-non-trailing-defaults.rs create mode 100644 src/test/parse-fail/issue-17904-2.rs (limited to 'src/test/parse-fail') diff --git a/src/test/parse-fail/generic-non-trailing-defaults.rs b/src/test/parse-fail/generic-non-trailing-defaults.rs deleted file mode 100644 index 2bb593258ae..00000000000 --- a/src/test/parse-fail/generic-non-trailing-defaults.rs +++ /dev/null @@ -1,19 +0,0 @@ -// 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. - -// compile-flags: -Z parse-only -Z continue-parse-after-error - -struct Heap; - -struct Vec; //~ ERROR type parameters with a default must be trailing - -struct Foo, C>; //~ ERROR type parameters with a default must be trailing - -fn main() {} diff --git a/src/test/parse-fail/issue-14303-path.rs b/src/test/parse-fail/issue-14303-path.rs index 431a917c2d9..f0d1feffec8 100644 --- a/src/test/parse-fail/issue-14303-path.rs +++ b/src/test/parse-fail/issue-14303-path.rs @@ -12,4 +12,3 @@ fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {} //~^ ERROR lifetime parameters must be declared prior to type parameters -//~^^ ERROR expected pattern, found `'c` diff --git a/src/test/parse-fail/issue-17904-2.rs b/src/test/parse-fail/issue-17904-2.rs new file mode 100644 index 00000000000..3f41c0edd2e --- /dev/null +++ b/src/test/parse-fail/issue-17904-2.rs @@ -0,0 +1,15 @@ +// 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. + +// compile-flags: -Z parse-only -Z continue-parse-after-error + +struct Bar { x: T } where T: Copy //~ ERROR expected item, found `where` + +fn main() {} diff --git a/src/test/parse-fail/issue-17904.rs b/src/test/parse-fail/issue-17904.rs index de5aeb02ab7..ae28ac76acb 100644 --- a/src/test/parse-fail/issue-17904.rs +++ b/src/test/parse-fail/issue-17904.rs @@ -13,7 +13,6 @@ struct Baz where U: Eq(U); //This is parsed as the new Fn* style parenthesis syntax. struct Baz where U: Eq(U) -> R; // Notice this parses as well. struct Baz(U) where U: Eq; // This rightfully signals no error as well. -struct Foo where T: Copy, (T); //~ ERROR unexpected token in `where` clause -struct Bar { x: T } where T: Copy //~ ERROR expected item, found `where` +struct Foo where T: Copy, (T); //~ ERROR expected one of `+`, `:`, `==`, or `=`, found `;` fn main() {} diff --git a/src/test/parse-fail/issue-32214.rs b/src/test/parse-fail/issue-32214.rs index 3ba59c8ee94..9e200094093 100644 --- a/src/test/parse-fail/issue-32214.rs +++ b/src/test/parse-fail/issue-32214.rs @@ -10,8 +10,7 @@ // compile-flags: -Z parse-only -Z continue-parse-after-error -pub fn test >() { - //~^ ERROR expected `=`, found `>` -} +pub fn test >() {} +//~^ ERROR type parameters must be declared prior to associated type bindings fn main() { } diff --git a/src/test/parse-fail/lifetime-semicolon.rs b/src/test/parse-fail/lifetime-semicolon.rs index 7010d0e7deb..e1975952fca 100644 --- a/src/test/parse-fail/lifetime-semicolon.rs +++ b/src/test/parse-fail/lifetime-semicolon.rs @@ -15,5 +15,4 @@ struct Foo<'a, 'b> { } fn foo<'a, 'b>(x: &mut Foo<'a; 'b>) {} -//~^ ERROR expected `,` or `>` after lifetime name, found `;` -//~^^ NOTE did you mean a single argument type &'a Type, or did you mean the comma-separated +//~^ ERROR expected one of `,` or `>`, found `;` diff --git a/src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs b/src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs index 78d97454087..cf67b518fff 100644 --- a/src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs +++ b/src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs @@ -10,13 +10,13 @@ // compile-flags: -Z parse-only -Z continue-parse-after-error +// Empty predicate list is OK fn equal1(_: &T, _: &T) -> bool where { -//~^ ERROR a `where` clause must have at least one predicate in it true } +// Empty bound list is OK fn equal2(_: &T, _: &T) -> bool where T: { -//~^ ERROR each predicate in a `where` clause must have at least one bound true } -- cgit 1.4.1-3-g733a5 From a8f5047430aa78c2d1ff30b5960cdbde24daab84 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 18 Jan 2017 17:41:57 +0300 Subject: Add tests --- src/test/compile-fail/impl-trait/no-trait.rs | 15 ++++++++++++++ .../compile-fail/where-equality-constraints.rs | 16 +++++++++++++++ src/test/compile-fail/where-lifetime-resolution.rs | 23 ++++++++++++++++++++++ src/test/parse-fail/bounds-lifetime-1.rs | 15 ++++++++++++++ src/test/parse-fail/bounds-lifetime-2.rs | 15 ++++++++++++++ src/test/parse-fail/bounds-lifetime-3.rs | 15 ++++++++++++++ src/test/parse-fail/bounds-lifetime-where-1.rs | 15 ++++++++++++++ src/test/parse-fail/bounds-lifetime-where-2.rs | 15 ++++++++++++++ src/test/parse-fail/bounds-lifetime-where.rs | 21 ++++++++++++++++++++ src/test/parse-fail/bounds-lifetime.rs | 23 ++++++++++++++++++++++ src/test/parse-fail/bounds-type-where-1.rs | 16 +++++++++++++++ src/test/parse-fail/bounds-type-where.rs | 21 ++++++++++++++++++++ src/test/parse-fail/bounds-type.rs | 23 ++++++++++++++++++++++ 13 files changed, 233 insertions(+) create mode 100644 src/test/compile-fail/impl-trait/no-trait.rs create mode 100644 src/test/compile-fail/where-equality-constraints.rs create mode 100644 src/test/compile-fail/where-lifetime-resolution.rs create mode 100644 src/test/parse-fail/bounds-lifetime-1.rs create mode 100644 src/test/parse-fail/bounds-lifetime-2.rs create mode 100644 src/test/parse-fail/bounds-lifetime-3.rs create mode 100644 src/test/parse-fail/bounds-lifetime-where-1.rs create mode 100644 src/test/parse-fail/bounds-lifetime-where-2.rs create mode 100644 src/test/parse-fail/bounds-lifetime-where.rs create mode 100644 src/test/parse-fail/bounds-lifetime.rs create mode 100644 src/test/parse-fail/bounds-type-where-1.rs create mode 100644 src/test/parse-fail/bounds-type-where.rs create mode 100644 src/test/parse-fail/bounds-type.rs (limited to 'src/test/parse-fail') diff --git a/src/test/compile-fail/impl-trait/no-trait.rs b/src/test/compile-fail/impl-trait/no-trait.rs new file mode 100644 index 00000000000..ce61c5bf63d --- /dev/null +++ b/src/test/compile-fail/impl-trait/no-trait.rs @@ -0,0 +1,15 @@ +// Copyright 2017 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. + +#![feature(conservative_impl_trait)] + +fn f() -> impl 'static {} //~ ERROR at least one trait must be specified + +fn main() {} diff --git a/src/test/compile-fail/where-equality-constraints.rs b/src/test/compile-fail/where-equality-constraints.rs new file mode 100644 index 00000000000..5b2fe2901c4 --- /dev/null +++ b/src/test/compile-fail/where-equality-constraints.rs @@ -0,0 +1,16 @@ +// Copyright 2017 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. + +fn f() where u8 = u16 {} +//~^ ERROR equality constraints are not yet supported in where clauses +fn g() where for<'a> &(u8,) == u16, {} +//~^ ERROR equality constraints are not yet supported in where clauses + +fn main() {} diff --git a/src/test/compile-fail/where-lifetime-resolution.rs b/src/test/compile-fail/where-lifetime-resolution.rs new file mode 100644 index 00000000000..f4c6842206d --- /dev/null +++ b/src/test/compile-fail/where-lifetime-resolution.rs @@ -0,0 +1,23 @@ +// Copyright 2017 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. + +trait Trait1 {} +trait Trait2 {} + +fn f() where + for<'a> Trait1<'a>: Trait1<'a>, // OK + (for<'a> Trait1<'a>): Trait1<'a>, + //~^ ERROR use of undeclared lifetime name `'a` + for<'a> for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>, + //~^ ERROR use of undeclared lifetime name `'b` + //~| ERROR nested quantification of lifetimes +{} + +fn main() {} diff --git a/src/test/parse-fail/bounds-lifetime-1.rs b/src/test/parse-fail/bounds-lifetime-1.rs new file mode 100644 index 00000000000..824d243d5f8 --- /dev/null +++ b/src/test/parse-fail/bounds-lifetime-1.rs @@ -0,0 +1,15 @@ +// Copyright 2017 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. + +// compile-flags: -Z parse-only + +type A = for<'a 'b> fn(); //~ ERROR expected one of `,`, `:`, or `>`, found `'b` + +fn main() {} diff --git a/src/test/parse-fail/bounds-lifetime-2.rs b/src/test/parse-fail/bounds-lifetime-2.rs new file mode 100644 index 00000000000..3c67dda70f5 --- /dev/null +++ b/src/test/parse-fail/bounds-lifetime-2.rs @@ -0,0 +1,15 @@ +// Copyright 2017 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. + +// compile-flags: -Z parse-only + +type A = for<'a + 'b> fn(); //~ ERROR expected one of `,`, `:`, or `>`, found `+` + +fn main() {} diff --git a/src/test/parse-fail/bounds-lifetime-3.rs b/src/test/parse-fail/bounds-lifetime-3.rs new file mode 100644 index 00000000000..be7c197245e --- /dev/null +++ b/src/test/parse-fail/bounds-lifetime-3.rs @@ -0,0 +1,15 @@ +// Copyright 2017 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. + +// compile-flags: -Z parse-only + +type A = for<,> fn(); //~ ERROR expected `>`, found `,` + +fn main() {} diff --git a/src/test/parse-fail/bounds-lifetime-where-1.rs b/src/test/parse-fail/bounds-lifetime-where-1.rs new file mode 100644 index 00000000000..aae9d729987 --- /dev/null +++ b/src/test/parse-fail/bounds-lifetime-where-1.rs @@ -0,0 +1,15 @@ +// Copyright 2017 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. + +// compile-flags: -Z parse-only + +type A where 'a; //~ ERROR expected `:`, found `;` + +fn main() {} diff --git a/src/test/parse-fail/bounds-lifetime-where-2.rs b/src/test/parse-fail/bounds-lifetime-where-2.rs new file mode 100644 index 00000000000..97dcd5cc5f8 --- /dev/null +++ b/src/test/parse-fail/bounds-lifetime-where-2.rs @@ -0,0 +1,15 @@ +// Copyright 2017 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. + +// compile-flags: -Z parse-only + +type A where , = u8; //~ ERROR expected `=`, found `,` + +fn main() {} diff --git a/src/test/parse-fail/bounds-lifetime-where.rs b/src/test/parse-fail/bounds-lifetime-where.rs new file mode 100644 index 00000000000..f7f56446006 --- /dev/null +++ b/src/test/parse-fail/bounds-lifetime-where.rs @@ -0,0 +1,21 @@ +// Copyright 2017 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. + +// compile-flags: -Z parse-only + +type A where 'a: 'b + 'c = u8; // OK +type A where 'a: 'b, = u8; // OK +type A where 'a: = u8; // OK +type A where 'a:, = u8; // OK +type A where 'a: 'b + 'c = u8; // OK +type A where = u8; // OK +type A where 'a: 'b + = u8; //~ ERROR expected one of `,` or `=`, found `+` + +fn main() {} diff --git a/src/test/parse-fail/bounds-lifetime.rs b/src/test/parse-fail/bounds-lifetime.rs new file mode 100644 index 00000000000..71547b543c3 --- /dev/null +++ b/src/test/parse-fail/bounds-lifetime.rs @@ -0,0 +1,23 @@ +// Copyright 2017 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. + +// compile-flags: -Z parse-only -Z continue-parse-after-error + +type A = for<'a: 'b + 'c> fn(); // OK +type A = for<'a: 'b,> fn(); // OK +type A = for<'a:> fn(); // OK +type A = for<'a:,> fn(); // OK +type A = for<'a> fn(); // OK +type A = for<> fn(); // OK + +type A = for<'a, T> fn(); //~ ERROR only lifetime parameters can be used in this context +type A = for<'a: 'b +> fn(); //~ ERROR expected one of `,` or `>`, found `+` + +fn main() {} diff --git a/src/test/parse-fail/bounds-type-where-1.rs b/src/test/parse-fail/bounds-type-where-1.rs new file mode 100644 index 00000000000..52b5035abda --- /dev/null +++ b/src/test/parse-fail/bounds-type-where-1.rs @@ -0,0 +1,16 @@ +// Copyright 2017 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. + +// compile-flags: -Z parse-only + +type A where T, = u8; +//~^ ERROR expected one of `!`, `(`, `+`, `::`, `:`, `<`, `==`, or `=`, found `,` + +fn main() {} diff --git a/src/test/parse-fail/bounds-type-where.rs b/src/test/parse-fail/bounds-type-where.rs new file mode 100644 index 00000000000..789a0934a83 --- /dev/null +++ b/src/test/parse-fail/bounds-type-where.rs @@ -0,0 +1,21 @@ +// Copyright 2017 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. + +// compile-flags: -Z parse-only + +type A where for<'a> for<'b> Trait1 + ?Trait2: 'a + Trait = u8; // OK +type A where T: Trait, = u8; // OK +type A where T: = u8; // OK +type A where T:, = u8; // OK +type A where T: Trait + Trait = u8; // OK +type A where = u8; // OK +type A where T: Trait + = u8; //~ ERROR expected one of `(`, `,`, `::`, `<`, or `=`, found `+` + +fn main() {} diff --git a/src/test/parse-fail/bounds-type.rs b/src/test/parse-fail/bounds-type.rs new file mode 100644 index 00000000000..6e339429eed --- /dev/null +++ b/src/test/parse-fail/bounds-type.rs @@ -0,0 +1,23 @@ +// Copyright 2017 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. + +// compile-flags: -Z parse-only -Z continue-parse-after-error + +struct S< + T: 'a + Tr, // OK + T: Tr + 'a, // OK + T: 'a, // OK + T:, // OK + T: ?for<'a: 'b + 'c> Trait, // OK + T: ?'a, //~ ERROR `?` may only modify trait bounds, not lifetime bounds + T: Tr +, //~ ERROR expected one of `(`, `,`, `::`, `<`, `=`, or `>`, found `+` +>; + +fn main() {} -- cgit 1.4.1-3-g733a5 From 375cb2eec70f239b477c6b88852c8258765b5420 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 18 Jan 2017 19:01:04 +0300 Subject: Improve some expected/found error messages from parser --- src/libsyntax/parse/parser.rs | 61 +++++++++++++++++++++----- src/test/compile-fail/issue-20616-3.rs | 2 +- src/test/compile-fail/issue-20616-4.rs | 3 +- src/test/compile-fail/issue-20616-5.rs | 3 +- src/test/compile-fail/issue-20616-6.rs | 3 +- src/test/compile-fail/issue-20616-7.rs | 2 +- src/test/compile-fail/issue-20616-8.rs | 2 +- src/test/compile-fail/issue-20616-9.rs | 2 +- src/test/parse-fail/bounds-lifetime-3.rs | 2 +- src/test/parse-fail/bounds-lifetime-where-2.rs | 2 +- 10 files changed, 61 insertions(+), 21 deletions(-) (limited to 'src/test/parse-fail') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c589f1a7aaa..939f126640d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -192,14 +192,22 @@ pub enum TokenType { Token(token::Token), Keyword(keywords::Keyword), Operator, + Lifetime, + Ident, + Path, + Type, } impl TokenType { fn to_string(&self) -> String { match *self { TokenType::Token(ref t) => format!("`{}`", Parser::token_to_string(t)), - TokenType::Operator => "an operator".to_string(), TokenType::Keyword(kw) => format!("`{}`", kw.name()), + TokenType::Operator => "an operator".to_string(), + TokenType::Lifetime => "lifetime".to_string(), + TokenType::Ident => "identifier".to_string(), + TokenType::Path => "path".to_string(), + TokenType::Type => "type".to_string(), } } } @@ -552,6 +560,33 @@ impl<'a> Parser<'a> { } } + fn check_ident(&mut self) -> bool { + if self.token.is_ident() { + true + } else { + self.expected_tokens.push(TokenType::Ident); + false + } + } + + fn check_path(&mut self) -> bool { + if self.token.is_path_start() { + true + } else { + self.expected_tokens.push(TokenType::Path); + false + } + } + + fn check_type(&mut self) -> bool { + if self.token.can_begin_type() { + true + } else { + self.expected_tokens.push(TokenType::Type); + false + } + } + /// Expect and consume an `&`. If `&&` is seen, replace it with a single /// `&` and continue. If an `&` is not seen, signal an error. fn expect_and(&mut self) -> PResult<'a, ()> { @@ -1802,7 +1837,10 @@ impl<'a> Parser<'a> { name: ident.name }) } - _ => None + _ => { + self.expected_tokens.push(TokenType::Lifetime); + None + } } } @@ -3953,7 +3991,7 @@ impl<'a> Parser<'a> { "`?` may only modify trait bounds, not lifetime bounds"); } bounds.push(RegionTyParamBound(lifetime)); - } else if self.token.is_keyword(keywords::For) || self.token.is_path_start() { + } else {if self.check_keyword(keywords::For) || self.check_path() { let poly_trait_ref = self.parse_poly_trait_ref()?; let modifier = if question.is_some() { TraitBoundModifier::Maybe @@ -3963,7 +4001,7 @@ impl<'a> Parser<'a> { bounds.push(TraitTyParamBound(poly_trait_ref, modifier)); } else { break - } + }} // Trailing plus is not allowed for now and we have to detect it. let is_bound_start = |token: &token::Token| { @@ -4047,7 +4085,7 @@ impl<'a> Parser<'a> { self.span_err(self.prev_span, "lifetime parameters must be declared prior to type parameters"); } - } else if self.token.is_ident() { + } else {if self.check_ident() { // Parse type parameter. ty_params.push(self.parse_ty_param(attrs)?); seen_ty_param = true; @@ -4059,7 +4097,7 @@ impl<'a> Parser<'a> { &format!("trailing attribute after {} parameters", param_kind)); } break - } + }} if !self.eat(&token::Comma) { break @@ -4105,7 +4143,6 @@ impl<'a> Parser<'a> { let mut seen_type = false; let mut seen_binding = false; loop { - let eq_is_next = self.look_ahead(1, |t| t == &token::Eq); // borrowck workaround if let Some(lifetime) = self.eat_lifetime() { // Parse lifetime argument. lifetimes.push(lifetime); @@ -4113,7 +4150,7 @@ impl<'a> Parser<'a> { self.span_err(self.prev_span, "lifetime parameters must be declared prior to type parameters"); } - } else if self.token.is_ident() && eq_is_next { + } else {if self.check_ident() && self.look_ahead(1, |t| t == &token::Eq) { // Parse associated type binding. let lo = self.span.lo; let ident = self.parse_ident()?; @@ -4126,7 +4163,7 @@ impl<'a> Parser<'a> { span: mk_sp(lo, self.prev_span.hi), }); seen_binding = true; - } else if self.token.can_begin_type() { + } else if self.check_type() { // Parse type argument. types.push(self.parse_ty()?); if seen_binding { @@ -4136,7 +4173,7 @@ impl<'a> Parser<'a> { seen_type = true; } else { break - } + }} if !self.eat(&token::Comma) { break @@ -4192,7 +4229,7 @@ impl<'a> Parser<'a> { bounds: bounds, } )); - } else if self.token.can_begin_type() { + } else {if self.check_type() { // Parse optional `for<'a, 'b>`. // This `for` is parsed greedily and applies to the whole predicate, // the bounded type can have its own `for` applying only to it. @@ -4230,7 +4267,7 @@ impl<'a> Parser<'a> { } } else { break - } + }} if !self.eat(&token::Comma) { break diff --git a/src/test/compile-fail/issue-20616-3.rs b/src/test/compile-fail/issue-20616-3.rs index 9a5972a7a16..e5ed46d2cb3 100644 --- a/src/test/compile-fail/issue-20616-3.rs +++ b/src/test/compile-fail/issue-20616-3.rs @@ -22,7 +22,7 @@ type Type_1_<'a, T> = &'a T; //type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(` -type Type_3 = Box; //~ error: expected `>`, found `,` +type Type_3 = Box; //~ error: expected one of `>`, identifier, lifetime, or type, found `,` //type Type_4 = Type_1_<'static,, T>; // error: expected type, found `,` diff --git a/src/test/compile-fail/issue-20616-4.rs b/src/test/compile-fail/issue-20616-4.rs index 1567698e476..9b731289e13 100644 --- a/src/test/compile-fail/issue-20616-4.rs +++ b/src/test/compile-fail/issue-20616-4.rs @@ -25,7 +25,8 @@ type Type_1_<'a, T> = &'a T; //type Type_3 = Box; // error: expected type, found `,` -type Type_4 = Type_1_<'static,, T>; //~ error: expected `>`, found `,` +type Type_4 = Type_1_<'static,, T>; +//~^ error: expected one of `>`, identifier, lifetime, or type, found `,` type Type_5_<'a> = Type_1_<'a, ()>; diff --git a/src/test/compile-fail/issue-20616-5.rs b/src/test/compile-fail/issue-20616-5.rs index c5a0624574d..5e3b024da9a 100644 --- a/src/test/compile-fail/issue-20616-5.rs +++ b/src/test/compile-fail/issue-20616-5.rs @@ -31,7 +31,8 @@ type Type_1_<'a, T> = &'a T; type Type_5_<'a> = Type_1_<'a, ()>; -type Type_5<'a> = Type_1_<'a, (),,>; //~ error: expected `>`, found `,` +type Type_5<'a> = Type_1_<'a, (),,>; +//~^ error: expected one of `>`, identifier, lifetime, or type, found `,` //type Type_6 = Type_5_<'a,,>; // error: expected type, found `,` diff --git a/src/test/compile-fail/issue-20616-6.rs b/src/test/compile-fail/issue-20616-6.rs index 56578409546..b6ee26f9f62 100644 --- a/src/test/compile-fail/issue-20616-6.rs +++ b/src/test/compile-fail/issue-20616-6.rs @@ -34,7 +34,8 @@ type Type_5_<'a> = Type_1_<'a, ()>; //type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,` -type Type_6 = Type_5_<'a,,>; //~ error: expected `>`, found `,` +type Type_6 = Type_5_<'a,,>; +//~^ error: expected one of `>`, identifier, lifetime, or type, found `,` //type Type_7 = Box<(),,>; // error: expected type, found `,` diff --git a/src/test/compile-fail/issue-20616-7.rs b/src/test/compile-fail/issue-20616-7.rs index ecd0a467cf6..fef3dd4e31d 100644 --- a/src/test/compile-fail/issue-20616-7.rs +++ b/src/test/compile-fail/issue-20616-7.rs @@ -37,7 +37,7 @@ type Type_5_<'a> = Type_1_<'a, ()>; //type Type_6 = Type_5_<'a,,>; // error: expected type, found `,` -type Type_7 = Box<(),,>; //~ error: expected `>`, found `,` +type Type_7 = Box<(),,>; //~ error: expected one of `>`, identifier, lifetime, or type, found `,` //type Type_8<'a,,> = &'a (); // error: expected ident, found `,` diff --git a/src/test/compile-fail/issue-20616-8.rs b/src/test/compile-fail/issue-20616-8.rs index 535672c65e4..b7bef47c4f4 100644 --- a/src/test/compile-fail/issue-20616-8.rs +++ b/src/test/compile-fail/issue-20616-8.rs @@ -40,7 +40,7 @@ type Type_5_<'a> = Type_1_<'a, ()>; //type Type_7 = Box<(),,>; // error: expected type, found `,` -type Type_8<'a,,> = &'a (); //~ error: expected `>`, found `,` +type Type_8<'a,,> = &'a (); //~ error: expected one of `>`, identifier, or lifetime, found `,` //type Type_9 = Box; // error: expected identifier, found `,` diff --git a/src/test/compile-fail/issue-20616-9.rs b/src/test/compile-fail/issue-20616-9.rs index b666a8b67aa..5c16d24cef8 100644 --- a/src/test/compile-fail/issue-20616-9.rs +++ b/src/test/compile-fail/issue-20616-9.rs @@ -43,4 +43,4 @@ type Type_5_<'a> = Type_1_<'a, ()>; //type Type_8<'a,,> = &'a (); // error: expected identifier, found `,` -type Type_9 = Box; //~ error: expected `>`, found `,` +type Type_9 = Box; //~ error: expected one of `>`, identifier, or lifetime, found `,` diff --git a/src/test/parse-fail/bounds-lifetime-3.rs b/src/test/parse-fail/bounds-lifetime-3.rs index be7c197245e..e0443159815 100644 --- a/src/test/parse-fail/bounds-lifetime-3.rs +++ b/src/test/parse-fail/bounds-lifetime-3.rs @@ -10,6 +10,6 @@ // compile-flags: -Z parse-only -type A = for<,> fn(); //~ ERROR expected `>`, found `,` +type A = for<,> fn(); //~ ERROR expected one of `>`, identifier, or lifetime, found `,` fn main() {} diff --git a/src/test/parse-fail/bounds-lifetime-where-2.rs b/src/test/parse-fail/bounds-lifetime-where-2.rs index 97dcd5cc5f8..ffcacdf357d 100644 --- a/src/test/parse-fail/bounds-lifetime-where-2.rs +++ b/src/test/parse-fail/bounds-lifetime-where-2.rs @@ -10,6 +10,6 @@ // compile-flags: -Z parse-only -type A where , = u8; //~ ERROR expected `=`, found `,` +type A where , = u8; //~ ERROR expected one of `=`, lifetime, or type, found `,` fn main() {} -- cgit 1.4.1-3-g733a5 From 65aeafa24f1542c23643a67172b7b2fec4f290cc Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 24 Jan 2017 22:55:45 +0300 Subject: parser: Permit trailing +'s in bound lists --- src/libsyntax/parse/parser.rs | 14 +++----------- src/test/parse-fail/bounds-lifetime-3.rs | 15 --------------- src/test/parse-fail/bounds-lifetime-where-2.rs | 15 --------------- src/test/parse-fail/bounds-lifetime-where.rs | 3 ++- src/test/parse-fail/bounds-lifetime.rs | 3 ++- src/test/parse-fail/bounds-type-where-1.rs | 16 ---------------- src/test/parse-fail/bounds-type-where.rs | 4 +++- src/test/parse-fail/bounds-type.rs | 2 +- 8 files changed, 11 insertions(+), 61 deletions(-) delete mode 100644 src/test/parse-fail/bounds-lifetime-3.rs delete mode 100644 src/test/parse-fail/bounds-lifetime-where-2.rs delete mode 100644 src/test/parse-fail/bounds-type-where-1.rs (limited to 'src/test/parse-fail') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 939f126640d..9e3c1dcef8a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4003,14 +4003,7 @@ impl<'a> Parser<'a> { break }} - // Trailing plus is not allowed for now and we have to detect it. - let is_bound_start = |token: &token::Token| { - token == &token::Question || token.is_lifetime() || - token.is_keyword(keywords::For) || token.is_path_start() - }; - if self.check(&token::BinOp(token::Plus)) && self.look_ahead(1, is_bound_start) { - self.bump(); - } else { + if !self.eat(&token::BinOp(token::Plus)) { break } } @@ -4024,9 +4017,8 @@ impl<'a> Parser<'a> { let mut lifetimes = Vec::new(); while let Some(lifetime) = self.eat_lifetime() { lifetimes.push(lifetime); - if self.check(&token::BinOp(token::Plus)) && self.look_ahead(1, |t| t.is_lifetime()) { - self.bump(); - } else { + + if !self.eat(&token::BinOp(token::Plus)) { break } } diff --git a/src/test/parse-fail/bounds-lifetime-3.rs b/src/test/parse-fail/bounds-lifetime-3.rs deleted file mode 100644 index e0443159815..00000000000 --- a/src/test/parse-fail/bounds-lifetime-3.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2017 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. - -// compile-flags: -Z parse-only - -type A = for<,> fn(); //~ ERROR expected one of `>`, identifier, or lifetime, found `,` - -fn main() {} diff --git a/src/test/parse-fail/bounds-lifetime-where-2.rs b/src/test/parse-fail/bounds-lifetime-where-2.rs deleted file mode 100644 index ffcacdf357d..00000000000 --- a/src/test/parse-fail/bounds-lifetime-where-2.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2017 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. - -// compile-flags: -Z parse-only - -type A where , = u8; //~ ERROR expected one of `=`, lifetime, or type, found `,` - -fn main() {} diff --git a/src/test/parse-fail/bounds-lifetime-where.rs b/src/test/parse-fail/bounds-lifetime-where.rs index f7f56446006..0a30818bc96 100644 --- a/src/test/parse-fail/bounds-lifetime-where.rs +++ b/src/test/parse-fail/bounds-lifetime-where.rs @@ -16,6 +16,7 @@ type A where 'a: = u8; // OK type A where 'a:, = u8; // OK type A where 'a: 'b + 'c = u8; // OK type A where = u8; // OK -type A where 'a: 'b + = u8; //~ ERROR expected one of `,` or `=`, found `+` +type A where 'a: 'b + = u8; // OK +type A where , = u8; //~ ERROR expected one of `=`, lifetime, or type, found `,` fn main() {} diff --git a/src/test/parse-fail/bounds-lifetime.rs b/src/test/parse-fail/bounds-lifetime.rs index 71547b543c3..5113a6b4803 100644 --- a/src/test/parse-fail/bounds-lifetime.rs +++ b/src/test/parse-fail/bounds-lifetime.rs @@ -16,8 +16,9 @@ type A = for<'a:> fn(); // OK type A = for<'a:,> fn(); // OK type A = for<'a> fn(); // OK type A = for<> fn(); // OK +type A = for<'a: 'b +> fn(); // OK type A = for<'a, T> fn(); //~ ERROR only lifetime parameters can be used in this context -type A = for<'a: 'b +> fn(); //~ ERROR expected one of `,` or `>`, found `+` +type A = for<,> fn(); //~ ERROR expected one of `>`, identifier, or lifetime, found `,` fn main() {} diff --git a/src/test/parse-fail/bounds-type-where-1.rs b/src/test/parse-fail/bounds-type-where-1.rs deleted file mode 100644 index 52b5035abda..00000000000 --- a/src/test/parse-fail/bounds-type-where-1.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2017 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. - -// compile-flags: -Z parse-only - -type A where T, = u8; -//~^ ERROR expected one of `!`, `(`, `+`, `::`, `:`, `<`, `==`, or `=`, found `,` - -fn main() {} diff --git a/src/test/parse-fail/bounds-type-where.rs b/src/test/parse-fail/bounds-type-where.rs index 789a0934a83..9dc5d827744 100644 --- a/src/test/parse-fail/bounds-type-where.rs +++ b/src/test/parse-fail/bounds-type-where.rs @@ -16,6 +16,8 @@ type A where T: = u8; // OK type A where T:, = u8; // OK type A where T: Trait + Trait = u8; // OK type A where = u8; // OK -type A where T: Trait + = u8; //~ ERROR expected one of `(`, `,`, `::`, `<`, or `=`, found `+` +type A where T: Trait + = u8; // OK +type A where T, = u8; +//~^ ERROR expected one of `!`, `(`, `+`, `::`, `:`, `<`, `==`, or `=`, found `,` fn main() {} diff --git a/src/test/parse-fail/bounds-type.rs b/src/test/parse-fail/bounds-type.rs index 6e339429eed..c224b44a14b 100644 --- a/src/test/parse-fail/bounds-type.rs +++ b/src/test/parse-fail/bounds-type.rs @@ -16,8 +16,8 @@ struct S< T: 'a, // OK T:, // OK T: ?for<'a: 'b + 'c> Trait, // OK + T: Tr +, // OK T: ?'a, //~ ERROR `?` may only modify trait bounds, not lifetime bounds - T: Tr +, //~ ERROR expected one of `(`, `,`, `::`, `<`, `=`, or `>`, found `+` >; fn main() {} -- cgit 1.4.1-3-g733a5