about summary refs log tree commit diff
diff options
context:
space:
mode:
authorWaffle Lapkin <waffle.lapkin@gmail.com>2024-06-04 15:47:16 +0200
committerMaybe Lapkin <waffle.lapkin@gmail.com>2024-07-04 17:56:09 +0200
commitc7435571ad725791494c32a48be1cd2c027af30b (patch)
treef213e5dbf339290e96749f047c8f5f842fcd1372
parente85295c3215bb9125e221df65feb563987045225 (diff)
downloadrust-c7435571ad725791494c32a48be1cd2c027af30b.tar.gz
rust-c7435571ad725791494c32a48be1cd2c027af30b.zip
Actually check that the traits are the same for casting pointers to dyn _
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs13
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-different-args.rs2
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-different-args.stderr9
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-wrap-upcast.rs14
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-wrap-upcast.stderr11
-rw-r--r--tests/ui/mismatched_types/cast-rfc0401.rs2
-rw-r--r--tests/ui/mismatched_types/cast-rfc0401.stderr6
7 files changed, 44 insertions, 13 deletions
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 5a0e307ef6f..1809f5e4b04 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -828,13 +828,18 @@ impl<'a, 'tcx> CastCheck<'tcx> {
             (Some(PointerKind::VTable(src_tty)), Some(PointerKind::VTable(dst_tty))) => {
                 match (src_tty.principal(), dst_tty.principal()) {
                     // A<dyn Trait + Auto> -> B<dyn Trait' + Auto'>. need to make sure
-                    // - traits are the same & have the same generic arguments
+                    // - traits are the same
+                    // - traits have the same generic arguments
                     // - Auto' is a subset of Auto
-                    //
-                    // This is checked by checking `dyn Trait + Auto + 'erased: Unsize<dyn Trait' + Auto' + 'erased>`.
-                    (Some(_), Some(_)) => {
+                    (Some(src_principal), Some(dst_principal)) => {
                         let tcx = fcx.tcx;
 
+                        // Check that the traits are actually the same
+                        // (this is required as the `Unsize` check below would allow upcasting, etc)
+                        if src_principal.def_id() != dst_principal.def_id() {
+                            return Err(CastError::DifferingKinds);
+                        }
+
                         // We need to reconstruct trait object types.
                         // `m_src` and `m_dst` won't work for us here because they will potentially
                         // contain wrappers, which we do not care about.
diff --git a/tests/ui/cast/ptr-to-trait-obj-different-args.rs b/tests/ui/cast/ptr-to-trait-obj-different-args.rs
index 41b6633d68a..88632f5506b 100644
--- a/tests/ui/cast/ptr-to-trait-obj-different-args.rs
+++ b/tests/ui/cast/ptr-to-trait-obj-different-args.rs
@@ -15,7 +15,7 @@ impl<T> Trait<Y> for T {}
 
 fn main() {
     let a: *const dyn A = &();
-    let b: *const dyn B = a as _; //~ error: the trait bound `dyn A: Unsize<dyn B>` is not satisfied
+    let b: *const dyn B = a as _; //~ error: casting `*const dyn A` as `*const dyn B` is invalid
 
     let x: *const dyn Trait<X> = &();
     let y: *const dyn Trait<Y> = x as _; //~ error: the trait bound `dyn Trait<X>: Unsize<dyn Trait<Y>>` is not satisfied
diff --git a/tests/ui/cast/ptr-to-trait-obj-different-args.stderr b/tests/ui/cast/ptr-to-trait-obj-different-args.stderr
index 74a95d85d4e..65f0be8541f 100644
--- a/tests/ui/cast/ptr-to-trait-obj-different-args.stderr
+++ b/tests/ui/cast/ptr-to-trait-obj-different-args.stderr
@@ -1,10 +1,10 @@
-error[E0277]: the trait bound `dyn A: Unsize<dyn B>` is not satisfied
+error[E0606]: casting `*const dyn A` as `*const dyn B` is invalid
   --> $DIR/ptr-to-trait-obj-different-args.rs:18:27
    |
 LL |     let b: *const dyn B = a as _;
-   |                           ^^^^^^ the trait `Unsize<dyn B>` is not implemented for `dyn A`
+   |                           ^^^^^^
    |
-   = note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information
+   = note: vtable kinds may not match
 
 error[E0277]: the trait bound `dyn Trait<X>: Unsize<dyn Trait<Y>>` is not satisfied
   --> $DIR/ptr-to-trait-obj-different-args.rs:21:34
@@ -48,4 +48,5 @@ LL |     x as _
 
 error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0277, E0606.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-upcast.rs b/tests/ui/cast/ptr-to-trait-obj-wrap-upcast.rs
new file mode 100644
index 00000000000..ff2c4cacfb1
--- /dev/null
+++ b/tests/ui/cast/ptr-to-trait-obj-wrap-upcast.rs
@@ -0,0 +1,14 @@
+trait Super {}
+trait Sub: Super {}
+
+struct Wrapper<T: ?Sized>(T);
+
+// This cast should not compile.
+// Upcasting can't work here, because we are also changing the type (`Wrapper`),
+// and reinterpreting would be confusing/surprising.
+// See <https://github.com/rust-lang/rust/pull/120248#discussion_r1487739518>
+fn cast(ptr: *const dyn Sub) -> *const Wrapper<dyn Super> {
+    ptr as _ //~ error: casting `*const (dyn Sub + 'static)` as `*const Wrapper<dyn Super>` is invalid
+}
+
+fn main() {}
diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-upcast.stderr b/tests/ui/cast/ptr-to-trait-obj-wrap-upcast.stderr
new file mode 100644
index 00000000000..38c8ba96bc5
--- /dev/null
+++ b/tests/ui/cast/ptr-to-trait-obj-wrap-upcast.stderr
@@ -0,0 +1,11 @@
+error[E0606]: casting `*const (dyn Sub + 'static)` as `*const Wrapper<dyn Super>` is invalid
+  --> $DIR/ptr-to-trait-obj-wrap-upcast.rs:11:5
+   |
+LL |     ptr as _
+   |     ^^^^^^^^
+   |
+   = note: vtable kinds may not match
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0606`.
diff --git a/tests/ui/mismatched_types/cast-rfc0401.rs b/tests/ui/mismatched_types/cast-rfc0401.rs
index 05e39f86cdf..b2ff5b4a0c0 100644
--- a/tests/ui/mismatched_types/cast-rfc0401.rs
+++ b/tests/ui/mismatched_types/cast-rfc0401.rs
@@ -66,7 +66,7 @@ fn main()
 
     let cf: *const dyn Foo = &0;
     let _ = cf as *const [u16]; //~ ERROR is invalid
-    let _ = cf as *const dyn Bar; //~ ERROR the trait bound `dyn Foo: Unsize<dyn Bar>` is not satisfied
+    let _ = cf as *const dyn Bar; //~ ERROR casting `*const dyn Foo` as `*const dyn Bar` is invalid
 
     vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>(); //~ ERROR is invalid
 }
diff --git a/tests/ui/mismatched_types/cast-rfc0401.stderr b/tests/ui/mismatched_types/cast-rfc0401.stderr
index 9f4a7aa858e..142a52aef13 100644
--- a/tests/ui/mismatched_types/cast-rfc0401.stderr
+++ b/tests/ui/mismatched_types/cast-rfc0401.stderr
@@ -210,13 +210,13 @@ LL |     let _ = cf as *const [u16];
    |
    = note: vtable kinds may not match
 
-error[E0277]: the trait bound `dyn Foo: Unsize<dyn Bar>` is not satisfied
+error[E0606]: casting `*const dyn Foo` as `*const dyn Bar` is invalid
   --> $DIR/cast-rfc0401.rs:69:13
    |
 LL |     let _ = cf as *const dyn Bar;
-   |             ^^^^^^^^^^^^^^^^^^^^ the trait `Unsize<dyn Bar>` is not implemented for `dyn Foo`
+   |             ^^^^^^^^^^^^^^^^^^^^
    |
-   = note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information
+   = note: vtable kinds may not match
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
   --> $DIR/cast-rfc0401.rs:53:13