Lyricdev
GitHub

LYR-SEM0185

a reflection access outside a round of its own

error · spec 11-metaprogramming

e.[f], E.[v], e.[m](…), e is v or an attribute query (fieldAttribute, variantAttribute, memberAttribute, parameterAttribute) uses a variable that is not the variable of a comptime for over a known type's fields, variants or members, or applies it to a value of another type, or uses E.[v] for a variant with a payload.

Explanation

A comptime for (f in fields<T>()) unrolls its body once per field, variant or member, and in each round the loop variable names one of them. x.[f] then is the ordinary access of that field, checked as one. That works only where the type is known: in a generic body over a type parameter there are no rounds, since its members are known per instance only. The value accessed must also be of the type the loop walks, and E.[v] is the value of a unit variant only.

Walk a concrete type, use the round's variable on a value of that type, and build a variant with a payload as E.[v](…) or E.[v] { … }.

Wrong

import std.meta { members };

struct Point {
    x: int,

    fn norm(): int { return this.x; }
}

fn callAll<T>(x: T): int {
    comptime for (m in members<T>()) {
        let _ = x.[m]();
    }
    return 0;
}

fn main(): void {
    assert(callAll(Point { x = 1 }) == 0);
}
import std.meta { members };

struct Point {
    x: int,

    fn norm(): int { return this.x; }
}

fn callAll(p: Point): int {
    comptime for (m in members<Point>()) {
        let _ = p.[m]();
    }
    return 0;
}

fn main(): void {
    assert(callAll(Point { x = 1 }) == 0);
}