From 177b0dc52550d7dad667903fa05978dad4ab960b Mon Sep 17 00:00:00 2001 From: furkanocalan Date: Wed, 13 Aug 2025 16:46:39 +0300 Subject: [PATCH] Array literal assign to a union of FixedArray Issue: #ICSU61 Description: There is a incorrect assignment in the array literal. Type checked for fixed array and warning message removed Signed-off-by: furkanocalan --- ets2panda/checker/ETSAnalyzer.cpp | 73 +++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 110ba4ec5c..767af7a73f 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -28,6 +28,7 @@ #include "types/type.h" #include "checker/types/typeError.h" +#include #include namespace ark::es2panda::checker { @@ -973,6 +974,68 @@ static Type *GetAppropriatePreferredType(Type *originalType, std::functionIsETSArrayType() && !type->IsETSResizableArrayType() && !type->IsETSTupleType(); +} + +static Type *SelectFixedArrayPreferredTypeForLiteral(ETSChecker *checker, ir::ArrayExpression *arrayLiteral, + Type *contextualType) +{ + if (checker == nullptr || arrayLiteral == nullptr || contextualType == nullptr || + !contextualType->IsETSUnionType()) { + return nullptr; + } + + auto &unionAlternatives = contextualType->AsETSUnionType()->ConstituentTypes(); + + Type *chosenFixedArray = nullptr; + bool multipleDifferentMatches = false; + + for (Type *candidate : unionAlternatives) { + if (!IsFixedArrayType(candidate)) { + continue; + } + + Type *candidateElementType = candidate->AsETSArrayType()->ElementType(); + if (candidateElementType == nullptr) { + continue; + } + + bool allElementsAssignable = true; + + for (auto *elementNode : arrayLiteral->Elements()) { + if (elementNode == nullptr || elementNode->IsSpreadElement()) { + allElementsAssignable = false; + break; + } + + Type *elementType = elementNode->TsType(); + if (elementType == nullptr) { + elementType = elementNode->Check(checker); + } + + if (elementType == nullptr || !checker->Relation()->IsAssignableTo(elementType, candidateElementType)) { + allElementsAssignable = false; + break; + } + } + + if (!allElementsAssignable) { + continue; + } + + if (chosenFixedArray != nullptr && !checker->Relation()->IsIdenticalTo(chosenFixedArray, candidate)) { + multipleDifferentMatches = true; + break; + } + + chosenFixedArray = candidate; + } + + return (chosenFixedArray != nullptr && !multipleDifferentMatches) ? chosenFixedArray : nullptr; +} + checker::Type *ETSAnalyzer::Check(ir::ArrayExpression *expr) const { ETSChecker *checker = GetETSChecker(); @@ -982,6 +1045,16 @@ checker::Type *ETSAnalyzer::Check(ir::ArrayExpression *expr) const auto *preferredType = GetAppropriatePreferredType(expr->PreferredType(), &Type::IsAnyETSArrayOrTupleType); + if (preferredType == nullptr || preferredType->IsETSUnionType()) { + Type *contextualType = (preferredType != nullptr) ? preferredType : expr->PreferredType(); + if (contextualType != nullptr && contextualType->IsETSUnionType()) { + if (Type *fixedArrayChoice = SelectFixedArrayPreferredTypeForLiteral(checker, expr, contextualType)) { + preferredType = fixedArrayChoice; + expr->SetPreferredType(preferredType); + } + } + } + if (preferredType != nullptr && preferredType->IsETSReadonlyArrayType()) { const auto elementType = preferredType->AsETSObjectType()->TypeArguments().front(); preferredType = checker->CreateETSResizableArrayType(elementType); -- Gitee