Skip to content

Commit 075713a

Browse files
swlynch99reivilibre
authored andcommitted
Suppress future incompatibility lint in CloneToAny impl
There's a new future incompatibility warning that recently started firing on the code in CloneToAny (see [1]). It's triggering on code that does a pointer cast from *mut dyn Trait to *mut dyn Trait + Send (or other auto trait) which is an exact match for what this crate is doing. The lint doesn't actually apply here though so it is safe to suppress it. The recommended way to suppress it is to replace the pointer cast with a transmute and that's what I have done here. See the new safety comment for a more detailed explanation of why it is safe. [1]: rust-lang/rust#127323
1 parent 1857234 commit 075713a

File tree

1 file changed

+26
-1
lines changed

1 file changed

+26
-1
lines changed

src/any.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,32 @@ macro_rules! impl_clone {
3434
// ² https://github.com/rust-lang/rust/blob/e7825f2b690c9a0d21b6f6d84c404bb53b151b38/library/alloc/src/boxed.rs#L1613-L1616
3535
let clone: Box<dyn CloneAny> = (**self).clone_to_any();
3636
let raw: *mut dyn CloneAny = Box::into_raw(clone);
37-
unsafe { Box::from_raw(raw as *mut $t) }
37+
38+
// SAFETY:
39+
// There's a future incompat warning ptr_cast_add_auto_to_object tracked in [1]
40+
// that warns when you use a pointer cast to add auto traits to a dyn Trait
41+
// pointer.
42+
//
43+
// The issue that it is trying to avoid is that the trait may have methods that
44+
// are conditional on the auto traits. e.g.
45+
//
46+
// #![feature(arbitrary_self_types)]
47+
// trait Trait {
48+
// fn func(self: *const Self) where Self: Send;
49+
// }
50+
//
51+
// If this happens then the vtable for dyn Trait and the vtable for dyn Trait + Send
52+
// may be different and so casting between pointers to each is UB.
53+
//
54+
// In our case we only care about the CloneAny trait. It has no methods that are
55+
// conditional on any auto traits. This means that the vtable will always be the
56+
// same and so the future incompatibility lint doesn't apply here.
57+
//
58+
// So, to avoid the lint, we use a transmute here instead of a pointer cast. As
59+
// described in [1], that is the recommended way to suppress the warning.
60+
//
61+
// [1]: https://github.com/rust-lang/rust/issues/127323
62+
unsafe { Box::from_raw(std::mem::transmute::<*mut dyn CloneAny, *mut _>(raw)) }
3863
}
3964
}
4065

0 commit comments

Comments
 (0)