Actually check that the traits are the same for casting pointers to dyn _
This commit is contained in:
parent
e85295c321
commit
c7435571ad
@ -828,13 +828,18 @@ fn check_ptr_ptr_cast(
|
||||
(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.
|
||||
|
@ -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
|
||||
|
@ -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`.
|
||||
|
14
tests/ui/cast/ptr-to-trait-obj-wrap-upcast.rs
Normal file
14
tests/ui/cast/ptr-to-trait-obj-wrap-upcast.rs
Normal file
@ -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() {}
|
11
tests/ui/cast/ptr-to-trait-obj-wrap-upcast.stderr
Normal file
11
tests/ui/cast/ptr-to-trait-obj-wrap-upcast.stderr
Normal file
@ -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`.
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user