Skip to content

Commit 320c8e7

Browse files
Merge pull request #334 from matthewjasper/underscore-lifetime
Document underscore lifetime elision
2 parents f7debc8 + 06ca0bf commit 320c8e7

File tree

2 files changed

+37
-26
lines changed

2 files changed

+37
-26
lines changed

src/lifetime-elision.md

+36-26
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@ compiler can infer a sensible default choice.
55

66
## Lifetime elision in functions
77

8-
In order to make common patterns more ergonomic, Rust allows lifetimes to be
8+
In order to make common patterns more ergonomic, lifetime arguments can be
99
*elided* in [function item], [function pointer] and [closure trait] signatures.
1010
The following rules are used to infer lifetime parameters for elided lifetimes.
11-
It is an error to elide lifetime parameters that cannot be inferred.
11+
It is an error to elide lifetime parameters that cannot be inferred. The
12+
placeholder lifetime, `'_`, can also be used to have a lifetime inferred in the
13+
same way. For lifetimes in paths, using `'_` is preferred. Trait object
14+
lifetimes follow different rules discussed
15+
[below](#default-trait-object-lifetimes).
1216

1317
* Each elided lifetime in the parameters becomes a distinct lifetime parameter.
1418
* If there is exactly one lifetime used in the parameters (elided or not), that
@@ -23,6 +27,7 @@ Examples:
2327

2428
```rust,ignore
2529
fn print(s: &str); // elided
30+
fn print(s: &'_ str); // also elided
2631
fn print<'a>(s: &'a str); // expanded
2732
2833
fn debug(lvl: usize, s: &str); // elided
@@ -41,22 +46,27 @@ fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
4146
fn args<T: ToCStr>(&mut self, args: &[T]) -> &mut Command; // elided
4247
fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command; // expanded
4348
49+
fn new(buf: &mut [u8]) -> BufWriter<'_>; // elided - preferred
4450
fn new(buf: &mut [u8]) -> BufWriter; // elided
4551
fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a>; // expanded
4652
4753
type FunPtr = fn(&str) -> &str; // elided
4854
type FunPtr = for<'a> fn(&'a str) -> &'a str; // expanded
4955
50-
type FunTrait = Fn(&str) -> &str; // elided
51-
type FunTrait = for<'a> Fn(&'a str) -> &'a str; // expanded
56+
type FunTrait = dyn Fn(&str) -> &str; // elided
57+
type FunTrait = dyn for<'a> Fn(&'a str) -> &'a str; // expanded
5258
```
5359

5460
## Default trait object lifetimes
5561

5662
The assumed lifetime of references held by a [trait object] is called its
5763
_default object lifetime bound_. These were defined in [RFC 599] and amended in
58-
[RFC 1156]. Default object lifetime bounds are used instead of the lifetime
59-
parameter elision rules defined above.
64+
[RFC 1156].
65+
66+
These default object lifetime bounds are used instead of the lifetime parameter
67+
elision rules defined above when the lifetime bound is omitted entirely. If
68+
`'_` is used as the lifetime bound then the bound follows the usual elision
69+
rules.
6070

6171
If the trait object is used as a type argument of a generic type then the
6272
containing type is first used to try to infer a bound.
@@ -78,45 +88,45 @@ If neither of those rules apply, then the bounds on the trait are used:
7888
trait Foo { }
7989
8090
// These two are the same as Box<T> has no lifetime bound on T
81-
Box<Foo>
82-
Box<Foo + 'static>
91+
Box<dyn Foo>
92+
Box<dyn Foo + 'static>
8393
8494
// ...and so are these:
85-
impl Foo {}
86-
impl Foo + 'static {}
95+
impl dyn Foo {}
96+
impl dyn Foo + 'static {}
8797
8898
// ...so are these, because &'a T requires T: 'a
89-
&'a Foo
90-
&'a (Foo + 'a)
99+
&'a dyn Foo
100+
&'a (dyn Foo + 'a)
91101
92102
// std::cell::Ref<'a, T> also requires T: 'a, so these are the same
93-
std::cell::Ref<'a, Foo>
94-
std::cell::Ref<'a, Foo + 'a>
103+
std::cell::Ref<'a, dyn Foo>
104+
std::cell::Ref<'a, dyn Foo + 'a>
95105
96106
// This is an error:
97107
struct TwoBounds<'a, 'b, T: ?Sized + 'a + 'b>
98-
TwoBounds<'a, 'b, Foo> // Error: the lifetime bound for this object type cannot
99-
// be deduced from context
108+
TwoBounds<'a, 'b, dyn Foo> // Error: the lifetime bound for this object type
109+
// cannot be deduced from context
100110
```
101111

102-
Note that the innermost object sets the bound, so `&'a Box<Foo>` is still `&'a
103-
Box<Foo + 'static>`.
112+
Note that the innermost object sets the bound, so `&'a Box<dyn Foo>` is still
113+
`&'a Box<dyn Foo + 'static>`.
104114

