slint-ui/slint · error · proc_macro::Error
The type of an #[field_offset] member in the vtable must be…
Error message
The type of an #[field_offset] member in the vtable must be 'usize'
What it means
Members of a #[vtable] struct annotated with #[field_offset(...)] represent byte offsets of fields in the concrete struct, so the macro requires them to be of type usize. Any other type on a #[field_offset] member is rejected at compile time.
Solutions
- Change the #[field_offset] member's type to usize.
- Remove the #[field_offset] attribute if the member is not meant to be an offset.
Example fix
// before
#[vtable]
struct FooVTable {
#[field_offset(data)]
data_offset: u32,
}
// after
#[vtable]
struct FooVTable {
#[field_offset(data)]
data_offset: usize,
} Defensive patterns
Strategy: validation
Validate before calling
let _: usize = data_offset; // every #[field_offset] member is usize
Prevention
- Type all #[field_offset] members as usize.
- Only attach #[field_offset] to members that represent struct field offsets.
When it happens
Trigger: Declaring e.g. `#[field_offset(foo)] x: u32` or `*const u8` inside a #[vtable] struct instead of `usize`.
Common situations: Guessing the offset-member type when hand-writing a vtable; copying an ordinary struct field declaration for the offset member.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Only supported for structure with named fields
- Self pointer need to be the first
- The structure does not ends in 'VTable'
- VTable cannot be mutable
- VTable pointer need to be the first
AI-assisted analysis of slint-ui/slint@bb937076de (2026-09-16).
Data as JSON: /api/errors/9e8389801bc60756.
Report an issue: GitHub.
Appendix: source
Thrown at helper_crates/vtable/macro/macro.rs:588
items: Vec::new(),
..generated_trait.clone()
});
let const_type = if let Some(o) = field
.attrs
.iter()
.position(|a| a.path().get_ident().map(|a| a == "field_offset").unwrap_or(false))
{
let a = field.attrs.remove(o);
let member_type = match a.parse_args::<Type>() {
Err(e) => return e.to_compile_error().into(),
Ok(ty) => ty,
};
match &field.ty {
Type::Path(p) if p.path.get_ident().map(|i| i == "usize").unwrap_or(false) => {}
ty => {
return Error::new(
ty.span(),
"The type of an #[field_offset] member in the vtable must be 'usize'",
)
.to_compile_error()
.into();
}
}
// add `: Sized` to the trait in case it does not have it
if generated_trait_assoc_const.supertraits.is_empty() {
generated_trait_assoc_const.colon_token = Some(Default::default());
generated_trait_assoc_const.supertraits.push(parse_quote!(Sized));
}
let offset_type: Type = parse_quote!(vtable::FieldOffset<Self, #member_type>);
vtable_ctor.push(quote!(#ident: T::#ident.get_byte_offset(),));
View on GitHub (pinned to bb937076de)