From 3910f520f5b74a6ee18e699268faf504d6c371f6 Mon Sep 17 00:00:00 2001 From: ASDAlexander77 Date: Sun, 12 Jul 2026 23:29:15 +0100 Subject: [PATCH] Fix non-converging generic parameter inference loop (review doc A3) Two defects fed each other in resolveGenericParamsFromFunctionCall: - optional/multi-args params past the call operands were counted as progress every round without being marked processed, inflating totalProcessed past the == termination check - the origin of the "loop detected" +100 guard. They are now marked processed and counted once. - that double-counting was also load-bearing: for signatures like reduce2(..., initial?: V) a callback param typed by a defaulted type param can never resolve inside the loop (defaults zip after it), and only the inflated count let the loop exit. A no-progress round now breaks out instead of erroring, letting the default zipping and the existing completeness check decide. The +100 guard is now defensive-only (each param counted at most once). Co-Authored-By: Claude Fable 5 --- tslang/lib/TypeScript/MLIRGen.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tslang/lib/TypeScript/MLIRGen.cpp b/tslang/lib/TypeScript/MLIRGen.cpp index 0b6b7ff65..8dea7cba4 100644 --- a/tslang/lib/TypeScript/MLIRGen.cpp +++ b/tslang/lib/TypeScript/MLIRGen.cpp @@ -2577,15 +2577,19 @@ class MLIRGenImpl if (callOpsCount <= paramIndex) { - // there is no more ops + // there is no more ops; mark processed so the param is counted once - + // recounting it every round inflated totalProcessed past the termination + // equality below and spun the loop into the "loop detected" guard if (paramInfo->getIsOptional() || isa(paramType)) { + paramInfo->processed = true; processed++; continue; } if (paramInfo->getIsMultiArgsParam()) { + paramInfo->processed = true; processed++; continue; } @@ -2640,8 +2644,11 @@ class MLIRGenImpl if (processed == 0) { - emitError(location) << "not all types could be inferred"; - return mlir::failure(); + // no progress in a full round: some params (e.g. a callback typed by a + // type param that only gets its value from a default) can't be inferred + // here; the default zipping and the completeness check below decide + // whether that is an error + break; } totalProcessed += processed; @@ -2653,7 +2660,7 @@ class MLIRGenImpl if (totalProcessed > funcOp->getParams().size() + 100) { - // TODO: find out the issue + // defensive only: with params counted exactly once this is unreachable emitError(location) << "loop detected."; return mlir::failure(); }