Skip to content

Commit

Permalink
Merge pull request #166 from pnkfelix/fsk-fix-typo-in-39
Browse files Browse the repository at this point in the history
Clarify definition of "input positions" in lifetime elision RFC.
  • Loading branch information
alexcrichton committed Jul 15, 2014
2 parents dd6f306 + b02141b commit 5185160
Showing 1 changed file with 40 additions and 3 deletions.
43 changes: 40 additions & 3 deletions active/0039-lifetime-elision.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,20 @@ elided a single lifetime.

Lifetime positions can appear as either "input" or "output":

* For `fn` definitions, input refers to argument types while output refers to
* For `fn` definitions, input refers to the types of the formal arguments
in the `fn` definition, while output refers to
result types. So `fn foo(s: &str) -> (&str, &str)` has elided one lifetime in
input position and two lifetimes in output position.
Note that the input positions of a `fn` method definition do not
include the lifetimes that occur in the method's `impl` header
(nor lifetimes that occur in the trait header, for a default method).


* For `impl` headers, input refers to the lifetimes appears in the type
receiving the `impl`, while output refers to the trait, if any. So `impl<'a>
Foo<'a>` has `'a` in input position, while `impl<'a> SomeTrait<'a> Foo<'a>`
has `'a` in both input and output positions.
Foo<'a>` has `'a` in input position, while `impl<'a, 'b, 'c>
SomeTrait<'b, 'c> for Foo<'a, 'c>` has `'a` in input position, `'b`
in output position, and `'c` in both input and output positions.

### The rules

Expand Down Expand Up @@ -152,6 +158,37 @@ impl<'a, 'b> Reader for (&'a str, &'b str) { ... } // expanded

impl StrSlice for &str { ... } // elided
impl<'a> StrSlice<'a> for &'a str { ... } // expanded

trait Bar<'a> { fn bound(&'a self) -> &int { ... } fn fresh(&self) -> &int { ... } } // elided
trait Bar<'a> { fn bound(&'a self) -> &'a int { ... } fn fresh<'b>(&'b self) -> &'b int { ... } } // expanded

impl<'a> Bar<'a> for &'a str {
fn bound(&'a self) -> &'a int { ... } fn fresh(&self) -> &int { ... } // elided
}
impl<'a> Bar<'a> for &'a str {
fn bound(&'a self) -> &'a int { ... } fn fresh<'b>(&'b self) -> &'b int { ... } // expanded
}

// Note that when the impl reuses the same signature (with the same elisions)
// from the trait definition, the expanded forms will also match, and thus
// the `impl` will be compatible with the `trait`.

impl Bar for &str { fn bound(&self) -> &int { ... } } // elided
impl<'a> Bar<'a> for &'a str { fn bound<'b>(&'b self) -> &'b int { ... } } // expanded

// Note that the preceding example's expanded methods do not match the
// signatures from the above trait definition for `Bar`; in the general
// case, if the elided signatures between the `impl` and the `trait` do
// not match, an expanded `impl` may not be compatible with the given
// `trait` (and thus would not compile).

impl Bar for &str { fn fresh(&self) -> &int { ... } } // elided
impl<'a> Bar<'a> for &'a str { fn fresh<'b>(&'b self) -> &'b int { ... } } // expanded

impl Bar for &str {
fn bound(&'a self) -> &'a int { ... } fn fresh(&self) -> &int { ... } // ILLEGAL: unbound 'a
}

```

## Error messages
Expand Down

0 comments on commit 5185160

Please sign in to comment.