提交 23a94697 编写于 作者: B bors

Auto merge of #39158 - petrochenkov:bounds, r=nikomatsakis

Bounds parsing refactoring 2

See https://github.com/rust-lang/rust/pull/37511 for previous discussion.
cc @matklad

Relaxed parsing rules:
 - zero bounds after `:` are allowed in all contexts.
 - zero predicates are allowed after `where`.
- trailing separator `,` is allowed after predicates in `where` clauses not followed by `{`.

Other parsing rules:
 - trailing separator `+` is still allowed in all bound lists.

Code is also cleaned up and tests added.

I haven't touched parsing of trait object types yet, I'll do it later.
......@@ -146,6 +146,12 @@ fn visit_ty(&mut self, ty: &'a Ty) {
TyKind::TraitObject(ref bounds) => {
self.no_questions_in_bounds(bounds, "trait object types", false);
}
TyKind::ImplTrait(ref bounds) => {
if !bounds.iter()
.any(|b| if let TraitTyParamBound(..) = *b { true } else { false }) {
self.err_handler().span_err(ty.span, "at least one trait must be specified");
}
}
_ => {}
}
......@@ -284,6 +290,26 @@ fn visit_vis(&mut self, vis: &'a Visibility) {
visit::walk_vis(self, vis)
}
fn visit_generics(&mut self, g: &'a Generics) {
let mut seen_default = None;
for ty_param in &g.ty_params {
if ty_param.default.is_some() {
seen_default = Some(ty_param.span);
} else if let Some(span) = seen_default {
self.err_handler()
.span_err(span, "type parameters with a default must be trailing");
break
}
}
for predicate in &g.where_clause.predicates {
if let WherePredicate::EqPredicate(ref predicate) = *predicate {
self.err_handler().span_err(predicate.span, "equality constraints are not yet \
supported in where clauses (#20041)");
}
}
visit::walk_generics(self, g)
}
}
pub fn check_crate(session: &Session, krate: &Crate) {
......
......@@ -1833,11 +1833,8 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
}
}
&hir::WherePredicate::EqPredicate(ref eq_pred) => {
&hir::WherePredicate::EqPredicate(..) => {
// FIXME(#20041)
span_bug!(eq_pred.span,
"Equality constraints are not yet \
implemented (#20041)")
}
}
}
......
......@@ -842,8 +842,11 @@ fn clean(&self, cx: &DocContext) -> WherePredicate {
}
}
hir::WherePredicate::EqPredicate(_) => {
unimplemented!() // FIXME(#20041)
hir::WherePredicate::EqPredicate(ref wrp) => {
WherePredicate::EqPredicate {
lhs: wrp.lhs_ty.clean(cx),
rhs: wrp.rhs_ty.clean(cx)
}
}
}
}
......
此差异已折叠。
......@@ -187,6 +187,29 @@ pub fn can_begin_expr(&self) -> bool {
}
}
/// Returns `true` if the token can appear at the start of a type.
pub fn can_begin_type(&self) -> bool {
match *self {
OpenDelim(Paren) => true, // tuple
OpenDelim(Bracket) => true, // array
Ident(..) => true, // type name or keyword
Underscore => true, // placeholder
Not => true, // never
BinOp(Star) => true, // raw pointer
BinOp(And) => true, // reference
AndAnd => true, // double reference
Lt | BinOp(Shl) => true, // associated path
ModSep => true, // global path
Interpolated(ref nt) => match **nt {
NtTy(..) => true,
NtIdent(..) => true,
NtPath(..) => true,
_ => false,
},
_ => false,
}
}
/// Returns `true` if the token is any literal
pub fn is_lit(&self) -> bool {
match *self {
......
......@@ -17,10 +17,7 @@
struct RefAny<'a, T>(&'a T);
impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {
//~^ ERROR expected identifier, found `>`
}
impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {}
//~^ ERROR trailing attribute after type parameters
fn main() {
}
fn main() {}
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct Heap;
struct Vec<A = Heap, T>;
//~^ ERROR type parameters with a default must be trailing
struct Foo<A, B = Vec<C>, C>;
//~^ ERROR type parameters with a default must be trailing
//~| ERROR type parameters with a default cannot use forward declared identifiers
fn main() {}
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
......@@ -16,7 +16,7 @@
type Type_1_<'a, T> = &'a T;
type Type_1<'a T> = &'a T; //~ error: expected `,` or `>` after lifetime name, found `T`
type Type_1<'a T> = &'a T; //~ error: expected one of `,`, `:`, or `>`, found `T`
//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
......
......@@ -19,7 +19,7 @@
//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
type Type_2 = Type_1_<'static ()>; //~ error: expected `,` or `>` after lifetime name, found `(`
type Type_2 = Type_1_<'static ()>; //~ error: expected one of `,` or `>`, found `(`
//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
......
......@@ -22,7 +22,7 @@
//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
type Type_3<T> = Box<T,,>; //~ error: expected type, found `,`
type Type_3<T> = Box<T,,>; //~ error: expected one of `>`, identifier, lifetime, or type, found `,`
//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
......
......@@ -25,7 +25,8 @@
//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
type Type_4<T> = Type_1_<'static,, T>; //~ error: expected type, found `,`
type Type_4<T> = Type_1_<'static,, T>;
//~^ error: expected one of `>`, identifier, lifetime, or type, found `,`
type Type_5_<'a> = Type_1_<'a, ()>;
......
......@@ -31,7 +31,8 @@
type Type_5_<'a> = Type_1_<'a, ()>;
type Type_5<'a> = Type_1_<'a, (),,>; //~ error: expected type, 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 `,`
......
......@@ -34,7 +34,8 @@
//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
type Type_6 = Type_5_<'a,,>; //~ error: expected type, found `,`
type Type_6 = Type_5_<'a,,>;
//~^ error: expected one of `>`, identifier, lifetime, or type, found `,`
//type Type_7 = Box<(),,>; // error: expected type, found `,`
......
......@@ -37,7 +37,7 @@
//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
type Type_7 = Box<(),,>; //~ error: expected type, found `,`
type Type_7 = Box<(),,>; //~ error: expected one of `>`, identifier, lifetime, or type, found `,`
//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
......
......@@ -40,7 +40,7 @@
//type Type_7 = Box<(),,>; // error: expected type, found `,`
type Type_8<'a,,> = &'a (); //~ error: expected identifier, found `,`
type Type_8<'a,,> = &'a (); //~ error: expected one of `>`, identifier, or lifetime, found `,`
//type Type_9<T,,> = Box<T>; // error: expected identifier, found `,`
......@@ -43,4 +43,4 @@
//type Type_8<'a,,> = &'a (); // error: expected identifier, found `,`
type Type_9<T,,> = Box<T>; //~ error: expected identifier, found `,`
type Type_9<T,,> = Box<T>; //~ error: expected one of `>`, identifier, or lifetime, found `,`
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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; // OK
type A where , = u8; //~ ERROR expected one of `=`, lifetime, or type, found `,`
fn main() {}
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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: 'b +> fn(); // OK
type A = for<'a, T> fn(); //~ ERROR only lifetime parameters can be used in this context
type A = for<,> fn(); //~ ERROR expected one of `>`, identifier, or lifetime, found `,`
fn main() {}
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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; // OK
type A where T, = u8;
//~^ ERROR expected one of `!`, `(`, `+`, `::`, `:`, `<`, `==`, or `=`, found `,`
fn main() {}
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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: Tr +, // OK
T: ?'a, //~ ERROR `?` may only modify trait bounds, not lifetime bounds
>;
fn main() {}
......@@ -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`
......@@ -10,10 +10,6 @@
// compile-flags: -Z parse-only -Z continue-parse-after-error
struct Heap;
struct Vec<A = Heap, T>; //~ ERROR type parameters with a default must be trailing
struct Foo<A, B = Vec<C>, C>; //~ ERROR type parameters with a default must be trailing
struct Bar<T> { x: T } where T: Copy //~ ERROR expected item, found `where`
fn main() {}
......@@ -13,7 +13,6 @@
struct Baz<U> where U: Eq(U); //This is parsed as the new Fn* style parenthesis syntax.
struct Baz<U> where U: Eq(U) -> R; // Notice this parses as well.
struct Baz<U>(U) where U: Eq; // This rightfully signals no error as well.
struct Foo<T> where T: Copy, (T); //~ ERROR unexpected token in `where` clause
struct Bar<T> { x: T } where T: Copy //~ ERROR expected item, found `where`
struct Foo<T> where T: Copy, (T); //~ ERROR expected one of `+`, `:`, `==`, or `=`, found `;`
fn main() {}
......@@ -10,8 +10,7 @@
// compile-flags: -Z parse-only -Z continue-parse-after-error
pub fn test<W, I: Iterator<Item=(), W> >() {
//~^ ERROR expected `=`, found `>`
}
pub fn test<W, I: Iterator<Item=(), W> >() {}
//~^ ERROR type parameters must be declared prior to associated type bindings
fn main() { }
......@@ -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 `;`
......@@ -10,13 +10,13 @@
// compile-flags: -Z parse-only -Z continue-parse-after-error
// Empty predicate list is OK
fn equal1<T>(_: &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, _: &T) -> bool where T: {
//~^ ERROR each predicate in a `where` clause must have at least one bound
true
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册