Unnamed repository; edit this file 'description' to name the repository.
Rollup merge of #120248 - WaffleLapkin:bonk-ptr-object-casts, r=compiler-errors,oli-obk,lnicola
Make casts of pointers to trait objects stricter This is an attempt to `fix` https://github.com/rust-lang/rust/issues/120222 and https://github.com/rust-lang/rust/issues/120217. This is done by adding restrictions on casting pointers to trait objects. Before this PR the rules were as follows: > When casting `*const X<dyn A>` -> `*const Y<dyn B>`, principal traits in `A` and `B` must refer to the same trait definition (or no trait). With this PR the rules are changed to > When casting `*const X<dyn Src>` -> `*const Y<dyn Dst>` > - if `Dst` has a principal trait `DstP`, > - `Src` must have a principal trait `SrcP` > - `dyn SrcP` and `dyn DstP` must be the same type (modulo the trait object lifetime, `dyn T+'a` -> `dyn T+'b` is allowed) > - Auto traits in `Dst` must be a subset of auto traits in `Src` > - Not adhering to this is currently a FCW (warn-by-default + `FutureReleaseErrorReportInDeps`), instead of an error > - if `Src` has a principal trait `Dst` must as well > - this restriction will be removed in a follow up PR This ensures that 1. Principal trait's generic arguments match (no `*const dyn Tr<A>` -> `*const dyn Tr<B>` casts, which are a problem for [#120222](https://github.com/rust-lang/rust/issues/120222)) 2. Principal trait's lifetime arguments match (no `*const dyn Tr<'a>` -> `*const dyn Tr<'b>` casts, which are a problem for [#120217](https://github.com/rust-lang/rust/issues/120217)) 3. No auto traits can be _added_ (this is a problem for arbitrary self types, see [this comment](https://github.com/rust-lang/rust/pull/120248#discussion_r1463835350)) Some notes: - We only care about the metadata/last field, so you can still cast `*const dyn T` to `*const WithHeader<dyn T>`, etc - The lifetime of the trait object itself (`dyn A + 'lt`) is not checked, so you can still cast `*mut FnOnce() + '_` to `*mut FnOnce() + 'static`, etc - This feels fishy, but I couldn't come up with a reason it must be checked The diagnostics are currently not great, to say the least, but as far as I can tell this correctly fixes the issues. cc `@oli-obk` `@compiler-errors` `@lcnr`
Matthias Krüger 2024-07-08
parent 7a4e9a0 · parent 0cea755 · commit 4bd78b0
-rw-r--r--crates/stdx/src/anymap.rs71
1 files changed, 0 insertions, 71 deletions
diff --git a/crates/stdx/src/anymap.rs b/crates/stdx/src/anymap.rs
index d189b56a46..4eafcfb060 100644
--- a/crates/stdx/src/anymap.rs
+++ b/crates/stdx/src/anymap.rs
@@ -68,8 +68,6 @@ pub type RawMap<A> = hash_map::HashMap<TypeId, Box<A>, BuildHasherDefault<TypeId
/// The type parameter `A` allows you to use a different value type; normally you will want
/// it to be `core::any::Any` (also known as `std::any::Any`), but there are other choices:
///
-/// - If you want the entire map to be cloneable, use `CloneAny` instead of `Any`; with
-/// that, you can only add types that implement `Clone` to the map.
/// - You can add on `+ Send` or `+ Send + Sync` (e.g. `Map<dyn Any + Send>`) to add those
/// auto traits.
///
@@ -79,9 +77,6 @@ pub type RawMap<A> = hash_map::HashMap<TypeId, Box<A>, BuildHasherDefault<TypeId
/// also spelled [`AnyMap`] for convenience.
/// - <code>[Map]&lt;dyn [core::any::Any] + Send&gt;</code>
/// - <code>[Map]&lt;dyn [core::any::Any] + Send + Sync&gt;</code>
-/// - <code>[Map]&lt;dyn [CloneAny]&gt;</code>
-/// - <code>[Map]&lt;dyn [CloneAny] + Send&gt;</code>
-/// - <code>[Map]&lt;dyn [CloneAny] + Send + Sync&gt;</code>
///
/// ## Example
///
@@ -205,12 +200,6 @@ mod tests {
assert_debug::<Map<dyn Any>>();
assert_debug::<Map<dyn Any + Send>>();
assert_debug::<Map<dyn Any + Send + Sync>>();
- assert_send::<Map<dyn CloneAny + Send>>();
- assert_send::<Map<dyn CloneAny + Send + Sync>>();
- assert_sync::<Map<dyn CloneAny + Send + Sync>>();
- assert_debug::<Map<dyn CloneAny>>();
- assert_debug::<Map<dyn CloneAny + Send>>();
- assert_debug::<Map<dyn CloneAny + Send + Sync>>();
}
#[test]
@@ -232,53 +221,6 @@ mod tests {
}
}
-// impl some traits for dyn Any
-use core::fmt;
-
-#[doc(hidden)]
-pub trait CloneToAny {
- /// Clone `self` into a new `Box<dyn CloneAny>` object.
- fn clone_to_any(&self) -> Box<dyn CloneAny>;
-}
-
-impl<T: Any + Clone> CloneToAny for T {
- #[inline]
- fn clone_to_any(&self) -> Box<dyn CloneAny> {
- Box::new(self.clone())
- }
-}
-
-macro_rules! impl_clone {
- ($t:ty) => {
- impl Clone for Box<$t> {
- #[inline]
- fn clone(&self) -> Box<$t> {
- // SAFETY: this dance is to reapply any Send/Sync marker. I’m not happy about this
- // approach, given that I used to do it in safe code, but then came a dodgy
- // future-compatibility warning where_clauses_object_safety, which is spurious for
- // auto traits but still super annoying (future-compatibility lints seem to mean
- // your bin crate needs a corresponding allow!). Although I explained my plight¹
- // and it was all explained and agreed upon, no action has been taken. So I finally
- // caved and worked around it by doing it this way, which matches what’s done for
- // core::any², so it’s probably not *too* bad.
- //
- // ¹ https://github.com/rust-lang/rust/issues/51443#issuecomment-421988013
- // ² https://github.com/rust-lang/rust/blob/e7825f2b690c9a0d21b6f6d84c404bb53b151b38/library/alloc/src/boxed.rs#L1613-L1616
- let clone: Box<dyn CloneAny> = (**self).clone_to_any();
- let raw: *mut dyn CloneAny = Box::into_raw(clone);
- unsafe { Box::from_raw(raw as *mut $t) }
- }
- }
-
- impl fmt::Debug for $t {
- #[inline]
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.pad(stringify!($t))
- }
- }
- };
-}
-
/// Methods for downcasting from an `Any`-like trait object.
///
/// This should only be implemented on trait objects for subtraits of `Any`, though you can
@@ -350,16 +292,3 @@ macro_rules! implement {
implement!(Any);
implement!(Any + Send);
implement!(Any + Send + Sync);
-
-/// [`Any`], but with cloning.
-///
-/// Every type with no non-`'static` references that implements `Clone` implements `CloneAny`.
-/// See [`core::any`] for more details on `Any` in general.
-pub trait CloneAny: Any + CloneToAny {}
-impl<T: Any + Clone> CloneAny for T {}
-implement!(CloneAny);
-implement!(CloneAny + Send);
-implement!(CloneAny + Send + Sync);
-impl_clone!(dyn CloneAny);
-impl_clone!(dyn CloneAny + Send);
-impl_clone!(dyn CloneAny + Send + Sync);