diff --git a/packages/typegpu/src/resolutionCtx.ts b/packages/typegpu/src/resolutionCtx.ts index 4b13aa8afb..5887bdc73d 100644 --- a/packages/typegpu/src/resolutionCtx.ts +++ b/packages/typegpu/src/resolutionCtx.ts @@ -607,6 +607,10 @@ export class ResolutionCtxImpl implements ResolutionCtx { } withSlots(pairs: SlotValuePair[], callback: () => T): T { + if (pairs.length === 0) { + return callback(); + } + this._itemStateStack.pushSlotBindings(pairs); try { diff --git a/packages/typegpu/src/tgsl/wgslGenerator.ts b/packages/typegpu/src/tgsl/wgslGenerator.ts index 11d6b703d6..6e48665edf 100644 --- a/packages/typegpu/src/tgsl/wgslGenerator.ts +++ b/packages/typegpu/src/tgsl/wgslGenerator.ts @@ -549,27 +549,36 @@ ${this.ctx.pre}}`; return callee.value.operator(callee.value.lhs, rhs); } - if (!isMarkedInternal(callee.value)) { - const args = argNodes.map((arg) => this.expression(arg)); - const shellless = this.ctx.shelllessRepo.get( - callee.value as (...args: never[]) => unknown, - args, - ); - if (shellless) { - const converted = args.map((s, idx) => { - const argType = shellless.argTypes[idx] as AnyData; - return tryConvertSnippet(s, argType, /* verbose */ false); - }); - - return this.ctx.withResetIndentLevel(() => { - const snippet = this.ctx.resolve(shellless); - return snip( - stitch`${snippet.value}(${converted})`, - snippet.dataType, - /* origin */ 'runtime', - ); - }); - } + if (!isMarkedInternal(callee.value) || isGenericFn(callee.value)) { + const slotPairs = isGenericFn(callee.value) + ? callee.value[$providing]?.pairs + : []; + const callback = isGenericFn(callee.value) + ? callee.value.callback + : (callee.value as (...args: never[]) => unknown); + + this.ctx.withSlots(slotPairs, () => { + const args = argNodes.map((arg) => this.expression(arg)); + const shellless = this.ctx.shelllessRepo.get( + callback, + args, + ); + if (shellless) { + const converted = args.map((s, idx) => { + const argType = shellless.argTypes[idx] as AnyData; + return tryConvertSnippet(s, argType, /* verbose */ false); + }); + + return this.ctx.withResetIndentLevel(() => { + const snippet = this.ctx.resolve(shellless); + return snip( + stitch`${snippet.value}(${converted})`, + snippet.dataType, + /* origin */ 'runtime', + ); + }); + } + }); throw new Error( `Function '${