@@ -1091,7 +1091,195 @@ pub trait FnPtr: Copy + Clone {
1091
1091
fn addr ( self ) -> * const ( ) ;
1092
1092
}
1093
1093
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
+ /// ```
1095
1283
#[ rustc_builtin_macro( CoercePointee , attributes( pointee) ) ]
1096
1284
#[ allow_internal_unstable( dispatch_from_dyn, coerce_unsized, unsize) ]
1097
1285
#[ unstable( feature = "derive_coerce_pointee" , issue = "123430" ) ]
0 commit comments