diff options
| author | Waffle Lapkin <waffle.lapkin@gmail.com> | 2024-06-04 15:47:16 +0200 |
|---|---|---|
| committer | Maybe Lapkin <waffle.lapkin@gmail.com> | 2024-07-04 17:56:09 +0200 |
| commit | c7435571ad725791494c32a48be1cd2c027af30b (patch) | |
| tree | f213e5dbf339290e96749f047c8f5f842fcd1372 | |
| parent | e85295c3215bb9125e221df65feb563987045225 (diff) | |
| download | rust-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.rs | 13 | ||||
| -rw-r--r-- | tests/ui/cast/ptr-to-trait-obj-different-args.rs | 2 | ||||
| -rw-r--r-- | tests/ui/cast/ptr-to-trait-obj-different-args.stderr | 9 | ||||
| -rw-r--r-- | tests/ui/cast/ptr-to-trait-obj-wrap-upcast.rs | 14 | ||||
| -rw-r--r-- | tests/ui/cast/ptr-to-trait-obj-wrap-upcast.stderr | 11 | ||||
| -rw-r--r-- | tests/ui/mismatched_types/cast-rfc0401.rs | 2 | ||||
| -rw-r--r-- | tests/ui/mismatched_types/cast-rfc0401.stderr | 6 |
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 |
