Skip to content

Commit b4aa80d

Browse files
committed
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](#15872 (comment)). 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
2 parents a0b0f5f + 94468da commit b4aa80d

20 files changed

+2081
-1107
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

+1,552-1,034
Large diffs are not rendered by default.

src/librustc/hir/mod.rs

+30-2
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,31 @@ pub struct Lifetime {
203203

204204
#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
205205
pub enum LifetimeName {
206+
/// User typed nothing. e.g. the lifetime in `&u32`.
206207
Implicit,
208+
209+
/// User typed `'_`.
207210
Underscore,
211+
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+
227+
/// User wrote `'static`
208228
Static,
229+
230+
/// Some user-given name like `'x`
209231
Name(Name),
210232
}
211233

@@ -214,7 +236,7 @@ impl LifetimeName {
214236
use self::LifetimeName::*;
215237
match *self {
216238
Implicit => keywords::Invalid.name(),
217-
Underscore => keywords::UnderscoreLifetime.name(),
239+
Fresh(_) | Underscore => keywords::UnderscoreLifetime.name(),
218240
Static => keywords::StaticLifetime.name(),
219241
Name(name) => name,
220242
}
@@ -235,7 +257,13 @@ impl Lifetime {
235257
use self::LifetimeName::*;
236258
match self.name {
237259
Implicit | Underscore => true,
238-
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,
239267
}
240268
}
241269

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
});

0 commit comments

Comments
 (0)