} else if self.eat_keyword(keywords::Impl) {
// FIXME: figure out priority of `+` in `impl Trait1 + Trait2` (#34511).
TyKind::ImplTrait(self.parse_ty_param_bounds()?)
- } else if self.check(&token::Question) {
+ } else if self.check(&token::Question) ||
+ self.check_lifetime() && self.look_ahead(1, |t| t == &token::BinOp(token::Plus)){
// Bound list (trait object type)
- // Bound lists starting with `'lt` are not currently supported (#40043)
TyKind::TraitObject(self.parse_ty_param_bounds_common(allow_plus)?)
} else {
let msg = format!("expected type, found {}", self.this_token_descr());
fn main() {
m!(Copy + Send + 'static); //~ ERROR the trait `std::marker::Copy` cannot be made into an object
+ m!('static + Send);
+ m!('static +); //~ ERROR at least one non-builtin trait is required for an object type
}
--- /dev/null
+// 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.
+
+// A few contrived examples where lifetime should (or should not) be parsed as an object type.
+// Lifetimes parsed as types are still rejected later by semantic checks.
+
+// compile-flags: -Z continue-parse-after-error
+
+// `'static` is a lifetime, `'static +` is a type, `'a` is a type
+fn g() where
+ 'static: 'static,
+ 'static +: 'static + Copy,
+ //~^ ERROR at least one non-builtin trait is required for an object type
+{}
+
+fn main() {}
--- /dev/null
+// 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.
+
+// A few contrived examples where lifetime should (or should not) be parsed as an object type.
+// Lifetimes parsed as types are still rejected later by semantic checks.
+
+// compile-flags: -Z continue-parse-after-error
+
+struct S<'a, T>(&'a u8, T);
+
+fn main() {
+ // `'static` is a lifetime argument, `'static +` is a type argument
+ let _: S<'static, u8>;
+ let _: S<'static, 'static +>;
+ //~^ at least one non-builtin trait is required for an object type
+ let _: S<'static, 'static>;
+ //~^ ERROR wrong number of lifetime parameters: expected 1, found 2
+ //~| ERROR wrong number of type arguments: expected 1, found 0
+ let _: S<'static +, 'static>;
+ //~^ ERROR lifetime parameters must be declared prior to type parameters
+ //~| ERROR at least one non-builtin trait is required for an object type
+}
--- /dev/null
+// 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.
+
+use std::fmt::Display;
+
+static BYTE: u8 = 33;
+
+fn main() {
+ let x: &('static + Display) = &BYTE;
+ let y: Box<'static + Display> = Box::new(BYTE);
+ let xstr = format!("{}", x);
+ let ystr = format!("{}", y);
+ assert_eq!(xstr, "33");
+ assert_eq!(ystr, "33");
+}