Re-derive the shared edge pointer and type-check the paint transmute

This commit is contained in:
Dennis Kobert
2026-08-29 20:16:12 +00:00
parent 3302a3b0b8
commit 78e35eb6ea
2 changed files with 22 additions and 2 deletions

View File

@@ -124,6 +124,13 @@ impl<N: ?Sized> SharedEdge<N> {
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::<SharedEdge<N>>().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::<ContextImpl>::set_layout(node, layout);
shared.rederive();
},
ty,
}

View File

@@ -378,9 +378,21 @@ fn forced_paint<'a, A: Attribute>(paint: LanePaint<'a>) -> Option<A::Value<'a>>
name if name == Stroke::NAME => paint.stroke,
_ => None,
}?;
assert_eq!(
std::any::TypeId::of::<A::Value<'static>>(),
std::any::TypeId::of::<Option<&'static List<Graphic<'static>>>>(),
"attribute `{}` is declared at another value type than this crate's paint form",
A::NAME
);
assert_eq!(
size_of::<A::Value<'a>>(),
size_of::<Option<&'a List<Graphic<'a>>>>(),
"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<Graphic>>` 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<Graphic>>`
// value form at the same size.
Some(unsafe { std::mem::transmute_copy::<Option<&'a List<Graphic>>, A::Value<'a>>(&Some(slot)) })
}