From cc0f9d95f2a88df04f8370ad36aac69cc22f2130 Mon Sep 17 00:00:00 2001 From: peterseres Date: Tue, 9 Apr 2024 16:07:09 +0200 Subject: [PATCH] [ArkTS frontend] es2panda fails with lambda When we resolve the type alias in lambda function the parameters now got type. Fixes #14254 internal issue. Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I97JBD Testing : I've added four test cases: one for the parser and three for runtime. The parser test verifies scenarios where a type alias references another type alias. The runtime tests confirm that my fix resolves issues with lambda functions, ensuring they now work correctly whether they have one parameter, or three parameters. These scenarios were problematic before my fix. And one more scenario to ensure the fix does not break scenario where a lambda function has no parameters. Signed-off-by: Peter Seres --- ets2panda/checker/ETSchecker.h | 1 + ets2panda/checker/ets/helpers.cpp | 41 +++++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index a7e1743da9..57e41f9a4d 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -459,6 +459,7 @@ public: bool IsNullLikeOrVoidExpression(const ir::Expression *expr) const; bool IsConstantExpression(ir::Expression *expr, Type *type); void ValidateUnaryOperatorOperand(varbinder::Variable *variable); + void InferAliasLambdaType(ir::TypeNode *localTypeAnnotation, ir::Expression *init); bool TestUnionType(Type *type, TypeFlag test); bool CheckPossibilityPromotion(Type *left, Type *right, TypeFlag test); std::tuple ApplyBinaryOperatorPromotion(Type *left, Type *right, TypeFlag test, diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 55b410391c..7d80dea86e 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -564,6 +564,37 @@ checker::Type *ETSChecker::CheckArrayElements(ir::Identifier *ident, ir::ArrayEx return annotationType; } +void ETSChecker::InferAliasLambdaType(ir::TypeNode *localTypeAnnotation, ir::Expression *init) +{ + if (localTypeAnnotation != nullptr && localTypeAnnotation->IsETSTypeReference()) { + bool isAnnotationTypeAlias = true; + while (localTypeAnnotation->IsETSTypeReference() && isAnnotationTypeAlias) { + auto *node = localTypeAnnotation->AsETSTypeReference() + ->Part() + ->Name() + ->AsIdentifier() + ->Variable() + ->Declaration() + ->Node(); + + isAnnotationTypeAlias = node->IsTSTypeAliasDeclaration(); + if (isAnnotationTypeAlias) { + localTypeAnnotation = node->AsTSTypeAliasDeclaration()->TypeAnnotation(); + } + } + } + + if (localTypeAnnotation != nullptr && localTypeAnnotation->IsETSFunctionType() && + init->IsArrowFunctionExpression()) { + auto *const arrowFuncExpr = init->AsArrowFunctionExpression(); + ir::ScriptFunction *const lambda = arrowFuncExpr->Function(); + if (lambda->Params().size() == localTypeAnnotation->AsETSFunctionType()->Params().size() && + NeedTypeInference(lambda)) { + InferTypesForLambda(lambda, localTypeAnnotation->AsETSFunctionType()); + } + } +} + checker::Type *ETSChecker::FixOptionalVariableType(varbinder::Variable *const bindingVar, ir::ModifierFlags flags) { if ((flags & ir::ModifierFlags::OPTIONAL) != 0) { @@ -633,14 +664,8 @@ checker::Type *ETSChecker::CheckVariableDeclaration(ir::Identifier *ident, ir::T init->AsObjectExpression()->SetPreferredType(annotationType); } - if (typeAnnotation != nullptr && typeAnnotation->IsETSFunctionType() && init->IsArrowFunctionExpression()) { - auto *const arrowFuncExpr = init->AsArrowFunctionExpression(); - ir::ScriptFunction *const lambda = arrowFuncExpr->Function(); - if (lambda->Params().size() == typeAnnotation->AsETSFunctionType()->Params().size() && - NeedTypeInference(lambda)) { - InferTypesForLambda(lambda, typeAnnotation->AsETSFunctionType()); - } - } + InferAliasLambdaType(typeAnnotation, init); + checker::Type *initType = init->Check(this); if (initType == nullptr) { -- Gitee