slint-ui/slint · error · proc_macro::Error

Only supported for structure with named fields

Error message

Only supported for structure with named fields

What it means

The #[vtable] proc macro only supports structs with named fields, because it generates offset accessors and constructors per field name. Applying #[vtable] to a tuple struct or unit struct causes this compile error at the macro call site.

Solutions

  1. Convert the struct to named fields, one per function pointer / data member.
  2. If you don't need vtable machinery, remove the #[vtable] attribute.

Example fix

// before
#[vtable]
struct FooVTable(*const c_void, fn(*const FooVTable, *mut u8));
// after
#[vtable]
struct FooVTable {
    drop_in_place: unsafe fn(VRefMut<FooVTable>),
    do_thing: fn(VRef<FooVTable>, u8),
}
Defensive patterns

Strategy: validation

Validate before calling

// ensure named fields before applying the macro
struct FooVTable { drop_in_place: unsafe fn(VRefMut<FooVTable>), }

Prevention

When it happens

Trigger: Annotating `struct FooVTable();`, `struct FooVTable(fn(), usize);` (tuple struct) or a unit struct `struct FooVTable;` with #[vtable].

Common situations: Copy-pasting a plain struct pattern when defining a new vtable; converting an existing tuple-struct of function pointers to the vtable macro system without converting to named fields.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of slint-ui/slint@bb937076de (2026-09-16). Data as JSON: /api/errors/17f1baeb1f2e5be9. Report an issue: GitHub.

Appendix: source

Thrown at helper_crates/vtable/macro/macro.rs:173

    // access to the vtable through the get_vtable() function
    assert_eq!(animal_vref.get_vtable().LEG_NUMBER, 4);
    // functions are also added for the #[field_offset] member
    assert_eq!(*animal_vref.IS_HUNGRY(), false);
    *animal_vref.IS_HUNGRY_mut() = true;
}
assert_eq!(dog.is_hungry, true);
```


*/
#[proc_macro_attribute]
pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
    let mut input = parse_macro_input!(item as ItemStruct);

    let fields = if let Fields::Named(fields) = &mut input.fields {
        fields
    } else {
        return Error::new(
            proc_macro2::Span::call_site(),
            "Only supported for structure with named fields",
        )
        .to_compile_error()
        .into();
    };

    let vtable_name = input.ident.to_string();
    if !vtable_name.ends_with("VTable") {
        return Error::new(input.ident.span(), "The structure does not ends in 'VTable'")
            .to_compile_error()
            .into();
    }

    let trait_name = Ident::new(&vtable_name[..vtable_name.len() - 6], input.ident.span());
    let to_name = quote::format_ident!("{}TO", trait_name);
    let module_name = quote::format_ident!("{}_vtable_mod", trait_name);
    let static_vtable_macro_name = quote::format_ident!("{}_static", vtable_name);

View on GitHub (pinned to bb937076de)