slint-ui/slint · error · proc_macro::Error
VTable pointer need to be the first
Error message
VTable pointer need to be the first
What it means
The macro treats a first parameter pointing to the vtable type as the implicit dispatch/self-slot and requires it to be the ONLY first parameter: it must appear before any other parameters, and the function must not be a #[call] entry (call_code). Encountering the vtable-pointer type in any other position, or in a function that already has a call target or other inputs, produces this compile error.
Solutions
- Move the *const MyVTable parameter to be the first parameter of the method.
- Remove extra parameters before the vtable pointer, or drop the vtable pointer if it is not needed.
- Do not combine the vtable-pointer form with a #[call] designated function.
Example fix
// before fn dispatch(arg: u32, vt: *const MyVTable); // after fn dispatch(vt: *const MyVTable, arg: u32);
Defensive patterns
Strategy: validation
Validate before calling
// vtable pointer must be parameter #1 and not in the #[call] fn fn dispatch(vt: *const MyVTable, /* other args */);
Prevention
- Keep the vtable pointer as the first parameter of any method that declares one.
- Never put a vtable pointer parameter in the function marked #[call].
When it happens
Trigger: Placing a `*const MyVTable` parameter after other arguments in a trait method signature; using the vtable-pointer form in the #[call] function which already has call_code set.
Common situations: Reordering parameters when adding context arguments; misunderstanding that the vtable pointer is positional and must lead the signature.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Self pointer need to be the first
- Only supported for structure with named fields
- The structure does not ends in 'VTable'
- The type of an #[field_offset] member in the vtable must be…
- VTable cannot be mutable
AI-assisted analysis of slint-ui/slint@bb937076de (2026-09-16).
Data as JSON: /api/errors/fe37704215716218.
Report an issue: GitHub.
Appendix: source
Thrown at helper_crates/vtable/macro/macro.rs:318
Some((matches!(mutability, PointerMutability::Mut(_)), elem))
}
Type::Reference(TypeReference { mutability, elem, .. }) => {
Some((mutability.is_some(), elem))
}
_ => None,
};
if let Some((is_mut, elem)) = ptr_target
&& let Type::Path(p) = &**elem
&& let Some(pointer_to) = p.path.get_ident()
&& pointer_to == &vtable_name
{
if is_mut {
return Error::new(p.span(), "VTable cannot be mutable")
.to_compile_error()
.into();
}
if call_code.is_some() || !sig.inputs.is_empty() {
return Error::new(p.span(), "VTable pointer need to be the first")
.to_compile_error()
.into();
}
call_code = Some(quote!(vtable as _,));
continue;
}
let (is_pin, self_ty) = match is_pin(¶m.ty) {
Some(t) => (true, t),
None => (false, ¶m.ty),
};
// check for self
if let (true, mutability) = if match_generic_type(self_ty, "VRef", &vtable_name) {
(true, None)
} else if match_generic_type(self_ty, "VRefMut", &vtable_name) {
(true, Some(Default::default()))
} else {View on GitHub (pinned to bb937076de)