Skip to content

Commit 94468da

Browse files
committed
permit '_ and &T in impl headers
Deprecated forms of elision are not supported.
1 parent df70060 commit 94468da

18 files changed

+617
-51
lines changed

src/librustc/hir/intravisit.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,10 @@ pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime
420420
LifetimeName::Name(name) => {
421421
visitor.visit_name(lifetime.span, name);
422422
}
423-
LifetimeName::Static | LifetimeName::Implicit | LifetimeName::Underscore => {}
423+
LifetimeName::Fresh(_) |
424+
LifetimeName::Static |
425+
LifetimeName::Implicit |
426+
LifetimeName::Underscore => {}
424427
}
425428
}
426429

src/librustc/hir/lowering.rs

+227-45
Large diffs are not rendered by default.

src/librustc/hir/mod.rs

+23-2
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,21 @@ pub enum LifetimeName {
209209
/// User typed `'_`.
210210
Underscore,
211211

212+
/// Synthetic name generated when user elided a lifetime in an impl header,
213+
/// e.g. the lifetimes in cases like these:
214+
///
215+
/// impl Foo for &u32
216+
/// impl Foo<'_> for u32
217+
///
218+
/// in that case, we rewrite to
219+
///
220+
/// impl<'f> Foo for &'f u32
221+
/// impl<'f> Foo<'f> for u32
222+
///
223+
/// where `'f` is something like `Fresh(0)`. The indices are
224+
/// unique per impl, but not necessarily continuous.
225+
Fresh(usize),
226+
212227
/// User wrote `'static`
213228
Static,
214229

@@ -221,7 +236,7 @@ impl LifetimeName {
221236
use self::LifetimeName::*;
222237
match *self {
223238
Implicit => keywords::Invalid.name(),
224-
Underscore => keywords::UnderscoreLifetime.name(),
239+
Fresh(_) | Underscore => keywords::UnderscoreLifetime.name(),
225240
Static => keywords::StaticLifetime.name(),
226241
Name(name) => name,
227242
}
@@ -242,7 +257,13 @@ impl Lifetime {
242257
use self::LifetimeName::*;
243258
match self.name {
244259
Implicit | Underscore => true,
245-
Static | Name(_) => false,
260+
261+
// It might seem surprising that `Fresh(_)` counts as
262+
// *not* elided -- but this is because, as far as the code
263+
// in the compiler is concerned -- `Fresh(_)` variants act
264+
// equivalently to "some fresh name". They correspond to
265+
// early-bound regions on an impl, in other words.
266+
Fresh(_) | Static | Name(_) => false,
246267
}
247268
}
248269

src/librustc/ich/impls_hir.rs

+1
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItemId {
145145
impl_stable_hash_for!(enum hir::LifetimeName {
146146
Implicit,
147147
Underscore,
148+
Fresh(index),
148149
Static,
149150
Name(name)
150151
});

src/librustc/middle/resolve_lifetime.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
582582
// cc #48468
583583
self.resolve_elided_lifetimes(slice::from_ref(lifetime), false)
584584
}
585-
LifetimeName::Static | LifetimeName::Name(_) => {
585+
LifetimeName::Fresh(_) | LifetimeName::Static | LifetimeName::Name(_) => {
586586
// If the user wrote an explicit name, use that.
587587
self.visit_lifetime(lifetime);
588588
}
@@ -2086,7 +2086,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
20862086
);
20872087
err.emit();
20882088
}
2089-
hir::LifetimeName::Implicit | hir::LifetimeName::Name(_) => {}
2089+
hir::LifetimeName::Fresh(_) | hir::LifetimeName::Implicit |
2090+
hir::LifetimeName::Name(_) => {}
20902091
}
20912092
}
20922093

