Skip to content

Commit 11898a5

Browse files
authored
Rollup merge of #88205 - danii:e0772, r=GuillaumeGomez
Add Explanation For Error E0772 I've added an error explanation for the error code E0772. Assists with #61137
2 parents ca43894 + 4f8b9a4 commit 11898a5

File tree

4 files changed

+94
-3
lines changed

4 files changed

+94
-3
lines changed

compiler/rustc_error_codes/src/error_codes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,7 @@ E0768: include_str!("./error_codes/E0768.md"),
472472
E0769: include_str!("./error_codes/E0769.md"),
473473
E0770: include_str!("./error_codes/E0770.md"),
474474
E0771: include_str!("./error_codes/E0771.md"),
475+
E0772: include_str!("./error_codes/E0772.md"),
475476
E0773: include_str!("./error_codes/E0773.md"),
476477
E0774: include_str!("./error_codes/E0774.md"),
477478
E0775: include_str!("./error_codes/E0775.md"),
@@ -642,5 +643,4 @@ E0787: include_str!("./error_codes/E0787.md"),
642643
// E0723, // unstable feature in `const` context
643644
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
644645
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
645-
E0772, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`.
646646
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
A trait object has some specific lifetime `'1`, but it was used in a way that
2+
requires it to have a `'static` lifetime.
3+
4+
Example of erroneous code:
5+
6+
```compile_fail,E0772
7+
trait BooleanLike {}
8+
trait Person {}
9+
10+
impl BooleanLike for bool {}
11+
12+
impl dyn Person {
13+
fn is_cool(&self) -> bool {
14+
// hey you, you're pretty cool
15+
true
16+
}
17+
}
18+
19+
fn get_is_cool<'p>(person: &'p dyn Person) -> impl BooleanLike {
20+
// error: `person` has an anonymous lifetime `'p` but calling
21+
// `print_cool_fn` introduces an implicit `'static` lifetime
22+
// requirement
23+
person.is_cool()
24+
}
25+
```
26+
27+
The trait object `person` in the function `get_is_cool`, while already being
28+
behind a reference with lifetime `'p`, also has it's own implicit lifetime,
29+
`'2`.
30+
31+
Lifetime `'2` represents the data the trait object might hold inside, for
32+
example:
33+
34+
```
35+
trait MyTrait {}
36+
37+
struct MyStruct<'a>(&'a i32);
38+
39+
impl<'a> MyTrait for MyStruct<'a> {}
40+
```
41+
42+
With this scenario, if a trait object of `dyn MyTrait + '2` was made from
43+
`MyStruct<'a>`, `'a` must live as long, if not longer than `'2`. This allows the
44+
trait object's internal data to be accessed safely from any trait methods. This
45+
rule also goes for any lifetime any struct made into a trait object may have.
46+
47+
In the implementation for `dyn Person`, the `'2` lifetime representing the
48+
internal data was ommitted, meaning that the compiler inferred the lifetime
49+
`'static`. As a result, the implementation's `is_cool` is inferred by the
50+
compiler to look like this:
51+
52+
```
53+
# trait Person {}
54+
#
55+
# impl dyn Person {
56+
fn is_cool<'a>(self: &'a (dyn Person + 'static)) -> bool {unimplemented!()}
57+
# }
58+
```
59+
60+
While the `get_is_cool` function is inferred to look like this:
61+
62+
```
63+
# trait Person {}
64+
# trait BooleanLike {}
65+
#
66+
fn get_is_cool<'p, R: BooleanLike>(person: &'p (dyn Person + 'p)) -> R {
67+
unimplemented!()
68+
}
69+
```
70+
71+
Which brings us to the core of the problem; the assignment of type
72+
`&'_ (dyn Person + '_)` to type `&'_ (dyn Person + 'static)` is impossible.
73+
74+
Fixing it is as simple as being generic over lifetime `'2`, as to prevent the
75+
compiler from inferring it as `'static`:
76+
77+
```
78+
# trait Person {}
79+
#
80+
impl<'d> dyn Person + 'd {/* ... */}
81+
82+
// This works too, and is more elegant:
83+
//impl dyn Person + '_ {/* ... */}
84+
```
85+
86+
See the [Rust Reference on Trait Object Lifetime Bounds][trait-objects] for
87+
more information on trait object lifetimes.
88+
89+
[trait-object-lifetime-bounds]: https://doc.rust-lang.org/reference/types/trait-object.html#trait-object-lifetime-bounds

src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,5 @@ LL | impl MyTrait for Box<dyn ObjectTrait<Assoc = i32> + '_> {
3838

3939
error: aborting due to 4 previous errors
4040

41-
For more information about this error, try `rustc --explain E0515`.
41+
Some errors have detailed explanations: E0515, E0772.
42+
For more information about an error, try `rustc --explain E0515`.

src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr

+2-1
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,5 @@ LL | impl MyTrait for Box<dyn ObjectTrait + '_> {
131131

132132
error: aborting due to 6 previous errors
133133

134-
For more information about this error, try `rustc --explain E0759`.
134+
Some errors have detailed explanations: E0759, E0772.
135+
For more information about an error, try `rustc --explain E0759`.

0 commit comments

Comments
 (0)