]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_error_codes/src/error_codes/E0772.md
Auto merge of #106227 - bryangarza:ctfe-limit, r=oli-obk
[rust.git] / compiler / rustc_error_codes / src / error_codes / E0772.md
1 #### Note: this error code is no longer emitted by the compiler.
2
3 A trait object has some specific lifetime `'1`, but it was used in a way that
4 requires it to have a `'static` lifetime.
5
6 Example of erroneous code:
7
8 ```compile_fail
9 trait BooleanLike {}
10 trait Person {}
11
12 impl BooleanLike for bool {}
13
14 impl dyn Person {
15     fn is_cool(&self) -> bool {
16         // hey you, you're pretty cool
17         true
18     }
19 }
20
21 fn get_is_cool<'p>(person: &'p dyn Person) -> impl BooleanLike {
22     // error: `person` has an anonymous lifetime `'p` but calling
23     //        `print_cool_fn` introduces an implicit `'static` lifetime
24     //        requirement
25     person.is_cool()
26 }
27 ```
28
29 The trait object `person` in the function `get_is_cool`, while already being
30 behind a reference with lifetime `'p`, also has it's own implicit lifetime,
31 `'2`.
32
33 Lifetime `'2` represents the data the trait object might hold inside, for
34 example:
35
36 ```
37 trait MyTrait {}
38
39 struct MyStruct<'a>(&'a i32);
40
41 impl<'a> MyTrait for MyStruct<'a> {}
42 ```
43
44 With this scenario, if a trait object of `dyn MyTrait + '2` was made from
45 `MyStruct<'a>`, `'a` must live as long, if not longer than `'2`. This allows the
46 trait object's internal data to be accessed safely from any trait methods. This
47 rule also goes for any lifetime any struct made into a trait object may have.
48
49 In the implementation for `dyn Person`, the `'2` lifetime representing the
50 internal data was omitted, meaning that the compiler inferred the lifetime
51 `'static`. As a result, the implementation's `is_cool` is inferred by the
52 compiler to look like this:
53
54 ```
55 # trait Person {}
56 #
57 # impl dyn Person {
58 fn is_cool<'a>(self: &'a (dyn Person + 'static)) -> bool {unimplemented!()}
59 # }
60 ```
61
62 While the `get_is_cool` function is inferred to look like this:
63
64 ```
65 # trait Person {}
66 # trait BooleanLike {}
67 #
68 fn get_is_cool<'p, R: BooleanLike>(person: &'p (dyn Person + 'p)) -> R {
69     unimplemented!()
70 }
71 ```
72
73 Which brings us to the core of the problem; the assignment of type
74 `&'_ (dyn Person + '_)` to type `&'_ (dyn Person + 'static)` is impossible.
75
76 Fixing it is as simple as being generic over lifetime `'2`, as to prevent the
77 compiler from inferring it as `'static`:
78
79 ```
80 # trait Person {}
81 #
82 impl<'d> dyn Person + 'd {/* ... */}
83
84 // This works too, and is more elegant:
85 //impl dyn Person + '_ {/* ... */}
86 ```
87
88 See the [Rust Reference on Trait Object Lifetime Bounds][trait-objects] for
89 more information on trait object lifetimes.
90
91 [trait-object-lifetime-bounds]: https://doc.rust-lang.org/reference/types/trait-object.html#trait-object-lifetime-bounds