From 78e35eb6ea778b17b8e9537ec63e59f9b4aa7c0c Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Sat, 29 Aug 2026 20:16:12 +0000 Subject: [PATCH] Re-derive the shared edge pointer and type-check the paint transmute --- node-graph/libraries/core-types/src/registry.rs | 8 ++++++++ .../libraries/graphic-types/src/graphic.rs | 16 ++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/node-graph/libraries/core-types/src/registry.rs b/node-graph/libraries/core-types/src/registry.rs index 5a28135e27..9027d91919 100644 --- a/node-graph/libraries/core-types/src/registry.rs +++ b/node-graph/libraries/core-types/src/registry.rs @@ -124,6 +124,13 @@ impl SharedEdge { pub fn share(&self) -> Self { Self { ptr: self.ptr, own: self.own.clone() } } + + /// 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. + pub fn rederive(&mut self) { + self.ptr = std::ptr::NonNull::from(&*self.own); + } } // SAFETY: `ptr` is derived from the owned Arc and never mutated through, so the edge is exactly as @@ -222,6 +229,7 @@ impl EdgeHandle { 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"); Node::::set_layout(node, layout); + shared.rederive(); }, ty, } diff --git a/node-graph/libraries/graphic-types/src/graphic.rs b/node-graph/libraries/graphic-types/src/graphic.rs index 8aaa8e9f37..6d0de79e69 100644 --- a/node-graph/libraries/graphic-types/src/graphic.rs +++ b/node-graph/libraries/graphic-types/src/graphic.rs @@ -378,9 +378,21 @@ fn forced_paint<'a, A: Attribute>(paint: LanePaint<'a>) -> Option> name if name == Stroke::NAME => paint.stroke, _ => None, }?; + assert_eq!( + std::any::TypeId::of::>(), + std::any::TypeId::of::>>>(), + "attribute `{}` is declared at another value type than this crate's paint form", + A::NAME + ); + assert_eq!( + size_of::>(), + size_of::>>>(), + "the paint value form must span the marker's value" + ); // SAFETY: the census admits one value type per attribute name and panics on - // a conflict at registration, so a marker named `fill` or `stroke` carries - // this crate's `Option<&List>` value form. + // a conflict at registration, and the asserts above re-check it, so a marker + // named `fill` or `stroke` carries this crate's `Option<&List>` + // value form at the same size. Some(unsafe { std::mem::transmute_copy::>, A::Value<'a>>(&Some(slot)) }) }