Auto merge of #49251 - nikomatsakis:issue-15872-elision-impl-header, r=cramertj
support elision in impl headers
You can now do things like:
```
impl MyTrait<'_> for &u32 { ... }
```
Each `'_` or elided lifetime is a fresh parameter. `'_` and elision are still not permitted in associated type values. (Plausibly we could support that if there is a single input lifetime.) The original lifetime elision RFC was a bit unclear on this point: [as documented here, I think this is the correct interpretation, both because it fits existing impls and it's most analogous to the behavior in fns](https://github.com/rust-lang/rust/issues/15872#issuecomment-338700138).
We do not support elision with deprecated forms:
```
impl MyTrait for std::cell::Ref<u32> { } // ERROR
```
Builds on the in-band lifetime stuff.
r? @cramertj
Fixes #15872
This commit is contained in:
commit
b4aa80dd73
20 changed files with 2081 additions and 1107 deletions
22
src/test/ui/feature-gate-in_band_lifetimes-impl.rs
Normal file
22
src/test/ui/feature-gate-in_band_lifetimes-impl.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// 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.
|
||||
|
||||
#![allow(warnings)]
|
||||
#![feature(underscore_lifetimes)]
|
||||
|
||||
trait MyTrait<'a> { }
|
||||
|
||||
impl<'a> MyTrait<'a> for &u32 { }
|
||||
//~^ ERROR missing lifetime specifier
|
||||
|
||||
impl<'a> MyTrait<'_> for &'a f32 { }
|
||||
//~^ ERROR missing lifetime specifier
|
||||
|
||||
fn main() {}
|
||||
15
src/test/ui/feature-gate-in_band_lifetimes-impl.stderr
Normal file
15
src/test/ui/feature-gate-in_band_lifetimes-impl.stderr
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/feature-gate-in_band_lifetimes-impl.rs:16:26
|
||||
|
|
||||
LL | impl<'a> MyTrait<'a> for &u32 { }
|
||||
| ^ expected lifetime parameter
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/feature-gate-in_band_lifetimes-impl.rs:19:18
|
||||
|
|
||||
LL | impl<'a> MyTrait<'_> for &'a f32 { }
|
||||
| ^^ expected lifetime parameter
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0106`.
|
||||
38
src/test/ui/in-band-lifetimes/impl/assoc-type.rs
Normal file
38
src/test/ui/in-band-lifetimes/impl/assoc-type.rs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
// Test that we do not yet support elision in associated types, even
|
||||
// when there is just one name we could take from the impl header.
|
||||
|
||||
#![allow(warnings)]
|
||||
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(underscore_lifetimes)]
|
||||
|
||||
trait MyTrait {
|
||||
type Output;
|
||||
}
|
||||
|
||||
impl MyTrait for &i32 {
|
||||
type Output = &i32;
|
||||
//~^ ERROR missing lifetime specifier
|
||||
}
|
||||
|
||||
impl MyTrait for &u32 {
|
||||
type Output = &'_ i32;
|
||||
//~^ ERROR missing lifetime specifier
|
||||
}
|
||||
|
||||
// This is what you have to do:
|
||||
impl MyTrait for &'a f32 {
|
||||
type Output = &'a f32;
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
15
src/test/ui/in-band-lifetimes/impl/assoc-type.stderr
Normal file
15
src/test/ui/in-band-lifetimes/impl/assoc-type.stderr
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/assoc-type.rs:24:19
|
||||
|
|
||||
LL | type Output = &i32;
|
||||
| ^ expected lifetime parameter
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/assoc-type.rs:29:20
|
||||
|
|
||||
LL | type Output = &'_ i32;
|
||||
| ^^ expected lifetime parameter
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0106`.
|
||||
45
src/test/ui/in-band-lifetimes/impl/dyn-trait.rs
Normal file
45
src/test/ui/in-band-lifetimes/impl/dyn-trait.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
// Test that `impl MyTrait<'_> for &i32` is equivalent to `impl<'a,
|
||||
// 'b> MyTrait<'a> for &'b i32`.
|
||||
|
||||
#![allow(warnings)]
|
||||
|
||||
#![feature(dyn_trait)]
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(underscore_lifetimes)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
// Equivalent to `Box<dyn Debug + 'static>`:
|
||||
trait StaticTrait { }
|
||||
impl StaticTrait for Box<dyn Debug> { }
|
||||
|
||||
// Equivalent to `Box<dyn Debug + 'static>`:
|
||||
trait NotStaticTrait { }
|
||||
impl NotStaticTrait for Box<dyn Debug + '_> { }
|
||||
|
||||
fn static_val<T: StaticTrait>(_: T) {
|
||||
}
|
||||
|
||||
fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
|
||||
static_val(x); //~ ERROR cannot infer
|
||||
}
|
||||
|
||||
fn not_static_val<T: NotStaticTrait>(_: T) {
|
||||
}
|
||||
|
||||
fn with_dyn_debug_not_static<'a>(x: Box<dyn Debug + 'a>) {
|
||||
not_static_val(x); // OK
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
22
src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr
Normal file
22
src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
|
||||
--> $DIR/dyn-trait.rs:34:16
|
||||
|
|
||||
LL | static_val(x); //~ ERROR cannot infer
|
||||
| ^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 33:1...
|
||||
--> $DIR/dyn-trait.rs:33:1
|
||||
|
|
||||
LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: ...so that the expression is assignable:
|
||||
expected std::boxed::Box<std::fmt::Debug>
|
||||
found std::boxed::Box<std::fmt::Debug + 'a>
|
||||
= note: but, the lifetime must be valid for the static lifetime...
|
||||
= note: ...so that the types are compatible:
|
||||
expected StaticTrait
|
||||
found StaticTrait
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0495`.
|
||||
23
src/test/ui/in-band-lifetimes/impl/path-elided.rs
Normal file
23
src/test/ui/in-band-lifetimes/impl/path-elided.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2018 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.
|
||||
#![allow(warnings)]
|
||||
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(underscore_lifetimes)]
|
||||
|
||||
trait MyTrait { }
|
||||
|
||||
struct Foo<'a> { x: &'a u32 }
|
||||
|
||||
impl MyTrait for Foo {
|
||||
//~^ ERROR missing lifetime specifier
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
9
src/test/ui/in-band-lifetimes/impl/path-elided.stderr
Normal file
9
src/test/ui/in-band-lifetimes/impl/path-elided.stderr
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/path-elided.rs:19:18
|
||||
|
|
||||
LL | impl MyTrait for Foo {
|
||||
| ^^^ expected lifetime parameter
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0106`.
|
||||
47
src/test/ui/in-band-lifetimes/impl/path-underscore.rs
Normal file
47
src/test/ui/in-band-lifetimes/impl/path-underscore.rs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
// Test that `impl MyTrait for Foo<'_>` works.
|
||||
|
||||
// run-pass
|
||||
|
||||
#![allow(warnings)]
|
||||
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(underscore_lifetimes)]
|
||||
|
||||
trait MyTrait { }
|
||||
|
||||
struct Foo<'a> { x: &'a u32 }
|
||||
|
||||
impl MyTrait for Foo<'_> {
|
||||
}
|
||||
|
||||
fn impls_my_trait<T: MyTrait>() { }
|
||||
|
||||
fn impls_my_trait_val<T: MyTrait>(_: T) {
|
||||
impls_my_trait::<T>();
|
||||
}
|
||||
|
||||
fn random_where_clause()
|
||||
where for<'a> Foo<'a>: MyTrait { }
|
||||
|
||||
fn main() {
|
||||
let x = 22;
|
||||
let f = Foo { x: &x };
|
||||
|
||||
// This type is `Foo<'x>` for a local lifetime `'x`; so the impl
|
||||
// must apply to any lifetime to apply to this.
|
||||
impls_my_trait_val(f);
|
||||
|
||||
impls_my_trait::<Foo<'static>>();
|
||||
|
||||
random_where_clause();
|
||||
}
|
||||
43
src/test/ui/in-band-lifetimes/impl/ref-underscore.rs
Normal file
43
src/test/ui/in-band-lifetimes/impl/ref-underscore.rs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
// Test that `impl MyTrait for &i32` works and is equivalent to any lifetime.
|
||||
|
||||
// run-pass
|
||||
|
||||
#![allow(warnings)]
|
||||
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(underscore_lifetimes)]
|
||||
|
||||
trait MyTrait { }
|
||||
|
||||
impl MyTrait for &i32 {
|
||||
}
|
||||
|
||||
fn impls_my_trait<T: MyTrait>() { }
|
||||
|
||||
fn impls_my_trait_val<T: MyTrait>(_: T) {
|
||||
impls_my_trait::<T>();
|
||||
}
|
||||
|
||||
fn random_where_clause()
|
||||
where for<'a> &'a i32: MyTrait { }
|
||||
|
||||
fn main() {
|
||||
let x = 22;
|
||||
let f = &x;
|
||||
|
||||
impls_my_trait_val(f);
|
||||
|
||||
impls_my_trait::<&'static i32>();
|
||||
|
||||
random_where_clause();
|
||||
}
|
||||
21
src/test/ui/in-band-lifetimes/impl/trait-elided.rs
Normal file
21
src/test/ui/in-band-lifetimes/impl/trait-elided.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2018 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.
|
||||
#![allow(warnings)]
|
||||
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(underscore_lifetimes)]
|
||||
|
||||
trait MyTrait<'a> { }
|
||||
|
||||
impl MyTrait for u32 {
|
||||
//~^ ERROR missing lifetime specifier
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
9
src/test/ui/in-band-lifetimes/impl/trait-elided.stderr
Normal file
9
src/test/ui/in-band-lifetimes/impl/trait-elided.stderr
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/trait-elided.rs:17:6
|
||||
|
|
||||
LL | impl MyTrait for u32 {
|
||||
| ^^^^^^^ expected lifetime parameter
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0106`.
|
||||
48
src/test/ui/in-band-lifetimes/impl/trait-underscore.rs
Normal file
48
src/test/ui/in-band-lifetimes/impl/trait-underscore.rs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
// Test that `impl MyTrait<'_> for &i32` is equivalent to `impl<'a,
|
||||
// 'b> MyTrait<'a> for &'b i32`.
|
||||
//
|
||||
// run-pass
|
||||
|
||||
#![allow(warnings)]
|
||||
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(underscore_lifetimes)]
|
||||
|
||||
trait MyTrait<'a> { }
|
||||
|
||||
// This is equivalent to `MyTrait<'a> for &'b i32`, which is proven by
|
||||
// the code below.
|
||||
impl MyTrait<'_> for &i32 {
|
||||
}
|
||||
|
||||
// When called, T will be `&'x i32` for some `'x`, so since we can
|
||||
// prove that `&'x i32: for<'a> MyTrait<'a>, then we know that the
|
||||
// lifetime parameter above is disconnected.
|
||||
fn impls_my_trait<T: for<'a> MyTrait<'a>>() { }
|
||||
|
||||
fn impls_my_trait_val<T: for<'a> MyTrait<'a>>(_: T) {
|
||||
impls_my_trait::<T>();
|
||||
}
|
||||
|
||||
fn random_where_clause()
|
||||
where for<'a, 'b> &'a i32: MyTrait<'b> { }
|
||||
|
||||
fn main() {
|
||||
let x = 22;
|
||||
let f = &x;
|
||||
impls_my_trait_val(f);
|
||||
|
||||
impls_my_trait::<&'static i32>();
|
||||
|
||||
random_where_clause();
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2015 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.
|
||||
|
||||
// Check that the `'_` in `dyn Trait + '_` acts like ordinary elision,
|
||||
// and not like an object lifetime default.
|
||||
//
|
||||
// cc #48468
|
||||
|
||||
#![feature(dyn_trait)]
|
||||
#![feature(underscore_lifetimes)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
struct Foo {
|
||||
x: Box<dyn Debug + '_>, //~ ERROR missing lifetime specifier
|
||||
//~^ ERROR E0228
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/dyn-trait-underscore-in-struct.rs:22:24
|
||||
|
|
||||
LL | x: Box<dyn Debug + '_>, //~ ERROR missing lifetime specifier
|
||||
| ^^ expected lifetime parameter
|
||||
|
||||
error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
|
||||
--> $DIR/dyn-trait-underscore-in-struct.rs:22:12
|
||||
|
|
||||
LL | x: Box<dyn Debug + '_>, //~ ERROR missing lifetime specifier
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors occurred: E0106, E0228.
|
||||
For more information about an error, try `rustc --explain E0106`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue