interpreter: fix unsafe in unsafe function warnings

This commit is contained in:
Olivier Goffart 2025-11-27 14:48:57 +01:00
parent b3470206ff
commit 579cef451d
5 changed files with 82 additions and 59 deletions

View file

@ -95,10 +95,12 @@ impl ItemWithinItemTree {
&self,
mem: *const u8,
) -> Pin<vtable::VRef<'_, ItemVTable>> {
Pin::new_unchecked(vtable::VRef::from_raw(
NonNull::from(self.rtti.vtable),
NonNull::new(mem.add(self.offset) as _).unwrap(),
))
unsafe {
Pin::new_unchecked(vtable::VRef::from_raw(
NonNull::from(self.rtti.vtable),
NonNull::new(mem.add(self.offset) as _).unwrap(),
))
}
}
pub(crate) fn item_index(&self) -> u32 {
@ -1998,14 +2000,14 @@ extern "C" fn layout_info(component: ItemTreeRefPin, orientation: Orientation) -
unsafe extern "C" fn get_item_ref(component: ItemTreeRefPin, index: u32) -> Pin<ItemRef> {
let tree = get_item_tree(component);
match &tree[index as usize] {
ItemTreeNode::Item { item_array_index, .. } => {
ItemTreeNode::Item { item_array_index, .. } => unsafe {
generativity::make_guard!(guard);
let instance_ref = InstanceRef::from_pin_ref(component, guard);
core::mem::transmute::<Pin<ItemRef>, Pin<ItemRef>>(
instance_ref.description.item_array[*item_array_index as usize]
.apply_pin(instance_ref.instance),
)
}
},
ItemTreeNode::DynamicTree { .. } => panic!("get_item_ref called on dynamic tree"),
}
}
@ -2101,7 +2103,7 @@ extern "C" fn subtree_index(component: ItemTreeRefPin) -> usize {
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
unsafe extern "C" fn parent_node(component: ItemTreeRefPin, result: &mut ItemWeak) {
generativity::make_guard!(guard);
let instance_ref = InstanceRef::from_pin_ref(component, guard);
let instance_ref = unsafe { InstanceRef::from_pin_ref(component, guard) };
let component_and_index = {
// Normal inner-compilation unit case:
@ -2334,15 +2336,17 @@ extern "C" fn window_adapter(
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
unsafe extern "C" fn drop_in_place(component: vtable::VRefMut<ItemTreeVTable>) -> vtable::Layout {
let instance_ptr = component.as_ptr() as *mut Instance<'static>;
let layout = (*instance_ptr).type_info().layout();
dynamic_type::TypeInfo::drop_in_place(instance_ptr);
layout.into()
unsafe {
let instance_ptr = component.as_ptr() as *mut Instance<'static>;
let layout = (*instance_ptr).type_info().layout();
dynamic_type::TypeInfo::drop_in_place(instance_ptr);
layout.into()
}
}
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
unsafe extern "C" fn dealloc(_vtable: &ItemTreeVTable, ptr: *mut u8, layout: vtable::Layout) {
std::alloc::dealloc(ptr, layout.try_into().unwrap());
unsafe { std::alloc::dealloc(ptr, layout.try_into().unwrap()) };
}
#[derive(Copy, Clone)]
@ -2356,11 +2360,15 @@ impl<'a, 'id> InstanceRef<'a, 'id> {
component: ItemTreeRefPin<'a>,
_guard: generativity::Guard<'id>,
) -> Self {
Self {
instance: Pin::new_unchecked(&*(component.as_ref().as_ptr() as *const Instance<'id>)),
description: &*(Pin::into_inner_unchecked(component).get_vtable()
as *const ItemTreeVTable
as *const ItemTreeDescription<'id>),
unsafe {
Self {
instance: Pin::new_unchecked(
&*(component.as_ref().as_ptr() as *const Instance<'id>),
),
description: &*(Pin::into_inner_unchecked(component).get_vtable()
as *const ItemTreeVTable
as *const ItemTreeDescription<'id>),
}
}
}

View file

@ -13,10 +13,10 @@ use i_slint_core::rtti::FieldOffset;
use std::rc::Rc;
unsafe fn construct_fn<T: Default>(ptr: *mut u8) {
core::ptr::write(ptr as *mut T, T::default());
unsafe { core::ptr::write(ptr as *mut T, T::default()) };
}
unsafe fn drop_fn<T>(ptr: *mut u8) {
core::ptr::drop_in_place(ptr as *mut T);
unsafe { core::ptr::drop_in_place(ptr as *mut T) };
}
/// Information for type that can be added to a dynamic type.
@ -142,10 +142,10 @@ impl<'id> TypeInfo<'id> {
pub unsafe fn create_instance_in_place(self: Rc<Self>, mem: *mut Instance<'id>) {
// Safety: the TypeInfo invariant means that the constructor can be called
let mem = mem as *mut u8;
std::ptr::write(mem as *mut Rc<_>, self.clone());
unsafe { std::ptr::write(mem as *mut Rc<_>, self.clone()) };
for f in &self.fields {
if let Some(ctor) = f.construct {
ctor(mem.add(f.offset));
unsafe { ctor(mem.add(f.offset)) };
}
}
}
@ -154,11 +154,11 @@ impl<'id> TypeInfo<'id> {
///
/// Safety, the instance must have been created by `TypeInfo::create_instance_in_place`
pub unsafe fn drop_in_place(instance: *mut Instance) {
let type_info = (*instance).type_info.clone();
let type_info = unsafe { (*instance).type_info.clone() };
let mem = instance as *mut u8;
for f in &type_info.fields {
if let Some(dtor) = f.drop {
dtor(mem.add(f.offset));
unsafe { dtor(mem.add(f.offset)) };
}
}
}
@ -167,10 +167,12 @@ impl<'id> TypeInfo<'id> {
///
/// Safety, the instance must have been created by `TypeInfo::create_instance`
unsafe fn delete_instance(instance: *mut Instance) {
let mem_layout = (&(*instance).type_info).mem_layout;
Self::drop_in_place(instance);
let mem = instance as *mut u8;
std::alloc::dealloc(mem, mem_layout);
unsafe {
let mem_layout = (&(*instance).type_info).mem_layout;
Self::drop_in_place(instance);
let mem = instance as *mut u8;
std::alloc::dealloc(mem, mem_layout);
}
}
pub fn layout(&self) -> core::alloc::Layout {

View file

@ -83,7 +83,7 @@ impl<Item: vtable::HasStaticVTable<corelib::items::ItemVTable>> ErasedPropertyIn
}
unsafe fn link_two_ways(&self, item: Pin<ItemRef>, property2: *const ()) {
// Safety: ErasedPropertyInfo::link_two_ways and PropertyInfo::link_two_ways have the same safety requirement
(*self).link_two_ways(ItemRef::downcast_pin(item).unwrap(), property2)
unsafe { (*self).link_two_ways(ItemRef::downcast_pin(item).unwrap(), property2) }
}
fn prepare_for_two_way_binding(&self, item: Pin<ItemRef>) -> Pin<Rc<corelib::Property<Value>>> {

View file

@ -85,10 +85,9 @@ pub unsafe extern "C" fn slint_interpreter_value_new_model(
model: NonNull<u8>,
vtable: &ModelAdaptorVTable,
) -> Box<Value> {
Box::new(Value::Model(ModelRc::new(ModelAdaptorWrapper(vtable::VBox::from_raw(
NonNull::from(vtable),
model,
)))))
Box::new(Value::Model(ModelRc::new(ModelAdaptorWrapper(unsafe {
vtable::VBox::from_raw(NonNull::from(vtable), model)
}))))
}
/// If the value contains a model set from [`slint_interpreter_value_new_model]` with the same vtable pointer,
@ -228,7 +227,7 @@ impl StructOpaque {
/// Construct a new Struct in the given memory location
#[unsafe(no_mangle)]
pub unsafe extern "C" fn slint_interpreter_struct_new(val: *mut StructOpaque) {
std::ptr::write(val as *mut Struct, Struct::default())
unsafe { std::ptr::write(val as *mut Struct, Struct::default()) }
}
/// Construct a new Struct in the given memory location
@ -237,13 +236,13 @@ pub unsafe extern "C" fn slint_interpreter_struct_clone(
other: &StructOpaque,
val: *mut StructOpaque,
) {
std::ptr::write(val as *mut Struct, other.as_struct().clone())
unsafe { std::ptr::write(val as *mut Struct, other.as_struct().clone()) }
}
/// Destruct the struct in that memory location
#[unsafe(no_mangle)]
pub unsafe extern "C" fn slint_interpreter_struct_destructor(val: *mut StructOpaque) {
drop(std::ptr::read(val as *mut Struct))
drop(unsafe { std::ptr::read(val as *mut Struct) })
}
#[unsafe(no_mangle)]
@ -279,7 +278,7 @@ const _: [(); std::mem::align_of::<StructIteratorOpaque>()] =
pub unsafe extern "C" fn slint_interpreter_struct_iterator_destructor(
val: *mut StructIteratorOpaque,
) {
drop(std::ptr::read(val as *mut StructIterator))
drop(unsafe { std::ptr::read(val as *mut StructIterator) })
}
/// Advance the iterator and return the next value, or a null pointer
@ -288,7 +287,9 @@ pub unsafe extern "C" fn slint_interpreter_struct_iterator_next<'a>(
iter: &'a mut StructIteratorOpaque,
k: &mut Slice<'a, u8>,
) -> *mut Value {
if let Some((str, val)) = (*(iter as *mut StructIteratorOpaque as *mut StructIterator)).next() {
if let Some((str, val)) =
unsafe { (*(iter as *mut StructIteratorOpaque as *mut StructIterator)).next() }
{
*k = Slice::from_slice(str.as_bytes());
Box::into_raw(Box::new(val.clone()))
} else {
@ -406,7 +407,7 @@ pub unsafe extern "C" fn slint_interpreter_component_instance_set_callback(
user_data: *mut c_void,
drop_user_data: Option<extern "C" fn(*mut c_void)>,
) -> bool {
let ud = CallbackUserData::new(user_data, drop_user_data, callback);
let ud = unsafe { CallbackUserData::new(user_data, drop_user_data, callback) };
generativity::make_guard!(guard);
let comp = inst.unerase(guard);
@ -472,7 +473,7 @@ pub unsafe extern "C" fn slint_interpreter_component_instance_set_global_callbac
user_data: *mut c_void,
drop_user_data: Option<extern "C" fn(*mut c_void)>,
) -> bool {
let ud = CallbackUserData::new(user_data, drop_user_data, callback);
let ud = unsafe { CallbackUserData::new(user_data, drop_user_data, callback) };
generativity::make_guard!(guard);
let comp = inst.unerase(guard);
@ -552,10 +553,12 @@ pub unsafe extern "C" fn slint_interpreter_component_instance_window(
core::mem::size_of::<Rc<dyn WindowAdapter>>(),
core::mem::size_of::<i_slint_core::window::ffi::WindowAdapterRcOpaque>()
);
core::ptr::write(
out as *mut *const Rc<dyn WindowAdapter>,
inst.window_adapter_ref().unwrap() as *const _,
)
unsafe {
core::ptr::write(
out as *mut *const Rc<dyn WindowAdapter>,
inst.window_adapter_ref().unwrap() as *const _,
)
}
}
/// Instantiate an instance from a definition.
@ -567,7 +570,7 @@ pub unsafe extern "C" fn slint_interpreter_component_instance_create(
def: &ComponentDefinitionOpaque,
out: *mut ComponentInstance,
) {
std::ptr::write(out, def.as_component_definition().create().unwrap())
unsafe { std::ptr::write(out, def.as_component_definition().create().unwrap()) }
}
#[unsafe(no_mangle)]
@ -577,7 +580,7 @@ pub unsafe extern "C" fn slint_interpreter_component_instance_component_definiti
) {
generativity::make_guard!(guard);
let definition = ComponentDefinition { inner: inst.unerase(guard).description().into() };
std::ptr::write(component_definition_ptr as *mut ComponentDefinition, definition);
unsafe { std::ptr::write(component_definition_ptr as *mut ComponentDefinition, definition) };
}
#[vtable::vtable]
@ -637,13 +640,13 @@ impl ModelNotifyOpaque {
/// Construct a new ModelNotifyNotify in the given memory region
#[unsafe(no_mangle)]
pub unsafe extern "C" fn slint_interpreter_model_notify_new(val: *mut ModelNotifyOpaque) {
std::ptr::write(val as *mut ModelNotify, ModelNotify::default());
unsafe { std::ptr::write(val as *mut ModelNotify, ModelNotify::default()) };
}
/// Destruct the value in that memory location
#[unsafe(no_mangle)]
pub unsafe extern "C" fn slint_interpreter_model_notify_destructor(val: *mut ModelNotifyOpaque) {
drop(std::ptr::read(val as *mut ModelNotify))
drop(unsafe { std::ptr::read(val as *mut ModelNotify) })
}
#[unsafe(no_mangle)]
@ -726,16 +729,18 @@ impl ComponentCompilerOpaque {
pub unsafe extern "C" fn slint_interpreter_component_compiler_new(
compiler: *mut ComponentCompilerOpaque,
) {
*compiler = ComponentCompilerOpaque(NonNull::new_unchecked(Box::into_raw(Box::new(
ComponentCompiler::default(),
))));
unsafe {
*compiler = ComponentCompilerOpaque(NonNull::new_unchecked(Box::into_raw(Box::new(
ComponentCompiler::default(),
))));
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn slint_interpreter_component_compiler_destructor(
compiler: *mut ComponentCompilerOpaque,
) {
drop(Box::from_raw((*compiler).0.as_ptr()))
drop(unsafe { Box::from_raw((*compiler).0.as_ptr()) })
}
#[unsafe(no_mangle)]
@ -826,7 +831,9 @@ pub unsafe extern "C" fn slint_interpreter_component_compiler_build_from_source(
std::str::from_utf8(&path).unwrap().to_string().into(),
)) {
Some(definition) => {
std::ptr::write(component_definition_ptr as *mut ComponentDefinition, definition);
unsafe {
std::ptr::write(component_definition_ptr as *mut ComponentDefinition, definition)
};
true
}
None => false,
@ -846,7 +853,9 @@ pub unsafe extern "C" fn slint_interpreter_component_compiler_build_from_path(
.build_from_path(PathBuf::from_str(std::str::from_utf8(&path).unwrap()).unwrap()),
) {
Some(definition) => {
std::ptr::write(component_definition_ptr as *mut ComponentDefinition, definition);
unsafe {
std::ptr::write(component_definition_ptr as *mut ComponentDefinition, definition)
};
true
}
None => false,
@ -888,7 +897,9 @@ pub unsafe extern "C" fn slint_interpreter_component_definition_clone(
other: &ComponentDefinitionOpaque,
def: *mut ComponentDefinitionOpaque,
) {
std::ptr::write(def as *mut ComponentDefinition, other.as_component_definition().clone())
unsafe {
std::ptr::write(def as *mut ComponentDefinition, other.as_component_definition().clone())
}
}
/// Destruct the component definition in that memory location
@ -896,7 +907,7 @@ pub unsafe extern "C" fn slint_interpreter_component_definition_clone(
pub unsafe extern "C" fn slint_interpreter_component_definition_destructor(
val: *mut ComponentDefinitionOpaque,
) {
drop(std::ptr::read(val as *mut ComponentDefinition))
drop(unsafe { std::ptr::read(val as *mut ComponentDefinition) })
}
/// Returns the list of properties of the component the component definition describes

View file

@ -373,14 +373,14 @@ mod ffi {
pub unsafe extern "C" fn slint_live_preview_clone(
component: *const LiveReloadingComponentInner,
) {
Rc::increment_strong_count(component);
unsafe { Rc::increment_strong_count(component) };
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn slint_live_preview_drop(
component: *const LiveReloadingComponentInner,
) {
Rc::decrement_strong_count(component);
unsafe { Rc::decrement_strong_count(component) };
}
#[unsafe(no_mangle)]
@ -438,7 +438,9 @@ mod ffi {
user_data: *mut c_void,
drop_user_data: Option<extern "C" fn(*mut c_void)>,
) {
let ud = crate::ffi::CallbackUserData::new(user_data, drop_user_data, callback_handler);
let ud = unsafe {
crate::ffi::CallbackUserData::new(user_data, drop_user_data, callback_handler)
};
let handler = Rc::new(move |args: &[Value]| ud.call(args));
let callback = std::str::from_utf8(&callback).unwrap();
if let Some((global, prop)) = callback.split_once('.') {
@ -460,6 +462,6 @@ mod ffi {
);
let borrow = component.borrow();
let adapter = borrow.instance().inner.window_adapter_ref().unwrap();
core::ptr::write(out as *mut *const Rc<dyn WindowAdapter>, adapter as *const _)
unsafe { core::ptr::write(out as *mut *const Rc<dyn WindowAdapter>, adapter as *const _) };
}
}