|
45 | 45 | //! #[pinned_drop] |
46 | 46 | //! impl PinnedDrop for Foo { |
47 | 47 | //! fn drop(self: Pin<&mut Self>) { |
48 | | -//! println!("{self:p} is getting dropped."); |
| 48 | +//! pr_info!("{self:p} is getting dropped."); |
49 | 49 | //! } |
50 | 50 | //! } |
51 | 51 | //! |
|
170 | 170 | //! t: T, |
171 | 171 | //! } |
172 | 172 | //! #[doc(hidden)] |
173 | | -//! impl<'__pin, T> |
174 | | -//! ::core::marker::Unpin for Bar<T> where __Unpin<'__pin, T>: ::core::marker::Unpin {} |
| 173 | +//! impl<'__pin, T> ::core::marker::Unpin for Bar<T> |
| 174 | +//! where |
| 175 | +//! __Unpin<'__pin, T>: ::core::marker::Unpin, |
| 176 | +//! {} |
175 | 177 | //! // Now we need to ensure that `Bar` does not implement `Drop`, since that would give users |
176 | 178 | //! // access to `&mut self` inside of `drop` even if the struct was pinned. This could lead to |
177 | 179 | //! // UB with only safe code, so we disallow this by giving a trait implementation error using |
|
188 | 190 | //! // for safety, but a good sanity check, since no normal code calls `PinnedDrop::drop`. |
189 | 191 | //! #[allow(non_camel_case_types)] |
190 | 192 | //! trait UselessPinnedDropImpl_you_need_to_specify_PinnedDrop {} |
191 | | -//! impl<T: ::kernel::init::PinnedDrop> |
192 | | -//! UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {} |
| 193 | +//! impl< |
| 194 | +//! T: ::kernel::init::PinnedDrop, |
| 195 | +//! > UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {} |
193 | 196 | //! impl<T> UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for Bar<T> {} |
194 | 197 | //! }; |
195 | 198 | //! ``` |
|
219 | 222 | //! // return type and shadow it later when we insert the arbitrary user code. That way |
220 | 223 | //! // there will be no possibility of returning without `unsafe`. |
221 | 224 | //! struct __InitOk; |
222 | | -//! // Get the pin-data type from the initialized type. |
| 225 | +//! // Get the data about fields from the supplied type. |
223 | 226 | //! // - the function is unsafe, hence the unsafe block |
224 | 227 | //! // - we `use` the `HasPinData` trait in the block, it is only available in that |
225 | 228 | //! // scope. |
226 | 229 | //! let data = unsafe { |
227 | 230 | //! use ::kernel::init::__internal::HasPinData; |
228 | 231 | //! Self::__pin_data() |
229 | 232 | //! }; |
230 | | -//! // Use `data` to help with type inference, the closure supplied will have the type |
231 | | -//! // `FnOnce(*mut Self) -> Result<__InitOk, Infallible>`. |
| 233 | +//! // Ensure that `data` really is of type `PinData` and help with type inference: |
232 | 234 | //! let init = ::kernel::init::__internal::PinData::make_closure::< |
233 | 235 | //! _, |
234 | 236 | //! __InitOk, |
235 | 237 | //! ::core::convert::Infallible, |
236 | 238 | //! >(data, move |slot| { |
237 | 239 | //! { |
238 | 240 | //! // Shadow the structure so it cannot be used to return early. If a user |
239 | | -//! // tries to write `return Ok(__InitOk)`, then they get a type error, since |
240 | | -//! // that will refer to this struct instead of the one defined above. |
| 241 | +//! // tries to write `return Ok(__InitOk)`, then they get a type error, |
| 242 | +//! // since that will refer to this struct instead of the one defined |
| 243 | +//! // above. |
241 | 244 | //! struct __InitOk; |
242 | 245 | //! // This is the expansion of `t,`, which is syntactic sugar for `t: t,`. |
243 | | -//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).t), t) }; |
244 | | -//! // Since initialization could fail later (not in this case, since the error |
245 | | -//! // type is `Infallible`) we will need to drop this field if there is an |
246 | | -//! // error later. This `DropGuard` will drop the field when it gets dropped |
247 | | -//! // and has not yet been forgotten. We make a reference to it, so users |
248 | | -//! // cannot `mem::forget` it from the initializer, since the name is the same |
249 | | -//! // as the field (including hygiene). |
250 | | -//! let t = &unsafe { |
251 | | -//! ::kernel::init::__internal::DropGuard::new( |
252 | | -//! ::core::addr_of_mut!((*slot).t), |
253 | | -//! ) |
| 246 | +//! { |
| 247 | +//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).t), t) }; |
| 248 | +//! } |
| 249 | +//! // Since initialization could fail later (not in this case, since the |
| 250 | +//! // error type is `Infallible`) we will need to drop this field if there |
| 251 | +//! // is an error later. This `DropGuard` will drop the field when it gets |
| 252 | +//! // dropped and has not yet been forgotten. |
| 253 | +//! let t = unsafe { |
| 254 | +//! ::pinned_init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).t)) |
254 | 255 | //! }; |
255 | 256 | //! // Expansion of `x: 0,`: |
256 | | -//! // Since this can be an arbitrary expression we cannot place it inside of |
257 | | -//! // the `unsafe` block, so we bind it here. |
258 | | -//! let x = 0; |
259 | | -//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).x), x) }; |
| 257 | +//! // Since this can be an arbitrary expression we cannot place it inside |
| 258 | +//! // of the `unsafe` block, so we bind it here. |
| 259 | +//! { |
| 260 | +//! let x = 0; |
| 261 | +//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).x), x) }; |
| 262 | +//! } |
260 | 263 | //! // We again create a `DropGuard`. |
261 | | -//! let x = &unsafe { |
262 | | -//! ::kernel::init::__internal::DropGuard::new( |
263 | | -//! ::core::addr_of_mut!((*slot).x), |
264 | | -//! ) |
| 264 | +//! let x = unsafe { |
| 265 | +//! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).x)) |
265 | 266 | //! }; |
266 | | -//! |
| 267 | +//! // Since initialization has successfully completed, we can now forget |
| 268 | +//! // the guards. This is not `mem::forget`, since we only have |
| 269 | +//! // `&DropGuard`. |
| 270 | +//! ::core::mem::forget(x); |
| 271 | +//! ::core::mem::forget(t); |
267 | 272 | //! // Here we use the type checker to ensure that every field has been |
268 | 273 | //! // initialized exactly once, since this is `if false` it will never get |
269 | 274 | //! // executed, but still type-checked. |
270 | | -//! // Additionally we abuse `slot` to automatically infer the correct type for |
271 | | -//! // the struct. This is also another check that every field is accessible |
272 | | -//! // from this scope. |
| 275 | +//! // Additionally we abuse `slot` to automatically infer the correct type |
| 276 | +//! // for the struct. This is also another check that every field is |
| 277 | +//! // accessible from this scope. |
273 | 278 | //! #[allow(unreachable_code, clippy::diverging_sub_expression)] |
274 | | -//! if false { |
| 279 | +//! let _ = || { |
275 | 280 | //! unsafe { |
276 | 281 | //! ::core::ptr::write( |
277 | 282 | //! slot, |
278 | 283 | //! Self { |
279 | | -//! // We only care about typecheck finding every field here, |
280 | | -//! // the expression does not matter, just conjure one using |
281 | | -//! // `panic!()`: |
| 284 | +//! // We only care about typecheck finding every field |
| 285 | +//! // here, the expression does not matter, just conjure |
| 286 | +//! // one using `panic!()`: |
282 | 287 | //! t: ::core::panic!(), |
283 | 288 | //! x: ::core::panic!(), |
284 | 289 | //! }, |
285 | 290 | //! ); |
286 | 291 | //! }; |
287 | | -//! } |
288 | | -//! // Since initialization has successfully completed, we can now forget the |
289 | | -//! // guards. This is not `mem::forget`, since we only have `&DropGuard`. |
290 | | -//! unsafe { ::kernel::init::__internal::DropGuard::forget(t) }; |
291 | | -//! unsafe { ::kernel::init::__internal::DropGuard::forget(x) }; |
| 292 | +//! }; |
292 | 293 | //! } |
293 | 294 | //! // We leave the scope above and gain access to the previously shadowed |
294 | 295 | //! // `__InitOk` that we need to return. |
295 | 296 | //! Ok(__InitOk) |
296 | 297 | //! }); |
297 | 298 | //! // Change the return type from `__InitOk` to `()`. |
298 | | -//! let init = move |slot| -> ::core::result::Result<(), ::core::convert::Infallible> { |
| 299 | +//! let init = move | |
| 300 | +//! slot, |
| 301 | +//! | -> ::core::result::Result<(), ::core::convert::Infallible> { |
299 | 302 | //! init(slot).map(|__InitOk| ()) |
300 | 303 | //! }; |
301 | 304 | //! // Construct the initializer. |
302 | 305 | //! let init = unsafe { |
303 | | -//! ::kernel::init::pin_init_from_closure::<_, ::core::convert::Infallible>(init) |
| 306 | +//! ::kernel::init::pin_init_from_closure::< |
| 307 | +//! _, |
| 308 | +//! ::core::convert::Infallible, |
| 309 | +//! >(init) |
304 | 310 | //! }; |
305 | 311 | //! init |
306 | 312 | //! } |
|
374 | 380 | //! b: Bar<u32>, |
375 | 381 | //! } |
376 | 382 | //! #[doc(hidden)] |
377 | | -//! impl<'__pin> ::core::marker::Unpin for Foo where __Unpin<'__pin>: ::core::marker::Unpin {} |
| 383 | +//! impl<'__pin> ::core::marker::Unpin for Foo |
| 384 | +//! where |
| 385 | +//! __Unpin<'__pin>: ::core::marker::Unpin, |
| 386 | +//! {} |
378 | 387 | //! // Since we specified `PinnedDrop` as the argument to `#[pin_data]`, we expect `Foo` to |
379 | 388 | //! // implement `PinnedDrop`. Thus we do not need to prevent `Drop` implementations like |
380 | 389 | //! // before, instead we implement `Drop` here and delegate to `PinnedDrop`. |
|
403 | 412 | //! #[pinned_drop] |
404 | 413 | //! impl PinnedDrop for Foo { |
405 | 414 | //! fn drop(self: Pin<&mut Self>) { |
406 | | -//! println!("{self:p} is getting dropped."); |
| 415 | +//! pr_info!("{self:p} is getting dropped."); |
407 | 416 | //! } |
408 | 417 | //! } |
409 | 418 | //! ``` |
|
414 | 423 | //! // `unsafe`, full path and the token parameter are added, everything else stays the same. |
415 | 424 | //! unsafe impl ::kernel::init::PinnedDrop for Foo { |
416 | 425 | //! fn drop(self: Pin<&mut Self>, _: ::kernel::init::__internal::OnlyCallFromDrop) { |
417 | | -//! println!("{self:p} is getting dropped."); |
| 426 | +//! pr_info!("{self:p} is getting dropped."); |
418 | 427 | //! } |
419 | 428 | //! } |
420 | 429 | //! ``` |
|
449 | 458 | //! >(data, move |slot| { |
450 | 459 | //! { |
451 | 460 | //! struct __InitOk; |
452 | | -//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).a), a) }; |
453 | | -//! let a = &unsafe { |
| 461 | +//! { |
| 462 | +//! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).a), a) }; |
| 463 | +//! } |
| 464 | +//! let a = unsafe { |
454 | 465 | //! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).a)) |
455 | 466 | //! }; |
456 | | -//! let b = Bar::new(36); |
| 467 | +//! let init = Bar::new(36); |
457 | 468 | //! unsafe { data.b(::core::addr_of_mut!((*slot).b), b)? }; |
458 | | -//! let b = &unsafe { |
| 469 | +//! let b = unsafe { |
459 | 470 | //! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).b)) |
460 | 471 | //! }; |
461 | | -//! |
| 472 | +//! ::core::mem::forget(b); |
| 473 | +//! ::core::mem::forget(a); |
462 | 474 | //! #[allow(unreachable_code, clippy::diverging_sub_expression)] |
463 | | -//! if false { |
| 475 | +//! let _ = || { |
464 | 476 | //! unsafe { |
465 | 477 | //! ::core::ptr::write( |
466 | 478 | //! slot, |
|
470 | 482 | //! }, |
471 | 483 | //! ); |
472 | 484 | //! }; |
473 | | -//! } |
474 | | -//! unsafe { ::kernel::init::__internal::DropGuard::forget(a) }; |
475 | | -//! unsafe { ::kernel::init::__internal::DropGuard::forget(b) }; |
| 485 | +//! }; |
476 | 486 | //! } |
477 | 487 | //! Ok(__InitOk) |
478 | 488 | //! }); |
479 | | -//! let init = move |slot| -> ::core::result::Result<(), ::core::convert::Infallible> { |
| 489 | +//! let init = move | |
| 490 | +//! slot, |
| 491 | +//! | -> ::core::result::Result<(), ::core::convert::Infallible> { |
480 | 492 | //! init(slot).map(|__InitOk| ()) |
481 | 493 | //! }; |
482 | 494 | //! let init = unsafe { |
|
0 commit comments