@@ -1091,7 +1091,195 @@ pub trait FnPtr: Copy + Clone {
10911091 fn addr ( self ) -> * const ( ) ;
10921092}
10931093
1094- /// Derive macro generating impls of traits related to smart pointers.
1094+ /// Derive macro that makes a smart pointer usable with trait objects.
1095+ ///
1096+ /// # What this macro does
1097+ ///
1098+ /// This macro is intended to be used with user-defined pointer types, and makes it possible to
1099+ /// perform coercions on the pointee of the user-defined pointer. There are two aspects to this:
1100+ ///
1101+ /// ## Unsizing coercions of the pointee
1102+ ///
1103+ /// By using the macro, the following example will compile:
1104+ /// ```
1105+ /// #![feature(derive_coerce_pointee)]
1106+ /// use std::marker::CoercePointee;
1107+ /// use std::ops::Deref;
1108+ ///
1109+ /// #[derive(CoercePointee)]
1110+ /// #[repr(transparent)]
1111+ /// struct MySmartPointer<T: ?Sized>(Box<T>);
1112+ ///
1113+ /// impl<T: ?Sized> Deref for MySmartPointer<T> {
1114+ /// type Target = T;
1115+ /// fn deref(&self) -> &T {
1116+ /// &self.0
1117+ /// }
1118+ /// }
1119+ ///
1120+ /// trait MyTrait {}
1121+ ///
1122+ /// impl MyTrait for i32 {}
1123+ ///
1124+ /// fn main() {
1125+ /// let ptr: MySmartPointer<i32> = MySmartPointer(Box::new(4));
1126+ ///
1127+ /// // This coercion would be an error without the derive.
1128+ /// let ptr: MySmartPointer<dyn MyTrait> = ptr;
1129+ /// }
1130+ /// ```
1131+ /// Without the `#[derive(CoercePointee)]` macro, this example would fail with the following error:
1132+ /// ```text
1133+ /// error[E0308]: mismatched types
1134+ /// --> src/main.rs:11:44
1135+ /// |
1136+ /// 11 | let ptr: MySmartPointer<dyn MyTrait> = ptr;
1137+ /// | --------------------------- ^^^ expected `MySmartPointer<dyn MyTrait>`, found `MySmartPointer<i32>`
1138+ /// | |
1139+ /// | expected due to this
1140+ /// |
1141+ /// = note: expected struct `MySmartPointer<dyn MyTrait>`
1142+ /// found struct `MySmartPointer<i32>`
1143+ /// = help: `i32` implements `MyTrait` so you could box the found value and coerce it to the trait object `Box<dyn MyTrait>`, you will have to change the expected type as well
1144+ /// ```
1145+ ///
1146+ /// ## Dyn compatibility
1147+ ///
1148+ /// This macro allows you to dispatch on the user-defined pointer type. That is, traits using the
1149+ /// type as a receiver are dyn-compatible. For example, this compiles:
1150+ ///
1151+ /// ```
1152+ /// #![feature(arbitrary_self_types, derive_coerce_pointee)]
1153+ /// use std::marker::CoercePointee;
1154+ /// use std::ops::Deref;
1155+ ///
1156+ /// #[derive(CoercePointee)]
1157+ /// #[repr(transparent)]
1158+ /// struct MySmartPointer<T: ?Sized>(Box<T>);
1159+ ///
1160+ /// impl<T: ?Sized> Deref for MySmartPointer<T> {
1161+ /// type Target = T;
1162+ /// fn deref(&self) -> &T {
1163+ /// &self.0
1164+ /// }
1165+ /// }
1166+ ///
1167+ /// // You can always define this trait. (as long as you have #![feature(arbitrary_self_types)])
1168+ /// trait MyTrait {
1169+ /// fn func(self: MySmartPointer<Self>);
1170+ /// }
1171+ ///
1172+ /// // But using `dyn MyTrait` requires #[derive(CoercePointee)].
1173+ /// fn call_func(value: MySmartPointer<dyn MyTrait>) {
1174+ /// value.func();
1175+ /// }
1176+ /// ```
1177+ /// If you remove the `#[derive(CoercePointee)]` annotation from the struct, then the above example
1178+ /// will fail with this error message:
1179+ /// ```text
1180+ /// error[E0038]: the trait `MyTrait` is not dyn compatible
1181+ /// --> src/lib.rs:21:36
1182+ /// |
1183+ /// 17 | fn func(self: MySmartPointer<Self>);
1184+ /// | -------------------- help: consider changing method `func`'s `self` parameter to be `&self`: `&Self`
1185+ /// ...
1186+ /// 21 | fn call_func(value: MySmartPointer<dyn MyTrait>) {
1187+ /// | ^^^^^^^^^^^ `MyTrait` is not dyn compatible
1188+ /// |
1189+ /// note: for a trait to be dyn compatible it needs to allow building a vtable
1190+ /// for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
1191+ /// --> src/lib.rs:17:19
1192+ /// |
1193+ /// 16 | trait MyTrait {
1194+ /// | ------- this trait is not dyn compatible...
1195+ /// 17 | fn func(self: MySmartPointer<Self>);
1196+ /// | ^^^^^^^^^^^^^^^^^^^^ ...because method `func`'s `self` parameter cannot be dispatched on
1197+ /// ```
1198+ ///
1199+ /// # Requirements for using the macro
1200+ ///
1201+ /// This macro can only be used if:
1202+ /// * The type is a `#[repr(transparent)]` struct.
1203+ /// * The type of its non-zero-sized field must either be a standard library pointer type
1204+ /// (reference, raw pointer, `NonNull`, `Box`, `Rc`, `Arc`, etc.) or another user-defined type
1205+ /// also using the `#[derive(CoercePointee)]` macro.
1206+ /// * Zero-sized fields must not mention any generic parameters unless the zero-sized field has
1207+ /// type [`PhantomData`].
1208+ ///
1209+ /// ## Multiple type parameters
1210+ ///
1211+ /// If the type has multiple type parameters, then you must explicitly specify which one should be
1212+ /// used for dynamic dispatch. For example:
1213+ /// ```
1214+ /// # #![feature(derive_coerce_pointee)]
1215+ /// # use std::marker::{CoercePointee, PhantomData};
1216+ /// #[derive(CoercePointee)]
1217+ /// #[repr(transparent)]
1218+ /// struct MySmartPointer<#[pointee] T: ?Sized, U> {
1219+ /// ptr: Box<T>,
1220+ /// _phantom: PhantomData<U>,
1221+ /// }
1222+ /// ```
1223+ /// Specifying `#[pointee]` when the struct has only one type parameter is allowed, but not required.
1224+ ///
1225+ /// # Examples
1226+ ///
1227+ /// A custom implementation of the `Rc` type:
1228+ /// ```
1229+ /// #![feature(derive_coerce_pointee)]
1230+ /// use std::marker::CoercePointee;
1231+ /// use std::ops::Deref;
1232+ /// use std::ptr::NonNull;
1233+ ///
1234+ /// #[derive(CoercePointee)]
1235+ /// #[repr(transparent)]
1236+ /// pub struct Rc<T: ?Sized> {
1237+ /// inner: NonNull<RcInner<T>>,
1238+ /// }
1239+ ///
1240+ /// struct RcInner<T: ?Sized> {
1241+ /// refcount: usize,
1242+ /// value: T,
1243+ /// }
1244+ ///
1245+ /// impl<T: ?Sized> Deref for Rc<T> {
1246+ /// type Target = T;
1247+ /// fn deref(&self) -> &T {
1248+ /// let ptr = self.inner.as_ptr();
1249+ /// unsafe { &(*ptr).value }
1250+ /// }
1251+ /// }
1252+ ///
1253+ /// impl<T> Rc<T> {
1254+ /// pub fn new(value: T) -> Self {
1255+ /// let inner = Box::new(RcInner {
1256+ /// refcount: 1,
1257+ /// value,
1258+ /// });
1259+ /// Self {
1260+ /// inner: NonNull::from(Box::leak(inner)),
1261+ /// }
1262+ /// }
1263+ /// }
1264+ ///
1265+ /// impl<T: ?Sized> Clone for Rc<T> {
1266+ /// fn clone(&self) -> Self {
1267+ /// // A real implementation would handle overflow here.
1268+ /// unsafe { (*self.inner.as_ptr()).refcount += 1 };
1269+ /// Self { inner: self.inner }
1270+ /// }
1271+ /// }
1272+ ///
1273+ /// impl<T: ?Sized> Drop for Rc<T> {
1274+ /// fn drop(&mut self) {
1275+ /// let ptr = self.inner.as_ptr();
1276+ /// unsafe { (*ptr).refcount -= 1 };
1277+ /// if unsafe { (*ptr).refcount } == 0 {
1278+ /// drop(unsafe { Box::from_raw(ptr) });
1279+ /// }
1280+ /// }
1281+ /// }
1282+ /// ```
10951283#[ rustc_builtin_macro( CoercePointee , attributes( pointee) ) ]
10961284#[ allow_internal_unstable( dispatch_from_dyn, coerce_unsized, unsize) ]
10971285#[ unstable( feature = "derive_coerce_pointee" , issue = "123430" ) ]
0 commit comments