From 8bbd4b1a2304cc7aa3428d07e1fa95d52e2e2ffe Mon Sep 17 00:00:00 2001 From: ASDAlexander77 Date: Tue, 21 Jul 2026 18:30:26 +0100 Subject: [PATCH] Fix generic constraint matching for method-shaped receivers (this-param misalignment) extendsTypeFuncTypes skipped the receiver's bound `this` param when comparing against a method-shaped constraint (e.g. `T extends { next(): ... }`), but never skipped the constraint's own leading `this` placeholder (OpaqueType) in lockstep. That misaligned the two param lists by one, so every extension method whose generic constraint required a method field (e.g. DefaultLib's __Iterator.take/drop/every/filter/find/forEach/map/reduce/some/toArray on generator return types) failed to resolve. Also add ObjectType/ObjectStorageType cases to getFieldTypeByFieldName so boxed generator return types expose their fields to structural constraint checks. Co-Authored-By: Claude Sonnet 5 --- .../TypeScript/MLIRLogic/MLIRTypeHelper.h | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/tslang/include/TypeScript/MLIRLogic/MLIRTypeHelper.h b/tslang/include/TypeScript/MLIRLogic/MLIRTypeHelper.h index 7308f4d98..c961c9891 100644 --- a/tslang/include/TypeScript/MLIRLogic/MLIRTypeHelper.h +++ b/tslang/include/TypeScript/MLIRLogic/MLIRTypeHelper.h @@ -2333,7 +2333,27 @@ class MLIRTypeHelper } return tupleType.getFieldInfo(index).type; - } + } + + if (auto objectStorageType = dyn_cast(srcType)) + { + auto index = objectStorageType.getIndex(fieldName); + if (index < 0) + { + return mlir::Type(); + } + + return objectStorageType.getFieldInfo(index).type; + } + + // a generator/boxed-object return type (e.g. `function*`'s BoxAsObject + // wrapper) is not itself a tuple - unwrap to its underlying storage type + // (TupleType/ConstTupleType/ObjectStorageType) so structural constraint + // matching (e.g. `TIter extends { next(): ... }`) can see its fields. + if (auto objectType = dyn_cast(srcType)) + { + return getFieldTypeByFieldName(objectType.getStorageType(), fieldName); + } if (auto srcInterfaceType = dyn_cast(srcType)) { @@ -2489,9 +2509,22 @@ class MLIRTypeHelper auto extIsVarArgs = getVarArgFromFuncRef(extendType); auto srcReturnType = getReturnTypeFromFuncRef(srcType); - auto extReturnType = getReturnTypeFromFuncRef(extendType); + auto extReturnType = getReturnTypeFromFuncRef(extendType); + + // when srcType's leading (bound `this`) param is being skipped, the + // constraint's own leading `this` placeholder (an OpaqueType standing + // in for "any this type", e.g. a method-shaped generic constraint like + // `{ next(): ... }`) must be skipped in lockstep - otherwise the two + // param lists go out of alignment by one and every real param after it + // is compared against the wrong slot (or a null past the end). + auto skipExtParams = skipSrcParams > 0 && !extParams.empty() && mlir::isa(extParams.front()) + ? 1 : 0; + if (skipExtParams) + { + extParams = extParams.drop_front(skipExtParams); + } - return extendsTypeFuncTypes(location, srcParams, extParams, extIsVarArgs, srcReturnType, extReturnType, typeParamsWithArgs, skipSrcParams); + return extendsTypeFuncTypes(location, srcParams, extParams, extIsVarArgs, srcReturnType, extReturnType, typeParamsWithArgs, skipSrcParams); } ExtendsResult extendsTypeFuncTypes(mlir::Location location, ArrayRef srcParams, ArrayRef extParams, bool extIsVarArgs,