]> git.lizzy.rs Git - rust.git/commitdiff
Add Explanation For Error E0772
authorDaniel Conley <himself@danii.dev>
Fri, 28 Jan 2022 16:00:56 +0000 (11:00 -0500)
committerDaniel Conley <himself@danii.dev>
Fri, 28 Jan 2022 16:00:56 +0000 (11:00 -0500)
compiler/rustc_error_codes/src/error_codes.rs
compiler/rustc_error_codes/src/error_codes/E0772.md [new file with mode: 0644]
src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr
src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr

index 724e3f7fed3996e1aeb2638a71681fda46a5a2ca..5dafbb26b83c793bc9a02bd7a66fa5fa8f237f06 100644 (file)
 E0769: include_str!("./error_codes/E0769.md"),
 E0770: include_str!("./error_codes/E0770.md"),
 E0771: include_str!("./error_codes/E0771.md"),
+E0772: include_str!("./error_codes/E0772.md"),
 E0773: include_str!("./error_codes/E0773.md"),
 E0774: include_str!("./error_codes/E0774.md"),
 E0775: include_str!("./error_codes/E0775.md"),
 //  E0723, unstable feature in `const` context
     E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
 //  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 {}`.
 }
diff --git a/compiler/rustc_error_codes/src/error_codes/E0772.md b/compiler/rustc_error_codes/src/error_codes/E0772.md
new file mode 100644 (file)
index 0000000..262e523
--- /dev/null
@@ -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
index 2961d8d7eacc99a9a0e59b6c3dc0d115dc2092d8..bd2e57517d7869a6ba4484909f250a4c90f4642e 100644 (file)
@@ -38,4 +38,5 @@ LL |     impl MyTrait for Box<dyn ObjectTrait<Assoc = i32> + '_> {
 
 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`.
index 6d9f0811b27358fee9f828610227ba87c6edf593..ea482ced98d624d5f07393ec038c04dc49677feb 100644 (file)
@@ -131,4 +131,5 @@ LL |     impl MyTrait for Box<dyn ObjectTrait + '_> {
 
 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`.