Skip to content

Commit

Permalink
Auto merge of #49251 - nikomatsakis:issue-15872-elision-impl-header, …
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
bors committed Mar 24, 2018
2 parents a0b0f5f + 94468da commit b4aa80d
Show file tree
Hide file tree
Showing 20 changed files with 2,081 additions and 1,107 deletions.
5 changes: 4 additions & 1 deletion src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,10 @@ pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime
LifetimeName::Name(name) => {
visitor.visit_name(lifetime.span, name);
}
LifetimeName::Static | LifetimeName::Implicit | LifetimeName::Underscore => {}
LifetimeName::Fresh(_) |
LifetimeName::Static |
LifetimeName::Implicit |
LifetimeName::Underscore => {}
}
}

Expand Down
2,586 changes: 1,552 additions & 1,034 deletions src/librustc/hir/lowering.rs

Large diffs are not rendered by default.

32 changes: 30 additions & 2 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,31 @@ pub struct Lifetime {

#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
pub enum LifetimeName {
/// User typed nothing. e.g. the lifetime in `&u32`.
Implicit,

/// User typed `'_`.
Underscore,

/// Synthetic name generated when user elided a lifetime in an impl header,
/// e.g. the lifetimes in cases like these:
///
/// impl Foo for &u32
/// impl Foo<'_> for u32
///
/// in that case, we rewrite to
///
/// impl<'f> Foo for &'f u32
/// impl<'f> Foo<'f> for u32
///
/// where `'f` is something like `Fresh(0)`. The indices are
/// unique per impl, but not necessarily continuous.
Fresh(usize),

/// User wrote `'static`
Static,

/// Some user-given name like `'x`
Name(Name),
}

Expand All @@ -214,7 +236,7 @@ impl LifetimeName {
use self::LifetimeName::*;
match *self {
Implicit => keywords::Invalid.name(),
Underscore => keywords::UnderscoreLifetime.name(),
Fresh(_) | Underscore => keywords::UnderscoreLifetime.name(),
Static => keywords::StaticLifetime.name(),
Name(name) => name,
}
Expand All @@ -235,7 +257,13 @@ impl Lifetime {
use self::LifetimeName::*;
match self.name {
Implicit | Underscore => true,
Static | Name(_) => false,

// It might seem surprising that `Fresh(_)` counts as
// *not* elided -- but this is because, as far as the code
// in the compiler is concerned -- `Fresh(_)` variants act
// equivalently to "some fresh name". They correspond to
// early-bound regions on an impl, in other words.
Fresh(_) | Static | Name(_) => false,
}
}

Expand Down
1 change: 1 addition & 0 deletions src/librustc/ich/impls_hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItemId {
impl_stable_hash_for!(enum hir::LifetimeName {
Implicit,
Underscore,
Fresh(index),
Static,
Name(name)
});
Expand Down
Loading

0 comments on commit b4aa80d

Please sign in to comment.