Refactor Capable::vtable to return Option<NonNull<()>> (#4252)

This commit is contained in:
+merlan #flirora 2024-05-25 15:17:07 -04:00 committed by GitHub
parent 4929262610
commit 1694327b70
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 12 additions and 8 deletions

View File

@ -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

View File

@ -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<T: ?Sized>(data: *mut (), vtable: *const ()) ->
/// # Safety
/// Must only be called when `T` is a `dyn Trait`.
#[track_caller]
pub unsafe fn vtable<T: ?Sized>(ptr: *const T) -> *const () {
pub unsafe fn vtable<T: ?Sized>(ptr: *const T) -> NonNull<()> {
debug_assert_eq!(Layout::new::<*const T>(), Layout::new::<FatPointer>());
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.

View File

@ -299,7 +299,7 @@ impl Content {
// use a `*const Content` pointer.
let vtable = self.elem().vtable()(TypeId::of::<C>())?;
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::<C>())?;
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.

View File

@ -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<NonNull<()>> {
self.0.vtable
}
@ -208,7 +209,7 @@ pub trait NativeElement:
/// `TypeId::of::<dyn C>()`.
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<NonNull<()>>;
}
/// Defines how fields of an element are accessed.
@ -275,7 +276,7 @@ pub struct NativeElementData {
pub set: fn(&mut Engine, &mut Args) -> SourceResult<Styles>,
/// 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<NonNull<()>>,
/// Gets the numeric index of this field by its name.
pub field_id: fn(name: &str) -> Option<u8>,
/// Gets the name of a field by its numeric index.