From 2b5845464c27efc6bd68abc3652a6a031aa3d0a2 Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Tue, 8 Sep 2026 13:15:13 +0000 Subject: [PATCH] Rederive the shared source pointer through an unwinding set_layout --- .../libraries/core-types/src/registry.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/node-graph/libraries/core-types/src/registry.rs b/node-graph/libraries/core-types/src/registry.rs index 4db3cce328..d5b106996c 100644 --- a/node-graph/libraries/core-types/src/registry.rs +++ b/node-graph/libraries/core-types/src/registry.rs @@ -127,12 +127,22 @@ impl SharedSource { /// Re-derives the cached pointer from the owned payload. An exclusive /// re-borrow of the payload invalidates the pointer taken before it, so - /// every mutation through `own` ends here. + /// every mutation through `own` ends here, an unwinding one included. pub fn rederive(&mut self) { self.ptr = std::ptr::NonNull::from(&*self.own); } } +/// Re-derives on the way out of an exclusive re-borrow, so a mutation that +/// panics cannot leave the cached pointer retired for a caller that catches. +struct Rederive<'a, N: ?Sized>(&'a mut SharedSource); + +impl Drop for Rederive<'_, N> { + fn drop(&mut self) { + self.0.rederive(); + } +} + // SAFETY: `ptr` is derived from the owned Arc and never mutated through, so the source is exactly as // thread safe as the payload it shares. unsafe impl Send for SharedSource {} @@ -224,9 +234,11 @@ impl SourceHandle { layout: |edge| Node::::layout(edge.downcast_ref::>().expect("layout hook matches the stored edge type")), set_layout: |edge, layout| { let shared = edge.downcast_mut::>().expect("set_layout hook matches the stored edge type"); - let node = std::sync::Arc::get_mut(&mut shared.own).expect("layout is installed before the node is shared"); + // The re-borrow below retires the cached pointer, so the rederive + // is a guard: a panicking `set_layout` must not leave it stale. + let guard = Rederive(shared); + let node = std::sync::Arc::get_mut(&mut guard.0.own).expect("layout is installed before the node is shared"); Node::::set_layout(node, layout); - shared.rederive(); }, ty, }