@@ -2138,7 +2139,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
21382139
))
21392140
.emit();
21402141
}
2141-
hir::LifetimeName::Implicit | hir::LifetimeName::Name(_) => {
2142+
hir::LifetimeName::Fresh(_) | hir::LifetimeName::Implicit |
2143+
hir::LifetimeName::Name(_) => {
21422144
self.resolve_lifetime_ref(bound);
21432145
}
21442146
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![allow(warnings)]
12+
#![feature(underscore_lifetimes)]
13+
14+
trait MyTrait<'a> { }
15+
16+
impl<'a> MyTrait<'a> for &u32 { }
17+
//~^ ERROR missing lifetime specifier
18+
19+
impl<'a> MyTrait<'_> for &'a f32 { }
20+
//~^ ERROR missing lifetime specifier
21+
22+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0106]: missing lifetime specifier
2+
--> $DIR/feature-gate-in_band_lifetimes-impl.rs:16:26
3+
|
4+
LL | impl<'a> MyTrait<'a> for &u32 { }
5+
| ^ expected lifetime parameter
6+
7+
error[E0106]: missing lifetime specifier
8+
--> $DIR/feature-gate-in_band_lifetimes-impl.rs:19:18
9+
|
10+
LL | impl<'a> MyTrait<'_> for &'a f32 { }
11+
| ^^ expected lifetime parameter
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0106`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that we do not yet support elision in associated types, even
12+
// when there is just one name we could take from the impl header.
13+
14+
#![allow(warnings)]
15+
16+
#![feature(in_band_lifetimes)]
17+
#![feature(underscore_lifetimes)]
18+
19+
trait MyTrait {
20+
type Output;
21+
}
22+
23+
impl MyTrait for &i32 {
24+
type Output = &i32;
25+
//~^ ERROR missing lifetime specifier
26+
}
27+
28+
impl MyTrait for &u32 {
29+
type Output = &'_ i32;
30+
//~^ ERROR missing lifetime specifier
31+
}
32+
33+
// This is what you have to do:
34+
impl MyTrait for &'a f32 {
35+
type Output = &'a f32;
36+
}
37+
38+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0106]: missing lifetime specifier
2+
--> $DIR/assoc-type.rs:24:19
3+
|
4+
LL | type Output = &i32;
5+
| ^ expected lifetime parameter
6+
7+
error[E0106]: missing lifetime specifier
8+
--> $DIR/assoc-type.rs:29:20
9+
|
10+
LL | type Output = &'_ i32;
11+
| ^^ expected lifetime parameter
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0106`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that `impl MyTrait<'_> for &i32` is equivalent to `impl<'a,
12+
// 'b> MyTrait<'a> for &'b i32`.
13+
14+
#![allow(warnings)]
15+
16+
#![feature(dyn_trait)]
17+
#![feature(in_band_lifetimes)]
18+
#![feature(underscore_lifetimes)]
19+
20+
use std::fmt::Debug;
21+
22+
// Equivalent to `Box<dyn Debug + 'static>`:
23+
trait StaticTrait { }
24+
impl StaticTrait for Box<dyn Debug> { }
25+
26+
// Equivalent to `Box<dyn Debug + 'static>`:
27+
trait NotStaticTrait { }
28+
impl NotStaticTrait for Box<dyn Debug + '_> { }
29+
30+
fn static_val<T: StaticTrait>(_: T) {
31+
}
32+
33+
fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
34+
static_val(x); //~ ERROR cannot infer
35+
}
36+
37+
fn not_static_val<T: NotStaticTrait>(_: T) {
38+
}
39+
40+
fn with_dyn_debug_not_static<'a>(x: Box<dyn Debug + 'a>) {
41+
not_static_val(x); // OK
42+
}
43+
44+
fn main() {
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
2+
--> $DIR/dyn-trait.rs:34:16
3+
|
4+
LL | static_val(x); //~ ERROR cannot infer
5+
| ^
6+
|
7+
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 33:1...
8+
--> $DIR/dyn-trait.rs:33:1
9+
|
10+
LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
= note: ...so that the expression is assignable:
13+
expected std::boxed::Box<std::fmt::Debug>
14+
found std::boxed::Box<std::fmt::Debug + 'a>
15+
= note: but, the lifetime must be valid for the static lifetime...
16+
= note: ...so that the types are compatible:
17+
expected StaticTrait
18+
found StaticTrait
19+
20+
error: aborting due to previous error
21+
22+
For more information about this error, try `rustc --explain E0495`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
#![allow(warnings)]
11+
12+
#![feature(in_band_lifetimes)]
13+
#![feature(underscore_lifetimes)]
14+
15+
trait MyTrait { }
16+
17+
struct Foo<'a> { x: &'a u32 }
18+
19+
impl MyTrait for Foo {
20+
//~^ ERROR missing lifetime specifier
21+
}
22+
23+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0106]: missing lifetime specifier
2+
--> $DIR/path-elided.rs:19:18
3+
|
4+
LL | impl MyTrait for Foo {
5+
| ^^^ expected lifetime parameter
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0106`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that `impl MyTrait for Foo<'_>` works.
12+
13+
// run-pass
14+
15+
#![allow(warnings)]
16+
17+
#![feature(in_band_lifetimes)]
18+
#![feature(underscore_lifetimes)]
19+
20+
trait MyTrait { }
21+
22+
struct Foo<'a> { x: &'a u32 }
23+
24+
impl MyTrait for Foo<'_> {
25+
}
26+
27+
fn impls_my_trait<T: MyTrait>() { }
28+
29+
fn impls_my_trait_val<T: MyTrait>(_: T) {
30+
impls_my_trait::<T>();
31+
}
32+
33+
fn random_where_clause()
34+
where for<'a> Foo<'a>: MyTrait { }
35+
36+
fn main() {
37+
let x = 22;
38+
let f = Foo { x: &x };
39+
40+
// This type is `Foo<'x>` for a local lifetime `'x`; so the impl
41+
// must apply to any lifetime to apply to this.
42+
impls_my_trait_val(f);
43+
44+
impls_my_trait::<Foo<'static>>();
45+
46+
random_where_clause();
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that `impl MyTrait for &i32` works and is equivalent to any lifetime.
12+
13+
// run-pass
14+
15+
#![allow(warnings)]
16+
17+
#![feature(in_band_lifetimes)]
18+
#![feature(underscore_lifetimes)]
19+
20+
trait MyTrait { }
21+
22+
impl MyTrait for &i32 {
23+
}
24+
25+
fn impls_my_trait<T: MyTrait>() { }
26+
27+
fn impls_my_trait_val<T: MyTrait>(_: T) {
28+
impls_my_trait::<T>();
29+
}
30+
31+
fn random_where_clause()
32+
where for<'a> &'a i32: MyTrait { }
33+
34+
fn main() {
35+
let x = 22;
36+
let f = &x;
37+
38+
impls_my_trait_val(f);
39+
40+
impls_my_trait::<&'static i32>();
41+
42+
random_where_clause();
43+
}

0 commit comments

Comments
 (0)