Skip to content

[AUD-1] web: bare unsafe impl Send for DerivedStateActor lacks SAFETY comment #435

@intendednull

Description

@intendednull

Audit finding from general-audit @ 00aa515 (2026-04-27)

Severity: low (code quality / safety doc)
Category: safety / unsafe
File: crates/web/src/state_bridge.rs:87
Obvious fix: yes

Description

unsafe impl<T: Send + Sync + 'static, U: PartialEq + Clone + Send + Sync + 'static> Send
    for DerivedStateActor<T, U>
{
}

Bare unsafe impl Send w/ zero // SAFETY: rationale. Compare crates/actor/src/addr.rs:87-91 which documents why unsafe impl Sync for Addr<A> holds (channel sender is Send+Sync, PhantomData<A> blocks auto-derive).

DerivedStateActor fields:

  • source: StateRef<T> — Send if T: Send
  • selector: Arc<dyn Fn(&T) -> U + Send + Sync> — Send by bound
  • cached: Arc<Mutex<Option<U>>> — Send if U: Send
  • write: SendWrapper<WriteSignal<U>>SendWrapper already unconditional Send

All fields look Send-clean already, so the impl may be redundant — or papering over a hidden non-Send (e.g. Leptos signal internals). Either way, no comment = future maintainer can't tell which.

Impact / Threat

Low. WASM is single-threaded so multi-thread races aren't reachable today. But:

  1. Removes review-time safety check — future change to fields could silently invalidate the impl.
  2. Violates project convention: every other unsafe in workspace has rationale (addr.rs:87 precedent).
  3. Hides whether the impl is redundant (delete it) or load-bearing (document why).

Suggested fix

Either:

  • Delete: try removing the unsafe impl and let auto-derive fire; if compiles, drop it.
  • Document: add // SAFETY: … comment explaining which field blocks auto-derive and why manually asserting Send is sound (likely "WASM single-threaded; SendWrapper provides runtime check on cross-thread access").

Verify

sed -n '85,91p' crates/web/src/state_bridge.rs
# Compare:
sed -n '85,91p' crates/actor/src/addr.rs

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions