diff --git a/crates/typst-macros/src/elem.rs b/crates/typst-macros/src/elem.rs index ffc4d8c26..35dc8b75a 100644 --- a/crates/typst-macros/src/elem.rs +++ b/crates/typst-macros/src/elem.rs @@ -845,7 +845,7 @@ fn create_capable_impl(element: &Elem) -> TokenStream { quote! { unsafe impl #foundations::Capable for #ident { - fn vtable(capability: ::std::any::TypeId) -> ::std::option::Option<*const ()> { + fn vtable(capability: ::std::any::TypeId) -> ::std::option::Option<::std::ptr::NonNull<()>> { let dangling = ::std::ptr::NonNull::<#foundations::Packed<#ident>>::dangling().as_ptr(); #(#checks)* None diff --git a/crates/typst-utils/src/fat.rs b/crates/typst-utils/src/fat.rs index d3c9bb200..b31a2bb1e 100644 --- a/crates/typst-utils/src/fat.rs +++ b/crates/typst-utils/src/fat.rs @@ -7,6 +7,7 @@ use std::alloc::Layout; use std::mem; +use std::ptr::NonNull; /// Create a fat pointer from a data address and a vtable address. /// @@ -39,9 +40,11 @@ pub unsafe fn from_raw_parts_mut(data: *mut (), vtable: *const ()) -> /// # Safety /// Must only be called when `T` is a `dyn Trait`. #[track_caller] -pub unsafe fn vtable(ptr: *const T) -> *const () { +pub unsafe fn vtable(ptr: *const T) -> NonNull<()> { debug_assert_eq!(Layout::new::<*const T>(), Layout::new::()); - mem::transmute_copy::<*const T, FatPointer>(&ptr).vtable + NonNull::new_unchecked( + mem::transmute_copy::<*const T, FatPointer>(&ptr).vtable as *mut (), + ) } /// The memory representation of a trait object pointer. diff --git a/crates/typst/src/foundations/content.rs b/crates/typst/src/foundations/content.rs index 741deb364..d072640b0 100644 --- a/crates/typst/src/foundations/content.rs +++ b/crates/typst/src/foundations/content.rs @@ -299,7 +299,7 @@ impl Content { // use a `*const Content` pointer. let vtable = self.elem().vtable()(TypeId::of::())?; let data = self as *const Content as *const (); - Some(unsafe { &*fat::from_raw_parts(data, vtable) }) + Some(unsafe { &*fat::from_raw_parts(data, vtable.as_ptr()) }) } /// Cast to a mutable trait object if the contained element has the given @@ -319,7 +319,7 @@ impl Content { // mutable access is required. let vtable = self.elem().vtable()(TypeId::of::())?; let data = self as *mut Content as *mut (); - Some(unsafe { &mut *fat::from_raw_parts_mut(data, vtable) }) + Some(unsafe { &mut *fat::from_raw_parts_mut(data, vtable.as_ptr()) }) } /// Whether the content is an empty sequence. diff --git a/crates/typst/src/foundations/element.rs b/crates/typst/src/foundations/element.rs index e58fc89ed..6ffeadb90 100644 --- a/crates/typst/src/foundations/element.rs +++ b/crates/typst/src/foundations/element.rs @@ -2,6 +2,7 @@ use std::any::TypeId; use std::cmp::Ordering; use std::fmt::{self, Debug}; use std::hash::Hash; +use std::ptr::NonNull; use ecow::EcoString; use once_cell::sync::Lazy; @@ -81,7 +82,7 @@ impl Element { } /// The VTable for capabilities dispatch. - pub fn vtable(self) -> fn(of: TypeId) -> Option<*const ()> { + pub fn vtable(self) -> fn(of: TypeId) -> Option> { self.0.vtable } @@ -208,7 +209,7 @@ pub trait NativeElement: /// `TypeId::of::()`. pub unsafe trait Capable { /// Get the pointer to the vtable for the given capability / trait. - fn vtable(capability: TypeId) -> Option<*const ()>; + fn vtable(capability: TypeId) -> Option>; } /// Defines how fields of an element are accessed. @@ -275,7 +276,7 @@ pub struct NativeElementData { pub set: fn(&mut Engine, &mut Args) -> SourceResult, /// Gets the vtable for one of this element's capabilities /// (see [`Capable`]). - pub vtable: fn(capability: TypeId) -> Option<*const ()>, + pub vtable: fn(capability: TypeId) -> Option>, /// Gets the numeric index of this field by its name. pub field_id: fn(name: &str) -> Option, /// Gets the name of a field by its numeric index.