about summary refs log tree commit diff
path: root/compiler/rustc_error_codes
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_error_codes')
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0804.md41
-rw-r--r--compiler/rustc_error_codes/src/lib.rs1
2 files changed, 42 insertions, 0 deletions
diff --git a/compiler/rustc_error_codes/src/error_codes/E0804.md b/compiler/rustc_error_codes/src/error_codes/E0804.md
new file mode 100644
index 00000000000..9a6937c0b52
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0804.md
@@ -0,0 +1,41 @@
+An auto trait cannot be added to the bounds of a `dyn Trait` type via
+a pointer cast.
+
+Erroneous code example:
+
+```rust,edition2021,compile_fail,E0804
+let ptr: *const dyn core::any::Any = &();
+_ = ptr as *const (dyn core::any::Any + Send);
+```
+
+Adding an auto trait can make the vtable invalid, potentially causing
+UB in safe code afterwards. For example:
+
+```rust,edition2021,no_run
+use core::{mem::transmute, ptr::NonNull};
+
+trait Trait {
+    fn f(&self)
+    where
+        Self: Send;
+}
+
+impl Trait for NonNull<()> {
+    fn f(&self) {
+        unreachable!()
+    }
+}
+
+fn main() {
+    let unsend: &dyn Trait = &NonNull::dangling();
+    let bad: &(dyn Trait + Send) = unsafe { transmute(unsend) };
+    // This crashes, since the vtable for `NonNull as dyn Trait` does
+    // not have an entry for `Trait::f`.
+    bad.f();
+}
+```
+
+To fix this error, you can use `transmute` rather than pointer casts,
+but you must ensure that the vtable is valid for the pointer's type
+before calling a method on the trait object or allowing other code to
+do so.
diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs
index 098ca42be2b..d53d5678832 100644
--- a/compiler/rustc_error_codes/src/lib.rs
+++ b/compiler/rustc_error_codes/src/lib.rs
@@ -547,6 +547,7 @@ E0800: 0800,
 E0801: 0801,
 E0802: 0802,
 E0803: 0803,
+E0804: 0804,
         );
     )
 }