Rust: fix compilation if the slint code declares struct named core

This commit is contained in:
Olivier Goffart 2025-06-30 12:37:13 +02:00
parent a319fe4ce9
commit ac24e0274e
5 changed files with 52 additions and 42 deletions

View file

@ -367,10 +367,10 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
}));
call_code = Some(
quote!(#call_code core::pin::Pin::new_unchecked(<#self_ty>::from_raw(self.vtable, self.ptr)),),
quote!(#call_code ::core::pin::Pin::new_unchecked(<#self_ty>::from_raw(self.vtable, self.ptr)),),
);
self_call = Some(
quote!(core::pin::Pin::new_unchecked(&#mutability (*(#arg_name.as_ptr() as *#const_or_mut T))),),
quote!(::core::pin::Pin::new_unchecked(&#mutability (*(#arg_name.as_ptr() as *#const_or_mut T))),),
);
}
continue;
@ -400,7 +400,7 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
wrap_trait_call = Some(quote! {
let wrap_trait_call = |x| unsafe {
// Put the object on the heap and get a pointer to it
let ptr = core::ptr::NonNull::from(Box::leak(Box::new(x)));
let ptr = ::core::ptr::NonNull::from(Box::leak(Box::new(x)));
VBox::<#vtable_name>::from_raw(vtable, ptr.cast())
};
wrap_trait_call
@ -430,7 +430,7 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
}
fn new_box<X: HasStaticVTable<#vtable_name>>(value: X) -> VBox<#vtable_name> {
// Put the object on the heap and get a pointer to it
let ptr = core::ptr::NonNull::from(Box::leak(Box::new(value)));
let ptr = ::core::ptr::NonNull::from(Box::leak(Box::new(value)));
unsafe { VBox::from_raw(core::ptr::NonNull::from(X::static_vtable()), ptr.cast()) }
}
}
@ -454,7 +454,7 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
unsafe impl VTableMetaDropInPlace for #vtable_name {
unsafe fn #ident(vtable: &Self::VTable, ptr: *mut u8) -> vtable::Layout {
// Safety: The vtable is valid and ptr is a type corresponding to the vtable,
(vtable.#ident)(VRefMut::from_raw(core::ptr::NonNull::from(vtable), core::ptr::NonNull::new_unchecked(ptr).cast()))
(vtable.#ident)(VRefMut::from_raw(core::ptr::NonNull::from(vtable), ::core::ptr::NonNull::new_unchecked(ptr).cast()))
}
unsafe fn dealloc(vtable: &Self::VTable, ptr: *mut u8, layout: vtable::Layout) {
(vtable.dealloc)(vtable, ptr, layout)
@ -538,7 +538,7 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
// This is safe since the self must be a instance of our type
#[allow(unused)]
#[allow(unsafe_code)]
let vtable = unsafe { core::ptr::NonNull::from(&*_0) };
let vtable = unsafe { ::core::ptr::NonNull::from(&*_0) };
#wrap_trait_call(T::#ident(#self_call #forward_code))
}
#some(#ident::<T>)
@ -549,7 +549,7 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
// If the return type contains a implicit lifetime, it is safe to erase it while returning it
// because a sound implementation of the trait wouldn't allow unsound things here
ReturnType::Type(_, r) => {
quote!(#[allow(clippy::useless_transmute)] core::mem::transmute::<#r, #r>)
quote!(#[allow(clippy::useless_transmute)] ::core::mem::transmute::<#r, #r>)
}
};
vtable_ctor.push(quote!(#ident: {
@ -719,8 +719,8 @@ and implements HasStaticVTable for it.
#[doc(hidden)]
#[repr(C)]
pub struct #to_name {
vtable: core::ptr::NonNull<#vtable_name>,
ptr: core::ptr::NonNull<u8>,
vtable: ::core::ptr::NonNull<#vtable_name>,
ptr: ::core::ptr::NonNull<u8>,
}
impl #to_name {
#(#generated_to_fn_trait)*

View file

@ -287,13 +287,13 @@ fn generate_public_component(
pub struct #public_component_id(sp::VRc<sp::ItemTreeVTable, #inner_component_id>);
impl #public_component_id {
pub fn new() -> core::result::Result<Self, slint::PlatformError> {
pub fn new() -> ::core::result::Result<Self, slint::PlatformError> {
let inner = #inner_component_id::new()?;
#init_bundle_translations
// ensure that the window exist as this point so further call to window() don't panic
inner.globals.get().unwrap().window_adapter_ref()?;
#inner_component_id::user_init(sp::VRc::map(inner.clone(), |x| x));
core::result::Result::Ok(Self(inner))
::core::result::Result::Ok(Self(inner))
}
#property_and_callback_accessors
@ -319,18 +319,18 @@ fn generate_public_component(
Self(inner)
}
fn run(&self) -> core::result::Result<(), slint::PlatformError> {
fn run(&self) -> ::core::result::Result<(), slint::PlatformError> {
self.show()?;
slint::run_event_loop()?;
self.hide()?;
core::result::Result::Ok(())
::core::result::Result::Ok(())
}
fn show(&self) -> core::result::Result<(), slint::PlatformError> {
fn show(&self) -> ::core::result::Result<(), slint::PlatformError> {
self.0.globals.get().unwrap().window_adapter_ref()?.window().show()
}
fn hide(&self) -> core::result::Result<(), slint::PlatformError> {
fn hide(&self) -> ::core::result::Result<(), slint::PlatformError> {
self.0.globals.get().unwrap().window_adapter_ref()?.window().hide()
}
@ -399,7 +399,7 @@ fn generate_shared_globals(
let root_rc = self.root_item_tree_weak.upgrade().unwrap();
sp::WindowInner::from_pub(adapter.window()).set_component(&root_rc);
#apply_constant_scale_factor
core::result::Result::Ok(adapter)
::core::result::Result::Ok(adapter)
})
}
@ -1104,7 +1104,7 @@ fn generate_sub_component(
let callback = compile_expression(&tmr.triggered.borrow(), &ctx);
quote!(
if #running {
let interval = core::time::Duration::from_millis(#interval as u64);
let interval = ::core::time::Duration::from_millis(#interval as u64);
if !self.#ident.running() || interval != self.#ident.interval() {
let self_weak = self.self_weak.get().unwrap().clone();
self.#ident.start(sp::TimerMode::Repeated, interval, move || {
@ -1602,7 +1602,7 @@ fn generate_item_tree(
#sub_comp
impl #inner_component_id {
fn new(#(parent: #parent_component_type,)* #globals_arg) -> core::result::Result<sp::VRc<sp::ItemTreeVTable, Self>, slint::PlatformError> {
fn new(#(parent: #parent_component_type,)* #globals_arg) -> ::core::result::Result<sp::VRc<sp::ItemTreeVTable, Self>, slint::PlatformError> {
#![allow(unused)]
slint::private_unstable_api::ensure_backend()?;
let mut _self = Self::default();
@ -1612,7 +1612,7 @@ fn generate_item_tree(
let globals = #globals;
sp::register_item_tree(&self_dyn_rc, globals.maybe_window_adapter_impl());
Self::init(sp::VRc::map(self_rc.clone(), |x| x), globals, 0, 1);
core::result::Result::Ok(self_rc)
::core::result::Result::Ok(self_rc)
}
fn item_tree() -> &'static [sp::ItemTreeNode] {
@ -1635,7 +1635,7 @@ fn generate_item_tree(
};
impl sp::PinnedDrop for #inner_component_id {
fn drop(self: core::pin::Pin<&mut #inner_component_id>) {
fn drop(self: ::core::pin::Pin<&mut #inner_component_id>) {
sp::vtable::new_vref!(let vref : VRef<sp::ItemTreeVTable> for sp::ItemTree = self.as_ref().get_ref());
if let Some(wa) = self.globals.get().unwrap().maybe_window_adapter_impl() {
sp::unregister_item_tree(self.as_ref(), vref, Self::item_array(), &wa);
@ -2845,7 +2845,7 @@ fn compile_builtin_function_call(
if let Some(self_rc) = self_weak.upgrade() {
let _self = self_rc.as_pin_ref();
#call
} else { Default::default() }
} else { ::core::default::Default::default() }
});
)
};

View file

@ -49,7 +49,7 @@ pub struct ItemTreeVTable {
/// Note that the root item is at index 0, so passing 0 would visit the item under root (the children of root).
/// If you want to visit the root item, you need to pass -1 as an index.
pub visit_children_item: extern "C" fn(
core::pin::Pin<VRef<ItemTreeVTable>>,
::core::pin::Pin<VRef<ItemTreeVTable>>,
index: isize,
order: TraversalOrder,
visitor: VRefMut<ItemVisitorVTable>,
@ -57,17 +57,17 @@ pub struct ItemTreeVTable {
/// Return a reference to an item using the given index
pub get_item_ref: extern "C" fn(
core::pin::Pin<VRef<ItemTreeVTable>>,
::core::pin::Pin<VRef<ItemTreeVTable>>,
index: u32,
) -> core::pin::Pin<VRef<ItemVTable>>,
) -> ::core::pin::Pin<VRef<ItemVTable>>,
/// Return the range of indices below the dynamic `ItemTreeNode` at `index`
pub get_subtree_range:
extern "C" fn(core::pin::Pin<VRef<ItemTreeVTable>>, index: u32) -> IndexRange,
extern "C" fn(::core::pin::Pin<VRef<ItemTreeVTable>>, index: u32) -> IndexRange,
/// Return the `ItemTreeRc` at `subindex` below the dynamic `ItemTreeNode` at `index`
pub get_subtree: extern "C" fn(
core::pin::Pin<VRef<ItemTreeVTable>>,
::core::pin::Pin<VRef<ItemTreeVTable>>,
index: u32,
subindex: usize,
result: &mut vtable::VWeak<ItemTreeVTable, Dyn>,
@ -76,7 +76,7 @@ pub struct ItemTreeVTable {
/// Return the item tree that is defined by this `ItemTree`.
/// The return value is an item weak because it can be null if there is no parent.
/// And the return value is passed by &mut because ItemWeak has a destructor
pub get_item_tree: extern "C" fn(core::pin::Pin<VRef<ItemTreeVTable>>) -> Slice<ItemTreeNode>,
pub get_item_tree: extern "C" fn(::core::pin::Pin<VRef<ItemTreeVTable>>) -> Slice<ItemTreeNode>,
/// Return the node this ItemTree is a part of in the parent ItemTree.
///
@ -84,35 +84,36 @@ pub struct ItemTreeVTable {
/// And the return value is passed by &mut because ItemWeak has a destructor
/// Note that the returned value will typically point to a repeater node, which is
/// strictly speaking not an Item at all!
pub parent_node: extern "C" fn(core::pin::Pin<VRef<ItemTreeVTable>>, result: &mut ItemWeak),
pub parent_node: extern "C" fn(::core::pin::Pin<VRef<ItemTreeVTable>>, result: &mut ItemWeak),
/// This embeds this ItemTree into the item tree of another ItemTree
///
/// Returns `true` if this ItemTree was embedded into the `parent`
/// at `parent_item_tree_index`.
pub embed_component: extern "C" fn(
core::pin::Pin<VRef<ItemTreeVTable>>,
::core::pin::Pin<VRef<ItemTreeVTable>>,
parent: &VWeak<ItemTreeVTable>,
parent_item_tree_index: u32,
) -> bool,
/// Return the index of the current subtree or usize::MAX if this is not a subtree
pub subtree_index: extern "C" fn(core::pin::Pin<VRef<ItemTreeVTable>>) -> usize,
pub subtree_index: extern "C" fn(::core::pin::Pin<VRef<ItemTreeVTable>>) -> usize,
/// Returns the layout info for the root of the ItemTree
pub layout_info: extern "C" fn(core::pin::Pin<VRef<ItemTreeVTable>>, Orientation) -> LayoutInfo,
pub layout_info:
extern "C" fn(::core::pin::Pin<VRef<ItemTreeVTable>>, Orientation) -> LayoutInfo,
/// Returns the item's geometry (relative to its parent item)
pub item_geometry:
extern "C" fn(core::pin::Pin<VRef<ItemTreeVTable>>, item_index: u32) -> LogicalRect,
extern "C" fn(::core::pin::Pin<VRef<ItemTreeVTable>>, item_index: u32) -> LogicalRect,
/// Returns the accessible role for a given item
pub accessible_role:
extern "C" fn(core::pin::Pin<VRef<ItemTreeVTable>>, item_index: u32) -> AccessibleRole,
extern "C" fn(::core::pin::Pin<VRef<ItemTreeVTable>>, item_index: u32) -> AccessibleRole,
/// Returns the accessible property via the `result`. Returns true if such a property exists.
pub accessible_string_property: extern "C" fn(
core::pin::Pin<VRef<ItemTreeVTable>>,
::core::pin::Pin<VRef<ItemTreeVTable>>,
item_index: u32,
what: AccessibleStringProperty,
result: &mut SharedString,
@ -120,27 +121,27 @@ pub struct ItemTreeVTable {
/// Executes an accessibility action.
pub accessibility_action: extern "C" fn(
core::pin::Pin<VRef<ItemTreeVTable>>,
::core::pin::Pin<VRef<ItemTreeVTable>>,
item_index: u32,
action: &AccessibilityAction,
),
/// Returns the supported accessibility actions.
pub supported_accessibility_actions: extern "C" fn(
core::pin::Pin<VRef<ItemTreeVTable>>,
::core::pin::Pin<VRef<ItemTreeVTable>>,
item_index: u32,
) -> SupportedAccessibilityAction,
/// Add the `ElementName::id` entries of the given item
pub item_element_infos: extern "C" fn(
core::pin::Pin<VRef<ItemTreeVTable>>,
::core::pin::Pin<VRef<ItemTreeVTable>>,
item_index: u32,
result: &mut SharedString,
) -> bool,
/// Returns a Window, creating a fresh one if `do_create` is true.
pub window_adapter: extern "C" fn(
core::pin::Pin<VRef<ItemTreeVTable>>,
::core::pin::Pin<VRef<ItemTreeVTable>>,
do_create: bool,
result: &mut Option<WindowAdapterRc>,
),

View file

@ -4,7 +4,7 @@
// Just use some of the internal names used in Slint to make sure it still compiles
import { Button, ComboBox } from "std-widgets.slint";
import { Button, ComboBox, ListView, LineEdit } from "std-widgets.slint";
export struct Some {}
export struct None { s: Some }
@ -23,8 +23,8 @@ export struct WindowItem {}
export struct Slint { slint: string }
export struct LayoutInfo { layout: int }
export struct BoxLayoutData { layout: length }
export struct core { core: string }
export enum alloc { Err, Ok }
export enum Slice { xxx }
export enum Coord { xxx }
@ -46,6 +46,10 @@ export component SharedString {
property ok <=> ComponentInstance.ok;
}
component T {
in property <core> T;
}
export global ItemVTable {}
export component TestCase {
@ -56,13 +60,18 @@ export component TestCase {
slint := SharedString {}
Button { text: "hello" + 42; }
ComboBox {}
T { T: { core: "foo" }; }
in-out property <int> Err;
animate Err { duration: 45s; }
out property <bool> test: slint.slint.value == "foobar";
Timer { interval: 45ms; }
if true: ListView {
for sp in 42 : LineEdit {}
}
}
/*

View file

@ -43,7 +43,7 @@ fn main() -> std::io::Result<()> {
write!(
output,
r"
#[test] {} fn t_{}() -> std::result::Result<(), std::boxed::Box<dyn std::error::Error>> {{
#[test] {} fn t_{}() -> ::std::result::Result<(), ::std::boxed::Box<dyn ::std::error::Error>> {{
use i_slint_backend_testing as slint_testing;
slint_testing::init_no_event_loop();
{}