From 5927b913570c11aec73bad10752e9723abe18f2f Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Mon, 22 Jan 2024 15:44:02 +0100 Subject: [PATCH] implement Waffle's cast semantics --- compiler/rustc_middle/src/traits/select.rs | 4 +- compiler/rustc_middle/src/ty/context.rs | 2 +- .../src/traits/select/candidate_assembly.rs | 40 +++++++++++++++---- .../src/traits/select/confirmation.rs | 11 ++++- .../src/traits/select/mod.rs | 6 +-- library/alloc/src/boxed.rs | 6 +-- tests/ui/cast/cast-rfc0401-vtable-kinds.rs | 24 ----------- tests/ui/cast/fat-ptr-cast-borrowck.rs | 8 ++++ tests/ui/cast/fat-ptr-cast-borrowck.stderr | 28 +++++++++++++ tests/ui/cast/fat-ptr-cast-rpass.rs | 8 ++-- tests/ui/cast/fat-ptr-cast.rs | 13 ++++++ tests/ui/cast/fat-ptr-cast.stderr | 36 ++++++++++++++--- ...sue-114797-bad-parentheses-dyn-trait.fixed | 2 +- .../issue-114797-bad-parentheses-dyn-trait.rs | 2 +- tests/ui/traits/metadata-cast-fail-traits.rs | 1 + .../traits/metadata-cast-fail-traits.stderr | 37 ++++++++++++----- tests/ui/traits/metadata-cast-pass.rs | 12 ++++-- tests/ui/traits/upcast_soundness_bug.rs | 3 +- tests/ui/traits/upcast_soundness_bug.stderr | 11 +++++ 19 files changed, 185 insertions(+), 69 deletions(-) create mode 100644 tests/ui/cast/fat-ptr-cast-borrowck.rs create mode 100644 tests/ui/cast/fat-ptr-cast-borrowck.stderr create mode 100644 tests/ui/traits/upcast_soundness_bug.stderr diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index d0d12cbfcf9bb..ac1c071bee80b 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -180,11 +180,13 @@ pub enum SelectionCandidate<'tcx> { } #[derive(PartialEq, Eq, Debug, Clone, TypeVisitable)] -pub enum MetadataCastKind { +pub enum MetadataCastKind<'tcx> { /// No further obligations. Unconditional, /// `T: MetadataCast` if `T <: U`. Subtype, + /// Require principals of dyn traits to be equal. + Dyn(ty::PolyExistentialTraitRef<'tcx>, ty::PolyExistentialTraitRef<'tcx>), } /// The result of trait evaluation. The order is important diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 0d53870a0baf0..d46bcc0c22f0d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1760,7 +1760,7 @@ impl<'tcx> TyCtxt<'tcx> { /// does not compute the full elaborated super-predicates but just the set of def-ids. It is used /// to identify which traits may define a given associated type to help avoid cycle errors. /// Returns a `DefId` iterator. - fn super_traits_of(self, trait_def_id: DefId) -> impl Iterator + 'tcx { + pub fn super_traits_of(self, trait_def_id: DefId) -> impl Iterator + 'tcx { let mut set = FxHashSet::default(); let mut stack = vec![trait_def_id]; diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index a62544e65149d..cdddb695f9c27 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -1183,21 +1183,47 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } + let tcx = self.tcx(); if let ty::Adt(src_def, src_args) = source.kind() && let ty::Adt(tgt_def, tgt_args) = target.kind() && src_def == tgt_def - && Some(src_def.did()) == self.tcx().lang_items().dyn_metadata() + && Some(src_def.did()) == tcx.lang_items().dyn_metadata() { let src_dyn = src_args.type_at(0); let tgt_dyn = tgt_args.type_at(0); - // We could theoretically allow casting the principal away, but `as` casts - // don't allow that, so neither does `MetadataCast` for now. - if let ty::Dynamic(src_pred, _, ty::Dyn) = src_dyn.kind() - && let ty::Dynamic(tgt_pred, _, ty::Dyn) = tgt_dyn.kind() - && src_pred.principal_def_id() == tgt_pred.principal_def_id() + if let ty::Dynamic(src_preds, _, ty::Dyn) = src_dyn.kind() + && let ty::Dynamic(tgt_preds, _, ty::Dyn) = tgt_dyn.kind() { - candidates.vec.push(MetadataCastCandidate(MetadataCastKind::Unconditional)); + let mut src_traits = src_preds.auto_traits().collect::>(); + + if let Some(src_principal_did) = src_preds.principal_def_id() { + src_traits.extend(tcx.super_traits_of(src_principal_did)); + } + + for tgt_auto_trait in tgt_preds.auto_traits() { + if !src_traits.contains(&tgt_auto_trait) { + // Adding auto traits that aren't on the source or implied by + // the source principal is not allowed. + return; + } + } + + if let Some(src_principal) = src_preds.principal() { + if let Some(tgt_principal) = tgt_preds.principal() { + candidates.vec.push(MetadataCastCandidate(MetadataCastKind::Dyn( + src_principal, + tgt_principal, + ))); + } else { + // We could theoretically allow casting the principal away, but `as` casts + // don't allow that, so neither does `MetadataCast` for now. + } + } else if tgt_preds.principal().is_none() { + // Casting between auto-trait-only trait objects is allowed if the target + // traits are a subset of the source traits, which we checked above. + candidates.vec.push(MetadataCastCandidate(MetadataCastKind::Unconditional)); + } return; } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 26a8e026b6a09..393fdaf738942 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -281,7 +281,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_metadata_cast_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - kind: MetadataCastKind, + kind: MetadataCastKind<'tcx>, ) -> Result>, SelectionError<'tcx>> { match kind { MetadataCastKind::Unconditional => Ok(Vec::new()), @@ -297,6 +297,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(obligations) } + MetadataCastKind::Dyn(source, target) => { + let InferOk { obligations, .. } = self + .infcx + .at(&obligation.cause, obligation.param_env) + .eq(DefineOpaqueTypes::No, source, target) + .map_err(|_| Unimplemented)?; + + Ok(obligations) + } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 1bf8578dfda60..92bb6c5057f04 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1910,7 +1910,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | BuiltinUnsizeCandidate | TraitUpcastingUnsizeCandidate(_) | BuiltinCandidate { has_nested: true } - | MetadataCastCandidate(MetadataCastKind::Subtype) + | MetadataCastCandidate(MetadataCastKind::Subtype | MetadataCastKind::Dyn(..)) | TraitAliasCandidate, ParamCandidate(ref victim_cand), ) => { @@ -2073,7 +2073,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | BuiltinUnsizeCandidate | TraitUpcastingUnsizeCandidate(_) | BuiltinCandidate { has_nested: true } - | MetadataCastCandidate(MetadataCastKind::Subtype) + | MetadataCastCandidate(MetadataCastKind::Subtype | MetadataCastKind::Dyn(..)) | TraitAliasCandidate, ImplCandidate(_) | ClosureCandidate { .. } @@ -2086,7 +2086,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | BuiltinUnsizeCandidate | TraitUpcastingUnsizeCandidate(_) | BuiltinCandidate { has_nested: true } - | MetadataCastCandidate(MetadataCastKind::Subtype) + | MetadataCastCandidate(MetadataCastKind::Subtype | MetadataCastKind::Dyn(..)) | TraitAliasCandidate, ) => DropVictim::No, } diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 6977681e5a397..f8ecc9ba56da7 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -2192,7 +2192,7 @@ impl dyn Error + Send { let err: Box = self; ::downcast(err).map_err(|s| unsafe { // Reapply the `Send` marker. - Box::from_raw(Box::into_raw(s) as *mut (dyn Error + Send)) + mem::transmute::, Box>(s) }) } } @@ -2205,8 +2205,8 @@ impl dyn Error + Send + Sync { pub fn downcast(self: Box) -> Result, Box> { let err: Box = self; ::downcast(err).map_err(|s| unsafe { - // Reapply the `Send + Sync` marker. - Box::from_raw(Box::into_raw(s) as *mut (dyn Error + Send + Sync)) + // Reapply the `Send + Sync` markers. + mem::transmute::, Box>(s) }) } } diff --git a/tests/ui/cast/cast-rfc0401-vtable-kinds.rs b/tests/ui/cast/cast-rfc0401-vtable-kinds.rs index 249481467e646..ec7e8f27107a1 100644 --- a/tests/ui/cast/cast-rfc0401-vtable-kinds.rs +++ b/tests/ui/cast/cast-rfc0401-vtable-kinds.rs @@ -4,25 +4,6 @@ #![feature(unsized_tuple_coercion)] -trait Foo { - fn foo(&self, _: T) -> u32 { 42 } -} - -trait Bar { - fn bar(&self) { println!("Bar!"); } -} - -impl Foo for () {} -impl Foo for u32 { fn foo(&self, _: u32) -> u32 { self+43 } } -impl Bar for () {} - -unsafe fn round_trip_and_call<'a>(t: *const (dyn Foo+'a)) -> u32 { - let foo_e : *const dyn Foo = t as *const _; - let r_1 = foo_e as *mut dyn Foo; - - (&*r_1).foo(0) -} - #[repr(C)] struct FooS(T); #[repr(C)] @@ -38,11 +19,6 @@ fn tuple_i32_to_u32(u: *const (i32, T)) -> *const (u32, T) { fn main() { - let x = 4u32; - let y : &dyn Foo = &x; - let fl = unsafe { round_trip_and_call(y as *const dyn Foo) }; - 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/fat-ptr-cast-borrowck.rs b/tests/ui/cast/fat-ptr-cast-borrowck.rs new file mode 100644 index 0000000000000..a1d24eb08b60b --- /dev/null +++ b/tests/ui/cast/fat-ptr-cast-borrowck.rs @@ -0,0 +1,8 @@ +trait LifetimeParam<'a> {} +fn lifetime_param<'a, 'b>(ptr: *const dyn LifetimeParam<'a>) -> *const dyn LifetimeParam<'b> { + ptr as _ + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/cast/fat-ptr-cast-borrowck.stderr b/tests/ui/cast/fat-ptr-cast-borrowck.stderr new file mode 100644 index 0000000000000..db5c842c6feab --- /dev/null +++ b/tests/ui/cast/fat-ptr-cast-borrowck.stderr @@ -0,0 +1,28 @@ +error: lifetime may not live long enough + --> $DIR/fat-ptr-cast-borrowck.rs:3:5 + | +LL | fn lifetime_param<'a, 'b>(ptr: *const dyn LifetimeParam<'a>) -> *const dyn LifetimeParam<'b> { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | ptr as _ + | ^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/fat-ptr-cast-borrowck.rs:3:5 + | +LL | fn lifetime_param<'a, 'b>(ptr: *const dyn LifetimeParam<'a>) -> *const dyn LifetimeParam<'b> { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | ptr as _ + | ^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +help: `'b` and `'a` must be the same: replace one with the other + +error: aborting due to 2 previous errors + diff --git a/tests/ui/cast/fat-ptr-cast-rpass.rs b/tests/ui/cast/fat-ptr-cast-rpass.rs index f55b017c19b46..5eadf2272007e 100644 --- a/tests/ui/cast/fat-ptr-cast-rpass.rs +++ b/tests/ui/cast/fat-ptr-cast-rpass.rs @@ -2,7 +2,7 @@ #![feature(ptr_metadata)] -trait Foo { +trait Foo: Send { fn foo(&self) {} } @@ -54,10 +54,10 @@ fn main() { assert_eq!(b, d); assert_eq!(c, d); - // Adding auto traits is OK. + // Adding auto traits is OK if they're implied by the principal. let _ = a as *mut (dyn Foo + Send); - // Casting between auto-trait-only trait objects is OK. - let unprincipled: *mut dyn Send = &mut Bar; + // Removing traits from auto-trait-only trait objects is OK. + let unprincipled: *mut (dyn Send + Sync) = &mut Bar; let _ = unprincipled as *mut dyn Sync; } diff --git a/tests/ui/cast/fat-ptr-cast.rs b/tests/ui/cast/fat-ptr-cast.rs index 3d36d2298d14b..0bf631e303173 100644 --- a/tests/ui/cast/fat-ptr-cast.rs +++ b/tests/ui/cast/fat-ptr-cast.rs @@ -81,9 +81,17 @@ fn main() { let _ = cf as *const [u16]; //~ ERROR is invalid let _ = cf as *const dyn Bar; //~ ERROR is invalid + // Adding auto traits is not allowed. + let _ = cf as *const (dyn Foo + Send); //~ ERROR is invalid + // casting principal away is not allowed for now let _ = cf as *const dyn Send; //~ ERROR is invalid + // Casting between auto-trait-only trait objects requires the target traits + // to be a subset of the source traits. + let unprincipled: *mut dyn Send = &mut (); + let _ = unprincipled as *mut dyn Sync; //~ ERROR is invalid + vec![0.0].iter().map(|s| s as f32).collect::>(); //~ ERROR is invalid } @@ -101,3 +109,8 @@ fn illegal_cast_2(u: *const U) -> *const str { u as *const str //~ ERROR is invalid } + +trait TypeParam {} +fn type_param(ptr: *const dyn TypeParam) -> *const dyn TypeParam { + ptr as _ //~ ERROR is invalid +} diff --git a/tests/ui/cast/fat-ptr-cast.stderr b/tests/ui/cast/fat-ptr-cast.stderr index 951bc9bb906dd..a1c73eb2e5a1e 100644 --- a/tests/ui/cast/fat-ptr-cast.stderr +++ b/tests/ui/cast/fat-ptr-cast.stderr @@ -278,14 +278,30 @@ LL | let _ = cf as *const dyn Bar; | = note: vtable kinds may not match -error[E0606]: casting `*const dyn Foo` as `*const dyn Send` is invalid +error[E0606]: casting `*const dyn Foo` as `*const dyn Foo + Send` is invalid --> $DIR/fat-ptr-cast.rs:85:13 | +LL | let _ = cf as *const (dyn Foo + Send); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: vtable kinds may not match + +error[E0606]: casting `*const dyn Foo` as `*const dyn Send` is invalid + --> $DIR/fat-ptr-cast.rs:88:13 + | LL | let _ = cf as *const dyn Send; | ^^^^^^^^^^^^^^^^^^^^^ | = note: vtable kinds may not match +error[E0606]: casting `*mut dyn Send` as `*mut dyn Sync` is invalid + --> $DIR/fat-ptr-cast.rs:93:13 + | +LL | let _ = unprincipled as *mut dyn Sync; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: vtable kinds may not match + error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> $DIR/fat-ptr-cast.rs:66:13 | @@ -305,7 +321,7 @@ LL | let _ = a as *const dyn Foo; = note: required for the cast from `*const str` to `*const dyn Foo` error[E0606]: casting `&{float}` as `f32` is invalid - --> $DIR/fat-ptr-cast.rs:87:30 + --> $DIR/fat-ptr-cast.rs:95:30 | LL | vec![0.0].iter().map(|s| s as f32).collect::>(); | ^^^^^^^^ @@ -316,7 +332,7 @@ LL | vec![0.0].iter().map(|s| *s as f32).collect::>(); | + error[E0606]: cannot cast `usize` to a pointer that may be wide - --> $DIR/fat-ptr-cast.rs:91:18 + --> $DIR/fat-ptr-cast.rs:99:18 | LL | let s = 0 as *const T; | - ^^^^^^^^ creating a `*const T` requires both an address and type-specific metadata @@ -324,7 +340,7 @@ LL | let s = 0 as *const T; | consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts` error[E0606]: casting `*const U` as `*const V` is invalid - --> $DIR/fat-ptr-cast.rs:97:5 + --> $DIR/fat-ptr-cast.rs:105:5 | LL | u as *const V | ^^^^^^^^^^^^^ @@ -332,14 +348,22 @@ LL | u as *const V = note: vtable kinds may not match error[E0606]: casting `*const U` as `*const str` is invalid - --> $DIR/fat-ptr-cast.rs:102:5 + --> $DIR/fat-ptr-cast.rs:110:5 | LL | u as *const str | ^^^^^^^^^^^^^^^ | = note: vtable kinds may not match -error: aborting due to 46 previous errors +error[E0606]: casting `*const (dyn TypeParam + 'static)` as `*const dyn TypeParam` is invalid + --> $DIR/fat-ptr-cast.rs:115:5 + | +LL | ptr as _ + | ^^^^^^^^ + | + = note: vtable kinds may not match + +error: aborting due to 49 previous errors Some errors have detailed explanations: E0054, E0277, E0604, E0605, E0606, E0607, E0609. For more information about an error, try `rustc --explain E0054`. diff --git a/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed index 57387936a4cab..4a00369e34535 100644 --- a/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed +++ b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed @@ -5,7 +5,7 @@ trait Trait {} fn assert_send(ptr: *mut dyn Trait) -> *mut (dyn Trait + Send) { //~^ ERROR incorrect parentheses around trait bounds - ptr as _ + unsafe { std::mem::transmute(ptr) } } fn foo2(_: &(dyn Trait + Send)) {} diff --git a/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs index 8a1939bcfe93c..cd779294da4bd 100644 --- a/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs +++ b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs @@ -5,7 +5,7 @@ trait Trait {} fn assert_send(ptr: *mut dyn Trait) -> *mut dyn (Trait + Send) { //~^ ERROR incorrect parentheses around trait bounds - ptr as _ + unsafe { std::mem::transmute(ptr) } } fn foo2(_: &dyn (Trait + Send)) {} diff --git a/tests/ui/traits/metadata-cast-fail-traits.rs b/tests/ui/traits/metadata-cast-fail-traits.rs index e1624e1b79c18..78c42879e9b7f 100644 --- a/tests/ui/traits/metadata-cast-fail-traits.rs +++ b/tests/ui/traits/metadata-cast-fail-traits.rs @@ -23,6 +23,7 @@ fn main() { check::<(), DynMetadata>(); //~ ERROR not satisfied check::>(); //~ ERROR not satisfied check::, usize>(); //~ ERROR not satisfied + check::, dyn Trait + Send>(); //~ ERROR not satisfied check::, DynMetadata>(); //~ ERROR not satisfied check::(); //~ ERROR not satisfied diff --git a/tests/ui/traits/metadata-cast-fail-traits.stderr b/tests/ui/traits/metadata-cast-fail-traits.stderr index 7525335c4d7bc..dec599a7970fa 100644 --- a/tests/ui/traits/metadata-cast-fail-traits.stderr +++ b/tests/ui/traits/metadata-cast-fail-traits.stderr @@ -58,9 +58,24 @@ LL | where LL | T: MetadataCast, | ^^^^^^^^^^^^^^^ required by this bound in `check` -error[E0277]: the trait bound `DynMetadata: MetadataCast>` is not satisfied +error[E0277]: the trait bound `DynMetadata: MetadataCast` is not satisfied --> $DIR/metadata-cast-fail-traits.rs:26:13 | +LL | check::, dyn Trait + Send>(); + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `MetadataCast` is not implemented for `DynMetadata` + | +note: required by a bound in `check` + --> $DIR/metadata-cast-fail-traits.rs:14:8 + | +LL | fn check() + | ----- required by a bound in this function +LL | where +LL | T: MetadataCast, + | ^^^^^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `DynMetadata: MetadataCast>` is not satisfied + --> $DIR/metadata-cast-fail-traits.rs:27:13 + | LL | check::, DynMetadata>(); | ^^^^^^^^^^^^^^^^^^^^^^ the trait `MetadataCast>` is not implemented for `DynMetadata` | @@ -74,7 +89,7 @@ LL | T: MetadataCast, | ^^^^^^^^^^^^^^^ required by this bound in `check` error[E0277]: the trait bound `dyn Trait + Send: MetadataCast` is not satisfied - --> $DIR/metadata-cast-fail-traits.rs:27:13 + --> $DIR/metadata-cast-fail-traits.rs:28:13 | LL | check::(); | ^^^^^^^^^^^^^^^^ the trait `MetadataCast` is not implemented for `dyn Trait + Send` @@ -89,7 +104,7 @@ LL | T: MetadataCast, | ^^^^^^^^^^^^^^^ required by this bound in `check` error[E0277]: the trait bound `dyn MetadataCast: MetadataCast` is not satisfied - --> $DIR/metadata-cast-fail-traits.rs:30:13 + --> $DIR/metadata-cast-fail-traits.rs:31:13 | LL | check::, usize>(); | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `MetadataCast` is not implemented for `dyn MetadataCast` @@ -104,7 +119,7 @@ LL | T: MetadataCast, | ^^^^^^^^^^^^^^^ required by this bound in `check` error[E0277]: the trait bound `DynMetadata: MetadataCast>` is not satisfied - --> $DIR/metadata-cast-fail-traits.rs:33:13 + --> $DIR/metadata-cast-fail-traits.rs:34:13 | LL | check::, DynMetadata>(); | ^^^^^^^^^^^^^^^^^^^^^^ the trait `MetadataCast>` is not implemented for `DynMetadata` @@ -119,7 +134,7 @@ LL | T: MetadataCast, | ^^^^^^^^^^^^^^^ required by this bound in `check` error[E0277]: the trait bound `(): MetadataCast` is not satisfied - --> $DIR/metadata-cast-fail-traits.rs:37:29 + --> $DIR/metadata-cast-fail-traits.rs:38:29 | LL | let _: *mut [u8] = cast(thin); | ---- ^^^^ the trait `MetadataCast` is not implemented for `()` @@ -137,7 +152,7 @@ LL | T: PointerCast, | ^^^^^^^^^^^^^^ required by this bound in `cast` error[E0277]: the trait bound `(): MetadataCast>` is not satisfied - --> $DIR/metadata-cast-fail-traits.rs:38:34 + --> $DIR/metadata-cast-fail-traits.rs:39:34 | LL | let _: *mut dyn Trait = cast(thin); | ---- ^^^^ the trait `MetadataCast>` is not implemented for `()` @@ -155,7 +170,7 @@ LL | T: PointerCast, | ^^^^^^^^^^^^^^ required by this bound in `cast` error[E0277]: the trait bound `DynMetadata: MetadataCast` is not satisfied - --> $DIR/metadata-cast-fail-traits.rs:39:29 + --> $DIR/metadata-cast-fail-traits.rs:40:29 | LL | let _: *mut [u8] = cast(trait_object); | ---- ^^^^^^^^^^^^ the trait `MetadataCast` is not implemented for `DynMetadata` @@ -173,7 +188,7 @@ LL | T: PointerCast, | ^^^^^^^^^^^^^^ required by this bound in `cast` error[E0277]: the trait bound `usize: MetadataCast>` is not satisfied - --> $DIR/metadata-cast-fail-traits.rs:40:34 + --> $DIR/metadata-cast-fail-traits.rs:41:34 | LL | let _: *mut dyn Trait = cast(slice); | ---- ^^^^^ the trait `MetadataCast>` is not implemented for `usize` @@ -191,7 +206,7 @@ LL | T: PointerCast, | ^^^^^^^^^^^^^^ required by this bound in `cast` error[E0277]: the trait bound `DynMetadata: MetadataCast>` is not satisfied - --> $DIR/metadata-cast-fail-traits.rs:41:35 + --> $DIR/metadata-cast-fail-traits.rs:42:35 | LL | let _: *mut dyn Trait2 = cast(trait_object); | ---- ^^^^^^^^^^^^ the trait `MetadataCast>` is not implemented for `DynMetadata` @@ -209,7 +224,7 @@ LL | T: PointerCast, | ^^^^^^^^^^^^^^ required by this bound in `cast` error[E0277]: the trait bound `DynMetadata: MetadataCast>` is not satisfied - --> $DIR/metadata-cast-fail-traits.rs:44:33 + --> $DIR/metadata-cast-fail-traits.rs:45:33 | LL | let _: *mut dyn Send = cast(trait_object); | ---- ^^^^^^^^^^^^ the trait `MetadataCast>` is not implemented for `DynMetadata` @@ -226,6 +241,6 @@ LL | where LL | T: PointerCast, | ^^^^^^^^^^^^^^ required by this bound in `cast` -error: aborting due to 14 previous errors +error: aborting due to 15 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/metadata-cast-pass.rs b/tests/ui/traits/metadata-cast-pass.rs index 73104781ac086..436d59d84bf0f 100644 --- a/tests/ui/traits/metadata-cast-pass.rs +++ b/tests/ui/traits/metadata-cast-pass.rs @@ -17,6 +17,7 @@ where } trait Trait {} +trait ImpliesSend: Send {} fn main() { // any to () is OK @@ -31,9 +32,12 @@ fn main() { check::, DynMetadata>(); check::, dyn MetadataCast>(); - // changing auto traits of trait object in DynMetadata is OK - check::, DynMetadata>(); - check::, DynMetadata>(); + // removing auto traits of trait object in DynMetadata is OK + check::, DynMetadata>(); + check::, DynMetadata>(); + + // adding implied auto traits is OK + check::, DynMetadata>(); } fn lifetimes_ok<'a, 'b>() { @@ -45,7 +49,7 @@ fn lifetimes_ok<'a, 'b>() { check::<&'static (), &'a ()>(); } -fn do_casts<'a>(thin: &mut i32, slice: &mut [i32], trait_object: &mut dyn Trait) { +fn do_casts<'a>(thin: &mut i32, slice: &mut [i32], trait_object: &mut (dyn Trait + Send + Sync)) { let _: *mut u8 = cast(thin); let _: *mut u8 = cast(slice); let _: *mut [u8] = cast(slice); diff --git a/tests/ui/traits/upcast_soundness_bug.rs b/tests/ui/traits/upcast_soundness_bug.rs index 32e32850925f7..ed51b6b38a7c6 100644 --- a/tests/ui/traits/upcast_soundness_bug.rs +++ b/tests/ui/traits/upcast_soundness_bug.rs @@ -1,6 +1,4 @@ #![feature(trait_upcasting)] -// known-bug: #120222 -// check-pass //! This will segfault at runtime. pub trait SupSupA { @@ -56,6 +54,7 @@ pub fn user2() -> &'static dyn Trait { fn main() { let p: *const dyn Trait = &(); let p = p as *const dyn Trait; // <- this is bad! + //~^ ERROR casting `*const dyn Trait` as `*const dyn Trait` is invalid let p = p as *const dyn Super; // <- this upcast accesses improper vtable entry // accessing from L__unnamed_2 the position for the 'Super vtable (pointer)', // thus reading 'null pointer for missing_method' diff --git a/tests/ui/traits/upcast_soundness_bug.stderr b/tests/ui/traits/upcast_soundness_bug.stderr new file mode 100644 index 0000000000000..0187ce808e703 --- /dev/null +++ b/tests/ui/traits/upcast_soundness_bug.stderr @@ -0,0 +1,11 @@ +error[E0606]: casting `*const dyn Trait` as `*const dyn Trait` is invalid + --> $DIR/upcast_soundness_bug.rs:56:13 + | +LL | let p = p as *const dyn Trait; // <- this is bad! + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: vtable kinds may not match + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0606`.