From 9aa2c0a3247b92fc0f9da7ab4624ef82ffe1cf01 Mon Sep 17 00:00:00 2001 From: Louis Dureuil Date: Sat, 16 Mar 2024 14:58:45 +0100 Subject: [PATCH] Add safety considerations for `RawScopeFields` --- src/box_scope.rs | 11 ++++++----- src/raw_scope.rs | 23 ++++++++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/box_scope.rs b/src/box_scope.rs index b7534be..b30889e 100644 --- a/src/box_scope.rs +++ b/src/box_scope.rs @@ -98,8 +98,10 @@ where let raw_scope: *mut RawScope = raw_scope.cast(); // SAFETY: - // 1. `raw_scope` allocated by the `Box` so is valid memory. - // 2. TODO + // 1. `raw_scope` allocated by the `Box` so is valid memory, although the future is not yet initialized + // 2. `raw_scope` was created from a valid `RawScope::>`, so `state` is fully initialized. + // + // Note: as a post-condition of `RawScope`, `raw_scope` is fully initialized. unsafe { RawScope::open(raw_scope, scope); } @@ -129,10 +131,9 @@ where G: for<'a> FnOnce(&'a mut >::Family) -> Output, { // SAFETY: - // 1. `self.0` is dereference-able due to coming from a `Box`. + // 1. `self.0` is valid as a post-condition of `new_typed`. // 2. The object pointed to by `self.0` did not move and won't before deallocation. - // 3. `BoxScope::enter` takes an exclusive reference. - // 4. TODO + // 3. `BoxScope::enter` takes an exclusive reference and the reference passed to `f` cannot escape `f`. unsafe { RawScope::enter(self.0, f) } } } diff --git a/src/raw_scope.rs b/src/raw_scope.rs index 6bf9b40..6c3520b 100644 --- a/src/raw_scope.rs +++ b/src/raw_scope.rs @@ -126,9 +126,15 @@ impl RawScope where T: for<'a> Family<'a>, { + /// SAFETY: + /// + /// 1. `this` points to an allocation that can hold a `RawScope`, + /// not necessarily initialized or properly aligned. unsafe fn fields(this: *mut Self) -> RawScopeFields { RawScopeFields { + // SAFETY: precondition (1) state: unsafe { addr_of_mut!((*this).state) }, + // SAFETY: precondition (1) active_fut: unsafe { addr_of_mut!((*this).active_fut) }, } } @@ -141,22 +147,26 @@ where { /// # Safety /// - /// 1. `this` is dereferenceable - /// 2. TODO: any precondition on `this` for RawScope::fields is satisfied. + /// 1. `this` points to a properly aligned allocation that can hold a `RawScope`, where `active_fut` is not necessarily initialized. + /// 2. `this.state` is initialized. + /// + /// # Post-condition + /// + /// 1. `this.active_fut` is fully initialized pub(crate) unsafe fn open>(this: *mut Self, scope: S) where T: for<'a> Family<'a>, F: Future, S: TopScope, { - // SAFETY: precondition (2) + // SAFETY: precondition (1) let RawScopeFields { state, active_fut } = unsafe { Self::fields(this) }; let time_capsule = TimeCapsule { state }; // SAFETY: // - precondition (1) - // - using `scope.run` from the executor. + // - using `scope.run` from the executor unsafe { active_fut.write(scope.run(time_capsule)); } @@ -170,16 +180,15 @@ where { /// # Safety /// - /// 1. `this` is dereferenceable + /// 1. `this` points to a properly aligned, fully initialized `RawScope`. /// 2. `this` verifies the guarantees of `Pin` (one of its fields is pinned in this function) /// 3. No other exclusive reference to the frozen value. In particular, no concurrent calls to this function. - /// 4. TODO: any precondition on `this` for RawScope::fields is satisfied. #[allow(unused_unsafe)] pub(crate) unsafe fn enter<'borrow, Output: 'borrow, G>(this: NonNull, f: G) -> Output where G: for<'a> FnOnce(&'a mut >::Family) -> Output, { - // SAFETY: precondition (4) + // SAFETY: precondition (1) let RawScopeFields { state, active_fut } = unsafe { Self::fields(this.as_ptr()) }; // SAFETY: precondition (2)