comptime value params: bind on generic-struct methods

A free function's $o comptime value param binds via lowerComptimeCall →
bindComptimeValueParams. The generic-struct-instance method path
(b.pick(.b)) took a different dispatch route: genericInstanceMethod →
ensureGenericInstanceMethodLowered emitted a plain call to the
monomorphized FuncId, never checking hasComptimeParams — so the method's
$o was never bound and lowered to 'unresolved o'.

Fix: when the selected generic-instance method declares comptime params,
route through the new lowerComptimeGenericInstanceMethod, which composes
the two mechanisms — installs the struct instance's type_bindings (so T /
*Box(T) resolve), pre-binds the receiver self as a normal pointer-param
alloca (so self.field reads work in the inlined body), then routes the
remaining ($) params through lowerComptimeCallArgsSkip(skip_params=1).
That reuses bindComptimeValueParams, so comptimeIntNamed /
comptimeValueRefNamed resolve the value param inside the method body,
identically to the free-function path.

lowerComptimeCall is refactored into lowerComptimeCallArgs(Skip) cores
parameterized over the effective arg-node slice + a leading skip count;
the original free-call entry point is unchanged behaviorally.

Loud-diagnostic behavior preserved: a non-constant / unknown-variant arg
still emits the value-param diagnostic, never a silent default. Int value
params ($n: i64) remain unbound — a pre-existing limitation shared with
free functions, orthogonal to this fix.

Locks examples/0642 (enum + tagged-union comptime value params on a
generic-struct method, incl. self.field read and comptimeIntNamed via a
type-position [o]i64).
This commit is contained in:
agra
2026-06-20 09:57:15 +03:00
parent d7a6857ee1
commit d95ba0a937
8 changed files with 180 additions and 9 deletions

View File

@@ -1581,6 +1581,8 @@ pub const Lowering = struct {
pub const lowerComptimeGlobal = lower_comptime.lowerComptimeGlobal;
pub const lowerComptimeSideEffect = lower_comptime.lowerComptimeSideEffect;
pub const lowerComptimeCall = lower_comptime.lowerComptimeCall;
pub const lowerComptimeCallArgs = lower_comptime.lowerComptimeCallArgs;
pub const lowerComptimeCallArgsSkip = lower_comptime.lowerComptimeCallArgsSkip;
pub const bindComptimeValueParams = lower_comptime.bindComptimeValueParams;
pub const recordComptimeTag = lower_comptime.recordComptimeTag;
pub const recordComptimeValueRef = lower_comptime.recordComptimeValueRef;
@@ -1894,6 +1896,7 @@ pub const Lowering = struct {
pub const returnExprMintsType = lower_generic.returnExprMintsType;
pub const genericInstanceMethod = lower_generic.genericInstanceMethod;
pub const ensureGenericInstanceMethodLowered = lower_generic.ensureGenericInstanceMethodLowered;
pub const lowerComptimeGenericInstanceMethod = lower_generic.lowerComptimeGenericInstanceMethod;
pub const assertInstanceMapsCoincide = lower_generic.assertInstanceMapsCoincide;
pub const isStaticTypeArg = lower_generic.isStaticTypeArg;
pub const isStaticTypeRef = lower_generic.isStaticTypeRef;