Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Type Conversions

Wyn performs no implicit numeric coercion — conversions between distinct numeric types must be written explicitly. The recommended form is constructor-style: T(value) invokes T’s conversion of value, with the source type read from value’s inferred type.

let xi: i32 = i32(2.5f32)        -- f32 -> i32
let xf: f32 = f32(7i32)          -- i32 -> f32
let xu: u32 = u32(-1i32)         -- i32 -> u32 (bitcast)
def pixel_coord(uv: vec2f32) vec2i32 = vec2i32(uv)  -- componentwise

For each (target, source) pair the compiler resolves an overload from the per-type conversion catalog (T.source) — e.g. i32(x: f32) dispatches to the same _w_intrinsic_i32_from_f32 that i32.f32(x) does. The dispatch table:

SourceAvailable targetsLowering
fNi8, i16, i32, i64float→signed-int
fNu8, u16, u32, u64float→unsigned-int
iNf16, f32, f64signed-int→float
uNf16, f32, f64unsigned-int→float
iN ↔ iMsame-signedness, different widthssign-extending convert
uN ↔ uMsame-signedness, different widthszero-extending convert
iN ↔ uNsame widthbitcast
iN ↔ uMdifferent widthssign/zero convert

Vec shorthand: vecNT(v) desugars to a @[T(v.x), T(v.y), ...] literal, applying the scalar T(...) conversion to each component. Arity is read from the constructor name (vec2/vec3/vec4); the arg must be a vec of matching arity, or it’s a type error.

Dot-form compatibility syntax (T.source(value))

The original surface — i32.f32(x) — remains supported and resolves to the same catalog entry as i32(x). The constructor form is preferred because it doesn’t require restating the source type. Vec conversions have no dot-form equivalent; use vecNT(v).

Broadcasting between vector and scalar in arithmetic (v + 1.0) performs no implicit numeric conversion — both sides must already share an element type (see the operators section for the broadcast rules).