LYR-SEM0185
a reflection access outside a round of its own
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);
}
Right
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);
}