105115
```rust,ignore
106116
// For the following trait...
107117
trait Bar<'a>: 'a { }
108118
109119
// ...these two are the same:
110-
Box<Bar<'a>>
111-
Box<Bar<'a> + 'a>
120+
Box<dyn Bar<'a>>
121+
Box<dyn Bar<'a> + 'a>
112122
113123
// ...and so are these:
114-
impl<'a> Foo<'a> {}
115-
impl<'a> Foo<'a> + 'a {}
124+
impl<'a> dyn Foo<'a> {}
125+
impl<'a> dyn Foo<'a> + 'a {}
116126
117127
// This is still an error:
118128
struct TwoBounds<'a, 'b, T: ?Sized + 'a + 'b>
119-
TwoBounds<'a, 'b, Foo<'c>>
129+
TwoBounds<'a, 'b, dyn Foo<'c>>
120130
```
121131

122132
## `'static` lifetime elision
@@ -136,7 +146,7 @@ struct BitsNStrings<'a> {
136146
}
137147

138148
// BITS_N_STRINGS: BitsNStrings<'static>
139-
const BITS_N_STRINGS: BitsNStrings = BitsNStrings {
149+
const BITS_N_STRINGS: BitsNStrings<'_> = BitsNStrings {
140150
mybits: [1, 2],
141151
mystring: STRING,
142152
};
@@ -152,11 +162,11 @@ usual rules, then it will error. By way of example:
152162
const RESOLVED_SINGLE: fn(&str) -> &str = ..
153163
154164
// Resolved as `Fn<'a, 'b, 'c>(&'a Foo, &'b Bar, &'c Baz) -> usize`.
155-
const RESOLVED_MULTIPLE: &Fn(&Foo, &Bar, &Baz) -> usize = ..
165+
const RESOLVED_MULTIPLE: &dyn Fn(&Foo, &Bar, &Baz) -> usize = ..
156166
157167
// There is insufficient information to bound the return reference lifetime
158168
// relative to the argument lifetimes, so this is an error.
159-
const RESOLVED_STATIC: &Fn(&Foo, &Bar) -> &Baz = ..
169+
const RESOLVED_STATIC: &dyn Fn(&Foo, &Bar) -> &Baz = ..
160170
```
161171

162172
[closure trait]: types.html#closure-types

src/trait-bounds.md

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
> _Lifetime_ :
2020
> &nbsp;&nbsp; &nbsp;&nbsp; [LIFETIME_OR_LABEL]
2121
> &nbsp;&nbsp; | `'static`
22+
> &nbsp;&nbsp; | `'_`
2223
2324
[Trait] and lifetime bounds provide a way for [generic items][generic] to
2425
restrict which types and lifetimes are used as their parameters. Bounds can be

0 commit comments

Comments
 (0)