vtable: make sure one cannot call the function with the wrong type

This commit is contained in:
Olivier Goffart 2020-05-15 20:10:23 +02:00
parent 0a973f65d5
commit 903fc513de
2 changed files with 18 additions and 28 deletions

View file

@ -221,6 +221,11 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
forward_code = Some(quote!(#forward_code #arg_name,)); forward_code = Some(quote!(#forward_code #arg_name,));
} }
if has_self {
// Add unsafe: The function are not safe to call unless the self parameter is of the correct type
f.unsafety = Some(Default::default());
}
// Add extern "C" if it isn't there // Add extern "C" if it isn't there
if let Some(a) = &f.abi { if let Some(a) = &f.abi {
if !a.name.as_ref().map(|s| s.value() == "C").unwrap_or(false) { if !a.name.as_ref().map(|s| s.value() == "C").unwrap_or(false) {
@ -462,7 +467,6 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
} }
} }
); );
// println!("{}", result); // println!("{}", result);
result.into() result.into()
} }

View file

@ -1,6 +1,6 @@
use core::marker::PhantomData;
use core::ops::{Deref, DerefMut, Drop}; use core::ops::{Deref, DerefMut, Drop};
use core::ptr::NonNull; use core::ptr::NonNull;
use core::marker::PhantomData;
pub use vtable_macro::*; pub use vtable_macro::*;
pub unsafe trait VTableMeta { pub unsafe trait VTableMeta {
@ -13,7 +13,6 @@ pub unsafe trait VTableMeta {
/// NOTE: the size must be 2*size_of<usize> /// NOTE: the size must be 2*size_of<usize>
type TraitObject: Copy; type TraitObject: Copy;
/// That maps from the tait object from the trait iteself /// That maps from the tait object from the trait iteself
/// (In other word, return 'to' since 'to' implements trait, /// (In other word, return 'to' since 'to' implements trait,
/// but we can't represent that in rust right now, hence these helper) /// but we can't represent that in rust right now, hence these helper)
@ -31,8 +30,6 @@ pub unsafe trait VTableMeta {
/// return a reference to the vtable /// return a reference to the vtable
unsafe fn get_vtable(from: &Self::TraitObject) -> &Self::VTable; unsafe fn get_vtable(from: &Self::TraitObject) -> &Self::VTable;
} }
pub trait VTableMetaDrop: VTableMeta { pub trait VTableMetaDrop: VTableMeta {
@ -83,32 +80,18 @@ impl<T: ?Sized + VTableMetaDrop> VBox<T> {
T::get_ptr(&x.inner) T::get_ptr(&x.inner)
} }
pub unsafe fn from_raw(vtable: NonNull<T::VTable>, ptr: NonNull<u8>) -> Self { pub unsafe fn from_raw(vtable: NonNull<T::VTable>, ptr: NonNull<u8>) -> Self {
Self {inner : T::from_raw(vtable, ptr)} Self { inner: T::from_raw(vtable, ptr) }
} }
pub fn get_vtable(&self) -> &T::VTable { pub fn get_vtable(&self) -> &T::VTable {
unsafe { T::get_vtable(&self.inner) } unsafe { T::get_vtable(&self.inner) }
} }
} pub fn borrow<'b>(&'b self) -> VRef<'b, T> {
unsafe { VRef::from_inner(self.inner) }
/* }
impl<T: ?Sized + VTableMeta> VBox<T> { pub fn borrow_mut<'b>(&'b mut self) -> VRefMut<'b, T> {
/// Construct the box from raw pointer of a vtable and a corresponding pointer unsafe { VRefMut::from_inner(self.inner) }
pub unsafe fn from_inner(
vtable: core::ptr::NonNull<#vtable_name>,
ptr: core::ptr::NonNull<#impl_name>,
) -> Self {
Self{inner: #to_name{vtable, ptr}}
} }
/*pub fn vtable(&self) -> & #vtable_name {
unsafe { self.inner.vtable.as_ref() }
}*/
/* pub fn get_ptr(&self) -> *mut #impl_name {
self.inner.ptr.get_ptr()
}*/
} }
*/
pub struct VRef<'a, T: ?Sized + VTableMeta> { pub struct VRef<'a, T: ?Sized + VTableMeta> {
inner: T::TraitObject, inner: T::TraitObject,
@ -143,7 +126,7 @@ impl<'a, T: ?Sized + VTableMeta> VRef<'a, T> {
T::get_ptr(&x.inner) T::get_ptr(&x.inner)
} }
pub unsafe fn from_raw(vtable: NonNull<T::VTable>, ptr: NonNull<u8>) -> Self { pub unsafe fn from_raw(vtable: NonNull<T::VTable>, ptr: NonNull<u8>) -> Self {
Self {inner : T::from_raw(vtable, ptr), _phantom: PhantomData } Self { inner: T::from_raw(vtable, ptr), _phantom: PhantomData }
} }
pub fn get_vtable(&self) -> &T::VTable { pub fn get_vtable(&self) -> &T::VTable {
unsafe { T::get_vtable(&self.inner) } unsafe { T::get_vtable(&self.inner) }
@ -190,9 +173,12 @@ impl<'a, T: ?Sized + VTableMeta> VRefMut<'a, T> {
unsafe { VRef::from_inner(VRefMut::inner(&self)) } unsafe { VRef::from_inner(VRefMut::inner(&self)) }
} }
pub unsafe fn from_raw(vtable: NonNull<T::VTable>, ptr: NonNull<u8>) -> Self { pub unsafe fn from_raw(vtable: NonNull<T::VTable>, ptr: NonNull<u8>) -> Self {
Self {inner : T::from_raw(vtable, ptr), _phantom: PhantomData } Self { inner: T::from_raw(vtable, ptr), _phantom: PhantomData }
} }
pub fn get_vtable(&self) -> &T::VTable { pub fn get_vtable(&self) -> &T::VTable {
unsafe { T::get_vtable(&self.inner) } unsafe { T::get_vtable(&self.inner) }
} }
} }
#[cfg(doctest)]
mod compile_fail_tests;