feat(metatype): comptime-eval generic type-fn body locals
A generic ($T) -> Type type-fn comptime-evaluated only its return
EXPRESSION, so a local declared before the return ('vs := …; return
make_enum(…, vs)') was unresolved. Now a body with a prelude (statements
before the return) has its full body evaluated: createComptimeFunction-
WithPrelude lowers the pre-return statements into the comptime function's
scope before the return expr, so the locals resolve.
- comptime.zig: createComptimeFunctionWithPrelude (prelude stmts +
expr); evalComptimeTypeBody (extract prelude + return expr, scan the
whole body for declare() forward types); runComptimeTypeFunc factored
out of evalComptimeType (shared bail/declare-never-defined handling).
- generic.zig: route a type-fn body WITH a prelude through
evalComptimeTypeBody; no-prelude bodies stay on evalComptimeType (zero
change for RecvResult/TryResult etc.).
Non-generic builders (whole body already evaluated) and the List-growth
path are unaffected. Suite green (684).
This commit is contained in:
@@ -1759,7 +1759,21 @@ pub fn instantiateTypeFunction(self: *Lowering, alias_name: []const u8, template
|
||||
// `resolveTypeWithBindings` can't evaluate a Type-returning call.
|
||||
if (findReturnTypeExpr(fd.body)) |ret_node| {
|
||||
if (self.returnExprMintsType(ret_node)) {
|
||||
const tid = self.evalComptimeType(ret_node) orelse return .unresolved;
|
||||
// A body with LOCALS before its `return` (e.g. `vs := …; return
|
||||
// make_enum(…, vs)`) needs its full body comptime-evaluated so those
|
||||
// locals resolve; the bare return-expr path leaves them unresolved.
|
||||
// A no-prelude body stays on the simpler `evalComptimeType` path.
|
||||
const has_prelude = fd.body.data == .block and blk: {
|
||||
for (fd.body.data.block.stmts) |stmt| {
|
||||
if (stmt.data == .return_stmt) break :blk false;
|
||||
break :blk true; // a non-return statement precedes the return
|
||||
}
|
||||
break :blk false;
|
||||
};
|
||||
const tid = (if (has_prelude)
|
||||
self.evalComptimeTypeBody(fd.body, ret_node)
|
||||
else
|
||||
self.evalComptimeType(ret_node)) orelse return .unresolved;
|
||||
// Re-key to the instantiation's mangled (or alias) name so the
|
||||
// cache check at the top dedups a second instantiation — Contract 1.
|
||||
self.renameNominalType(tid, if (has_alias) alias_name else mangled_name);
|
||||
|
||||
Reference in New Issue
Block a user