]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_error_codes/src/error_codes/E0772.md
Rollup merge of #93556 - dtolnay:trailingcomma, r=cjgillot
[rust.git] / compiler / rustc_error_codes / src / error_codes / E0772.md
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