Skip to content
CryoCryo home
Stdlibcore

varargs

import std::core::varargs; — in the prelude · source

VaArgs

type struct VaArgs {
    ptr: void*;

    static new(va: void*) -> VaArgs;
    as_ptr(&this) -> void*;
    ![implicit]
    next<T>(&this) -> T
    where T: VaArg;
}

A function declared with a trailing args... bucket mirrors C's variadic calling convention, which keeps it ABI-compatible for printf-style interop. The compiler emits va_start/va_end around the body and binds args to the raw va_list. VaArgs wraps that pointer so you can read typed values without hand-rolling va_arg:

function logf(fmt: string, args...) -> void {
    mut va: VaArgs = VaArgs::new(args);
    const count: i32 = va.next();          // T inferred as i32
    const name: string = va.next();
}

as_ptr() hands back the raw va_list for forwarding the rest to a C v*-family function such as vfprintf.

Two limits come from C varargs and no wrapper can fix them. It is not count-safe — nothing records how many arguments were passed or their types, so the callee has to know out of band (a format string, a leading count, a sentinel). And the default argument promotions apply: a variadic call promotes i8, i16, and boolean to i32, and f32 to f64. VaArg is therefore implemented only for the promoted set, and va.next<i8>() is a compile error by design — read it as i32 and narrow.

Trait implementations

implement trait Copy for VaArgs

implement trait Drop for VaArgs

VaArg

type trait VaArg {
    static __pluck(p: void*) -> This;
}

The trait next<T> dispatches through. It is implemented for exactly the types that survive C's default argument promotions, which is why va.next<i8>() is a compile error rather than a silent misread.

Implementors

implement trait VaArg for i32

implement trait VaArg for u32

implement trait VaArg for i64

implement trait VaArg for u64

implement trait VaArg for f64

implement trait VaArg for string