about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMaybe Waffle <waffle.lapkin@gmail.com>2024-01-22 17:22:09 +0000
committerMaybe Lapkin <waffle.lapkin@gmail.com>2024-07-04 17:56:08 +0200
commitd06cf5b3997aaf9fcb3a9a8f1dc608c3cdfafde5 (patch)
tree21b72aadb65abeec15b67109e1de54d70324823b
parent36b1f4411db4a35fbbeaec58f0603e4e086e851f (diff)
downloadrust-d06cf5b3997aaf9fcb3a9a8f1dc608c3cdfafde5.tar.gz
rust-d06cf5b3997aaf9fcb3a9a8f1dc608c3cdfafde5.zip
Forbid casts of raw pointers to trait objects with the same trait, but different args
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs6
-rw-r--r--tests/ui/cast/cast-rfc0401-vtable-kinds.rs12
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-different-args.rs6
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-different-args.stderr26
4 files changed, 31 insertions, 19 deletions
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index cb1a412d17e..3207e4ea533 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -44,7 +44,7 @@ use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::TyCtxt;
 use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitableExt, VariantDef};
 use rustc_session::lint;
-use rustc_span::def_id::{DefId, LOCAL_CRATE};
+use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_span::DUMMY_SP;
@@ -73,7 +73,7 @@ enum PointerKind<'tcx> {
     /// No metadata attached, ie pointer to sized type or foreign type
     Thin,
     /// A trait object
-    VTable(Option<DefId>),
+    VTable(Option<ty::Binder<'tcx, ty::ExistentialTraitRef<'tcx>>>),
     /// Slice
     Length,
     /// The unsize info of this projection or opaque type
@@ -101,7 +101,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         Ok(match *t.kind() {
             ty::Slice(_) | ty::Str => Some(PointerKind::Length),
-            ty::Dynamic(tty, _, ty::Dyn) => Some(PointerKind::VTable(tty.principal_def_id())),
+            ty::Dynamic(tty, _, ty::Dyn) => Some(PointerKind::VTable(tty.principal())),
             ty::Adt(def, args) if def.is_struct() => match def.non_enum_variant().tail_opt() {
                 None => Some(PointerKind::Thin),
                 Some(f) => {
diff --git a/tests/ui/cast/cast-rfc0401-vtable-kinds.rs b/tests/ui/cast/cast-rfc0401-vtable-kinds.rs
index 0d8f92f013f..b13ea94c4c9 100644
--- a/tests/ui/cast/cast-rfc0401-vtable-kinds.rs
+++ b/tests/ui/cast/cast-rfc0401-vtable-kinds.rs
@@ -16,13 +16,6 @@ impl<T> Foo<T> for () {}
 impl Foo<u32> for u32 { fn foo(&self, _: u32) -> u32 { self+43 } }
 impl Bar for () {}
 
-unsafe fn round_trip_and_call<'a>(t: *const (dyn Foo<u32>+'a)) -> u32 {
-    let foo_e : *const dyn Foo<u32> = t as *const _;
-    let r_1 = foo_e as *mut dyn Foo<u32>;
-
-    (&*r_1).foo(0)
-}
-
 #[repr(C)]
 struct FooS<T:?Sized>(T);
 #[repr(C)]
@@ -38,11 +31,6 @@ fn tuple_i32_to_u32<T:?Sized>(u: *const (i32, T)) -> *const (u32, T) {
 
 
 fn main() {
-    let x = 4u32;
-    let y : &dyn Foo<u32> = &x;
-    let fl = unsafe { round_trip_and_call(y as *const dyn Foo<u32>) };
-    assert_eq!(fl, (43+4));
-
     let s = FooS([0,1,2]);
     let u: &FooS<[u32]> = &s;
     let u: *const FooS<[u32]> = u;
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 2cb661ba016..e1c0c66433d 100644
--- a/tests/ui/cast/ptr-to-trait-obj-different-args.rs
+++ b/tests/ui/cast/ptr-to-trait-obj-different-args.rs
@@ -19,12 +19,12 @@ fn main() {
     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 _;
+    let y: *const dyn Trait<Y> = x as _; //~ error: casting `*const dyn Trait<X>` as `*const dyn Trait<Y>` is invalid
 
     _ = (b, y);
 }
 
 fn generic<T>(x: *const dyn Trait<X>, t: *const dyn Trait<T>) {
-    let _: *const dyn Trait<T> = x as _;
-    let _: *const dyn Trait<X> = t as _;
+    let _: *const dyn Trait<T> = x as _; //~ error: casting `*const (dyn Trait<X> + 'static)` as `*const dyn Trait<T>` is invalid
+    let _: *const dyn Trait<X> = t as _; //~ error: casting `*const (dyn Trait<T> + 'static)` as `*const dyn Trait<X>` is invalid
 }
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 14e8a48ffd9..cd67b52ad27 100644
--- a/tests/ui/cast/ptr-to-trait-obj-different-args.stderr
+++ b/tests/ui/cast/ptr-to-trait-obj-different-args.stderr
@@ -6,6 +6,30 @@ LL |     let b: *const dyn B = a as _;
    |
    = note: vtable kinds may not match
 
-error: aborting due to 1 previous error
+error[E0606]: casting `*const dyn Trait<X>` as `*const dyn Trait<Y>` is invalid
+  --> $DIR/ptr-to-trait-obj-different-args.rs:22:34
+   |
+LL |     let y: *const dyn Trait<Y> = x as _;
+   |                                  ^^^^^^
+   |
+   = note: vtable kinds may not match
+
+error[E0606]: casting `*const (dyn Trait<X> + 'static)` as `*const dyn Trait<T>` is invalid
+  --> $DIR/ptr-to-trait-obj-different-args.rs:28:34
+   |
+LL |     let _: *const dyn Trait<T> = x as _;
+   |                                  ^^^^^^
+   |
+   = note: vtable kinds may not match
+
+error[E0606]: casting `*const (dyn Trait<T> + 'static)` as `*const dyn Trait<X>` is invalid
+  --> $DIR/ptr-to-trait-obj-different-args.rs:29:34
+   |
+LL |     let _: *const dyn Trait<X> = t as _;
+   |                                  ^^^^^^
+   |
+   = note: vtable kinds may not match
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0606`.