From bd5c5b0748adc69f5f4ff71dce0f0e0da8a4d671 Mon Sep 17 00:00:00 2001 From: oh-rgx Date: Tue, 26 Aug 2025 11:55:41 +0800 Subject: [PATCH] Fix lambda type infer Issue: Signed-off-by: oh-rgx --- ets2panda/checker/ETSAnalyzer.cpp | 4 ++- ets2panda/checker/ets/function_helpers.h | 34 ++++++++++++++++--- ets2panda/checker/ets/helpers.cpp | 6 ++++ ets2panda/checker/ets/typeCheckingHelpers.cpp | 1 + 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 1c1b999761..ef12a31252 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -3833,7 +3833,9 @@ checker::Type *ETSAnalyzer::Check(ir::TSAsExpression *expr) const expr->Expr()->SetPreferredType(targetType); auto const sourceType = expr->Expr()->Check(checker); - FORWARD_TYPE_ERROR(checker, sourceType, expr); + if (sourceType->IsTypeError()) { + return checker->InvalidateType(expr); + } if (sourceType->DefinitelyETSNullish() && !targetType->PossiblyETSNullish()) { return expr->SetTsType(checker->TypeError(expr, diagnostic::NULLISH_CAST_TO_NONNULLISH, expr->Start())); diff --git a/ets2panda/checker/ets/function_helpers.h b/ets2panda/checker/ets/function_helpers.h index 7730c65f76..2f9346e603 100644 --- a/ets2panda/checker/ets/function_helpers.h +++ b/ets2panda/checker/ets/function_helpers.h @@ -66,6 +66,27 @@ static Type *MaybeBoxedType(ETSChecker *checker, Type *type, ir::Expression *exp return res; } +static bool isMatch(ir::Expression *arg, Type *paramType) +{ + auto *lambda = arg->AsArrowFunctionExpression()->Function(); + if (!paramType->IsETSUnionType()) { + if (paramType->IsETSArrowType()) { + auto *signature = paramType->AsETSFunctionType()->CallSignaturesOfMethodOrArrow()[0]; + return signature->Params().size() >= lambda->Params().size(); + } + return false; + } + + for (auto &ct : paramType->AsETSUnionType()->ConstituentTypes()) { + if (!ct->IsETSArrowType()) { + continue;; + } + auto *signature = ct->AsETSFunctionType()->CallSignaturesOfMethodOrArrow()[0]; + return signature->Params().size() >= lambda->Params().size(); + } + return false; +} + static void InferUntilFail(Signature const *const signature, const ArenaVector &arguments, ETSChecker *checker, Substitution *substitution) { @@ -91,10 +112,6 @@ static void InferUntilFail(Signature const *const signature, const ArenaVectorIsSpreadElement() - ? MaybeBoxedType(checker, arg->AsSpreadElement()->Argument()->Check(checker), - arg->AsSpreadElement()->Argument()) - : MaybeBoxedType(checker, arg->Check(checker), arg); auto *const paramType = (ix < signature->ArgCount()) ? sigInfo->params[ix]->TsType() : sigInfo->restVar != nullptr ? sigInfo->restVar->TsType() : nullptr; @@ -104,8 +121,17 @@ static void InferUntilFail(Signature const *const signature, const ArenaVectorIsArrowFunctionExpression()) { checker->Relation()->SetNode(arg); + if (!isMatch(arg, paramType)) { + continue; + } + arg->AsArrowFunctionExpression()->SetPreferredType(paramType); } + auto *const argType = arg->IsSpreadElement() + ? MaybeBoxedType(checker, arg->AsSpreadElement()->Argument()->Check(checker), + arg->AsSpreadElement()->Argument()) + : MaybeBoxedType(checker, arg->Check(checker), arg); + if (checker->EnhanceSubstitutionForType(sigInfo->typeParams, paramType, argType, substitution)) { inferStatus[ix] = true; } diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 259e0032e0..b2a6a50b55 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -2727,12 +2727,18 @@ void ETSChecker::InferTypesForLambda(ir::ScriptFunction *lambda, Signature *sign } auto *const lambdaParam = lambda->Params().at(i)->AsETSParameterExpression()->Ident(); if (lambdaParam->TypeAnnotation() == nullptr) { + if (signature->Params().at(i)->TsType()->IsETSTypeParameter()) { + continue; + } lambdaParam->Variable()->SetTsType(signature->Params().at(i)->TsType()); lambdaParam->SetTsType(signature->Params().at(i)->TsType()); } } if (lambda->ReturnTypeAnnotation() == nullptr) { + if (signature->ReturnType()->IsETSTypeParameter()) { + return; + } lambda->SetPreferredReturnType(signature->ReturnType()); } } diff --git a/ets2panda/checker/ets/typeCheckingHelpers.cpp b/ets2panda/checker/ets/typeCheckingHelpers.cpp index e1b046b4d2..c2e82eb0e8 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -1581,6 +1581,7 @@ bool ETSChecker::ResolveLambdaArgumentType(Signature *signature, ir::Expression } arrowFuncExpr->SetTsType(nullptr); + arrowFuncExpr->SetPreferredType(nullptr); auto *const param = signature->GetSignatureInfo()->params[paramPosition]->Declaration()->Node()->AsETSParameterExpression(); Type *const parameterType = signature->Params()[paramPosition]->TsType(); -- Gitee