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
This commit is contained in:
commit
11898a56c2
@ -472,6 +472,7 @@
|
|||||||
E0769: include_str!("./error_codes/E0769.md"),
|
E0769: include_str!("./error_codes/E0769.md"),
|
||||||
E0770: include_str!("./error_codes/E0770.md"),
|
E0770: include_str!("./error_codes/E0770.md"),
|
||||||
E0771: include_str!("./error_codes/E0771.md"),
|
E0771: include_str!("./error_codes/E0771.md"),
|
||||||
|
E0772: include_str!("./error_codes/E0772.md"),
|
||||||
E0773: include_str!("./error_codes/E0773.md"),
|
E0773: include_str!("./error_codes/E0773.md"),
|
||||||
E0774: include_str!("./error_codes/E0774.md"),
|
E0774: include_str!("./error_codes/E0774.md"),
|
||||||
E0775: include_str!("./error_codes/E0775.md"),
|
E0775: include_str!("./error_codes/E0775.md"),
|
||||||
@ -642,5 +643,4 @@
|
|||||||
// E0723, // unstable feature in `const` context
|
// E0723, // unstable feature in `const` context
|
||||||
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
|
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
|
||||||
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
|
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
|
||||||
E0772, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`.
|
|
||||||
}
|
}
|
||||||
|
89
compiler/rustc_error_codes/src/error_codes/E0772.md
Normal file
89
compiler/rustc_error_codes/src/error_codes/E0772.md
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
A trait object has some specific lifetime `'1`, but it was used in a way that
|
||||||
|
requires it to have a `'static` lifetime.
|
||||||
|
|
||||||
|
Example of erroneous code:
|
||||||
|
|
||||||
|
```compile_fail,E0772
|
||||||
|
trait BooleanLike {}
|
||||||
|
trait Person {}
|
||||||
|
|
||||||
|
impl BooleanLike for bool {}
|
||||||
|
|
||||||
|
impl dyn Person {
|
||||||
|
fn is_cool(&self) -> bool {
|
||||||
|
// hey you, you're pretty cool
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_is_cool<'p>(person: &'p dyn Person) -> impl BooleanLike {
|
||||||
|
// error: `person` has an anonymous lifetime `'p` but calling
|
||||||
|
// `print_cool_fn` introduces an implicit `'static` lifetime
|
||||||
|
// requirement
|
||||||
|
person.is_cool()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The trait object `person` in the function `get_is_cool`, while already being
|
||||||
|
behind a reference with lifetime `'p`, also has it's own implicit lifetime,
|
||||||
|
`'2`.
|
||||||
|
|
||||||
|
Lifetime `'2` represents the data the trait object might hold inside, for
|
||||||
|
example:
|
||||||
|
|
||||||
|
```
|
||||||
|
trait MyTrait {}
|
||||||
|
|
||||||
|
struct MyStruct<'a>(&'a i32);
|
||||||
|
|
||||||
|
impl<'a> MyTrait for MyStruct<'a> {}
|
||||||
|
```
|
||||||
|
|
||||||
|
With this scenario, if a trait object of `dyn MyTrait + '2` was made from
|
||||||
|
`MyStruct<'a>`, `'a` must live as long, if not longer than `'2`. This allows the
|
||||||
|
trait object's internal data to be accessed safely from any trait methods. This
|
||||||
|
rule also goes for any lifetime any struct made into a trait object may have.
|
||||||
|
|
||||||
|
In the implementation for `dyn Person`, the `'2` lifetime representing the
|
||||||
|
internal data was ommitted, meaning that the compiler inferred the lifetime
|
||||||
|
`'static`. As a result, the implementation's `is_cool` is inferred by the
|
||||||
|
compiler to look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
# trait Person {}
|
||||||
|
#
|
||||||
|
# impl dyn Person {
|
||||||
|
fn is_cool<'a>(self: &'a (dyn Person + 'static)) -> bool {unimplemented!()}
|
||||||
|
# }
|
||||||
|
```
|
||||||
|
|
||||||
|
While the `get_is_cool` function is inferred to look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
# trait Person {}
|
||||||
|
# trait BooleanLike {}
|
||||||
|
#
|
||||||
|
fn get_is_cool<'p, R: BooleanLike>(person: &'p (dyn Person + 'p)) -> R {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Which brings us to the core of the problem; the assignment of type
|
||||||
|
`&'_ (dyn Person + '_)` to type `&'_ (dyn Person + 'static)` is impossible.
|
||||||
|
|
||||||
|
Fixing it is as simple as being generic over lifetime `'2`, as to prevent the
|
||||||
|
compiler from inferring it as `'static`:
|
||||||
|
|
||||||
|
```
|
||||||
|
# trait Person {}
|
||||||
|
#
|
||||||
|
impl<'d> dyn Person + 'd {/* ... */}
|
||||||
|
|
||||||
|
// This works too, and is more elegant:
|
||||||
|
//impl dyn Person + '_ {/* ... */}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [Rust Reference on Trait Object Lifetime Bounds][trait-objects] for
|
||||||
|
more information on trait object lifetimes.
|
||||||
|
|
||||||
|
[trait-object-lifetime-bounds]: https://doc.rust-lang.org/reference/types/trait-object.html#trait-object-lifetime-bounds
|
@ -38,4 +38,5 @@ LL | impl MyTrait for Box<dyn ObjectTrait<Assoc = i32> + '_> {
|
|||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0515`.
|
Some errors have detailed explanations: E0515, E0772.
|
||||||
|
For more information about an error, try `rustc --explain E0515`.
|
||||||
|
@ -131,4 +131,5 @@ LL | impl MyTrait for Box<dyn ObjectTrait + '_> {
|
|||||||
|
|
||||||
error: aborting due to 6 previous errors
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0759`.
|
Some errors have detailed explanations: E0759, E0772.
|
||||||
|
For more information about an error, try `rustc --explain E0759`.
|
||||||
|
Loading…
Reference in New Issue
Block a user