13af6ab5fSopenharmony_ci/** 23af6ab5fSopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License. 53af6ab5fSopenharmony_ci * You may obtain a copy of the License at 63af6ab5fSopenharmony_ci * 73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83af6ab5fSopenharmony_ci * 93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and 133af6ab5fSopenharmony_ci * limitations under the License. 143af6ab5fSopenharmony_ci */ 153af6ab5fSopenharmony_ci 163af6ab5fSopenharmony_ci#include "utils/logger.h" 173af6ab5fSopenharmony_ci#include "varbinder/ETSBinder.h" 183af6ab5fSopenharmony_ci#include "checker/ETSchecker.h" 193af6ab5fSopenharmony_ci#include "checker/ets/castingContext.h" 203af6ab5fSopenharmony_ci#include "checker/ets/function_helpers.h" 213af6ab5fSopenharmony_ci#include "checker/ets/typeRelationContext.h" 223af6ab5fSopenharmony_ci#include "checker/types/ets/etsAsyncFuncReturnType.h" 233af6ab5fSopenharmony_ci#include "checker/types/ets/etsObjectType.h" 243af6ab5fSopenharmony_ci#include "ir/base/catchClause.h" 253af6ab5fSopenharmony_ci#include "ir/base/classDefinition.h" 263af6ab5fSopenharmony_ci#include "ir/base/classProperty.h" 273af6ab5fSopenharmony_ci#include "ir/base/methodDefinition.h" 283af6ab5fSopenharmony_ci#include "ir/base/scriptFunction.h" 293af6ab5fSopenharmony_ci#include "ir/base/spreadElement.h" 303af6ab5fSopenharmony_ci#include "ir/ets/etsFunctionType.h" 313af6ab5fSopenharmony_ci#include "ir/ets/etsParameterExpression.h" 323af6ab5fSopenharmony_ci#include "ir/ets/etsTypeReference.h" 333af6ab5fSopenharmony_ci#include "ir/ets/etsTypeReferencePart.h" 343af6ab5fSopenharmony_ci#include "ir/ets/etsUnionType.h" 353af6ab5fSopenharmony_ci#include "ir/expressions/arrowFunctionExpression.h" 363af6ab5fSopenharmony_ci#include "ir/expressions/assignmentExpression.h" 373af6ab5fSopenharmony_ci#include "ir/expressions/callExpression.h" 383af6ab5fSopenharmony_ci#include "ir/expressions/functionExpression.h" 393af6ab5fSopenharmony_ci#include "ir/expressions/identifier.h" 403af6ab5fSopenharmony_ci#include "ir/expressions/literals/numberLiteral.h" 413af6ab5fSopenharmony_ci#include "ir/expressions/literals/undefinedLiteral.h" 423af6ab5fSopenharmony_ci#include "ir/expressions/memberExpression.h" 433af6ab5fSopenharmony_ci#include "ir/expressions/objectExpression.h" 443af6ab5fSopenharmony_ci#include "ir/expressions/thisExpression.h" 453af6ab5fSopenharmony_ci#include "ir/statements/blockStatement.h" 463af6ab5fSopenharmony_ci#include "ir/statements/doWhileStatement.h" 473af6ab5fSopenharmony_ci#include "ir/statements/expressionStatement.h" 483af6ab5fSopenharmony_ci#include "ir/statements/forInStatement.h" 493af6ab5fSopenharmony_ci#include "ir/statements/forOfStatement.h" 503af6ab5fSopenharmony_ci#include "ir/statements/forUpdateStatement.h" 513af6ab5fSopenharmony_ci#include "ir/statements/returnStatement.h" 523af6ab5fSopenharmony_ci#include "ir/statements/switchStatement.h" 533af6ab5fSopenharmony_ci#include "ir/statements/whileStatement.h" 543af6ab5fSopenharmony_ci#include "ir/ts/tsTypeAliasDeclaration.h" 553af6ab5fSopenharmony_ci#include "ir/ts/tsTypeParameter.h" 563af6ab5fSopenharmony_ci#include "ir/ts/tsTypeParameterInstantiation.h" 573af6ab5fSopenharmony_ci#include "parser/program/program.h" 583af6ab5fSopenharmony_ci#include "util/helpers.h" 593af6ab5fSopenharmony_ci#include "util/language.h" 603af6ab5fSopenharmony_ci 613af6ab5fSopenharmony_cinamespace ark::es2panda::checker { 623af6ab5fSopenharmony_ci 633af6ab5fSopenharmony_ci// NOTE: #14993 merge with InstantiationContext::ValidateTypeArg 643af6ab5fSopenharmony_cibool ETSChecker::IsCompatibleTypeArgument(ETSTypeParameter *typeParam, Type *typeArgument, 653af6ab5fSopenharmony_ci const Substitution *substitution) 663af6ab5fSopenharmony_ci{ 673af6ab5fSopenharmony_ci if (typeArgument->IsWildcardType()) { 683af6ab5fSopenharmony_ci return true; 693af6ab5fSopenharmony_ci } 703af6ab5fSopenharmony_ci ASSERT(IsReferenceType(typeArgument) || typeArgument->IsETSVoidType()); 713af6ab5fSopenharmony_ci auto *constraint = typeParam->GetConstraintType()->Substitute(Relation(), substitution); 723af6ab5fSopenharmony_ci bool retVal = false; 733af6ab5fSopenharmony_ci if (typeArgument->IsETSVoidType()) { 743af6ab5fSopenharmony_ci retVal = Relation()->IsSupertypeOf(constraint, GlobalETSUndefinedType()); 753af6ab5fSopenharmony_ci } else if (typeArgument->IsETSFunctionType()) { 763af6ab5fSopenharmony_ci retVal = Relation()->IsSupertypeOf( 773af6ab5fSopenharmony_ci constraint, 783af6ab5fSopenharmony_ci this->FunctionTypeToFunctionalInterfaceType(typeArgument->AsETSFunctionType()->CallSignatures().front())); 793af6ab5fSopenharmony_ci } else { 803af6ab5fSopenharmony_ci retVal = Relation()->IsSupertypeOf(constraint, typeArgument); 813af6ab5fSopenharmony_ci } 823af6ab5fSopenharmony_ci 833af6ab5fSopenharmony_ci return retVal; 843af6ab5fSopenharmony_ci} 853af6ab5fSopenharmony_ci 863af6ab5fSopenharmony_cibool ETSChecker::HasTypeArgsOfObject(Type *argType, Type *paramType) 873af6ab5fSopenharmony_ci{ 883af6ab5fSopenharmony_ci return paramType->IsETSObjectType() && argType->IsETSObjectType() && 893af6ab5fSopenharmony_ci !argType->AsETSObjectType()->TypeArguments().empty() && 903af6ab5fSopenharmony_ci !paramType->AsETSObjectType()->TypeArguments().empty(); 913af6ab5fSopenharmony_ci} 923af6ab5fSopenharmony_ci 933af6ab5fSopenharmony_cibool ETSChecker::InsertTypeIntoSubstitution(const ArenaVector<Type *> &typeParams, const Type *typeParam, 943af6ab5fSopenharmony_ci const size_t index, Substitution *substitution, Type *objectParam) 953af6ab5fSopenharmony_ci{ 963af6ab5fSopenharmony_ci // Check if the type parameter is in the signature, and the type argument is not already in the return vector 973af6ab5fSopenharmony_ci if (typeParams.size() > index && 983af6ab5fSopenharmony_ci IsCompatibleTypeArgument(typeParams[index]->AsETSTypeParameter(), objectParam, substitution) && 993af6ab5fSopenharmony_ci std::find(typeParams.begin(), typeParams.end(), typeParam) != typeParams.end()) { 1003af6ab5fSopenharmony_ci substitution->emplace(typeParams[index]->AsETSTypeParameter(), objectParam); 1013af6ab5fSopenharmony_ci return true; 1023af6ab5fSopenharmony_ci } 1033af6ab5fSopenharmony_ci 1043af6ab5fSopenharmony_ci return false; 1053af6ab5fSopenharmony_ci} 1063af6ab5fSopenharmony_ci 1073af6ab5fSopenharmony_cibool ETSChecker::EnhanceSubstitutionForGenericType(const ArenaVector<Type *> &typeParams, const Type *argType, 1083af6ab5fSopenharmony_ci const Type *paramType, Substitution *substitution) 1093af6ab5fSopenharmony_ci{ 1103af6ab5fSopenharmony_ci ArenaVector<Type *> objectParams(Allocator()->Adapter()); 1113af6ab5fSopenharmony_ci 1123af6ab5fSopenharmony_ci if (!argType->AsETSObjectType()->GetDeclNode()->IsClassDefinition()) { 1133af6ab5fSopenharmony_ci return false; 1143af6ab5fSopenharmony_ci } 1153af6ab5fSopenharmony_ci 1163af6ab5fSopenharmony_ci const auto paramTypeArgs = paramType->AsETSObjectType()->TypeArguments(); 1173af6ab5fSopenharmony_ci 1183af6ab5fSopenharmony_ci for (const auto it : typeParams) { 1193af6ab5fSopenharmony_ci bool found = false; 1203af6ab5fSopenharmony_ci 1213af6ab5fSopenharmony_ci for (size_t i = 0; i < paramTypeArgs.size() && !found; i++) { 1223af6ab5fSopenharmony_ci if (paramTypeArgs[i] == it) { 1233af6ab5fSopenharmony_ci objectParams.push_back(argType->AsETSObjectType()->TypeArguments()[i]); 1243af6ab5fSopenharmony_ci found = true; 1253af6ab5fSopenharmony_ci } 1263af6ab5fSopenharmony_ci } 1273af6ab5fSopenharmony_ci 1283af6ab5fSopenharmony_ci if (!found) { 1293af6ab5fSopenharmony_ci objectParams.push_back(nullptr); 1303af6ab5fSopenharmony_ci } 1313af6ab5fSopenharmony_ci } 1323af6ab5fSopenharmony_ci 1333af6ab5fSopenharmony_ci if (objectParams.size() < paramTypeArgs.size()) { 1343af6ab5fSopenharmony_ci return false; 1353af6ab5fSopenharmony_ci } 1363af6ab5fSopenharmony_ci 1373af6ab5fSopenharmony_ci bool res = true; 1383af6ab5fSopenharmony_ci for (size_t j = 0; j < paramTypeArgs.size() && res; ++j) { 1393af6ab5fSopenharmony_ci if (objectParams[j] != nullptr) { 1403af6ab5fSopenharmony_ci res = InsertTypeIntoSubstitution(typeParams, paramTypeArgs[j], j, substitution, objectParams[j]); 1413af6ab5fSopenharmony_ci } else { 1423af6ab5fSopenharmony_ci res = EnhanceSubstitutionForType(typeParams, paramTypeArgs[j], 1433af6ab5fSopenharmony_ci argType->AsETSObjectType()->TypeArguments()[j], substitution); 1443af6ab5fSopenharmony_ci } 1453af6ab5fSopenharmony_ci } 1463af6ab5fSopenharmony_ci 1473af6ab5fSopenharmony_ci return res; 1483af6ab5fSopenharmony_ci} 1493af6ab5fSopenharmony_ci 1503af6ab5fSopenharmony_cibool ETSChecker::EnhanceSubstitutionForReadonly(const ArenaVector<Type *> &typeParams, ETSReadonlyType *paramType, 1513af6ab5fSopenharmony_ci Type *argumentType, Substitution *substitution) 1523af6ab5fSopenharmony_ci{ 1533af6ab5fSopenharmony_ci return EnhanceSubstitutionForType(typeParams, paramType->GetUnderlying(), GetReadonlyType(argumentType), 1543af6ab5fSopenharmony_ci substitution); 1553af6ab5fSopenharmony_ci} 1563af6ab5fSopenharmony_ci 1573af6ab5fSopenharmony_ci/* A very rough and imprecise partial type inference */ 1583af6ab5fSopenharmony_cibool ETSChecker::EnhanceSubstitutionForType(const ArenaVector<Type *> &typeParams, Type *paramType, Type *argumentType, 1593af6ab5fSopenharmony_ci Substitution *substitution) 1603af6ab5fSopenharmony_ci{ 1613af6ab5fSopenharmony_ci if (argumentType->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) { 1623af6ab5fSopenharmony_ci argumentType = PrimitiveTypeAsETSBuiltinType(argumentType); 1633af6ab5fSopenharmony_ci } 1643af6ab5fSopenharmony_ci if (paramType->IsETSTypeParameter()) { 1653af6ab5fSopenharmony_ci auto *const tparam = paramType->AsETSTypeParameter(); 1663af6ab5fSopenharmony_ci auto *const originalTparam = tparam->GetOriginal(); 1673af6ab5fSopenharmony_ci if (std::find(typeParams.begin(), typeParams.end(), originalTparam) != typeParams.end() && 1683af6ab5fSopenharmony_ci substitution->count(originalTparam) == 0) { 1693af6ab5fSopenharmony_ci if (!IsReferenceType(argumentType)) { 1703af6ab5fSopenharmony_ci LogTypeError({argumentType, " is not compatible with type ", tparam}, tparam->GetDeclNode()->Start()); 1713af6ab5fSopenharmony_ci return false; 1723af6ab5fSopenharmony_ci } 1733af6ab5fSopenharmony_ci 1743af6ab5fSopenharmony_ci ETSChecker::EmplaceSubstituted(substitution, originalTparam, argumentType); 1753af6ab5fSopenharmony_ci return IsCompatibleTypeArgument(tparam, argumentType, substitution); 1763af6ab5fSopenharmony_ci } 1773af6ab5fSopenharmony_ci } 1783af6ab5fSopenharmony_ci 1793af6ab5fSopenharmony_ci if (paramType->IsETSReadonlyType()) { 1803af6ab5fSopenharmony_ci return EnhanceSubstitutionForReadonly(typeParams, paramType->AsETSReadonlyType(), argumentType, substitution); 1813af6ab5fSopenharmony_ci } 1823af6ab5fSopenharmony_ci if (paramType->IsETSUnionType()) { 1833af6ab5fSopenharmony_ci return EnhanceSubstitutionForUnion(typeParams, paramType->AsETSUnionType(), argumentType, substitution); 1843af6ab5fSopenharmony_ci } 1853af6ab5fSopenharmony_ci if (paramType->IsETSObjectType()) { 1863af6ab5fSopenharmony_ci if (HasTypeArgsOfObject(argumentType, paramType) && 1873af6ab5fSopenharmony_ci EnhanceSubstitutionForGenericType(typeParams, argumentType, paramType, substitution)) { 1883af6ab5fSopenharmony_ci return true; 1893af6ab5fSopenharmony_ci } 1903af6ab5fSopenharmony_ci return EnhanceSubstitutionForObject(typeParams, paramType->AsETSObjectType(), argumentType, substitution); 1913af6ab5fSopenharmony_ci } 1923af6ab5fSopenharmony_ci if (paramType->IsETSArrayType()) { 1933af6ab5fSopenharmony_ci return EnhanceSubstitutionForArray(typeParams, paramType->AsETSArrayType(), argumentType, substitution); 1943af6ab5fSopenharmony_ci } 1953af6ab5fSopenharmony_ci 1963af6ab5fSopenharmony_ci return true; 1973af6ab5fSopenharmony_ci} 1983af6ab5fSopenharmony_ci 1993af6ab5fSopenharmony_cibool ETSChecker::EnhanceSubstitutionForUnion(const ArenaVector<Type *> &typeParams, ETSUnionType *paramUn, 2003af6ab5fSopenharmony_ci Type *argumentType, Substitution *substitution) 2013af6ab5fSopenharmony_ci{ 2023af6ab5fSopenharmony_ci if (!argumentType->IsETSUnionType()) { 2033af6ab5fSopenharmony_ci return std::any_of( 2043af6ab5fSopenharmony_ci paramUn->ConstituentTypes().begin(), paramUn->ConstituentTypes().end(), 2053af6ab5fSopenharmony_ci [this, typeParams, argumentType, substitution](Type *ctype) { 2063af6ab5fSopenharmony_ci return EnhanceSubstitutionForType(typeParams, ctype, argumentType, substitution) && 2073af6ab5fSopenharmony_ci (!ctype->IsETSTypeParameter() || 2083af6ab5fSopenharmony_ci (substitution->find(ctype->AsETSTypeParameter()) != substitution->end() && 2093af6ab5fSopenharmony_ci Relation()->IsAssignableTo(argumentType, substitution->at(ctype->AsETSTypeParameter())))); 2103af6ab5fSopenharmony_ci }); 2113af6ab5fSopenharmony_ci } 2123af6ab5fSopenharmony_ci auto *const argUn = argumentType->AsETSUnionType(); 2133af6ab5fSopenharmony_ci 2143af6ab5fSopenharmony_ci ArenaVector<Type *> paramWlist(Allocator()->Adapter()); 2153af6ab5fSopenharmony_ci ArenaVector<Type *> argWlist(Allocator()->Adapter()); 2163af6ab5fSopenharmony_ci 2173af6ab5fSopenharmony_ci for (auto *pc : paramUn->ConstituentTypes()) { 2183af6ab5fSopenharmony_ci for (auto *ac : argUn->ConstituentTypes()) { 2193af6ab5fSopenharmony_ci if (ETSChecker::GetOriginalBaseType(pc) != ETSChecker::GetOriginalBaseType(ac)) { 2203af6ab5fSopenharmony_ci paramWlist.push_back(pc); 2213af6ab5fSopenharmony_ci argWlist.push_back(ac); 2223af6ab5fSopenharmony_ci continue; 2233af6ab5fSopenharmony_ci } 2243af6ab5fSopenharmony_ci if (!EnhanceSubstitutionForType(typeParams, pc, ac, substitution)) { 2253af6ab5fSopenharmony_ci return false; 2263af6ab5fSopenharmony_ci } 2273af6ab5fSopenharmony_ci } 2283af6ab5fSopenharmony_ci } 2293af6ab5fSopenharmony_ci auto *const newArg = CreateETSUnionType(std::move(argWlist)); 2303af6ab5fSopenharmony_ci 2313af6ab5fSopenharmony_ci for (auto *pc : paramWlist) { 2323af6ab5fSopenharmony_ci if (!EnhanceSubstitutionForType(typeParams, pc, newArg, substitution)) { 2333af6ab5fSopenharmony_ci return false; 2343af6ab5fSopenharmony_ci } 2353af6ab5fSopenharmony_ci } 2363af6ab5fSopenharmony_ci return true; 2373af6ab5fSopenharmony_ci} 2383af6ab5fSopenharmony_ci 2393af6ab5fSopenharmony_cibool ETSChecker::EnhanceSubstitutionForObject(const ArenaVector<Type *> &typeParams, ETSObjectType *paramType, 2403af6ab5fSopenharmony_ci Type *argumentType, Substitution *substitution) 2413af6ab5fSopenharmony_ci{ 2423af6ab5fSopenharmony_ci auto *paramObjType = paramType->AsETSObjectType(); 2433af6ab5fSopenharmony_ci 2443af6ab5fSopenharmony_ci auto const enhance = [this, typeParams, substitution](Type *ptype, Type *atype) { 2453af6ab5fSopenharmony_ci return EnhanceSubstitutionForType(typeParams, ptype, atype, substitution); 2463af6ab5fSopenharmony_ci }; 2473af6ab5fSopenharmony_ci 2483af6ab5fSopenharmony_ci if (argumentType->IsETSObjectType()) { 2493af6ab5fSopenharmony_ci auto *argObjType = argumentType->AsETSObjectType(); 2503af6ab5fSopenharmony_ci if (GetOriginalBaseType(argObjType) != GetOriginalBaseType(paramObjType)) { 2513af6ab5fSopenharmony_ci return true; // don't attempt anything fancy for now 2523af6ab5fSopenharmony_ci } 2533af6ab5fSopenharmony_ci bool res = true; 2543af6ab5fSopenharmony_ci for (size_t i = 0; i < argObjType->TypeArguments().size(); i++) { 2553af6ab5fSopenharmony_ci res &= enhance(paramObjType->TypeArguments()[i], argObjType->TypeArguments()[i]); 2563af6ab5fSopenharmony_ci } 2573af6ab5fSopenharmony_ci return res; 2583af6ab5fSopenharmony_ci } 2593af6ab5fSopenharmony_ci 2603af6ab5fSopenharmony_ci if (argumentType->IsETSFunctionType() && paramObjType->HasObjectFlag(ETSObjectFlags::FUNCTIONAL_INTERFACE)) { 2613af6ab5fSopenharmony_ci auto ¶meterSignatures = 2623af6ab5fSopenharmony_ci paramObjType 2633af6ab5fSopenharmony_ci ->GetOwnProperty<checker::PropertyType::INSTANCE_METHOD>(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME) 2643af6ab5fSopenharmony_ci ->TsType() 2653af6ab5fSopenharmony_ci ->AsETSFunctionType() 2663af6ab5fSopenharmony_ci ->CallSignatures(); 2673af6ab5fSopenharmony_ci auto &argumentSignatures = argumentType->AsETSFunctionType()->CallSignatures(); 2683af6ab5fSopenharmony_ci ASSERT(argumentSignatures.size() == 1); 2693af6ab5fSopenharmony_ci ASSERT(parameterSignatures.size() == 1); 2703af6ab5fSopenharmony_ci auto *argumentSignature = argumentSignatures[0]; 2713af6ab5fSopenharmony_ci auto *parameterSignature = parameterSignatures[0]; 2723af6ab5fSopenharmony_ci // NOTE(gogabr): handle rest parameter for argumentSignature 2733af6ab5fSopenharmony_ci if (parameterSignature->GetSignatureInfo()->params.size() != 2743af6ab5fSopenharmony_ci argumentSignature->GetSignatureInfo()->params.size()) { 2753af6ab5fSopenharmony_ci return false; 2763af6ab5fSopenharmony_ci } 2773af6ab5fSopenharmony_ci bool res = true; 2783af6ab5fSopenharmony_ci for (size_t idx = 0; idx < argumentSignature->GetSignatureInfo()->params.size(); idx++) { 2793af6ab5fSopenharmony_ci res &= enhance(parameterSignature->GetSignatureInfo()->params[idx]->TsType(), 2803af6ab5fSopenharmony_ci argumentSignature->GetSignatureInfo()->params[idx]->TsType()); 2813af6ab5fSopenharmony_ci } 2823af6ab5fSopenharmony_ci res &= enhance(parameterSignature->ReturnType(), argumentSignature->ReturnType()); 2833af6ab5fSopenharmony_ci return res; 2843af6ab5fSopenharmony_ci } 2853af6ab5fSopenharmony_ci 2863af6ab5fSopenharmony_ci return true; 2873af6ab5fSopenharmony_ci} 2883af6ab5fSopenharmony_ci 2893af6ab5fSopenharmony_cibool ETSChecker::EnhanceSubstitutionForArray(const ArenaVector<Type *> &typeParams, ETSArrayType *const paramType, 2903af6ab5fSopenharmony_ci Type *const argumentType, Substitution *const substitution) 2913af6ab5fSopenharmony_ci{ 2923af6ab5fSopenharmony_ci auto *const elementType = 2933af6ab5fSopenharmony_ci argumentType->IsETSArrayType() ? argumentType->AsETSArrayType()->ElementType() : argumentType; 2943af6ab5fSopenharmony_ci 2953af6ab5fSopenharmony_ci return EnhanceSubstitutionForType(typeParams, paramType->ElementType(), elementType, substitution); 2963af6ab5fSopenharmony_ci} 2973af6ab5fSopenharmony_ci 2983af6ab5fSopenharmony_ciSignature *ETSChecker::ValidateParameterlessConstructor(Signature *signature, const lexer::SourcePosition &pos, 2993af6ab5fSopenharmony_ci TypeRelationFlag flags) 3003af6ab5fSopenharmony_ci{ 3013af6ab5fSopenharmony_ci std::size_t const parameterCount = signature->MinArgCount(); 3023af6ab5fSopenharmony_ci auto const reportError = (flags & TypeRelationFlag::NO_THROW) == 0; 3033af6ab5fSopenharmony_ci 3043af6ab5fSopenharmony_ci if (parameterCount != 0) { 3053af6ab5fSopenharmony_ci if (reportError) { 3063af6ab5fSopenharmony_ci LogTypeError({"No Matching Parameterless Constructor, parameter count ", parameterCount}, pos); 3073af6ab5fSopenharmony_ci } 3083af6ab5fSopenharmony_ci return nullptr; 3093af6ab5fSopenharmony_ci } 3103af6ab5fSopenharmony_ci return signature; 3113af6ab5fSopenharmony_ci} 3123af6ab5fSopenharmony_ci 3133af6ab5fSopenharmony_cibool ETSChecker::CheckOptionalLambdaFunction(ir::Expression *argument, Signature *substitutedSig, std::size_t index) 3143af6ab5fSopenharmony_ci{ 3153af6ab5fSopenharmony_ci if (argument->IsArrowFunctionExpression()) { 3163af6ab5fSopenharmony_ci auto *const arrowFuncExpr = argument->AsArrowFunctionExpression(); 3173af6ab5fSopenharmony_ci 3183af6ab5fSopenharmony_ci if (ir::ScriptFunction *const lambda = arrowFuncExpr->Function(); 3193af6ab5fSopenharmony_ci CheckLambdaAssignable(substitutedSig->Function()->Params()[index], lambda)) { 3203af6ab5fSopenharmony_ci if (arrowFuncExpr->TsTypeOrError() != nullptr) { 3213af6ab5fSopenharmony_ci arrowFuncExpr->Check(this); 3223af6ab5fSopenharmony_ci return true; 3233af6ab5fSopenharmony_ci } 3243af6ab5fSopenharmony_ci } 3253af6ab5fSopenharmony_ci } 3263af6ab5fSopenharmony_ci 3273af6ab5fSopenharmony_ci return false; 3283af6ab5fSopenharmony_ci} 3293af6ab5fSopenharmony_ci 3303af6ab5fSopenharmony_cibool ETSChecker::ValidateArgumentAsIdentifier(const ir::Identifier *identifier) 3313af6ab5fSopenharmony_ci{ 3323af6ab5fSopenharmony_ci auto result = Scope()->Find(identifier->Name()); 3333af6ab5fSopenharmony_ci return result.variable != nullptr && (result.variable->HasFlag(varbinder::VariableFlags::CLASS_OR_INTERFACE)); 3343af6ab5fSopenharmony_ci} 3353af6ab5fSopenharmony_ci 3363af6ab5fSopenharmony_cibool ETSChecker::ValidateSignatureRequiredParams(Signature *substitutedSig, 3373af6ab5fSopenharmony_ci const ArenaVector<ir::Expression *> &arguments, TypeRelationFlag flags, 3383af6ab5fSopenharmony_ci const std::vector<bool> &argTypeInferenceRequired, bool reportError) 3393af6ab5fSopenharmony_ci{ 3403af6ab5fSopenharmony_ci std::size_t const argumentCount = arguments.size(); 3413af6ab5fSopenharmony_ci std::size_t const parameterCount = substitutedSig->MinArgCount(); 3423af6ab5fSopenharmony_ci auto count = std::min(parameterCount, argumentCount); 3433af6ab5fSopenharmony_ci for (std::size_t index = 0; index < count; ++index) { 3443af6ab5fSopenharmony_ci auto &argument = arguments[index]; 3453af6ab5fSopenharmony_ci 3463af6ab5fSopenharmony_ci if (argument->IsObjectExpression()) { 3473af6ab5fSopenharmony_ci if (substitutedSig->Params()[index]->TsType()->IsETSObjectType()) { 3483af6ab5fSopenharmony_ci // No chance to check the argument at this point 3493af6ab5fSopenharmony_ci continue; 3503af6ab5fSopenharmony_ci } 3513af6ab5fSopenharmony_ci return false; 3523af6ab5fSopenharmony_ci } 3533af6ab5fSopenharmony_ci 3543af6ab5fSopenharmony_ci if (argument->IsMemberExpression()) { 3553af6ab5fSopenharmony_ci SetArrayPreferredTypeForNestedMemberExpressions(arguments[index]->AsMemberExpression(), 3563af6ab5fSopenharmony_ci substitutedSig->Params()[index]->TsType()); 3573af6ab5fSopenharmony_ci } else if (argument->IsSpreadElement()) { 3583af6ab5fSopenharmony_ci if (reportError) { 3593af6ab5fSopenharmony_ci LogTypeError("Spread argument cannot be passed for ordinary parameter.", argument->Start()); 3603af6ab5fSopenharmony_ci } 3613af6ab5fSopenharmony_ci return false; 3623af6ab5fSopenharmony_ci } 3633af6ab5fSopenharmony_ci 3643af6ab5fSopenharmony_ci if (argTypeInferenceRequired[index]) { 3653af6ab5fSopenharmony_ci ASSERT(argument->IsArrowFunctionExpression()); 3663af6ab5fSopenharmony_ci auto *const arrowFuncExpr = argument->AsArrowFunctionExpression(); 3673af6ab5fSopenharmony_ci ir::ScriptFunction *const lambda = arrowFuncExpr->Function(); 3683af6ab5fSopenharmony_ci if (CheckLambdaAssignable(substitutedSig->Function()->Params()[index], lambda)) { 3693af6ab5fSopenharmony_ci continue; 3703af6ab5fSopenharmony_ci } 3713af6ab5fSopenharmony_ci return false; 3723af6ab5fSopenharmony_ci } 3733af6ab5fSopenharmony_ci 3743af6ab5fSopenharmony_ci if (argument->IsArrayExpression()) { 3753af6ab5fSopenharmony_ci argument->AsArrayExpression()->GetPrefferedTypeFromFuncParam( 3763af6ab5fSopenharmony_ci this, substitutedSig->Function()->Params()[index], flags); 3773af6ab5fSopenharmony_ci } 3783af6ab5fSopenharmony_ci 3793af6ab5fSopenharmony_ci if (!CheckInvokable(substitutedSig, argument, index, flags)) { 3803af6ab5fSopenharmony_ci return false; 3813af6ab5fSopenharmony_ci } 3823af6ab5fSopenharmony_ci 3833af6ab5fSopenharmony_ci if (argument->IsIdentifier() && ValidateArgumentAsIdentifier(argument->AsIdentifier())) { 3843af6ab5fSopenharmony_ci LogTypeError("Class name can't be the argument of function or method.", argument->Start()); 3853af6ab5fSopenharmony_ci return false; 3863af6ab5fSopenharmony_ci } 3873af6ab5fSopenharmony_ci 3883af6ab5fSopenharmony_ci // clang-format off 3893af6ab5fSopenharmony_ci if (!ValidateSignatureInvocationContext( 3903af6ab5fSopenharmony_ci substitutedSig, argument, 3913af6ab5fSopenharmony_ci TryGettingFunctionTypeFromInvokeFunction(substitutedSig->Params()[index]->TsType()), index, flags)) { 3923af6ab5fSopenharmony_ci // clang-format on 3933af6ab5fSopenharmony_ci return false; 3943af6ab5fSopenharmony_ci } 3953af6ab5fSopenharmony_ci } 3963af6ab5fSopenharmony_ci 3973af6ab5fSopenharmony_ci return true; 3983af6ab5fSopenharmony_ci} 3993af6ab5fSopenharmony_ci 4003af6ab5fSopenharmony_cibool ETSChecker::CheckInvokable(Signature *substitutedSig, ir::Expression *argument, std::size_t index, 4013af6ab5fSopenharmony_ci TypeRelationFlag flags) 4023af6ab5fSopenharmony_ci{ 4033af6ab5fSopenharmony_ci auto *argumentType = argument->Check(this); 4043af6ab5fSopenharmony_ci auto *targetType = substitutedSig->Params()[index]->TsType(); 4053af6ab5fSopenharmony_ci 4063af6ab5fSopenharmony_ci auto const invocationCtx = 4073af6ab5fSopenharmony_ci checker::InvocationContext(Relation(), argument, argumentType, targetType, argument->Start(), 4083af6ab5fSopenharmony_ci {"Type '", argumentType, "' is not compatible with type '", 4093af6ab5fSopenharmony_ci TryGettingFunctionTypeFromInvokeFunction(targetType), "' at index ", index + 1}, 4103af6ab5fSopenharmony_ci flags); 4113af6ab5fSopenharmony_ci return invocationCtx.IsInvocable() || CheckOptionalLambdaFunction(argument, substitutedSig, index); 4123af6ab5fSopenharmony_ci} 4133af6ab5fSopenharmony_ci 4143af6ab5fSopenharmony_cibool ETSChecker::ValidateSignatureInvocationContext(Signature *substitutedSig, ir::Expression *argument, 4153af6ab5fSopenharmony_ci const Type *targetType, std::size_t index, TypeRelationFlag flags) 4163af6ab5fSopenharmony_ci{ 4173af6ab5fSopenharmony_ci Type *argumentType = argument->Check(this); 4183af6ab5fSopenharmony_ci auto const invocationCtx = checker::InvocationContext( 4193af6ab5fSopenharmony_ci Relation(), argument, argumentType, substitutedSig->Params()[index]->TsType(), argument->Start(), 4203af6ab5fSopenharmony_ci {"Type '", argumentType, "' is not compatible with type '", targetType, "' at index ", index + 1}, flags); 4213af6ab5fSopenharmony_ci if (!invocationCtx.IsInvocable()) { 4223af6ab5fSopenharmony_ci return CheckOptionalLambdaFunction(argument, substitutedSig, index); 4233af6ab5fSopenharmony_ci } 4243af6ab5fSopenharmony_ci 4253af6ab5fSopenharmony_ci return true; 4263af6ab5fSopenharmony_ci} 4273af6ab5fSopenharmony_ci 4283af6ab5fSopenharmony_cibool ETSChecker::ValidateSignatureRestParams(Signature *substitutedSig, const ArenaVector<ir::Expression *> &arguments, 4293af6ab5fSopenharmony_ci TypeRelationFlag flags, bool reportError) 4303af6ab5fSopenharmony_ci{ 4313af6ab5fSopenharmony_ci std::size_t const argumentCount = arguments.size(); 4323af6ab5fSopenharmony_ci std::size_t const parameterCount = substitutedSig->MinArgCount(); 4333af6ab5fSopenharmony_ci auto count = std::min(parameterCount, argumentCount); 4343af6ab5fSopenharmony_ci auto const restCount = argumentCount - count; 4353af6ab5fSopenharmony_ci 4363af6ab5fSopenharmony_ci for (std::size_t index = count; index < argumentCount; ++index) { 4373af6ab5fSopenharmony_ci auto &argument = arguments[index]; 4383af6ab5fSopenharmony_ci 4393af6ab5fSopenharmony_ci if (!argument->IsSpreadElement()) { 4403af6ab5fSopenharmony_ci auto *const argumentType = argument->Check(this); 4413af6ab5fSopenharmony_ci const Type *targetType = TryGettingFunctionTypeFromInvokeFunction( 4423af6ab5fSopenharmony_ci substitutedSig->RestVar()->TsType()->AsETSArrayType()->ElementType()); 4433af6ab5fSopenharmony_ci const Type *sourceType = TryGettingFunctionTypeFromInvokeFunction(argumentType); 4443af6ab5fSopenharmony_ci auto const invocationCtx = checker::InvocationContext( 4453af6ab5fSopenharmony_ci Relation(), argument, argumentType, 4463af6ab5fSopenharmony_ci substitutedSig->RestVar()->TsType()->AsETSArrayType()->ElementType(), argument->Start(), 4473af6ab5fSopenharmony_ci {"Type '", sourceType, "' is not compatible with rest parameter type '", targetType, "' at index ", 4483af6ab5fSopenharmony_ci index + 1}, 4493af6ab5fSopenharmony_ci flags); 4503af6ab5fSopenharmony_ci if (!invocationCtx.IsInvocable()) { 4513af6ab5fSopenharmony_ci return false; 4523af6ab5fSopenharmony_ci } 4533af6ab5fSopenharmony_ci continue; 4543af6ab5fSopenharmony_ci } 4553af6ab5fSopenharmony_ci 4563af6ab5fSopenharmony_ci if (restCount > 1U) { 4573af6ab5fSopenharmony_ci if (reportError) { 4583af6ab5fSopenharmony_ci LogTypeError("Spread argument for the rest parameter can be only one.", argument->Start()); 4593af6ab5fSopenharmony_ci } 4603af6ab5fSopenharmony_ci return false; 4613af6ab5fSopenharmony_ci } 4623af6ab5fSopenharmony_ci 4633af6ab5fSopenharmony_ci auto *const restArgument = argument->AsSpreadElement()->Argument(); 4643af6ab5fSopenharmony_ci auto *const argumentType = restArgument->Check(this); 4653af6ab5fSopenharmony_ci const Type *targetType = TryGettingFunctionTypeFromInvokeFunction(substitutedSig->RestVar()->TsType()); 4663af6ab5fSopenharmony_ci const Type *sourceType = TryGettingFunctionTypeFromInvokeFunction(argumentType); 4673af6ab5fSopenharmony_ci 4683af6ab5fSopenharmony_ci auto const invocationCtx = checker::InvocationContext( 4693af6ab5fSopenharmony_ci Relation(), restArgument, argumentType, substitutedSig->RestVar()->TsType(), argument->Start(), 4703af6ab5fSopenharmony_ci {"Type '", sourceType, "' is not compatible with rest parameter type '", targetType, "' at index ", 4713af6ab5fSopenharmony_ci index + 1}, 4723af6ab5fSopenharmony_ci flags); 4733af6ab5fSopenharmony_ci if (!invocationCtx.IsInvocable()) { 4743af6ab5fSopenharmony_ci return false; 4753af6ab5fSopenharmony_ci } 4763af6ab5fSopenharmony_ci } 4773af6ab5fSopenharmony_ci 4783af6ab5fSopenharmony_ci return true; 4793af6ab5fSopenharmony_ci} 4803af6ab5fSopenharmony_ci 4813af6ab5fSopenharmony_civoid ETSChecker::MaybeSubstituteLambdaArgumentsInFunctionCall(ir::CallExpression *callExpr) 4823af6ab5fSopenharmony_ci{ 4833af6ab5fSopenharmony_ci ir::AstNode *expr = callExpr; 4843af6ab5fSopenharmony_ci 4853af6ab5fSopenharmony_ci while (!expr->IsFunctionExpression()) { 4863af6ab5fSopenharmony_ci if (expr->Parent() == nullptr || expr->Parent()->IsClassDefinition()) { 4873af6ab5fSopenharmony_ci return; 4883af6ab5fSopenharmony_ci } 4893af6ab5fSopenharmony_ci expr = expr->Parent(); 4903af6ab5fSopenharmony_ci } 4913af6ab5fSopenharmony_ci 4923af6ab5fSopenharmony_ci for (const auto it : expr->AsFunctionExpression()->Function()->Params()) { 4933af6ab5fSopenharmony_ci if (const auto ident = it->AsETSParameterExpression()->Ident(); 4943af6ab5fSopenharmony_ci callExpr->Callee()->IsIdentifier() && ident->Name() == callExpr->Callee()->AsIdentifier()->Name() && 4953af6ab5fSopenharmony_ci ident->IsAnnotatedExpression()) { 4963af6ab5fSopenharmony_ci if (ident->AsAnnotatedExpression()->TypeAnnotation()->IsETSFunctionType()) { 4973af6ab5fSopenharmony_ci MaybeSubstituteLambdaArguments( 4983af6ab5fSopenharmony_ci ident->AsAnnotatedExpression()->TypeAnnotation()->AsETSFunctionType()->Params(), callExpr); 4993af6ab5fSopenharmony_ci } 5003af6ab5fSopenharmony_ci } 5013af6ab5fSopenharmony_ci } 5023af6ab5fSopenharmony_ci} 5033af6ab5fSopenharmony_ci 5043af6ab5fSopenharmony_civoid ETSChecker::MaybeSubstituteLambdaArgumentsInFunctionCallHelper(ir::CallExpression *callExpr, ir::Identifier *ident) 5053af6ab5fSopenharmony_ci{ 5063af6ab5fSopenharmony_ci ir::ETSFunctionType *funcType = nullptr; 5073af6ab5fSopenharmony_ci ir::TypeNode *typeAnnotation = ident->TypeAnnotation(); 5083af6ab5fSopenharmony_ci 5093af6ab5fSopenharmony_ci if (typeAnnotation->IsETSTypeReference()) { 5103af6ab5fSopenharmony_ci auto typeAnnotationIdentifier = ident->TypeAnnotation()->AsETSTypeReference()->Part()->Name()->Variable(); 5113af6ab5fSopenharmony_ci typeAnnotation = typeAnnotationIdentifier->Declaration()->Node()->AsTSTypeAliasDeclaration()->TypeAnnotation(); 5123af6ab5fSopenharmony_ci } 5133af6ab5fSopenharmony_ci 5143af6ab5fSopenharmony_ci if (typeAnnotation->IsETSFunctionType()) { 5153af6ab5fSopenharmony_ci funcType = typeAnnotation->AsETSFunctionType(); 5163af6ab5fSopenharmony_ci } else if (typeAnnotation->IsETSUnionType()) { 5173af6ab5fSopenharmony_ci auto found = std::find_if(typeAnnotation->AsETSUnionType()->Types().begin(), 5183af6ab5fSopenharmony_ci typeAnnotation->AsETSUnionType()->Types().end(), 5193af6ab5fSopenharmony_ci [](ir::TypeNode *const type) { return type->IsETSFunctionType(); }); 5203af6ab5fSopenharmony_ci if (found != typeAnnotation->AsETSUnionType()->Types().end()) { 5213af6ab5fSopenharmony_ci funcType = (*found)->AsETSFunctionType(); 5223af6ab5fSopenharmony_ci } 5233af6ab5fSopenharmony_ci } 5243af6ab5fSopenharmony_ci 5253af6ab5fSopenharmony_ci if (funcType == nullptr) { 5263af6ab5fSopenharmony_ci return; 5273af6ab5fSopenharmony_ci } 5283af6ab5fSopenharmony_ci 5293af6ab5fSopenharmony_ci MaybeSubstituteLambdaArguments(funcType->AsETSFunctionType()->Params(), callExpr); 5303af6ab5fSopenharmony_ci} 5313af6ab5fSopenharmony_ci 5323af6ab5fSopenharmony_civoid ETSChecker::MaybeSubstituteLambdaArguments(const ArenaVector<ir::Expression *> ¶ms, 5333af6ab5fSopenharmony_ci ir::CallExpression *callExpr) 5343af6ab5fSopenharmony_ci{ 5353af6ab5fSopenharmony_ci for (size_t i = 0; i < params.size(); i++) { 5363af6ab5fSopenharmony_ci if (params[i]->AsETSParameterExpression()->IsDefault() && callExpr->Arguments().size() <= i && 5373af6ab5fSopenharmony_ci params[i]->AsETSParameterExpression()->Initializer() != nullptr) { 5383af6ab5fSopenharmony_ci callExpr->Arguments().push_back( 5393af6ab5fSopenharmony_ci params[i]->AsETSParameterExpression()->Initializer()->Clone(Allocator(), callExpr)->AsExpression()); 5403af6ab5fSopenharmony_ci } 5413af6ab5fSopenharmony_ci } 5423af6ab5fSopenharmony_ci} 5433af6ab5fSopenharmony_ci 5443af6ab5fSopenharmony_ciSignature *ETSChecker::ValidateSignature( 5453af6ab5fSopenharmony_ci std::tuple<Signature *, const ir::TSTypeParameterInstantiation *, TypeRelationFlag> info, 5463af6ab5fSopenharmony_ci const ArenaVector<ir::Expression *> &arguments, const lexer::SourcePosition &pos, 5473af6ab5fSopenharmony_ci const std::vector<bool> &argTypeInferenceRequired) 5483af6ab5fSopenharmony_ci{ 5493af6ab5fSopenharmony_ci auto [signature, typeArguments, flags] = info; 5503af6ab5fSopenharmony_ci Signature *substitutedSig = MaybeSubstituteTypeParameters(this, signature, typeArguments, arguments, pos, flags); 5513af6ab5fSopenharmony_ci if (substitutedSig == nullptr) { 5523af6ab5fSopenharmony_ci return nullptr; 5533af6ab5fSopenharmony_ci } 5543af6ab5fSopenharmony_ci 5553af6ab5fSopenharmony_ci fflush(stdout); 5563af6ab5fSopenharmony_ci 5573af6ab5fSopenharmony_ci auto const hasRestParameter = substitutedSig->RestVar() != nullptr; 5583af6ab5fSopenharmony_ci std::size_t const argumentCount = arguments.size(); 5593af6ab5fSopenharmony_ci std::size_t const parameterCount = substitutedSig->MinArgCount(); 5603af6ab5fSopenharmony_ci auto const reportError = (flags & TypeRelationFlag::NO_THROW) == 0; 5613af6ab5fSopenharmony_ci 5623af6ab5fSopenharmony_ci if (argumentCount < parameterCount || (argumentCount > parameterCount && !hasRestParameter)) { 5633af6ab5fSopenharmony_ci if (reportError) { 5643af6ab5fSopenharmony_ci LogTypeError({"Expected ", parameterCount, " arguments, got ", argumentCount, "."}, pos); 5653af6ab5fSopenharmony_ci } 5663af6ab5fSopenharmony_ci return nullptr; 5673af6ab5fSopenharmony_ci } 5683af6ab5fSopenharmony_ci 5693af6ab5fSopenharmony_ci if (argumentCount > parameterCount && hasRestParameter && (flags & TypeRelationFlag::IGNORE_REST_PARAM) != 0) { 5703af6ab5fSopenharmony_ci return nullptr; 5713af6ab5fSopenharmony_ci } 5723af6ab5fSopenharmony_ci 5733af6ab5fSopenharmony_ci auto count = std::min(parameterCount, argumentCount); 5743af6ab5fSopenharmony_ci // Check all required formal parameter(s) first 5753af6ab5fSopenharmony_ci if (!ValidateSignatureRequiredParams(substitutedSig, arguments, flags, argTypeInferenceRequired, reportError)) { 5763af6ab5fSopenharmony_ci return nullptr; 5773af6ab5fSopenharmony_ci } 5783af6ab5fSopenharmony_ci 5793af6ab5fSopenharmony_ci // Check rest parameter(s) if any exists 5803af6ab5fSopenharmony_ci if (!hasRestParameter || count >= argumentCount) { 5813af6ab5fSopenharmony_ci return substitutedSig; 5823af6ab5fSopenharmony_ci } 5833af6ab5fSopenharmony_ci if (!ValidateSignatureRestParams(substitutedSig, arguments, flags, reportError)) { 5843af6ab5fSopenharmony_ci return nullptr; 5853af6ab5fSopenharmony_ci } 5863af6ab5fSopenharmony_ci 5873af6ab5fSopenharmony_ci return substitutedSig; 5883af6ab5fSopenharmony_ci} 5893af6ab5fSopenharmony_ci 5903af6ab5fSopenharmony_ciSignature *ETSChecker::CollectParameterlessConstructor(ArenaVector<Signature *> &signatures, 5913af6ab5fSopenharmony_ci const lexer::SourcePosition &pos, TypeRelationFlag resolveFlags) 5923af6ab5fSopenharmony_ci{ 5933af6ab5fSopenharmony_ci Signature *compatibleSignature = nullptr; 5943af6ab5fSopenharmony_ci 5953af6ab5fSopenharmony_ci auto collectSignatures = [&](TypeRelationFlag relationFlags) { 5963af6ab5fSopenharmony_ci for (auto *sig : signatures) { 5973af6ab5fSopenharmony_ci if (auto *concreteSig = ValidateParameterlessConstructor(sig, pos, relationFlags); concreteSig != nullptr) { 5983af6ab5fSopenharmony_ci compatibleSignature = concreteSig; 5993af6ab5fSopenharmony_ci break; 6003af6ab5fSopenharmony_ci } 6013af6ab5fSopenharmony_ci } 6023af6ab5fSopenharmony_ci }; 6033af6ab5fSopenharmony_ci 6043af6ab5fSopenharmony_ci // We are able to provide more specific error messages. 6053af6ab5fSopenharmony_ci if (signatures.size() == 1) { 6063af6ab5fSopenharmony_ci collectSignatures(resolveFlags); 6073af6ab5fSopenharmony_ci } else { 6083af6ab5fSopenharmony_ci collectSignatures(resolveFlags | TypeRelationFlag::NO_THROW); 6093af6ab5fSopenharmony_ci } 6103af6ab5fSopenharmony_ci 6113af6ab5fSopenharmony_ci if (compatibleSignature == nullptr) { 6123af6ab5fSopenharmony_ci if ((resolveFlags & TypeRelationFlag::NO_THROW) == 0) { 6133af6ab5fSopenharmony_ci LogTypeError({"No matching parameterless constructor"}, pos); 6143af6ab5fSopenharmony_ci } 6153af6ab5fSopenharmony_ci } 6163af6ab5fSopenharmony_ci return compatibleSignature; 6173af6ab5fSopenharmony_ci} 6183af6ab5fSopenharmony_ci 6193af6ab5fSopenharmony_cibool IsSignatureAccessible(Signature *sig, ETSObjectType *containingClass, TypeRelation *relation) 6203af6ab5fSopenharmony_ci{ 6213af6ab5fSopenharmony_ci // NOTE(vivienvoros): this check can be removed if signature is implicitly declared as public according to the spec. 6223af6ab5fSopenharmony_ci if (!sig->HasSignatureFlag(SignatureFlags::PUBLIC | SignatureFlags::PROTECTED | SignatureFlags::PRIVATE | 6233af6ab5fSopenharmony_ci SignatureFlags::INTERNAL)) { 6243af6ab5fSopenharmony_ci return true; 6253af6ab5fSopenharmony_ci } 6263af6ab5fSopenharmony_ci 6273af6ab5fSopenharmony_ci // NOTE(vivienvoros): take care of SignatureFlags::INTERNAL and SignatureFlags::INTERNAL_PROTECTED 6283af6ab5fSopenharmony_ci if (sig->HasSignatureFlag(SignatureFlags::INTERNAL) && !sig->HasSignatureFlag(SignatureFlags::PROTECTED)) { 6293af6ab5fSopenharmony_ci return true; 6303af6ab5fSopenharmony_ci } 6313af6ab5fSopenharmony_ci 6323af6ab5fSopenharmony_ci if (sig->HasSignatureFlag(SignatureFlags::PUBLIC) || sig->Owner() == containingClass || 6333af6ab5fSopenharmony_ci (sig->HasSignatureFlag(SignatureFlags::PROTECTED) && relation->IsSupertypeOf(sig->Owner(), containingClass))) { 6343af6ab5fSopenharmony_ci return true; 6353af6ab5fSopenharmony_ci } 6363af6ab5fSopenharmony_ci 6373af6ab5fSopenharmony_ci return false; 6383af6ab5fSopenharmony_ci} 6393af6ab5fSopenharmony_ci 6403af6ab5fSopenharmony_ci// NOLINTNEXTLINE(readability-magic-numbers) 6413af6ab5fSopenharmony_cistd::array<TypeRelationFlag, 9U> GetFlagVariants() 6423af6ab5fSopenharmony_ci{ 6433af6ab5fSopenharmony_ci // NOTE(boglarkahaag): Not in sync with specification, but solves the issues with rest params for now (#17483) 6443af6ab5fSopenharmony_ci return { 6453af6ab5fSopenharmony_ci TypeRelationFlag::NO_THROW | TypeRelationFlag::NO_UNBOXING | TypeRelationFlag::NO_BOXING | 6463af6ab5fSopenharmony_ci TypeRelationFlag::IGNORE_REST_PARAM, 6473af6ab5fSopenharmony_ci TypeRelationFlag::NO_THROW | TypeRelationFlag::NO_UNBOXING | TypeRelationFlag::NO_BOXING, 6483af6ab5fSopenharmony_ci TypeRelationFlag::NO_THROW | TypeRelationFlag::IGNORE_REST_PARAM, 6493af6ab5fSopenharmony_ci TypeRelationFlag::NO_THROW, 6503af6ab5fSopenharmony_ci TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING | TypeRelationFlag::NO_UNBOXING | 6513af6ab5fSopenharmony_ci TypeRelationFlag::NO_BOXING | TypeRelationFlag::IGNORE_REST_PARAM, 6523af6ab5fSopenharmony_ci TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING | TypeRelationFlag::NO_UNBOXING | 6533af6ab5fSopenharmony_ci TypeRelationFlag::NO_BOXING, 6543af6ab5fSopenharmony_ci TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING | TypeRelationFlag::IGNORE_REST_PARAM, 6553af6ab5fSopenharmony_ci TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING, 6563af6ab5fSopenharmony_ci TypeRelationFlag::NO_THROW | TypeRelationFlag::STRING_TO_CHAR, 6573af6ab5fSopenharmony_ci }; 6583af6ab5fSopenharmony_ci} 6593af6ab5fSopenharmony_ciArenaVector<Signature *> ETSChecker::CollectSignatures(ArenaVector<Signature *> &signatures, 6603af6ab5fSopenharmony_ci const ir::TSTypeParameterInstantiation *typeArguments, 6613af6ab5fSopenharmony_ci const ArenaVector<ir::Expression *> &arguments, 6623af6ab5fSopenharmony_ci const lexer::SourcePosition &pos, TypeRelationFlag resolveFlags) 6633af6ab5fSopenharmony_ci{ 6643af6ab5fSopenharmony_ci ArenaVector<Signature *> compatibleSignatures(Allocator()->Adapter()); 6653af6ab5fSopenharmony_ci std::vector<bool> argTypeInferenceRequired = FindTypeInferenceArguments(arguments); 6663af6ab5fSopenharmony_ci Signature *notVisibleSignature = nullptr; 6673af6ab5fSopenharmony_ci 6683af6ab5fSopenharmony_ci auto collectSignatures = [&](TypeRelationFlag relationFlags) { 6693af6ab5fSopenharmony_ci for (auto *sig : signatures) { 6703af6ab5fSopenharmony_ci if (notVisibleSignature != nullptr && 6713af6ab5fSopenharmony_ci !IsSignatureAccessible(sig, Context().ContainingClass(), Relation())) { 6723af6ab5fSopenharmony_ci continue; 6733af6ab5fSopenharmony_ci } 6743af6ab5fSopenharmony_ci auto *concreteSig = ValidateSignature(std::make_tuple(sig, typeArguments, relationFlags), arguments, pos, 6753af6ab5fSopenharmony_ci argTypeInferenceRequired); 6763af6ab5fSopenharmony_ci if (concreteSig == nullptr) { 6773af6ab5fSopenharmony_ci continue; 6783af6ab5fSopenharmony_ci } 6793af6ab5fSopenharmony_ci if (notVisibleSignature == nullptr && 6803af6ab5fSopenharmony_ci !IsSignatureAccessible(sig, Context().ContainingClass(), Relation())) { 6813af6ab5fSopenharmony_ci notVisibleSignature = concreteSig; 6823af6ab5fSopenharmony_ci } else { 6833af6ab5fSopenharmony_ci compatibleSignatures.push_back(concreteSig); 6843af6ab5fSopenharmony_ci } 6853af6ab5fSopenharmony_ci } 6863af6ab5fSopenharmony_ci }; 6873af6ab5fSopenharmony_ci 6883af6ab5fSopenharmony_ci // If there's only one signature, we don't need special checks for boxing/unboxing/widening. 6893af6ab5fSopenharmony_ci // We are also able to provide more specific error messages. 6903af6ab5fSopenharmony_ci if (signatures.size() == 1) { 6913af6ab5fSopenharmony_ci TypeRelationFlag flags = TypeRelationFlag::WIDENING | TypeRelationFlag::STRING_TO_CHAR | resolveFlags; 6923af6ab5fSopenharmony_ci collectSignatures(flags); 6933af6ab5fSopenharmony_ci } else { 6943af6ab5fSopenharmony_ci for (auto flags : GetFlagVariants()) { 6953af6ab5fSopenharmony_ci flags = flags | resolveFlags; 6963af6ab5fSopenharmony_ci collectSignatures(flags); 6973af6ab5fSopenharmony_ci if (!compatibleSignatures.empty()) { 6983af6ab5fSopenharmony_ci break; 6993af6ab5fSopenharmony_ci } 7003af6ab5fSopenharmony_ci } 7013af6ab5fSopenharmony_ci } 7023af6ab5fSopenharmony_ci 7033af6ab5fSopenharmony_ci if (compatibleSignatures.empty() && notVisibleSignature != nullptr) { 7043af6ab5fSopenharmony_ci LogTypeError( 7053af6ab5fSopenharmony_ci {"Signature ", notVisibleSignature->Function()->Id()->Name(), notVisibleSignature, " is not visible here."}, 7063af6ab5fSopenharmony_ci pos); 7073af6ab5fSopenharmony_ci } 7083af6ab5fSopenharmony_ci return compatibleSignatures; 7093af6ab5fSopenharmony_ci} 7103af6ab5fSopenharmony_ci 7113af6ab5fSopenharmony_ciSignature *ETSChecker::GetMostSpecificSignature(ArenaVector<Signature *> &compatibleSignatures, 7123af6ab5fSopenharmony_ci const ArenaVector<ir::Expression *> &arguments, 7133af6ab5fSopenharmony_ci const lexer::SourcePosition &pos, TypeRelationFlag resolveFlags) 7143af6ab5fSopenharmony_ci{ 7153af6ab5fSopenharmony_ci std::vector<bool> argTypeInferenceRequired = FindTypeInferenceArguments(arguments); 7163af6ab5fSopenharmony_ci Signature *mostSpecificSignature = ChooseMostSpecificSignature(compatibleSignatures, argTypeInferenceRequired, pos); 7173af6ab5fSopenharmony_ci 7183af6ab5fSopenharmony_ci if (mostSpecificSignature == nullptr) { 7193af6ab5fSopenharmony_ci LogTypeError({"Reference to ", compatibleSignatures.front()->Function()->Id()->Name(), " is ambiguous"}, pos); 7203af6ab5fSopenharmony_ci return nullptr; 7213af6ab5fSopenharmony_ci } 7223af6ab5fSopenharmony_ci 7233af6ab5fSopenharmony_ci if (!TypeInference(mostSpecificSignature, arguments, resolveFlags)) { 7243af6ab5fSopenharmony_ci return nullptr; 7253af6ab5fSopenharmony_ci } 7263af6ab5fSopenharmony_ci 7273af6ab5fSopenharmony_ci return mostSpecificSignature; 7283af6ab5fSopenharmony_ci} 7293af6ab5fSopenharmony_ci 7303af6ab5fSopenharmony_ciSignature *ETSChecker::ValidateSignatures(ArenaVector<Signature *> &signatures, 7313af6ab5fSopenharmony_ci const ir::TSTypeParameterInstantiation *typeArguments, 7323af6ab5fSopenharmony_ci const ArenaVector<ir::Expression *> &arguments, 7333af6ab5fSopenharmony_ci const lexer::SourcePosition &pos, std::string_view signatureKind, 7343af6ab5fSopenharmony_ci TypeRelationFlag resolveFlags) 7353af6ab5fSopenharmony_ci{ 7363af6ab5fSopenharmony_ci auto compatibleSignatures = CollectSignatures(signatures, typeArguments, arguments, pos, resolveFlags); 7373af6ab5fSopenharmony_ci if (!compatibleSignatures.empty()) { 7383af6ab5fSopenharmony_ci return GetMostSpecificSignature(compatibleSignatures, arguments, pos, resolveFlags); 7393af6ab5fSopenharmony_ci } 7403af6ab5fSopenharmony_ci 7413af6ab5fSopenharmony_ci if ((resolveFlags & TypeRelationFlag::NO_THROW) == 0 && !arguments.empty() && !signatures.empty()) { 7423af6ab5fSopenharmony_ci std::stringstream ss; 7433af6ab5fSopenharmony_ci 7443af6ab5fSopenharmony_ci if (signatures[0]->Function()->IsConstructor()) { 7453af6ab5fSopenharmony_ci ss << util::Helpers::GetClassDefiniton(signatures[0]->Function())->PrivateId().Mutf8(); 7463af6ab5fSopenharmony_ci } else { 7473af6ab5fSopenharmony_ci ss << signatures[0]->Function()->Id()->Name().Mutf8(); 7483af6ab5fSopenharmony_ci } 7493af6ab5fSopenharmony_ci 7503af6ab5fSopenharmony_ci ss << "("; 7513af6ab5fSopenharmony_ci 7523af6ab5fSopenharmony_ci for (uint32_t index = 0; index < arguments.size(); ++index) { 7533af6ab5fSopenharmony_ci if (arguments[index]->IsArrowFunctionExpression()) { 7543af6ab5fSopenharmony_ci // NOTE(peterseres): Refactor this case and add test case 7553af6ab5fSopenharmony_ci break; 7563af6ab5fSopenharmony_ci } 7573af6ab5fSopenharmony_ci 7583af6ab5fSopenharmony_ci arguments[index]->Check(this); 7593af6ab5fSopenharmony_ci arguments[index]->TsType()->ToString(ss); 7603af6ab5fSopenharmony_ci 7613af6ab5fSopenharmony_ci if (index == arguments.size() - 1) { 7623af6ab5fSopenharmony_ci ss << ")"; 7633af6ab5fSopenharmony_ci LogTypeError({"No matching ", signatureKind, " signature for ", ss.str().c_str()}, pos); 7643af6ab5fSopenharmony_ci return nullptr; 7653af6ab5fSopenharmony_ci } 7663af6ab5fSopenharmony_ci 7673af6ab5fSopenharmony_ci ss << ", "; 7683af6ab5fSopenharmony_ci } 7693af6ab5fSopenharmony_ci } 7703af6ab5fSopenharmony_ci 7713af6ab5fSopenharmony_ci if ((resolveFlags & TypeRelationFlag::NO_THROW) == 0) { 7723af6ab5fSopenharmony_ci LogTypeError({"No matching ", signatureKind, " signature"}, pos); 7733af6ab5fSopenharmony_ci } 7743af6ab5fSopenharmony_ci 7753af6ab5fSopenharmony_ci return nullptr; 7763af6ab5fSopenharmony_ci} 7773af6ab5fSopenharmony_ci 7783af6ab5fSopenharmony_ciSignature *ETSChecker::FindMostSpecificSignature(const ArenaVector<Signature *> &signatures, 7793af6ab5fSopenharmony_ci const ArenaMultiMap<size_t, Signature *> &bestSignaturesForParameter, 7803af6ab5fSopenharmony_ci size_t paramCount) 7813af6ab5fSopenharmony_ci{ 7823af6ab5fSopenharmony_ci Signature *mostSpecificSignature = nullptr; 7833af6ab5fSopenharmony_ci 7843af6ab5fSopenharmony_ci for (auto *sig : signatures) { 7853af6ab5fSopenharmony_ci bool mostSpecific = true; 7863af6ab5fSopenharmony_ci 7873af6ab5fSopenharmony_ci for (size_t paramIdx = 0; paramIdx < paramCount; ++paramIdx) { 7883af6ab5fSopenharmony_ci const auto range = bestSignaturesForParameter.equal_range(paramIdx); 7893af6ab5fSopenharmony_ci // Check if signature is most specific for i. parameter type. 7903af6ab5fSopenharmony_ci mostSpecific = std::any_of(range.first, range.second, [&sig](auto entry) { return entry.second == sig; }); 7913af6ab5fSopenharmony_ci if (!mostSpecific) { 7923af6ab5fSopenharmony_ci break; 7933af6ab5fSopenharmony_ci } 7943af6ab5fSopenharmony_ci } 7953af6ab5fSopenharmony_ci 7963af6ab5fSopenharmony_ci if (!mostSpecific) { 7973af6ab5fSopenharmony_ci continue; 7983af6ab5fSopenharmony_ci } 7993af6ab5fSopenharmony_ci if (mostSpecificSignature == nullptr) { 8003af6ab5fSopenharmony_ci mostSpecificSignature = sig; 8013af6ab5fSopenharmony_ci continue; 8023af6ab5fSopenharmony_ci } 8033af6ab5fSopenharmony_ci if (mostSpecificSignature->Owner() == sig->Owner()) { 8043af6ab5fSopenharmony_ci // NOTE: audovichenko. Remove this 'if' when #12443 gets resolved 8053af6ab5fSopenharmony_ci if (mostSpecificSignature->Function() == sig->Function()) { 8063af6ab5fSopenharmony_ci // The same signature 8073af6ab5fSopenharmony_ci continue; 8083af6ab5fSopenharmony_ci } 8093af6ab5fSopenharmony_ci return nullptr; 8103af6ab5fSopenharmony_ci } 8113af6ab5fSopenharmony_ci } 8123af6ab5fSopenharmony_ci return mostSpecificSignature; 8133af6ab5fSopenharmony_ci} 8143af6ab5fSopenharmony_ci 8153af6ab5fSopenharmony_cistatic void InitMostSpecificType(const ArenaVector<Signature *> &signatures, [[maybe_unused]] Type *&mostSpecificType, 8163af6ab5fSopenharmony_ci [[maybe_unused]] Signature *&prevSig, const size_t idx) 8173af6ab5fSopenharmony_ci{ 8183af6ab5fSopenharmony_ci for (auto *sig : signatures) { 8193af6ab5fSopenharmony_ci if (Type *sigType = sig->Params().at(idx)->TsType(); 8203af6ab5fSopenharmony_ci sigType->IsETSObjectType() && !sigType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INTERFACE)) { 8213af6ab5fSopenharmony_ci mostSpecificType = sigType; 8223af6ab5fSopenharmony_ci prevSig = sig; 8233af6ab5fSopenharmony_ci return; 8243af6ab5fSopenharmony_ci } 8253af6ab5fSopenharmony_ci } 8263af6ab5fSopenharmony_ci} 8273af6ab5fSopenharmony_ci 8283af6ab5fSopenharmony_civoid ETSChecker::SearchAmongMostSpecificTypes( 8293af6ab5fSopenharmony_ci Type *&mostSpecificType, Signature *&prevSig, 8303af6ab5fSopenharmony_ci std::tuple<const lexer::SourcePosition &, size_t, size_t, size_t, Signature *> info, bool lookForClassType) 8313af6ab5fSopenharmony_ci{ 8323af6ab5fSopenharmony_ci auto [pos, argumentsSize, paramCount, idx, sig] = info; 8333af6ab5fSopenharmony_ci if (lookForClassType && argumentsSize == ULONG_MAX) { 8343af6ab5fSopenharmony_ci [[maybe_unused]] const bool equalParamSize = sig->Params().size() == paramCount; 8353af6ab5fSopenharmony_ci ASSERT(equalParamSize); 8363af6ab5fSopenharmony_ci } 8373af6ab5fSopenharmony_ci Type *sigType = sig->Params().at(idx)->TsType(); 8383af6ab5fSopenharmony_ci const bool isClassType = 8393af6ab5fSopenharmony_ci sigType->IsETSObjectType() && !sigType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INTERFACE); 8403af6ab5fSopenharmony_ci if (isClassType == lookForClassType) { 8413af6ab5fSopenharmony_ci if (Relation()->IsIdenticalTo(sigType, mostSpecificType)) { 8423af6ab5fSopenharmony_ci return; 8433af6ab5fSopenharmony_ci } 8443af6ab5fSopenharmony_ci if (Relation()->IsAssignableTo(sigType, mostSpecificType)) { 8453af6ab5fSopenharmony_ci mostSpecificType = sigType; 8463af6ab5fSopenharmony_ci prevSig = sig; 8473af6ab5fSopenharmony_ci } else if (sigType->IsETSObjectType() && mostSpecificType->IsETSObjectType() && 8483af6ab5fSopenharmony_ci !Relation()->IsAssignableTo(mostSpecificType, sigType)) { 8493af6ab5fSopenharmony_ci auto funcName = sig->Function()->Id()->Name(); 8503af6ab5fSopenharmony_ci LogTypeError({"Call to `", funcName, "` is ambiguous as `2` versions of `", funcName, "` are available: `", 8513af6ab5fSopenharmony_ci funcName, prevSig, "` and `", funcName, sig, "`"}, 8523af6ab5fSopenharmony_ci pos); 8533af6ab5fSopenharmony_ci } 8543af6ab5fSopenharmony_ci } 8553af6ab5fSopenharmony_ci} 8563af6ab5fSopenharmony_ci 8573af6ab5fSopenharmony_ciArenaMultiMap<size_t, Signature *> ETSChecker::GetSuitableSignaturesForParameter( 8583af6ab5fSopenharmony_ci const std::vector<bool> &argTypeInferenceRequired, size_t paramCount, ArenaVector<Signature *> &signatures, 8593af6ab5fSopenharmony_ci const lexer::SourcePosition &pos, size_t argumentsSize) 8603af6ab5fSopenharmony_ci{ 8613af6ab5fSopenharmony_ci // Collect which signatures are most specific for each parameter. 8623af6ab5fSopenharmony_ci ArenaMultiMap<size_t /* parameter index */, Signature *> bestSignaturesForParameter(Allocator()->Adapter()); 8633af6ab5fSopenharmony_ci 8643af6ab5fSopenharmony_ci const checker::SavedTypeRelationFlagsContext savedTypeRelationFlagCtx(Relation(), 8653af6ab5fSopenharmony_ci TypeRelationFlag::ONLY_CHECK_WIDENING); 8663af6ab5fSopenharmony_ci 8673af6ab5fSopenharmony_ci for (size_t i = 0; i < paramCount; ++i) { 8683af6ab5fSopenharmony_ci if (argTypeInferenceRequired[i]) { 8693af6ab5fSopenharmony_ci for (auto *sig : signatures) { 8703af6ab5fSopenharmony_ci bestSignaturesForParameter.insert({i, sig}); 8713af6ab5fSopenharmony_ci } 8723af6ab5fSopenharmony_ci continue; 8733af6ab5fSopenharmony_ci } 8743af6ab5fSopenharmony_ci // 1st step: check which is the most specific parameter type for i. parameter. 8753af6ab5fSopenharmony_ci Type *mostSpecificType = signatures.front()->Params().at(i)->TsType(); 8763af6ab5fSopenharmony_ci Signature *prevSig = signatures.front(); 8773af6ab5fSopenharmony_ci 8783af6ab5fSopenharmony_ci InitMostSpecificType(signatures, mostSpecificType, prevSig, i); 8793af6ab5fSopenharmony_ci for (auto *sig : signatures) { 8803af6ab5fSopenharmony_ci SearchAmongMostSpecificTypes(mostSpecificType, prevSig, 8813af6ab5fSopenharmony_ci std::make_tuple(pos, argumentsSize, paramCount, i, sig), true); 8823af6ab5fSopenharmony_ci } 8833af6ab5fSopenharmony_ci for (auto *sig : signatures) { 8843af6ab5fSopenharmony_ci SearchAmongMostSpecificTypes(mostSpecificType, prevSig, 8853af6ab5fSopenharmony_ci std::make_tuple(pos, argumentsSize, paramCount, i, sig), false); 8863af6ab5fSopenharmony_ci } 8873af6ab5fSopenharmony_ci 8883af6ab5fSopenharmony_ci for (auto *sig : signatures) { 8893af6ab5fSopenharmony_ci Type *sigType = sig->Params().at(i)->TsType(); 8903af6ab5fSopenharmony_ci if (Relation()->IsIdenticalTo(sigType, mostSpecificType)) { 8913af6ab5fSopenharmony_ci bestSignaturesForParameter.insert({i, sig}); 8923af6ab5fSopenharmony_ci } 8933af6ab5fSopenharmony_ci } 8943af6ab5fSopenharmony_ci } 8953af6ab5fSopenharmony_ci return bestSignaturesForParameter; 8963af6ab5fSopenharmony_ci} 8973af6ab5fSopenharmony_ci 8983af6ab5fSopenharmony_ciSignature *ETSChecker::ChooseMostSpecificSignature(ArenaVector<Signature *> &signatures, 8993af6ab5fSopenharmony_ci const std::vector<bool> &argTypeInferenceRequired, 9003af6ab5fSopenharmony_ci const lexer::SourcePosition &pos, size_t argumentsSize) 9013af6ab5fSopenharmony_ci{ 9023af6ab5fSopenharmony_ci ASSERT(signatures.empty() == false); 9033af6ab5fSopenharmony_ci 9043af6ab5fSopenharmony_ci if (signatures.size() == 1) { 9053af6ab5fSopenharmony_ci return signatures.front(); 9063af6ab5fSopenharmony_ci } 9073af6ab5fSopenharmony_ci 9083af6ab5fSopenharmony_ci size_t paramCount = signatures.front()->Params().size(); 9093af6ab5fSopenharmony_ci if (argumentsSize != ULONG_MAX) { 9103af6ab5fSopenharmony_ci paramCount = argumentsSize; 9113af6ab5fSopenharmony_ci } 9123af6ab5fSopenharmony_ci // Multiple signatures with zero parameter because of inheritance. 9133af6ab5fSopenharmony_ci // Return the closest one in inheritance chain that is defined at the beginning of the vector. 9143af6ab5fSopenharmony_ci if (paramCount == 0) { 9153af6ab5fSopenharmony_ci auto zeroParamSignature = std::find_if(signatures.begin(), signatures.end(), 9163af6ab5fSopenharmony_ci [](auto *signature) { return signature->RestVar() == nullptr; }); 9173af6ab5fSopenharmony_ci // If there is a zero parameter signature, return that 9183af6ab5fSopenharmony_ci if (zeroParamSignature != signatures.end()) { 9193af6ab5fSopenharmony_ci return *zeroParamSignature; 9203af6ab5fSopenharmony_ci } 9213af6ab5fSopenharmony_ci // If there are multiple rest parameter signatures with different argument types, throw error 9223af6ab5fSopenharmony_ci if (signatures.size() > 1 && std::any_of(signatures.begin(), signatures.end(), [signatures](const auto *param) { 9233af6ab5fSopenharmony_ci return param->RestVar()->TsType() != signatures.front()->RestVar()->TsType(); 9243af6ab5fSopenharmony_ci })) { 9253af6ab5fSopenharmony_ci ThrowTypeError({"Call to `", signatures.front()->Function()->Id()->Name(), "` is ambiguous "}, pos); 9263af6ab5fSopenharmony_ci } 9273af6ab5fSopenharmony_ci // Else return the signature with the rest parameter 9283af6ab5fSopenharmony_ci auto restParamSignature = std::find_if(signatures.begin(), signatures.end(), 9293af6ab5fSopenharmony_ci [](auto *signature) { return signature->RestVar() != nullptr; }); 9303af6ab5fSopenharmony_ci return *restParamSignature; 9313af6ab5fSopenharmony_ci } 9323af6ab5fSopenharmony_ci 9333af6ab5fSopenharmony_ci ArenaMultiMap<size_t /* parameter index */, Signature *> bestSignaturesForParameter = 9343af6ab5fSopenharmony_ci GetSuitableSignaturesForParameter(argTypeInferenceRequired, paramCount, signatures, pos, argumentsSize); 9353af6ab5fSopenharmony_ci // Find the signature that are most specific for all parameters. 9363af6ab5fSopenharmony_ci Signature *mostSpecificSignature = FindMostSpecificSignature(signatures, bestSignaturesForParameter, paramCount); 9373af6ab5fSopenharmony_ci 9383af6ab5fSopenharmony_ci return mostSpecificSignature; 9393af6ab5fSopenharmony_ci} 9403af6ab5fSopenharmony_ci 9413af6ab5fSopenharmony_ciSignature *ETSChecker::ResolveCallExpressionAndTrailingLambda(ArenaVector<Signature *> &signatures, 9423af6ab5fSopenharmony_ci ir::CallExpression *callExpr, 9433af6ab5fSopenharmony_ci const lexer::SourcePosition &pos, 9443af6ab5fSopenharmony_ci const TypeRelationFlag reportFlag) 9453af6ab5fSopenharmony_ci{ 9463af6ab5fSopenharmony_ci Signature *sig = nullptr; 9473af6ab5fSopenharmony_ci if (callExpr->TrailingBlock() == nullptr) { 9483af6ab5fSopenharmony_ci for (auto it : signatures) { 9493af6ab5fSopenharmony_ci MaybeSubstituteLambdaArguments(it->Function()->Params(), callExpr); 9503af6ab5fSopenharmony_ci 9513af6ab5fSopenharmony_ci if (callExpr->Arguments().size() != it->Function()->Params().size()) { 9523af6ab5fSopenharmony_ci MaybeSubstituteLambdaArgumentsInFunctionCall(callExpr); 9533af6ab5fSopenharmony_ci } 9543af6ab5fSopenharmony_ci } 9553af6ab5fSopenharmony_ci 9563af6ab5fSopenharmony_ci sig = ValidateSignatures(signatures, callExpr->TypeParams(), callExpr->Arguments(), pos, "call", reportFlag); 9573af6ab5fSopenharmony_ci return sig; 9583af6ab5fSopenharmony_ci } 9593af6ab5fSopenharmony_ci 9603af6ab5fSopenharmony_ci // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 9613af6ab5fSopenharmony_ci auto arguments = ExtendArgumentsWithFakeLamda(callExpr); 9623af6ab5fSopenharmony_ci sig = ValidateSignatures(signatures, callExpr->TypeParams(), arguments, pos, "call", 9633af6ab5fSopenharmony_ci TypeRelationFlag::NO_THROW | TypeRelationFlag::NO_CHECK_TRAILING_LAMBDA); 9643af6ab5fSopenharmony_ci if (sig != nullptr) { 9653af6ab5fSopenharmony_ci // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 9663af6ab5fSopenharmony_ci TransformTraillingLambda(callExpr); 9673af6ab5fSopenharmony_ci TypeInference(sig, callExpr->Arguments()); 9683af6ab5fSopenharmony_ci return sig; 9693af6ab5fSopenharmony_ci } 9703af6ab5fSopenharmony_ci 9713af6ab5fSopenharmony_ci sig = ValidateSignatures(signatures, callExpr->TypeParams(), callExpr->Arguments(), pos, "call", reportFlag); 9723af6ab5fSopenharmony_ci if (sig != nullptr) { 9733af6ab5fSopenharmony_ci EnsureValidCurlyBrace(callExpr); 9743af6ab5fSopenharmony_ci } 9753af6ab5fSopenharmony_ci 9763af6ab5fSopenharmony_ci return sig; 9773af6ab5fSopenharmony_ci} 9783af6ab5fSopenharmony_ci 9793af6ab5fSopenharmony_ciSignature *ETSChecker::ResolveConstructExpression(ETSObjectType *type, const ArenaVector<ir::Expression *> &arguments, 9803af6ab5fSopenharmony_ci const lexer::SourcePosition &pos) 9813af6ab5fSopenharmony_ci{ 9823af6ab5fSopenharmony_ci return ValidateSignatures(type->ConstructSignatures(), nullptr, arguments, pos, "construct"); 9833af6ab5fSopenharmony_ci} 9843af6ab5fSopenharmony_ci 9853af6ab5fSopenharmony_ci/* 9863af6ab5fSopenharmony_ci * Object literals do not get checked in the process of call resolution; we need to check them separately 9873af6ab5fSopenharmony_ci * afterwards. 9883af6ab5fSopenharmony_ci */ 9893af6ab5fSopenharmony_civoid ETSChecker::CheckObjectLiteralArguments(Signature *signature, ArenaVector<ir::Expression *> const &arguments) 9903af6ab5fSopenharmony_ci{ 9913af6ab5fSopenharmony_ci for (uint32_t index = 0; index < arguments.size(); index++) { 9923af6ab5fSopenharmony_ci if (!arguments[index]->IsObjectExpression()) { 9933af6ab5fSopenharmony_ci continue; 9943af6ab5fSopenharmony_ci } 9953af6ab5fSopenharmony_ci 9963af6ab5fSopenharmony_ci Type *tp; 9973af6ab5fSopenharmony_ci if (index >= signature->MinArgCount()) { 9983af6ab5fSopenharmony_ci ASSERT(signature->RestVar()); 9993af6ab5fSopenharmony_ci tp = signature->RestVar()->TsType(); 10003af6ab5fSopenharmony_ci } else { 10013af6ab5fSopenharmony_ci tp = signature->Params()[index]->TsType(); 10023af6ab5fSopenharmony_ci } 10033af6ab5fSopenharmony_ci 10043af6ab5fSopenharmony_ci arguments[index]->AsObjectExpression()->SetPreferredType(tp); 10053af6ab5fSopenharmony_ci arguments[index]->Check(this); 10063af6ab5fSopenharmony_ci } 10073af6ab5fSopenharmony_ci} 10083af6ab5fSopenharmony_ci 10093af6ab5fSopenharmony_cichecker::ETSFunctionType *ETSChecker::BuildMethodSignature(ir::MethodDefinition *method) 10103af6ab5fSopenharmony_ci{ 10113af6ab5fSopenharmony_ci if (method->TsTypeOrError() != nullptr) { 10123af6ab5fSopenharmony_ci return method->TsTypeOrError()->AsETSFunctionType(); 10133af6ab5fSopenharmony_ci } 10143af6ab5fSopenharmony_ci 10153af6ab5fSopenharmony_ci bool isConstructSig = method->IsConstructor(); 10163af6ab5fSopenharmony_ci 10173af6ab5fSopenharmony_ci method->Function()->Id()->SetVariable(method->Id()->Variable()); 10183af6ab5fSopenharmony_ci BuildFunctionSignature(method->Function(), isConstructSig); 10193af6ab5fSopenharmony_ci if (method->Function()->Signature() == nullptr) { 10203af6ab5fSopenharmony_ci return nullptr; 10213af6ab5fSopenharmony_ci } 10223af6ab5fSopenharmony_ci auto *funcType = BuildNamedFunctionType(method->Function()); 10233af6ab5fSopenharmony_ci std::vector<checker::ETSFunctionType *> overloads; 10243af6ab5fSopenharmony_ci 10253af6ab5fSopenharmony_ci for (ir::MethodDefinition *const currentFunc : method->Overloads()) { 10263af6ab5fSopenharmony_ci currentFunc->Function()->Id()->SetVariable(currentFunc->Id()->Variable()); 10273af6ab5fSopenharmony_ci BuildFunctionSignature(currentFunc->Function(), isConstructSig); 10283af6ab5fSopenharmony_ci if (currentFunc->Function()->Signature() == nullptr) { 10293af6ab5fSopenharmony_ci return nullptr; 10303af6ab5fSopenharmony_ci } 10313af6ab5fSopenharmony_ci auto *const overloadType = BuildNamedFunctionType(currentFunc->Function()); 10323af6ab5fSopenharmony_ci CheckIdenticalOverloads(funcType, overloadType, currentFunc); 10333af6ab5fSopenharmony_ci currentFunc->SetTsType(overloadType); 10343af6ab5fSopenharmony_ci funcType->AddCallSignature(currentFunc->Function()->Signature()); 10353af6ab5fSopenharmony_ci overloads.push_back(overloadType); 10363af6ab5fSopenharmony_ci } 10373af6ab5fSopenharmony_ci for (size_t baseFuncCounter = 0; baseFuncCounter < overloads.size(); ++baseFuncCounter) { 10383af6ab5fSopenharmony_ci auto *overloadType = overloads.at(baseFuncCounter); 10393af6ab5fSopenharmony_ci for (size_t compareFuncCounter = baseFuncCounter + 1; compareFuncCounter < overloads.size(); 10403af6ab5fSopenharmony_ci compareFuncCounter++) { 10413af6ab5fSopenharmony_ci auto *compareOverloadType = overloads.at(compareFuncCounter); 10423af6ab5fSopenharmony_ci CheckIdenticalOverloads(overloadType, compareOverloadType, method->Overloads()[compareFuncCounter]); 10433af6ab5fSopenharmony_ci } 10443af6ab5fSopenharmony_ci } 10453af6ab5fSopenharmony_ci 10463af6ab5fSopenharmony_ci method->Id()->Variable()->SetTsType(funcType); 10473af6ab5fSopenharmony_ci return funcType; 10483af6ab5fSopenharmony_ci} 10493af6ab5fSopenharmony_ci 10503af6ab5fSopenharmony_civoid ETSChecker::CheckIdenticalOverloads(ETSFunctionType *func, ETSFunctionType *overload, 10513af6ab5fSopenharmony_ci const ir::MethodDefinition *const currentFunc) 10523af6ab5fSopenharmony_ci{ 10533af6ab5fSopenharmony_ci SavedTypeRelationFlagsContext savedFlagsCtx(Relation(), TypeRelationFlag::NO_RETURN_TYPE_CHECK); 10543af6ab5fSopenharmony_ci 10553af6ab5fSopenharmony_ci Relation()->IsIdenticalTo(func, overload); 10563af6ab5fSopenharmony_ci if (Relation()->IsTrue() && func->CallSignatures()[0]->GetSignatureInfo()->restVar == 10573af6ab5fSopenharmony_ci overload->CallSignatures()[0]->GetSignatureInfo()->restVar) { 10583af6ab5fSopenharmony_ci LogTypeError("Function " + func->Name().Mutf8() + " is already declared.", currentFunc->Start()); 10593af6ab5fSopenharmony_ci return; 10603af6ab5fSopenharmony_ci } 10613af6ab5fSopenharmony_ci if (HasSameAssemblySignatures(func, overload)) { 10623af6ab5fSopenharmony_ci LogTypeError("Function " + func->Name().Mutf8() + " with this assembly signature already declared.", 10633af6ab5fSopenharmony_ci currentFunc->Start()); 10643af6ab5fSopenharmony_ci } 10653af6ab5fSopenharmony_ci} 10663af6ab5fSopenharmony_ci 10673af6ab5fSopenharmony_ciSignature *ETSChecker::ComposeSignature(ir::ScriptFunction *func, SignatureInfo *signatureInfo, Type *returnType, 10683af6ab5fSopenharmony_ci varbinder::Variable *nameVar) 10693af6ab5fSopenharmony_ci{ 10703af6ab5fSopenharmony_ci auto *signature = CreateSignature(signatureInfo, returnType, func); 10713af6ab5fSopenharmony_ci signature->SetOwner(Context().ContainingClass()); 10723af6ab5fSopenharmony_ci signature->SetOwnerVar(nameVar); 10733af6ab5fSopenharmony_ci 10743af6ab5fSopenharmony_ci const auto *returnTypeAnnotation = func->ReturnTypeAnnotation(); 10753af6ab5fSopenharmony_ci if (returnTypeAnnotation == nullptr && ((func->Flags() & ir::ScriptFunctionFlags::HAS_RETURN) != 0)) { 10763af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::NEED_RETURN_TYPE); 10773af6ab5fSopenharmony_ci } 10783af6ab5fSopenharmony_ci 10793af6ab5fSopenharmony_ci if (returnTypeAnnotation != nullptr && returnTypeAnnotation->IsTSThisType()) { 10803af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::THIS_RETURN_TYPE); 10813af6ab5fSopenharmony_ci } 10823af6ab5fSopenharmony_ci 10833af6ab5fSopenharmony_ci if (func->IsAbstract()) { 10843af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::ABSTRACT); 10853af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::VIRTUAL); 10863af6ab5fSopenharmony_ci } 10873af6ab5fSopenharmony_ci 10883af6ab5fSopenharmony_ci if (func->IsStatic()) { 10893af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::STATIC); 10903af6ab5fSopenharmony_ci } 10913af6ab5fSopenharmony_ci 10923af6ab5fSopenharmony_ci if (func->IsConstructor()) { 10933af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::CONSTRUCTOR); 10943af6ab5fSopenharmony_ci } 10953af6ab5fSopenharmony_ci 10963af6ab5fSopenharmony_ci if (signature->Owner()->GetDeclNode()->IsFinal() || func->IsFinal()) { 10973af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::FINAL); 10983af6ab5fSopenharmony_ci } 10993af6ab5fSopenharmony_ci 11003af6ab5fSopenharmony_ci if (func->IsPublic()) { 11013af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::PUBLIC); 11023af6ab5fSopenharmony_ci } else if (func->IsInternal()) { 11033af6ab5fSopenharmony_ci if (func->IsProtected()) { 11043af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::INTERNAL_PROTECTED); 11053af6ab5fSopenharmony_ci } else { 11063af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::INTERNAL); 11073af6ab5fSopenharmony_ci } 11083af6ab5fSopenharmony_ci } else if (func->IsProtected()) { 11093af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::PROTECTED); 11103af6ab5fSopenharmony_ci } else if (func->IsPrivate()) { 11113af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::PRIVATE); 11123af6ab5fSopenharmony_ci } 11133af6ab5fSopenharmony_ci 11143af6ab5fSopenharmony_ci return signature; 11153af6ab5fSopenharmony_ci} 11163af6ab5fSopenharmony_ci 11173af6ab5fSopenharmony_ciType *ETSChecker::ComposeReturnType(ir::ScriptFunction *func) 11183af6ab5fSopenharmony_ci{ 11193af6ab5fSopenharmony_ci auto *const returnTypeAnnotation = func->ReturnTypeAnnotation(); 11203af6ab5fSopenharmony_ci checker::Type *returnType {}; 11213af6ab5fSopenharmony_ci 11223af6ab5fSopenharmony_ci if (returnTypeAnnotation == nullptr) { 11233af6ab5fSopenharmony_ci // implicit void return type 11243af6ab5fSopenharmony_ci returnType = GlobalVoidType(); 11253af6ab5fSopenharmony_ci 11263af6ab5fSopenharmony_ci if (func->IsAsyncFunc()) { 11273af6ab5fSopenharmony_ci auto implicitPromiseVoid = [this]() { 11283af6ab5fSopenharmony_ci const auto &promiseGlobal = GlobalBuiltinPromiseType()->AsETSObjectType(); 11293af6ab5fSopenharmony_ci auto promiseType = 11303af6ab5fSopenharmony_ci promiseGlobal->Instantiate(Allocator(), Relation(), GetGlobalTypesHolder())->AsETSObjectType(); 11313af6ab5fSopenharmony_ci promiseType->AddTypeFlag(checker::TypeFlag::GENERIC); 11323af6ab5fSopenharmony_ci promiseType->TypeArguments().clear(); 11333af6ab5fSopenharmony_ci promiseType->TypeArguments().emplace_back(GlobalVoidType()); 11343af6ab5fSopenharmony_ci return promiseType; 11353af6ab5fSopenharmony_ci }; 11363af6ab5fSopenharmony_ci 11373af6ab5fSopenharmony_ci returnType = implicitPromiseVoid(); 11383af6ab5fSopenharmony_ci } 11393af6ab5fSopenharmony_ci } else if (func->IsEntryPoint() && returnTypeAnnotation->GetType(this) == GlobalVoidType()) { 11403af6ab5fSopenharmony_ci returnType = GlobalVoidType(); 11413af6ab5fSopenharmony_ci } else { 11423af6ab5fSopenharmony_ci returnType = returnTypeAnnotation->GetType(this); 11433af6ab5fSopenharmony_ci returnTypeAnnotation->SetTsType(returnType); 11443af6ab5fSopenharmony_ci } 11453af6ab5fSopenharmony_ci 11463af6ab5fSopenharmony_ci return returnType; 11473af6ab5fSopenharmony_ci} 11483af6ab5fSopenharmony_ci 11493af6ab5fSopenharmony_ciSignatureInfo *ETSChecker::ComposeSignatureInfo(ir::ScriptFunction *func) 11503af6ab5fSopenharmony_ci{ 11513af6ab5fSopenharmony_ci auto *signatureInfo = CreateSignatureInfo(); 11523af6ab5fSopenharmony_ci signatureInfo->restVar = nullptr; 11533af6ab5fSopenharmony_ci signatureInfo->minArgCount = 0; 11543af6ab5fSopenharmony_ci 11553af6ab5fSopenharmony_ci if ((func->IsConstructor() || !func->IsStatic()) && !func->IsArrow()) { 11563af6ab5fSopenharmony_ci auto *thisVar = func->Scope()->ParamScope()->Params().front(); 11573af6ab5fSopenharmony_ci thisVar->SetTsType(Context().ContainingClass()); 11583af6ab5fSopenharmony_ci } 11593af6ab5fSopenharmony_ci 11603af6ab5fSopenharmony_ci if (func->TypeParams() != nullptr) { 11613af6ab5fSopenharmony_ci auto [typeParamTypes, ok] = CreateUnconstrainedTypeParameters(func->TypeParams()); 11623af6ab5fSopenharmony_ci signatureInfo->typeParams = std::move(typeParamTypes); 11633af6ab5fSopenharmony_ci if (ok) { 11643af6ab5fSopenharmony_ci AssignTypeParameterConstraints(func->TypeParams()); 11653af6ab5fSopenharmony_ci } 11663af6ab5fSopenharmony_ci } 11673af6ab5fSopenharmony_ci 11683af6ab5fSopenharmony_ci for (auto *const it : func->Params()) { 11693af6ab5fSopenharmony_ci auto *const param = it->AsETSParameterExpression(); 11703af6ab5fSopenharmony_ci 11713af6ab5fSopenharmony_ci if (param->IsRestParameter()) { 11723af6ab5fSopenharmony_ci auto const *const restIdent = param->Ident(); 11733af6ab5fSopenharmony_ci 11743af6ab5fSopenharmony_ci ASSERT(restIdent->Variable()); 11753af6ab5fSopenharmony_ci signatureInfo->restVar = restIdent->Variable()->AsLocalVariable(); 11763af6ab5fSopenharmony_ci 11773af6ab5fSopenharmony_ci auto *const restParamTypeAnnotation = param->TypeAnnotation(); 11783af6ab5fSopenharmony_ci ASSERT(restParamTypeAnnotation); 11793af6ab5fSopenharmony_ci 11803af6ab5fSopenharmony_ci signatureInfo->restVar->SetTsType(restParamTypeAnnotation->GetType(this)); 11813af6ab5fSopenharmony_ci auto arrayType = signatureInfo->restVar->TsType()->AsETSArrayType(); 11823af6ab5fSopenharmony_ci CreateBuiltinArraySignature(arrayType, arrayType->Rank()); 11833af6ab5fSopenharmony_ci } else { 11843af6ab5fSopenharmony_ci auto *const paramIdent = param->Ident(); 11853af6ab5fSopenharmony_ci 11863af6ab5fSopenharmony_ci varbinder::Variable *const paramVar = paramIdent->Variable(); 11873af6ab5fSopenharmony_ci ASSERT(paramVar); 11883af6ab5fSopenharmony_ci 11893af6ab5fSopenharmony_ci auto *const paramTypeAnnotation = param->TypeAnnotation(); 11903af6ab5fSopenharmony_ci if (paramIdent->TsType() == nullptr && paramTypeAnnotation == nullptr) { 11913af6ab5fSopenharmony_ci LogTypeError({"The type of parameter '", paramIdent->Name(), "' cannot be determined"}, param->Start()); 11923af6ab5fSopenharmony_ci return nullptr; 11933af6ab5fSopenharmony_ci } 11943af6ab5fSopenharmony_ci 11953af6ab5fSopenharmony_ci if (paramIdent->TsType() == nullptr) { 11963af6ab5fSopenharmony_ci ASSERT(paramTypeAnnotation); 11973af6ab5fSopenharmony_ci 11983af6ab5fSopenharmony_ci paramVar->SetTsType(paramTypeAnnotation->GetType(this)); 11993af6ab5fSopenharmony_ci } else { 12003af6ab5fSopenharmony_ci paramVar->SetTsType(paramIdent->TsTypeOrError()); 12013af6ab5fSopenharmony_ci } 12023af6ab5fSopenharmony_ci signatureInfo->params.push_back(paramVar->AsLocalVariable()); 12033af6ab5fSopenharmony_ci ++signatureInfo->minArgCount; 12043af6ab5fSopenharmony_ci } 12053af6ab5fSopenharmony_ci } 12063af6ab5fSopenharmony_ci 12073af6ab5fSopenharmony_ci return signatureInfo; 12083af6ab5fSopenharmony_ci} 12093af6ab5fSopenharmony_ci 12103af6ab5fSopenharmony_ciArenaVector<SignatureInfo *> ETSChecker::ComposeSignatureInfosForArrowFunction( 12113af6ab5fSopenharmony_ci ir::ArrowFunctionExpression *arrowFuncExpr) 12123af6ab5fSopenharmony_ci{ 12133af6ab5fSopenharmony_ci ArenaVector<SignatureInfo *> signatureInfos(Allocator()->Adapter()); 12143af6ab5fSopenharmony_ci 12153af6ab5fSopenharmony_ci for (size_t i = arrowFuncExpr->Function()->DefaultParamIndex(); i < arrowFuncExpr->Function()->Params().size(); 12163af6ab5fSopenharmony_ci i++) { 12173af6ab5fSopenharmony_ci auto *signatureInfo = CreateSignatureInfo(); 12183af6ab5fSopenharmony_ci signatureInfo->restVar = nullptr; 12193af6ab5fSopenharmony_ci signatureInfo->minArgCount = 0; 12203af6ab5fSopenharmony_ci 12213af6ab5fSopenharmony_ci if (arrowFuncExpr->Function()->TypeParams() != nullptr) { 12223af6ab5fSopenharmony_ci signatureInfo->typeParams = 12233af6ab5fSopenharmony_ci CreateUnconstrainedTypeParameters(arrowFuncExpr->Function()->TypeParams()).first; 12243af6ab5fSopenharmony_ci } 12253af6ab5fSopenharmony_ci 12263af6ab5fSopenharmony_ci for (size_t j = 0; j < i; j++) { 12273af6ab5fSopenharmony_ci SetParamForSignatureInfoOfArrowFunction(signatureInfo, 12283af6ab5fSopenharmony_ci arrowFuncExpr->Function()->Params()[j]->AsETSParameterExpression()); 12293af6ab5fSopenharmony_ci } 12303af6ab5fSopenharmony_ci 12313af6ab5fSopenharmony_ci signatureInfos.push_back(signatureInfo); 12323af6ab5fSopenharmony_ci } 12333af6ab5fSopenharmony_ci 12343af6ab5fSopenharmony_ci return signatureInfos; 12353af6ab5fSopenharmony_ci} 12363af6ab5fSopenharmony_ci 12373af6ab5fSopenharmony_civoid ETSChecker::SetParamForSignatureInfoOfArrowFunction(SignatureInfo *signatureInfo, 12383af6ab5fSopenharmony_ci ir::ETSParameterExpression *param) 12393af6ab5fSopenharmony_ci{ 12403af6ab5fSopenharmony_ci if (param->IsRestParameter()) { 12413af6ab5fSopenharmony_ci auto const *const restIdent = param->Ident(); 12423af6ab5fSopenharmony_ci 12433af6ab5fSopenharmony_ci ASSERT(restIdent->Variable()); 12443af6ab5fSopenharmony_ci signatureInfo->restVar = restIdent->Variable()->AsLocalVariable(); 12453af6ab5fSopenharmony_ci 12463af6ab5fSopenharmony_ci auto *const restParamTypeAnnotation = param->TypeAnnotation(); 12473af6ab5fSopenharmony_ci ASSERT(restParamTypeAnnotation); 12483af6ab5fSopenharmony_ci 12493af6ab5fSopenharmony_ci signatureInfo->restVar->SetTsType(restParamTypeAnnotation->GetType(this)); 12503af6ab5fSopenharmony_ci auto arrayType = signatureInfo->restVar->TsType()->AsETSArrayType(); 12513af6ab5fSopenharmony_ci CreateBuiltinArraySignature(arrayType, arrayType->Rank()); 12523af6ab5fSopenharmony_ci } else { 12533af6ab5fSopenharmony_ci auto *const paramIdent = param->Ident(); 12543af6ab5fSopenharmony_ci 12553af6ab5fSopenharmony_ci varbinder::Variable *const paramVar = paramIdent->Variable(); 12563af6ab5fSopenharmony_ci ASSERT(paramVar); 12573af6ab5fSopenharmony_ci 12583af6ab5fSopenharmony_ci auto *const paramTypeAnnotation = param->TypeAnnotation(); 12593af6ab5fSopenharmony_ci if (paramIdent->TsType() == nullptr) { 12603af6ab5fSopenharmony_ci ASSERT(paramTypeAnnotation); 12613af6ab5fSopenharmony_ci 12623af6ab5fSopenharmony_ci paramVar->SetTsType(paramTypeAnnotation->GetType(this)); 12633af6ab5fSopenharmony_ci } else { 12643af6ab5fSopenharmony_ci paramVar->SetTsType(paramIdent->TsType()); 12653af6ab5fSopenharmony_ci } 12663af6ab5fSopenharmony_ci signatureInfo->params.push_back(paramVar->AsLocalVariable()); 12673af6ab5fSopenharmony_ci ++signatureInfo->minArgCount; 12683af6ab5fSopenharmony_ci } 12693af6ab5fSopenharmony_ci} 12703af6ab5fSopenharmony_ci 12713af6ab5fSopenharmony_civoid ETSChecker::ValidateMainSignature(ir::ScriptFunction *func) 12723af6ab5fSopenharmony_ci{ 12733af6ab5fSopenharmony_ci if (func->Params().size() >= 2U) { 12743af6ab5fSopenharmony_ci LogTypeError("0 or 1 argument are allowed", func->Start()); 12753af6ab5fSopenharmony_ci return; 12763af6ab5fSopenharmony_ci } 12773af6ab5fSopenharmony_ci 12783af6ab5fSopenharmony_ci if (func->Params().size() == 1) { 12793af6ab5fSopenharmony_ci auto const *const param = func->Params()[0]->AsETSParameterExpression(); 12803af6ab5fSopenharmony_ci 12813af6ab5fSopenharmony_ci if (param->IsRestParameter()) { 12823af6ab5fSopenharmony_ci LogTypeError("Rest parameter is not allowed in the 'main' function.", param->Start()); 12833af6ab5fSopenharmony_ci } 12843af6ab5fSopenharmony_ci 12853af6ab5fSopenharmony_ci const auto paramType = param->Variable()->TsType(); 12863af6ab5fSopenharmony_ci if (!paramType->IsETSArrayType() || !paramType->AsETSArrayType()->ElementType()->IsETSStringType()) { 12873af6ab5fSopenharmony_ci LogTypeError("Only 'string[]' type argument is allowed.", param->Start()); 12883af6ab5fSopenharmony_ci } 12893af6ab5fSopenharmony_ci } 12903af6ab5fSopenharmony_ci} 12913af6ab5fSopenharmony_ci 12923af6ab5fSopenharmony_cistatic void AddSignatureFlags(const ir::ScriptFunction *const func, Signature *const signature) 12933af6ab5fSopenharmony_ci{ 12943af6ab5fSopenharmony_ci if (func->IsAbstract()) { 12953af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::ABSTRACT); 12963af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::VIRTUAL); 12973af6ab5fSopenharmony_ci } 12983af6ab5fSopenharmony_ci 12993af6ab5fSopenharmony_ci if (func->IsStatic()) { 13003af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::STATIC); 13013af6ab5fSopenharmony_ci } 13023af6ab5fSopenharmony_ci 13033af6ab5fSopenharmony_ci if (func->IsConstructor()) { 13043af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::CONSTRUCTOR); 13053af6ab5fSopenharmony_ci } 13063af6ab5fSopenharmony_ci 13073af6ab5fSopenharmony_ci if (func->Signature()->Owner()->GetDeclNode()->IsFinal() || func->IsFinal()) { 13083af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::FINAL); 13093af6ab5fSopenharmony_ci } 13103af6ab5fSopenharmony_ci 13113af6ab5fSopenharmony_ci if (func->IsPublic()) { 13123af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::PUBLIC); 13133af6ab5fSopenharmony_ci } else if (func->IsInternal()) { 13143af6ab5fSopenharmony_ci if (func->IsProtected()) { 13153af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::INTERNAL_PROTECTED); 13163af6ab5fSopenharmony_ci } else { 13173af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::INTERNAL); 13183af6ab5fSopenharmony_ci } 13193af6ab5fSopenharmony_ci } else if (func->IsProtected()) { 13203af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::PROTECTED); 13213af6ab5fSopenharmony_ci } else if (func->IsPrivate()) { 13223af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::PRIVATE); 13233af6ab5fSopenharmony_ci } 13243af6ab5fSopenharmony_ci 13253af6ab5fSopenharmony_ci if (func->IsSetter()) { 13263af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::SETTER); 13273af6ab5fSopenharmony_ci } else if (func->IsGetter()) { 13283af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::GETTER); 13293af6ab5fSopenharmony_ci } 13303af6ab5fSopenharmony_ci} 13313af6ab5fSopenharmony_ci 13323af6ab5fSopenharmony_civoid ETSChecker::BuildFunctionSignature(ir::ScriptFunction *func, bool isConstructSig) 13333af6ab5fSopenharmony_ci{ 13343af6ab5fSopenharmony_ci bool isArrow = func->IsArrow(); 13353af6ab5fSopenharmony_ci auto *nameVar = isArrow ? nullptr : func->Id()->Variable(); 13363af6ab5fSopenharmony_ci auto funcName = nameVar == nullptr ? util::StringView() : nameVar->Name(); 13373af6ab5fSopenharmony_ci 13383af6ab5fSopenharmony_ci auto *signatureInfo = ComposeSignatureInfo(func); 13393af6ab5fSopenharmony_ci if (signatureInfo == nullptr) { 13403af6ab5fSopenharmony_ci return; 13413af6ab5fSopenharmony_ci } 13423af6ab5fSopenharmony_ci 13433af6ab5fSopenharmony_ci if (funcName.Is(compiler::Signatures::MAIN) && 13443af6ab5fSopenharmony_ci func->Scope()->Name().Utf8().find(compiler::Signatures::ETS_GLOBAL) != std::string::npos) { 13453af6ab5fSopenharmony_ci func->AddFlag(ir::ScriptFunctionFlags::ENTRY_POINT); 13463af6ab5fSopenharmony_ci } 13473af6ab5fSopenharmony_ci if (func->IsEntryPoint()) { 13483af6ab5fSopenharmony_ci ValidateMainSignature(func); 13493af6ab5fSopenharmony_ci } 13503af6ab5fSopenharmony_ci 13513af6ab5fSopenharmony_ci auto *returnType = ComposeReturnType(func); 13523af6ab5fSopenharmony_ci auto *signature = ComposeSignature(func, signatureInfo, returnType, nameVar); 13533af6ab5fSopenharmony_ci if (isConstructSig) { 13543af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::CONSTRUCT); 13553af6ab5fSopenharmony_ci } else { 13563af6ab5fSopenharmony_ci signature->AddSignatureFlag(SignatureFlags::CALL); 13573af6ab5fSopenharmony_ci } 13583af6ab5fSopenharmony_ci func->SetSignature(signature); 13593af6ab5fSopenharmony_ci AddSignatureFlags(func, signature); 13603af6ab5fSopenharmony_ci VarBinder()->AsETSBinder()->BuildFunctionName(func); 13613af6ab5fSopenharmony_ci} 13623af6ab5fSopenharmony_ci 13633af6ab5fSopenharmony_cichecker::ETSFunctionType *ETSChecker::BuildNamedFunctionType(ir::ScriptFunction *func) 13643af6ab5fSopenharmony_ci{ 13653af6ab5fSopenharmony_ci ASSERT(!func->IsArrow()); 13663af6ab5fSopenharmony_ci auto *nameVar = func->Id()->Variable(); 13673af6ab5fSopenharmony_ci auto *funcType = CreateETSFunctionType(func, func->Signature(), nameVar->Name()); 13683af6ab5fSopenharmony_ci funcType->SetVariable(nameVar); 13693af6ab5fSopenharmony_ci return funcType; 13703af6ab5fSopenharmony_ci} 13713af6ab5fSopenharmony_ci 13723af6ab5fSopenharmony_ciSignature *ETSChecker::CheckEveryAbstractSignatureIsOverridden(ETSFunctionType *target, ETSFunctionType *source) 13733af6ab5fSopenharmony_ci{ 13743af6ab5fSopenharmony_ci for (auto targetSig = target->CallSignatures().begin(); targetSig != target->CallSignatures().end();) { 13753af6ab5fSopenharmony_ci if (!(*targetSig)->HasSignatureFlag(SignatureFlags::ABSTRACT)) { 13763af6ab5fSopenharmony_ci continue; 13773af6ab5fSopenharmony_ci } 13783af6ab5fSopenharmony_ci 13793af6ab5fSopenharmony_ci bool isOverridden = false; 13803af6ab5fSopenharmony_ci for (auto sourceSig : source->CallSignatures()) { 13813af6ab5fSopenharmony_ci if ((*targetSig)->Function()->Id()->Name() == sourceSig->Function()->Id()->Name() && 13823af6ab5fSopenharmony_ci Relation()->IsCompatibleTo(*targetSig, sourceSig)) { 13833af6ab5fSopenharmony_ci target->CallSignatures().erase(targetSig); 13843af6ab5fSopenharmony_ci isOverridden = true; 13853af6ab5fSopenharmony_ci break; 13863af6ab5fSopenharmony_ci } 13873af6ab5fSopenharmony_ci sourceSig++; 13883af6ab5fSopenharmony_ci } 13893af6ab5fSopenharmony_ci 13903af6ab5fSopenharmony_ci if (!isOverridden) { 13913af6ab5fSopenharmony_ci return *targetSig; 13923af6ab5fSopenharmony_ci } 13933af6ab5fSopenharmony_ci } 13943af6ab5fSopenharmony_ci 13953af6ab5fSopenharmony_ci return nullptr; 13963af6ab5fSopenharmony_ci} 13973af6ab5fSopenharmony_ci 13983af6ab5fSopenharmony_cibool ETSChecker::IsOverridableIn(Signature *signature) 13993af6ab5fSopenharmony_ci{ 14003af6ab5fSopenharmony_ci if (signature->HasSignatureFlag(SignatureFlags::PRIVATE)) { 14013af6ab5fSopenharmony_ci return false; 14023af6ab5fSopenharmony_ci } 14033af6ab5fSopenharmony_ci 14043af6ab5fSopenharmony_ci // NOTE: #15095 workaround, separate internal visibility check 14053af6ab5fSopenharmony_ci if (signature->HasSignatureFlag(SignatureFlags::PUBLIC | SignatureFlags::INTERNAL)) { 14063af6ab5fSopenharmony_ci return true; 14073af6ab5fSopenharmony_ci } 14083af6ab5fSopenharmony_ci 14093af6ab5fSopenharmony_ci return signature->HasSignatureFlag(SignatureFlags::PROTECTED); 14103af6ab5fSopenharmony_ci} 14113af6ab5fSopenharmony_ci 14123af6ab5fSopenharmony_cibool ETSChecker::IsMethodOverridesOther(Signature *base, Signature *derived) 14133af6ab5fSopenharmony_ci{ 14143af6ab5fSopenharmony_ci if (derived->Function()->IsConstructor()) { 14153af6ab5fSopenharmony_ci return false; 14163af6ab5fSopenharmony_ci } 14173af6ab5fSopenharmony_ci 14183af6ab5fSopenharmony_ci if (base == derived) { 14193af6ab5fSopenharmony_ci return true; 14203af6ab5fSopenharmony_ci } 14213af6ab5fSopenharmony_ci 14223af6ab5fSopenharmony_ci if (derived->HasSignatureFlag(SignatureFlags::STATIC) != base->HasSignatureFlag(SignatureFlags::STATIC)) { 14233af6ab5fSopenharmony_ci return false; 14243af6ab5fSopenharmony_ci } 14253af6ab5fSopenharmony_ci 14263af6ab5fSopenharmony_ci if (IsOverridableIn(base)) { 14273af6ab5fSopenharmony_ci SavedTypeRelationFlagsContext savedFlagsCtx(Relation(), TypeRelationFlag::NO_RETURN_TYPE_CHECK | 14283af6ab5fSopenharmony_ci TypeRelationFlag::OVERRIDING_CONTEXT); 14293af6ab5fSopenharmony_ci if (Relation()->IsCompatibleTo(base, derived)) { 14303af6ab5fSopenharmony_ci CheckThrowMarkers(base, derived); 14313af6ab5fSopenharmony_ci 14323af6ab5fSopenharmony_ci if (derived->HasSignatureFlag(SignatureFlags::STATIC)) { 14333af6ab5fSopenharmony_ci return false; 14343af6ab5fSopenharmony_ci } 14353af6ab5fSopenharmony_ci 14363af6ab5fSopenharmony_ci derived->Function()->SetOverride(); 14373af6ab5fSopenharmony_ci return true; 14383af6ab5fSopenharmony_ci } 14393af6ab5fSopenharmony_ci } 14403af6ab5fSopenharmony_ci 14413af6ab5fSopenharmony_ci return false; 14423af6ab5fSopenharmony_ci} 14433af6ab5fSopenharmony_ci 14443af6ab5fSopenharmony_cibool ETSChecker::CheckThrowMarkers(Signature *source, Signature *target) 14453af6ab5fSopenharmony_ci{ 14463af6ab5fSopenharmony_ci ir::ScriptFunctionFlags throwMarkers = ir::ScriptFunctionFlags::THROWS | ir::ScriptFunctionFlags::RETHROWS; 14473af6ab5fSopenharmony_ci if ((source->Function()->Flags() & throwMarkers) == (target->Function()->Flags() & throwMarkers)) { 14483af6ab5fSopenharmony_ci return true; 14493af6ab5fSopenharmony_ci } 14503af6ab5fSopenharmony_ci 14513af6ab5fSopenharmony_ci if ((source->Function()->IsRethrowing() && target->Function()->IsThrowing()) || 14523af6ab5fSopenharmony_ci (!source->Function()->IsThrowing() && 14533af6ab5fSopenharmony_ci (target->Function()->IsRethrowing() || target->Function()->IsThrowing()))) { 14543af6ab5fSopenharmony_ci ThrowTypeError( 14553af6ab5fSopenharmony_ci "A method that overrides or hides another method cannot change throw or rethrow clauses of the " 14563af6ab5fSopenharmony_ci "overridden " 14573af6ab5fSopenharmony_ci "or hidden method.", 14583af6ab5fSopenharmony_ci target->Function()->Body() == nullptr ? target->Function()->Start() : target->Function()->Body()->Start()); 14593af6ab5fSopenharmony_ci return false; 14603af6ab5fSopenharmony_ci } 14613af6ab5fSopenharmony_ci return true; 14623af6ab5fSopenharmony_ci} 14633af6ab5fSopenharmony_ci 14643af6ab5fSopenharmony_ciOverrideErrorCode ETSChecker::CheckOverride(Signature *signature, Signature *other) 14653af6ab5fSopenharmony_ci{ 14663af6ab5fSopenharmony_ci if (other->HasSignatureFlag(SignatureFlags::STATIC)) { 14673af6ab5fSopenharmony_ci ASSERT(signature->HasSignatureFlag(SignatureFlags::STATIC)); 14683af6ab5fSopenharmony_ci return OverrideErrorCode::NO_ERROR; 14693af6ab5fSopenharmony_ci } 14703af6ab5fSopenharmony_ci 14713af6ab5fSopenharmony_ci if (other->IsFinal()) { 14723af6ab5fSopenharmony_ci return OverrideErrorCode::OVERRIDDEN_FINAL; 14733af6ab5fSopenharmony_ci } 14743af6ab5fSopenharmony_ci 14753af6ab5fSopenharmony_ci if (!other->ReturnType()->IsETSTypeParameter()) { 14763af6ab5fSopenharmony_ci if (!IsReturnTypeSubstitutable(signature, other)) { 14773af6ab5fSopenharmony_ci return OverrideErrorCode::INCOMPATIBLE_RETURN; 14783af6ab5fSopenharmony_ci } 14793af6ab5fSopenharmony_ci } else { 14803af6ab5fSopenharmony_ci // We need to have this branch to allow generic overriding of the form: 14813af6ab5fSopenharmony_ci // foo<T>(x: T): T -> foo<someClass>(x: someClass): someClass 14823af6ab5fSopenharmony_ci if (!signature->ReturnType()->IsETSReferenceType()) { 14833af6ab5fSopenharmony_ci return OverrideErrorCode::INCOMPATIBLE_RETURN; 14843af6ab5fSopenharmony_ci } 14853af6ab5fSopenharmony_ci } 14863af6ab5fSopenharmony_ci 14873af6ab5fSopenharmony_ci if (signature->ProtectionFlag() > other->ProtectionFlag()) { 14883af6ab5fSopenharmony_ci return OverrideErrorCode::OVERRIDDEN_WEAKER; 14893af6ab5fSopenharmony_ci } 14903af6ab5fSopenharmony_ci 14913af6ab5fSopenharmony_ci return OverrideErrorCode::NO_ERROR; 14923af6ab5fSopenharmony_ci} 14933af6ab5fSopenharmony_ci 14943af6ab5fSopenharmony_ciSignature *ETSChecker::AdjustForTypeParameters(Signature *source, Signature *target) 14953af6ab5fSopenharmony_ci{ 14963af6ab5fSopenharmony_ci auto &sourceTypeParams = source->GetSignatureInfo()->typeParams; 14973af6ab5fSopenharmony_ci auto &targetTypeParams = target->GetSignatureInfo()->typeParams; 14983af6ab5fSopenharmony_ci if (sourceTypeParams.size() != targetTypeParams.size()) { 14993af6ab5fSopenharmony_ci return nullptr; 15003af6ab5fSopenharmony_ci } 15013af6ab5fSopenharmony_ci if (sourceTypeParams.empty()) { 15023af6ab5fSopenharmony_ci return target; 15033af6ab5fSopenharmony_ci } 15043af6ab5fSopenharmony_ci auto *substitution = NewSubstitution(); 15053af6ab5fSopenharmony_ci for (size_t ix = 0; ix < sourceTypeParams.size(); ix++) { 15063af6ab5fSopenharmony_ci if (!targetTypeParams[ix]->IsETSTypeParameter()) { 15073af6ab5fSopenharmony_ci continue; 15083af6ab5fSopenharmony_ci } 15093af6ab5fSopenharmony_ci ETSChecker::EmplaceSubstituted(substitution, targetTypeParams[ix]->AsETSTypeParameter(), sourceTypeParams[ix]); 15103af6ab5fSopenharmony_ci } 15113af6ab5fSopenharmony_ci return target->Substitute(Relation(), substitution); 15123af6ab5fSopenharmony_ci} 15133af6ab5fSopenharmony_ci 15143af6ab5fSopenharmony_civoid ETSChecker::ReportOverrideError(Signature *signature, Signature *overriddenSignature, 15153af6ab5fSopenharmony_ci const OverrideErrorCode &errorCode) 15163af6ab5fSopenharmony_ci{ 15173af6ab5fSopenharmony_ci const char *reason {}; 15183af6ab5fSopenharmony_ci switch (errorCode) { 15193af6ab5fSopenharmony_ci case OverrideErrorCode::OVERRIDDEN_FINAL: { 15203af6ab5fSopenharmony_ci reason = "overridden method is final."; 15213af6ab5fSopenharmony_ci break; 15223af6ab5fSopenharmony_ci } 15233af6ab5fSopenharmony_ci case OverrideErrorCode::INCOMPATIBLE_RETURN: { 15243af6ab5fSopenharmony_ci reason = "overriding return type is not compatible with the other return type."; 15253af6ab5fSopenharmony_ci break; 15263af6ab5fSopenharmony_ci } 15273af6ab5fSopenharmony_ci case OverrideErrorCode::OVERRIDDEN_WEAKER: { 15283af6ab5fSopenharmony_ci reason = "overridden method has weaker access privilege."; 15293af6ab5fSopenharmony_ci break; 15303af6ab5fSopenharmony_ci } 15313af6ab5fSopenharmony_ci default: { 15323af6ab5fSopenharmony_ci UNREACHABLE(); 15333af6ab5fSopenharmony_ci } 15343af6ab5fSopenharmony_ci } 15353af6ab5fSopenharmony_ci 15363af6ab5fSopenharmony_ci LogTypeError({signature->Function()->Id()->Name(), signature, " in ", signature->Owner(), " cannot override ", 15373af6ab5fSopenharmony_ci overriddenSignature->Function()->Id()->Name(), overriddenSignature, " in ", 15383af6ab5fSopenharmony_ci overriddenSignature->Owner(), " because ", reason}, 15393af6ab5fSopenharmony_ci signature->Function()->Start()); 15403af6ab5fSopenharmony_ci} 15413af6ab5fSopenharmony_ci 15423af6ab5fSopenharmony_cibool ETSChecker::CheckOverride(Signature *signature, ETSObjectType *site) 15433af6ab5fSopenharmony_ci{ 15443af6ab5fSopenharmony_ci auto *target = site->GetProperty(signature->Function()->Id()->Name(), PropertySearchFlags::SEARCH_METHOD); 15453af6ab5fSopenharmony_ci bool isOverridingAnySignature = false; 15463af6ab5fSopenharmony_ci 15473af6ab5fSopenharmony_ci if (target == nullptr) { 15483af6ab5fSopenharmony_ci return isOverridingAnySignature; 15493af6ab5fSopenharmony_ci } 15503af6ab5fSopenharmony_ci 15513af6ab5fSopenharmony_ci for (auto *it : target->TsType()->AsETSFunctionType()->CallSignatures()) { 15523af6ab5fSopenharmony_ci auto *itSubst = AdjustForTypeParameters(signature, it); 15533af6ab5fSopenharmony_ci 15543af6ab5fSopenharmony_ci if (itSubst == nullptr) { 15553af6ab5fSopenharmony_ci continue; 15563af6ab5fSopenharmony_ci } 15573af6ab5fSopenharmony_ci 15583af6ab5fSopenharmony_ci if (itSubst->HasSignatureFlag(SignatureFlags::ABSTRACT) || site->HasObjectFlag(ETSObjectFlags::INTERFACE)) { 15593af6ab5fSopenharmony_ci if (site->HasObjectFlag(ETSObjectFlags::INTERFACE) && !CheckThrowMarkers(itSubst, signature)) { 15603af6ab5fSopenharmony_ci return false; 15613af6ab5fSopenharmony_ci } 15623af6ab5fSopenharmony_ci 15633af6ab5fSopenharmony_ci if ((itSubst->Function()->IsSetter() && !signature->Function()->IsSetter()) || 15643af6ab5fSopenharmony_ci (itSubst->Function()->IsGetter() && !signature->Function()->IsGetter())) { 15653af6ab5fSopenharmony_ci continue; 15663af6ab5fSopenharmony_ci } 15673af6ab5fSopenharmony_ci } 15683af6ab5fSopenharmony_ci 15693af6ab5fSopenharmony_ci if (!IsMethodOverridesOther(itSubst, signature)) { 15703af6ab5fSopenharmony_ci continue; 15713af6ab5fSopenharmony_ci } 15723af6ab5fSopenharmony_ci 15733af6ab5fSopenharmony_ci if (auto err = CheckOverride(signature, itSubst); err != OverrideErrorCode::NO_ERROR) { 15743af6ab5fSopenharmony_ci ReportOverrideError(signature, it, err); 15753af6ab5fSopenharmony_ci return false; 15763af6ab5fSopenharmony_ci } 15773af6ab5fSopenharmony_ci 15783af6ab5fSopenharmony_ci if (signature->Owner()->HasObjectFlag(ETSObjectFlags::INTERFACE) && 15793af6ab5fSopenharmony_ci Relation()->IsIdenticalTo(itSubst->Owner(), GlobalETSObjectType()) && 15803af6ab5fSopenharmony_ci !itSubst->HasSignatureFlag(SignatureFlags::PRIVATE)) { 15813af6ab5fSopenharmony_ci LogTypeError("Cannot override non-private method of the class Object from an interface.", 15823af6ab5fSopenharmony_ci signature->Function()->Start()); 15833af6ab5fSopenharmony_ci return false; 15843af6ab5fSopenharmony_ci } 15853af6ab5fSopenharmony_ci 15863af6ab5fSopenharmony_ci isOverridingAnySignature = true; 15873af6ab5fSopenharmony_ci it->AddSignatureFlag(SignatureFlags::VIRTUAL); 15883af6ab5fSopenharmony_ci } 15893af6ab5fSopenharmony_ci 15903af6ab5fSopenharmony_ci return isOverridingAnySignature; 15913af6ab5fSopenharmony_ci} 15923af6ab5fSopenharmony_ci 15933af6ab5fSopenharmony_civoid ETSChecker::CheckOverride(Signature *signature) 15943af6ab5fSopenharmony_ci{ 15953af6ab5fSopenharmony_ci auto *owner = signature->Owner(); 15963af6ab5fSopenharmony_ci bool isOverriding = false; 15973af6ab5fSopenharmony_ci 15983af6ab5fSopenharmony_ci if (!owner->HasObjectFlag(ETSObjectFlags::CLASS | ETSObjectFlags::INTERFACE)) { 15993af6ab5fSopenharmony_ci return; 16003af6ab5fSopenharmony_ci } 16013af6ab5fSopenharmony_ci 16023af6ab5fSopenharmony_ci for (auto *const interface : owner->Interfaces()) { 16033af6ab5fSopenharmony_ci isOverriding |= CheckInterfaceOverride(this, interface, signature); 16043af6ab5fSopenharmony_ci } 16053af6ab5fSopenharmony_ci 16063af6ab5fSopenharmony_ci ETSObjectType *iter = owner->SuperType(); 16073af6ab5fSopenharmony_ci while (iter != nullptr) { 16083af6ab5fSopenharmony_ci isOverriding |= CheckOverride(signature, iter); 16093af6ab5fSopenharmony_ci 16103af6ab5fSopenharmony_ci for (auto *const interface : iter->Interfaces()) { 16113af6ab5fSopenharmony_ci isOverriding |= CheckInterfaceOverride(this, interface, signature); 16123af6ab5fSopenharmony_ci } 16133af6ab5fSopenharmony_ci 16143af6ab5fSopenharmony_ci iter = iter->SuperType(); 16153af6ab5fSopenharmony_ci } 16163af6ab5fSopenharmony_ci 16173af6ab5fSopenharmony_ci if (!isOverriding && signature->Function()->IsOverride()) { 16183af6ab5fSopenharmony_ci LogTypeError({"Method ", signature->Function()->Id()->Name(), signature, " in ", signature->Owner(), 16193af6ab5fSopenharmony_ci " not overriding any method"}, 16203af6ab5fSopenharmony_ci signature->Function()->Start()); 16213af6ab5fSopenharmony_ci } 16223af6ab5fSopenharmony_ci} 16233af6ab5fSopenharmony_ci 16243af6ab5fSopenharmony_ciSignature *ETSChecker::GetSignatureFromMethodDefinition(const ir::MethodDefinition *methodDef) 16253af6ab5fSopenharmony_ci{ 16263af6ab5fSopenharmony_ci if (methodDef->TsTypeOrError()->IsTypeError()) { 16273af6ab5fSopenharmony_ci return nullptr; 16283af6ab5fSopenharmony_ci } 16293af6ab5fSopenharmony_ci ASSERT(methodDef->TsType() && methodDef->TsType()->IsETSFunctionType()); 16303af6ab5fSopenharmony_ci for (auto *it : methodDef->TsType()->AsETSFunctionType()->CallSignatures()) { 16313af6ab5fSopenharmony_ci if (it->Function() == methodDef->Function()) { 16323af6ab5fSopenharmony_ci return it; 16333af6ab5fSopenharmony_ci } 16343af6ab5fSopenharmony_ci } 16353af6ab5fSopenharmony_ci 16363af6ab5fSopenharmony_ci return nullptr; 16373af6ab5fSopenharmony_ci} 16383af6ab5fSopenharmony_ci 16393af6ab5fSopenharmony_civoid ETSChecker::ValidateSignatureAccessibility(ETSObjectType *callee, const ir::CallExpression *callExpr, 16403af6ab5fSopenharmony_ci Signature *signature, const lexer::SourcePosition &pos, 16413af6ab5fSopenharmony_ci char const *errorMessage) 16423af6ab5fSopenharmony_ci{ 16433af6ab5fSopenharmony_ci if ((Context().Status() & CheckerStatus::IGNORE_VISIBILITY) != 0U || 16443af6ab5fSopenharmony_ci (!signature->HasSignatureFlag(SignatureFlags::PRIVATE) && 16453af6ab5fSopenharmony_ci !signature->HasSignatureFlag(SignatureFlags::PROTECTED))) { 16463af6ab5fSopenharmony_ci return; 16473af6ab5fSopenharmony_ci } 16483af6ab5fSopenharmony_ci const auto *declNode = callee->GetDeclNode(); 16493af6ab5fSopenharmony_ci auto *containingClass = Context().ContainingClass(); 16503af6ab5fSopenharmony_ci bool isContainingSignatureInherited = containingClass->IsSignatureInherited(signature); 16513af6ab5fSopenharmony_ci ASSERT(declNode && (declNode->IsClassDefinition() || declNode->IsTSInterfaceDeclaration())); 16523af6ab5fSopenharmony_ci 16533af6ab5fSopenharmony_ci if (declNode->IsTSInterfaceDeclaration()) { 16543af6ab5fSopenharmony_ci const auto *enclosingFunc = 16553af6ab5fSopenharmony_ci util::Helpers::FindAncestorGivenByType(callExpr, ir::AstNodeType::SCRIPT_FUNCTION)->AsScriptFunction(); 16563af6ab5fSopenharmony_ci if (callExpr->Callee()->IsMemberExpression() && 16573af6ab5fSopenharmony_ci callExpr->Callee()->AsMemberExpression()->Object()->IsThisExpression() && 16583af6ab5fSopenharmony_ci signature->Function()->IsPrivate() && !enclosingFunc->IsPrivate()) { 16593af6ab5fSopenharmony_ci LogTypeError({"Cannot reference 'this' in this context."}, enclosingFunc->Start()); 16603af6ab5fSopenharmony_ci } 16613af6ab5fSopenharmony_ci 16623af6ab5fSopenharmony_ci if (containingClass == declNode->AsTSInterfaceDeclaration()->TsType() && isContainingSignatureInherited) { 16633af6ab5fSopenharmony_ci return; 16643af6ab5fSopenharmony_ci } 16653af6ab5fSopenharmony_ci } 16663af6ab5fSopenharmony_ci if (containingClass == declNode->AsClassDefinition()->TsType() && isContainingSignatureInherited) { 16673af6ab5fSopenharmony_ci return; 16683af6ab5fSopenharmony_ci } 16693af6ab5fSopenharmony_ci 16703af6ab5fSopenharmony_ci bool isSignatureInherited = callee->IsSignatureInherited(signature); 16713af6ab5fSopenharmony_ci const auto *currentOutermost = containingClass->OutermostClass(); 16723af6ab5fSopenharmony_ci if (!signature->HasSignatureFlag(SignatureFlags::PRIVATE) && 16733af6ab5fSopenharmony_ci ((signature->HasSignatureFlag(SignatureFlags::PROTECTED) && containingClass->IsDescendantOf(callee)) || 16743af6ab5fSopenharmony_ci (currentOutermost != nullptr && currentOutermost == callee->OutermostClass())) && 16753af6ab5fSopenharmony_ci isSignatureInherited) { 16763af6ab5fSopenharmony_ci return; 16773af6ab5fSopenharmony_ci } 16783af6ab5fSopenharmony_ci 16793af6ab5fSopenharmony_ci if (errorMessage == nullptr) { 16803af6ab5fSopenharmony_ci LogTypeError({"Signature ", signature->Function()->Id()->Name(), signature, " is not visible here."}, pos); 16813af6ab5fSopenharmony_ci return; 16823af6ab5fSopenharmony_ci } 16833af6ab5fSopenharmony_ci LogTypeError(errorMessage, pos); 16843af6ab5fSopenharmony_ci} 16853af6ab5fSopenharmony_ci 16863af6ab5fSopenharmony_civoid ETSChecker::CheckCapturedVariable(ir::AstNode *const node, varbinder::Variable *const var) 16873af6ab5fSopenharmony_ci{ 16883af6ab5fSopenharmony_ci if (node->IsIdentifier()) { 16893af6ab5fSopenharmony_ci const auto *const parent = node->Parent(); 16903af6ab5fSopenharmony_ci 16913af6ab5fSopenharmony_ci if (parent->IsUpdateExpression() || 16923af6ab5fSopenharmony_ci (parent->IsAssignmentExpression() && parent->AsAssignmentExpression()->Left() == node)) { 16933af6ab5fSopenharmony_ci const auto *const identNode = node->AsIdentifier(); 16943af6ab5fSopenharmony_ci 16953af6ab5fSopenharmony_ci const auto *resolved = identNode->Variable(); 16963af6ab5fSopenharmony_ci 16973af6ab5fSopenharmony_ci if (resolved == nullptr) { 16983af6ab5fSopenharmony_ci resolved = 16993af6ab5fSopenharmony_ci FindVariableInFunctionScope(identNode->Name(), varbinder::ResolveBindingOptions::ALL_NON_TYPE); 17003af6ab5fSopenharmony_ci } 17013af6ab5fSopenharmony_ci 17023af6ab5fSopenharmony_ci if (resolved == nullptr) { 17033af6ab5fSopenharmony_ci resolved = FindVariableInGlobal(identNode, varbinder::ResolveBindingOptions::ALL_NON_TYPE); 17043af6ab5fSopenharmony_ci } 17053af6ab5fSopenharmony_ci 17063af6ab5fSopenharmony_ci if (resolved == var) { 17073af6ab5fSopenharmony_ci // For mutable captured variable [possible] smart-cast is senseless (or even erroneous) 17083af6ab5fSopenharmony_ci Context().RemoveSmartCast(var); 17093af6ab5fSopenharmony_ci } 17103af6ab5fSopenharmony_ci } 17113af6ab5fSopenharmony_ci } 17123af6ab5fSopenharmony_ci 17133af6ab5fSopenharmony_ci CheckCapturedVariableInSubnodes(node, var); 17143af6ab5fSopenharmony_ci} 17153af6ab5fSopenharmony_ci 17163af6ab5fSopenharmony_civoid ETSChecker::CheckCapturedVariableInSubnodes(ir::AstNode *node, varbinder::Variable *var) 17173af6ab5fSopenharmony_ci{ 17183af6ab5fSopenharmony_ci if (!node->IsClassDefinition()) { 17193af6ab5fSopenharmony_ci node->Iterate([this, var](ir::AstNode *childNode) { CheckCapturedVariable(childNode, var); }); 17203af6ab5fSopenharmony_ci } 17213af6ab5fSopenharmony_ci} 17223af6ab5fSopenharmony_ci 17233af6ab5fSopenharmony_civoid ETSChecker::CheckCapturedVariables() 17243af6ab5fSopenharmony_ci{ 17253af6ab5fSopenharmony_ci // If we want to capture non constant local variables, we should wrap them in a generic reference class 17263af6ab5fSopenharmony_ci for (auto [var, _] : Context().CapturedVars()) { 17273af6ab5fSopenharmony_ci (void)_; 17283af6ab5fSopenharmony_ci if ((var->Declaration() == nullptr) || var->Declaration()->IsConstDecl() || 17293af6ab5fSopenharmony_ci !var->HasFlag(varbinder::VariableFlags::LOCAL) || var->GetScope()->Node()->IsArrowFunctionExpression()) { 17303af6ab5fSopenharmony_ci continue; 17313af6ab5fSopenharmony_ci } 17323af6ab5fSopenharmony_ci 17333af6ab5fSopenharmony_ci auto *searchNode = var->Declaration()->Node()->Parent(); 17343af6ab5fSopenharmony_ci 17353af6ab5fSopenharmony_ci if (searchNode->IsVariableDeclarator()) { 17363af6ab5fSopenharmony_ci searchNode = searchNode->Parent()->Parent(); 17373af6ab5fSopenharmony_ci } 17383af6ab5fSopenharmony_ci 17393af6ab5fSopenharmony_ci CheckCapturedVariableInSubnodes(searchNode, var); 17403af6ab5fSopenharmony_ci } 17413af6ab5fSopenharmony_ci} 17423af6ab5fSopenharmony_ci 17433af6ab5fSopenharmony_cibool ETSChecker::AreOverrideEquivalent(Signature *const s1, Signature *const s2) 17443af6ab5fSopenharmony_ci{ 17453af6ab5fSopenharmony_ci // Two functions, methods or constructors M and N have the same signature if 17463af6ab5fSopenharmony_ci // their names and type parameters (if any) are the same, and their formal parameter 17473af6ab5fSopenharmony_ci // types are also the same (after the formal parameter types of N are adapted to the type parameters of M). 17483af6ab5fSopenharmony_ci // Signatures s1 and s2 are override-equivalent only if s1 and s2 are the same. 17493af6ab5fSopenharmony_ci 17503af6ab5fSopenharmony_ci SavedTypeRelationFlagsContext savedFlagsCtx(Relation(), TypeRelationFlag::OVERRIDING_CONTEXT); 17513af6ab5fSopenharmony_ci return s1->Function()->Id()->Name() == s2->Function()->Id()->Name() && Relation()->IsCompatibleTo(s1, s2); 17523af6ab5fSopenharmony_ci} 17533af6ab5fSopenharmony_ci 17543af6ab5fSopenharmony_cibool ETSChecker::IsReturnTypeSubstitutable(Signature *const s1, Signature *const s2) 17553af6ab5fSopenharmony_ci{ 17563af6ab5fSopenharmony_ci auto *const r1 = s1->ReturnType(); 17573af6ab5fSopenharmony_ci auto *const r2 = s2->ReturnType(); 17583af6ab5fSopenharmony_ci 17593af6ab5fSopenharmony_ci // A method declaration d1 with return type R1 is return-type-substitutable for another method d2 with return 17603af6ab5fSopenharmony_ci // type R2 if any of the following is true: 17613af6ab5fSopenharmony_ci 17623af6ab5fSopenharmony_ci // - If R1 is a primitive type then R2 is identical to R1. 17633af6ab5fSopenharmony_ci if (r1->HasTypeFlag(TypeFlag::ETS_PRIMITIVE | TypeFlag::ETS_INT_ENUM | TypeFlag::ETS_STRING_ENUM | 17643af6ab5fSopenharmony_ci TypeFlag::ETS_VOID)) { 17653af6ab5fSopenharmony_ci return Relation()->IsIdenticalTo(r2, r1); 17663af6ab5fSopenharmony_ci } 17673af6ab5fSopenharmony_ci 17683af6ab5fSopenharmony_ci // - If R1 is a reference type then R1, adapted to the type parameters of d2 (link to generic methods), is a 17693af6ab5fSopenharmony_ci // subtype of R2. 17703af6ab5fSopenharmony_ci ASSERT(IsReferenceType(r1)); 17713af6ab5fSopenharmony_ci 17723af6ab5fSopenharmony_ci if (Relation()->IsSupertypeOf(r2, r1)) { 17733af6ab5fSopenharmony_ci return true; 17743af6ab5fSopenharmony_ci } 17753af6ab5fSopenharmony_ci 17763af6ab5fSopenharmony_ci return s2->Function()->ReturnTypeAnnotation()->IsETSTypeReference() && 17773af6ab5fSopenharmony_ci Relation()->IsSupertypeOf( 17783af6ab5fSopenharmony_ci s2->Function()->ReturnTypeAnnotation()->GetType(this)->AsETSTypeParameter()->GetConstraintType(), r1); 17793af6ab5fSopenharmony_ci} 17803af6ab5fSopenharmony_ci 17813af6ab5fSopenharmony_cistd::string ETSChecker::GetAsyncImplName(const util::StringView &name) 17823af6ab5fSopenharmony_ci{ 17833af6ab5fSopenharmony_ci std::string implName(name); 17843af6ab5fSopenharmony_ci implName += "$asyncimpl"; 17853af6ab5fSopenharmony_ci return implName; 17863af6ab5fSopenharmony_ci} 17873af6ab5fSopenharmony_ci 17883af6ab5fSopenharmony_cistd::string ETSChecker::GetAsyncImplName(ir::MethodDefinition *asyncMethod) 17893af6ab5fSopenharmony_ci{ 17903af6ab5fSopenharmony_ci ir::Identifier *asyncName = asyncMethod->Function()->Id(); 17913af6ab5fSopenharmony_ci ASSERT(asyncName != nullptr); 17923af6ab5fSopenharmony_ci return GetAsyncImplName(asyncName->Name()); 17933af6ab5fSopenharmony_ci} 17943af6ab5fSopenharmony_ci 17953af6ab5fSopenharmony_cibool ETSChecker::IsAsyncImplMethod(ir::MethodDefinition const *method) 17963af6ab5fSopenharmony_ci{ 17973af6ab5fSopenharmony_ci auto methodName = method->Key()->AsIdentifier()->Name().Utf8(); 17983af6ab5fSopenharmony_ci std::string_view asyncSuffix = "$asyncimpl"; 17993af6ab5fSopenharmony_ci if (methodName.size() < asyncSuffix.size()) { 18003af6ab5fSopenharmony_ci return false; 18013af6ab5fSopenharmony_ci } 18023af6ab5fSopenharmony_ci return methodName.substr(methodName.size() - asyncSuffix.size()) == asyncSuffix; 18033af6ab5fSopenharmony_ci} 18043af6ab5fSopenharmony_ci 18053af6ab5fSopenharmony_ciir::MethodDefinition *ETSChecker::CreateAsyncImplMethod(ir::MethodDefinition *asyncMethod, 18063af6ab5fSopenharmony_ci ir::ClassDefinition *classDef) 18073af6ab5fSopenharmony_ci{ 18083af6ab5fSopenharmony_ci util::UString implName(GetAsyncImplName(asyncMethod), Allocator()); 18093af6ab5fSopenharmony_ci ir::ModifierFlags modifiers = asyncMethod->Modifiers(); 18103af6ab5fSopenharmony_ci // clear ASYNC flag for implementation 18113af6ab5fSopenharmony_ci modifiers &= ~ir::ModifierFlags::ASYNC; 18123af6ab5fSopenharmony_ci ir::ScriptFunction *asyncFunc = asyncMethod->Function(); 18133af6ab5fSopenharmony_ci ir::ScriptFunctionFlags flags = ir::ScriptFunctionFlags::METHOD; 18143af6ab5fSopenharmony_ci 18153af6ab5fSopenharmony_ci if (asyncFunc->IsProxy()) { 18163af6ab5fSopenharmony_ci flags |= ir::ScriptFunctionFlags::PROXY; 18173af6ab5fSopenharmony_ci } 18183af6ab5fSopenharmony_ci 18193af6ab5fSopenharmony_ci if (asyncFunc->HasReturnStatement()) { 18203af6ab5fSopenharmony_ci flags |= ir::ScriptFunctionFlags::HAS_RETURN; 18213af6ab5fSopenharmony_ci } 18223af6ab5fSopenharmony_ci 18233af6ab5fSopenharmony_ci asyncMethod->AddModifier(ir::ModifierFlags::NATIVE); 18243af6ab5fSopenharmony_ci asyncFunc->AddModifier(ir::ModifierFlags::NATIVE); 18253af6ab5fSopenharmony_ci // Create async_impl method copied from CreateInvokeFunction 18263af6ab5fSopenharmony_ci auto scopeCtx = 18273af6ab5fSopenharmony_ci varbinder::LexicalScope<varbinder::ClassScope>::Enter(VarBinder(), classDef->Scope()->AsClassScope()); 18283af6ab5fSopenharmony_ci auto *body = asyncFunc->Body(); 18293af6ab5fSopenharmony_ci ArenaVector<ir::Expression *> params(Allocator()->Adapter()); 18303af6ab5fSopenharmony_ci // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 18313af6ab5fSopenharmony_ci varbinder::FunctionParamScope *paramScope = CopyParams(asyncFunc->Params(), params); 18323af6ab5fSopenharmony_ci 18333af6ab5fSopenharmony_ci ir::ETSTypeReference *returnTypeAnn = nullptr; 18343af6ab5fSopenharmony_ci 18353af6ab5fSopenharmony_ci if (!asyncFunc->Signature()->HasSignatureFlag(SignatureFlags::NEED_RETURN_TYPE)) { 18363af6ab5fSopenharmony_ci // Set impl method return type "Object" because it may return Promise as well as Promise parameter's type 18373af6ab5fSopenharmony_ci auto *objectId = AllocNode<ir::Identifier>(compiler::Signatures::BUILTIN_OBJECT_CLASS, Allocator()); 18383af6ab5fSopenharmony_ci objectId->SetReference(); 18393af6ab5fSopenharmony_ci VarBinder()->AsETSBinder()->LookupTypeReference(objectId, false); 18403af6ab5fSopenharmony_ci returnTypeAnn = 18413af6ab5fSopenharmony_ci AllocNode<ir::ETSTypeReference>(AllocNode<ir::ETSTypeReferencePart>(objectId, nullptr, nullptr)); 18423af6ab5fSopenharmony_ci objectId->SetParent(returnTypeAnn->Part()); 18433af6ab5fSopenharmony_ci returnTypeAnn->Part()->SetParent(returnTypeAnn); 18443af6ab5fSopenharmony_ci auto *asyncFuncRetTypeAnn = asyncFunc->ReturnTypeAnnotation(); 18453af6ab5fSopenharmony_ci auto *promiseType = [this](ir::TypeNode *type) { 18463af6ab5fSopenharmony_ci if (type != nullptr) { 18473af6ab5fSopenharmony_ci return type->GetType(this)->AsETSObjectType(); 18483af6ab5fSopenharmony_ci } 18493af6ab5fSopenharmony_ci 18503af6ab5fSopenharmony_ci return GlobalBuiltinPromiseType()->AsETSObjectType(); 18513af6ab5fSopenharmony_ci }(asyncFuncRetTypeAnn); 18523af6ab5fSopenharmony_ci // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 18533af6ab5fSopenharmony_ci auto *retType = Allocator()->New<ETSAsyncFuncReturnType>(Allocator(), Relation(), promiseType); 18543af6ab5fSopenharmony_ci returnTypeAnn->SetTsType(retType); 18553af6ab5fSopenharmony_ci } 18563af6ab5fSopenharmony_ci 18573af6ab5fSopenharmony_ci ir::MethodDefinition *implMethod = 18583af6ab5fSopenharmony_ci CreateMethod(implName.View(), modifiers, flags, std::move(params), paramScope, returnTypeAnn, body); 18593af6ab5fSopenharmony_ci asyncFunc->SetBody(nullptr); 18603af6ab5fSopenharmony_ci 18613af6ab5fSopenharmony_ci if (returnTypeAnn != nullptr) { 18623af6ab5fSopenharmony_ci returnTypeAnn->SetParent(implMethod->Function()); 18633af6ab5fSopenharmony_ci } 18643af6ab5fSopenharmony_ci 18653af6ab5fSopenharmony_ci implMethod->Function()->AddFlag(ir::ScriptFunctionFlags::ASYNC_IMPL); 18663af6ab5fSopenharmony_ci implMethod->SetParent(asyncMethod->Parent()); 18673af6ab5fSopenharmony_ci return implMethod; 18683af6ab5fSopenharmony_ci} 18693af6ab5fSopenharmony_ci 18703af6ab5fSopenharmony_cistatic void CreateFuncDecl(ETSChecker *checker, ir::MethodDefinition *func, varbinder::LocalScope *scope) 18713af6ab5fSopenharmony_ci{ 18723af6ab5fSopenharmony_ci auto *allocator = checker->Allocator(); 18733af6ab5fSopenharmony_ci auto *varBinder = checker->VarBinder(); 18743af6ab5fSopenharmony_ci // Add the function declarations to the lambda class scope 18753af6ab5fSopenharmony_ci auto ctx = varbinder::LexicalScope<varbinder::LocalScope>::Enter(varBinder, scope); 18763af6ab5fSopenharmony_ci varbinder::Variable *var = scope->FindLocal(func->Id()->Name(), varbinder::ResolveBindingOptions::ALL_DECLARATION); 18773af6ab5fSopenharmony_ci if (var == nullptr) { 18783af6ab5fSopenharmony_ci var = std::get<1>( 18793af6ab5fSopenharmony_ci varBinder->NewVarDecl<varbinder::FunctionDecl>(func->Start(), allocator, func->Id()->Name(), func)); 18803af6ab5fSopenharmony_ci } 18813af6ab5fSopenharmony_ci var->AddFlag(varbinder::VariableFlags::METHOD); 18823af6ab5fSopenharmony_ci var->SetScope(ctx.GetScope()); 18833af6ab5fSopenharmony_ci func->Function()->Id()->SetVariable(var); 18843af6ab5fSopenharmony_ci} 18853af6ab5fSopenharmony_ci 18863af6ab5fSopenharmony_ciir::MethodDefinition *ETSChecker::CreateAsyncProxy(ir::MethodDefinition *asyncMethod, ir::ClassDefinition *classDef, 18873af6ab5fSopenharmony_ci bool createDecl) 18883af6ab5fSopenharmony_ci{ 18893af6ab5fSopenharmony_ci ir::ScriptFunction *asyncFunc = asyncMethod->Function(); 18903af6ab5fSopenharmony_ci if (!asyncFunc->IsExternal()) { 18913af6ab5fSopenharmony_ci VarBinder()->AsETSBinder()->GetRecordTable()->Signatures().push_back(asyncFunc->Scope()); 18923af6ab5fSopenharmony_ci } 18933af6ab5fSopenharmony_ci 18943af6ab5fSopenharmony_ci // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 18953af6ab5fSopenharmony_ci ir::MethodDefinition *implMethod = CreateAsyncImplMethod(asyncMethod, classDef); 18963af6ab5fSopenharmony_ci varbinder::FunctionScope *implFuncScope = implMethod->Function()->Scope(); 18973af6ab5fSopenharmony_ci for (auto *decl : asyncFunc->Scope()->Decls()) { 18983af6ab5fSopenharmony_ci auto res = asyncFunc->Scope()->Bindings().find(decl->Name()); 18993af6ab5fSopenharmony_ci ASSERT(res != asyncFunc->Scope()->Bindings().end()); 19003af6ab5fSopenharmony_ci auto *const var = std::get<1>(*res); 19013af6ab5fSopenharmony_ci var->SetScope(implFuncScope); 19023af6ab5fSopenharmony_ci implFuncScope->Decls().push_back(decl); 19033af6ab5fSopenharmony_ci implFuncScope->InsertBinding(decl->Name(), var); 19043af6ab5fSopenharmony_ci } 19053af6ab5fSopenharmony_ci 19063af6ab5fSopenharmony_ci ReplaceScope(implMethod->Function()->Body(), asyncFunc, implFuncScope); 19073af6ab5fSopenharmony_ci 19083af6ab5fSopenharmony_ci ArenaVector<varbinder::Variable *> captured(Allocator()->Adapter()); 19093af6ab5fSopenharmony_ci 19103af6ab5fSopenharmony_ci bool isStatic = asyncMethod->IsStatic(); 19113af6ab5fSopenharmony_ci if (createDecl) { 19123af6ab5fSopenharmony_ci if (isStatic) { 19133af6ab5fSopenharmony_ci CreateFuncDecl(this, implMethod, classDef->Scope()->AsClassScope()->StaticMethodScope()); 19143af6ab5fSopenharmony_ci } else { 19153af6ab5fSopenharmony_ci CreateFuncDecl(this, implMethod, classDef->Scope()->AsClassScope()->InstanceMethodScope()); 19163af6ab5fSopenharmony_ci } 19173af6ab5fSopenharmony_ci implMethod->Id()->SetVariable(implMethod->Function()->Id()->Variable()); 19183af6ab5fSopenharmony_ci } 19193af6ab5fSopenharmony_ci VarBinder()->AsETSBinder()->BuildProxyMethod(implMethod->Function(), classDef->InternalName(), isStatic, 19203af6ab5fSopenharmony_ci asyncFunc->IsExternal()); 19213af6ab5fSopenharmony_ci implMethod->SetParent(asyncMethod->Parent()); 19223af6ab5fSopenharmony_ci 19233af6ab5fSopenharmony_ci return implMethod; 19243af6ab5fSopenharmony_ci} 19253af6ab5fSopenharmony_ci 19263af6ab5fSopenharmony_ciir::MethodDefinition *ETSChecker::CreateMethod(const util::StringView &name, ir::ModifierFlags modifiers, 19273af6ab5fSopenharmony_ci ir::ScriptFunctionFlags flags, ArenaVector<ir::Expression *> &¶ms, 19283af6ab5fSopenharmony_ci varbinder::FunctionParamScope *paramScope, ir::TypeNode *returnType, 19293af6ab5fSopenharmony_ci ir::AstNode *body) 19303af6ab5fSopenharmony_ci{ 19313af6ab5fSopenharmony_ci // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 19323af6ab5fSopenharmony_ci auto *nameId = AllocNode<ir::Identifier>(name, Allocator()); 19333af6ab5fSopenharmony_ci // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 19343af6ab5fSopenharmony_ci auto *scope = VarBinder()->Allocator()->New<varbinder::FunctionScope>(Allocator(), paramScope); 19353af6ab5fSopenharmony_ci // clang-format off 19363af6ab5fSopenharmony_ci auto *const func = AllocNode<ir::ScriptFunction>( 19373af6ab5fSopenharmony_ci Allocator(), ir::ScriptFunction::ScriptFunctionData { 19383af6ab5fSopenharmony_ci body, ir::FunctionSignature(nullptr, std::move(params), returnType), flags, modifiers}); 19393af6ab5fSopenharmony_ci // clang-format on 19403af6ab5fSopenharmony_ci func->SetScope(scope); 19413af6ab5fSopenharmony_ci func->SetIdent(nameId); 19423af6ab5fSopenharmony_ci if (body != nullptr && body->IsBlockStatement()) { 19433af6ab5fSopenharmony_ci body->AsBlockStatement()->SetScope(scope); 19443af6ab5fSopenharmony_ci } 19453af6ab5fSopenharmony_ci scope->BindNode(func); 19463af6ab5fSopenharmony_ci paramScope->BindNode(func); 19473af6ab5fSopenharmony_ci scope->BindParamScope(paramScope); 19483af6ab5fSopenharmony_ci paramScope->BindFunctionScope(scope); 19493af6ab5fSopenharmony_ci // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 19503af6ab5fSopenharmony_ci auto *funcExpr = AllocNode<ir::FunctionExpression>(func); 19513af6ab5fSopenharmony_ci auto *nameClone = nameId->Clone(Allocator(), nullptr); 19523af6ab5fSopenharmony_ci // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 19533af6ab5fSopenharmony_ci auto *method = AllocNode<ir::MethodDefinition>(ir::MethodDefinitionKind::METHOD, nameClone, funcExpr, modifiers, 19543af6ab5fSopenharmony_ci Allocator(), false); 19553af6ab5fSopenharmony_ci return method; 19563af6ab5fSopenharmony_ci} 19573af6ab5fSopenharmony_ci 19583af6ab5fSopenharmony_civarbinder::FunctionParamScope *ETSChecker::CopyParams(const ArenaVector<ir::Expression *> ¶ms, 19593af6ab5fSopenharmony_ci ArenaVector<ir::Expression *> &outParams) 19603af6ab5fSopenharmony_ci{ 19613af6ab5fSopenharmony_ci auto paramCtx = varbinder::LexicalScope<varbinder::FunctionParamScope>(VarBinder()); 19623af6ab5fSopenharmony_ci 19633af6ab5fSopenharmony_ci for (auto *const it : params) { 19643af6ab5fSopenharmony_ci auto *const paramOld = it->AsETSParameterExpression(); 19653af6ab5fSopenharmony_ci // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 19663af6ab5fSopenharmony_ci auto *const paramNew = paramOld->Clone(Allocator(), paramOld->Parent())->AsETSParameterExpression(); 19673af6ab5fSopenharmony_ci 19683af6ab5fSopenharmony_ci auto *const var = std::get<1>(VarBinder()->AddParamDecl(paramNew)); 19693af6ab5fSopenharmony_ci 19703af6ab5fSopenharmony_ci var->SetTsType(paramOld->Ident()->Variable()->TsType()); 19713af6ab5fSopenharmony_ci var->SetScope(paramCtx.GetScope()); 19723af6ab5fSopenharmony_ci paramNew->SetVariable(var); 19733af6ab5fSopenharmony_ci 19743af6ab5fSopenharmony_ci paramNew->SetTsType(paramOld->Ident()->Variable()->TsType()); 19753af6ab5fSopenharmony_ci 19763af6ab5fSopenharmony_ci outParams.emplace_back(paramNew); 19773af6ab5fSopenharmony_ci } 19783af6ab5fSopenharmony_ci 19793af6ab5fSopenharmony_ci return paramCtx.GetScope(); 19803af6ab5fSopenharmony_ci} 19813af6ab5fSopenharmony_ci 19823af6ab5fSopenharmony_civoid ETSChecker::ReplaceScope(ir::AstNode *root, ir::AstNode *oldNode, varbinder::Scope *newScope) 19833af6ab5fSopenharmony_ci{ 19843af6ab5fSopenharmony_ci if (root == nullptr) { 19853af6ab5fSopenharmony_ci return; 19863af6ab5fSopenharmony_ci } 19873af6ab5fSopenharmony_ci 19883af6ab5fSopenharmony_ci root->Iterate([this, oldNode, newScope](ir::AstNode *child) { 19893af6ab5fSopenharmony_ci auto *scope = NodeScope(child); 19903af6ab5fSopenharmony_ci if (scope != nullptr) { 19913af6ab5fSopenharmony_ci while (scope->Parent() != nullptr && scope->Parent()->Node() != oldNode) { 19923af6ab5fSopenharmony_ci scope = scope->Parent(); 19933af6ab5fSopenharmony_ci } 19943af6ab5fSopenharmony_ci scope->SetParent(newScope); 19953af6ab5fSopenharmony_ci } else { 19963af6ab5fSopenharmony_ci ReplaceScope(child, oldNode, newScope); 19973af6ab5fSopenharmony_ci } 19983af6ab5fSopenharmony_ci }); 19993af6ab5fSopenharmony_ci} 20003af6ab5fSopenharmony_ci 20013af6ab5fSopenharmony_civoid ETSChecker::MoveTrailingBlockToEnclosingBlockStatement(ir::CallExpression *callExpr) 20023af6ab5fSopenharmony_ci{ 20033af6ab5fSopenharmony_ci if (callExpr == nullptr) { 20043af6ab5fSopenharmony_ci return; 20053af6ab5fSopenharmony_ci } 20063af6ab5fSopenharmony_ci 20073af6ab5fSopenharmony_ci ir::AstNode *parent = callExpr->Parent(); 20083af6ab5fSopenharmony_ci ir::AstNode *current = callExpr; 20093af6ab5fSopenharmony_ci while (parent != nullptr) { 20103af6ab5fSopenharmony_ci if (!parent->IsBlockStatement()) { 20113af6ab5fSopenharmony_ci current = parent; 20123af6ab5fSopenharmony_ci parent = parent->Parent(); 20133af6ab5fSopenharmony_ci } else { 20143af6ab5fSopenharmony_ci // Collect trailing block, insert it only when block statements traversal ends to avoid order mismatch. 20153af6ab5fSopenharmony_ci parent->AsBlockStatement()->AddTrailingBlock(current, callExpr->TrailingBlock()); 20163af6ab5fSopenharmony_ci callExpr->TrailingBlock()->SetParent(parent); 20173af6ab5fSopenharmony_ci callExpr->SetTrailingBlock(nullptr); 20183af6ab5fSopenharmony_ci break; 20193af6ab5fSopenharmony_ci } 20203af6ab5fSopenharmony_ci } 20213af6ab5fSopenharmony_ci} 20223af6ab5fSopenharmony_ci 20233af6ab5fSopenharmony_civoid ETSChecker::TransformTraillingLambda(ir::CallExpression *callExpr) 20243af6ab5fSopenharmony_ci{ 20253af6ab5fSopenharmony_ci auto *trailingBlock = callExpr->TrailingBlock(); 20263af6ab5fSopenharmony_ci ASSERT(trailingBlock != nullptr); 20273af6ab5fSopenharmony_ci 20283af6ab5fSopenharmony_ci auto *funcParamScope = varbinder::LexicalScope<varbinder::FunctionParamScope>(VarBinder()).GetScope(); 20293af6ab5fSopenharmony_ci auto paramCtx = varbinder::LexicalScope<varbinder::FunctionParamScope>::Enter(VarBinder(), funcParamScope, false); 20303af6ab5fSopenharmony_ci 20313af6ab5fSopenharmony_ci auto funcCtx = varbinder::LexicalScope<varbinder::FunctionScope>(VarBinder()); 20323af6ab5fSopenharmony_ci auto *funcScope = funcCtx.GetScope(); 20333af6ab5fSopenharmony_ci funcScope->BindParamScope(funcParamScope); 20343af6ab5fSopenharmony_ci funcParamScope->BindFunctionScope(funcScope); 20353af6ab5fSopenharmony_ci funcParamScope->SetParent(trailingBlock->Scope()->Parent()); 20363af6ab5fSopenharmony_ci 20373af6ab5fSopenharmony_ci for (auto [_, var] : trailingBlock->Scope()->Bindings()) { 20383af6ab5fSopenharmony_ci (void)_; 20393af6ab5fSopenharmony_ci if (var->GetScope() == trailingBlock->Scope()) { 20403af6ab5fSopenharmony_ci var->SetScope(funcScope); 20413af6ab5fSopenharmony_ci funcScope->InsertBinding(var->Name(), var); 20423af6ab5fSopenharmony_ci } 20433af6ab5fSopenharmony_ci } 20443af6ab5fSopenharmony_ci 20453af6ab5fSopenharmony_ci ArenaVector<ir::Expression *> params(Allocator()->Adapter()); 20463af6ab5fSopenharmony_ci auto *funcNode = AllocNode<ir::ScriptFunction>( 20473af6ab5fSopenharmony_ci Allocator(), ir::ScriptFunction::ScriptFunctionData {trailingBlock, 20483af6ab5fSopenharmony_ci ir::FunctionSignature(nullptr, std::move(params), nullptr), 20493af6ab5fSopenharmony_ci ir::ScriptFunctionFlags::ARROW}); 20503af6ab5fSopenharmony_ci funcNode->SetScope(funcScope); 20513af6ab5fSopenharmony_ci funcScope->BindNode(funcNode); 20523af6ab5fSopenharmony_ci funcParamScope->BindNode(funcNode); 20533af6ab5fSopenharmony_ci 20543af6ab5fSopenharmony_ci trailingBlock->SetScope(funcScope); 20553af6ab5fSopenharmony_ci ReplaceScope(funcNode->Body(), trailingBlock, funcScope); 20563af6ab5fSopenharmony_ci callExpr->SetTrailingBlock(nullptr); 20573af6ab5fSopenharmony_ci 20583af6ab5fSopenharmony_ci // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 20593af6ab5fSopenharmony_ci auto *arrowFuncNode = AllocNode<ir::ArrowFunctionExpression>(funcNode); 20603af6ab5fSopenharmony_ci arrowFuncNode->SetRange(trailingBlock->Range()); 20613af6ab5fSopenharmony_ci arrowFuncNode->SetParent(callExpr); 20623af6ab5fSopenharmony_ci 20633af6ab5fSopenharmony_ci callExpr->Arguments().push_back(arrowFuncNode); 20643af6ab5fSopenharmony_ci} 20653af6ab5fSopenharmony_ci 20663af6ab5fSopenharmony_ciArenaVector<ir::Expression *> ETSChecker::ExtendArgumentsWithFakeLamda(ir::CallExpression *callExpr) 20673af6ab5fSopenharmony_ci{ 20683af6ab5fSopenharmony_ci auto funcCtx = varbinder::LexicalScope<varbinder::FunctionScope>(VarBinder()); 20693af6ab5fSopenharmony_ci auto *funcScope = funcCtx.GetScope(); 20703af6ab5fSopenharmony_ci ArenaVector<ir::Expression *> params(Allocator()->Adapter()); 20713af6ab5fSopenharmony_ci 20723af6ab5fSopenharmony_ci ArenaVector<ir::Statement *> statements(Allocator()->Adapter()); 20733af6ab5fSopenharmony_ci // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 20743af6ab5fSopenharmony_ci auto *body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements)); 20753af6ab5fSopenharmony_ci body->SetScope(funcScope); 20763af6ab5fSopenharmony_ci 20773af6ab5fSopenharmony_ci auto *funcNode = AllocNode<ir::ScriptFunction>( 20783af6ab5fSopenharmony_ci Allocator(), 20793af6ab5fSopenharmony_ci ir::ScriptFunction::ScriptFunctionData {body, ir::FunctionSignature(nullptr, std::move(params), nullptr), 20803af6ab5fSopenharmony_ci ir::ScriptFunctionFlags::ARROW}); 20813af6ab5fSopenharmony_ci funcNode->SetScope(funcScope); 20823af6ab5fSopenharmony_ci funcScope->BindNode(funcNode); 20833af6ab5fSopenharmony_ci auto *arrowFuncNode = AllocNode<ir::ArrowFunctionExpression>(funcNode); 20843af6ab5fSopenharmony_ci arrowFuncNode->SetParent(callExpr); 20853af6ab5fSopenharmony_ci 20863af6ab5fSopenharmony_ci ArenaVector<ir::Expression *> fakeArguments = callExpr->Arguments(); 20873af6ab5fSopenharmony_ci fakeArguments.push_back(arrowFuncNode); 20883af6ab5fSopenharmony_ci return fakeArguments; 20893af6ab5fSopenharmony_ci} 20903af6ab5fSopenharmony_ci 20913af6ab5fSopenharmony_civoid ETSChecker::EnsureValidCurlyBrace(ir::CallExpression *callExpr) 20923af6ab5fSopenharmony_ci{ 20933af6ab5fSopenharmony_ci if (callExpr->TrailingBlock() == nullptr) { 20943af6ab5fSopenharmony_ci return; 20953af6ab5fSopenharmony_ci } 20963af6ab5fSopenharmony_ci 20973af6ab5fSopenharmony_ci if (callExpr->IsTrailingBlockInNewLine()) { 20983af6ab5fSopenharmony_ci MoveTrailingBlockToEnclosingBlockStatement(callExpr); 20993af6ab5fSopenharmony_ci return; 21003af6ab5fSopenharmony_ci } 21013af6ab5fSopenharmony_ci 21023af6ab5fSopenharmony_ci LogTypeError({"No matching call signature with trailing lambda"}, callExpr->Start()); 21033af6ab5fSopenharmony_ci} 21043af6ab5fSopenharmony_ci 21053af6ab5fSopenharmony_ciETSObjectType *ETSChecker::GetCachedFunctionalInterface(ir::ETSFunctionType *type) 21063af6ab5fSopenharmony_ci{ 21073af6ab5fSopenharmony_ci auto hash = GetHashFromFunctionType(type); 21083af6ab5fSopenharmony_ci auto it = functionalInterfaceCache_.find(hash); 21093af6ab5fSopenharmony_ci if (it == functionalInterfaceCache_.cend()) { 21103af6ab5fSopenharmony_ci return nullptr; 21113af6ab5fSopenharmony_ci } 21123af6ab5fSopenharmony_ci return it->second; 21133af6ab5fSopenharmony_ci} 21143af6ab5fSopenharmony_ci 21153af6ab5fSopenharmony_civoid ETSChecker::CacheFunctionalInterface(ir::ETSFunctionType *type, ETSObjectType *ifaceType) 21163af6ab5fSopenharmony_ci{ 21173af6ab5fSopenharmony_ci auto hash = GetHashFromFunctionType(type); 21183af6ab5fSopenharmony_ci ASSERT(functionalInterfaceCache_.find(hash) == functionalInterfaceCache_.cend()); 21193af6ab5fSopenharmony_ci functionalInterfaceCache_.emplace(hash, ifaceType); 21203af6ab5fSopenharmony_ci} 21213af6ab5fSopenharmony_ci 21223af6ab5fSopenharmony_civoid ETSChecker::CollectReturnStatements(ir::AstNode *parent) 21233af6ab5fSopenharmony_ci{ 21243af6ab5fSopenharmony_ci parent->Iterate([this](ir::AstNode *childNode) -> void { 21253af6ab5fSopenharmony_ci if (childNode->IsScriptFunction()) { 21263af6ab5fSopenharmony_ci return; 21273af6ab5fSopenharmony_ci } 21283af6ab5fSopenharmony_ci 21293af6ab5fSopenharmony_ci if (childNode->IsReturnStatement()) { 21303af6ab5fSopenharmony_ci ir::ReturnStatement *returnStmt = childNode->AsReturnStatement(); 21313af6ab5fSopenharmony_ci returnStmt->Check(this); 21323af6ab5fSopenharmony_ci } 21333af6ab5fSopenharmony_ci 21343af6ab5fSopenharmony_ci CollectReturnStatements(childNode); 21353af6ab5fSopenharmony_ci }); 21363af6ab5fSopenharmony_ci} 21373af6ab5fSopenharmony_ci 21383af6ab5fSopenharmony_ciArenaVector<ConstraintCheckRecord> &ETSChecker::PendingConstraintCheckRecords() 21393af6ab5fSopenharmony_ci{ 21403af6ab5fSopenharmony_ci return pendingConstraintCheckRecords_; 21413af6ab5fSopenharmony_ci} 21423af6ab5fSopenharmony_ci 21433af6ab5fSopenharmony_cisize_t &ETSChecker::ConstraintCheckScopesCount() 21443af6ab5fSopenharmony_ci{ 21453af6ab5fSopenharmony_ci return constraintCheckScopesCount_; 21463af6ab5fSopenharmony_ci} 21473af6ab5fSopenharmony_ci 21483af6ab5fSopenharmony_cibool ETSChecker::CmpAssemblerTypesWithRank(Signature const *const sig1, Signature const *const sig2) noexcept 21493af6ab5fSopenharmony_ci{ 21503af6ab5fSopenharmony_ci for (size_t ix = 0; ix < sig1->MinArgCount(); ix++) { 21513af6ab5fSopenharmony_ci std::stringstream s1; 21523af6ab5fSopenharmony_ci std::stringstream s2; 21533af6ab5fSopenharmony_ci sig1->Params()[ix]->TsType()->ToAssemblerTypeWithRank(s1); 21543af6ab5fSopenharmony_ci sig2->Params()[ix]->TsType()->ToAssemblerTypeWithRank(s2); 21553af6ab5fSopenharmony_ci if (s1.str() != s2.str()) { 21563af6ab5fSopenharmony_ci return false; 21573af6ab5fSopenharmony_ci break; 21583af6ab5fSopenharmony_ci } 21593af6ab5fSopenharmony_ci } 21603af6ab5fSopenharmony_ci return true; 21613af6ab5fSopenharmony_ci} 21623af6ab5fSopenharmony_ci 21633af6ab5fSopenharmony_cibool ETSChecker::HasSameAssemblySignature(Signature const *const sig1, Signature const *const sig2) noexcept 21643af6ab5fSopenharmony_ci{ 21653af6ab5fSopenharmony_ci if (sig1->MinArgCount() != sig2->MinArgCount()) { 21663af6ab5fSopenharmony_ci return false; 21673af6ab5fSopenharmony_ci } 21683af6ab5fSopenharmony_ci 21693af6ab5fSopenharmony_ci if (!CmpAssemblerTypesWithRank(sig1, sig2)) { 21703af6ab5fSopenharmony_ci return false; 21713af6ab5fSopenharmony_ci } 21723af6ab5fSopenharmony_ci auto *rv1 = sig1->RestVar(); 21733af6ab5fSopenharmony_ci auto *rv2 = sig2->RestVar(); 21743af6ab5fSopenharmony_ci if (rv1 == nullptr && rv2 == nullptr) { 21753af6ab5fSopenharmony_ci return true; 21763af6ab5fSopenharmony_ci } 21773af6ab5fSopenharmony_ci if (rv1 == nullptr || rv2 == nullptr) { // exactly one of them is null 21783af6ab5fSopenharmony_ci return false; 21793af6ab5fSopenharmony_ci } 21803af6ab5fSopenharmony_ci std::stringstream s1; 21813af6ab5fSopenharmony_ci std::stringstream s2; 21823af6ab5fSopenharmony_ci rv1->TsType()->ToAssemblerTypeWithRank(s1); 21833af6ab5fSopenharmony_ci rv2->TsType()->ToAssemblerTypeWithRank(s2); 21843af6ab5fSopenharmony_ci return s1.str() == s2.str(); 21853af6ab5fSopenharmony_ci} 21863af6ab5fSopenharmony_ci 21873af6ab5fSopenharmony_cibool ETSChecker::HasSameAssemblySignatures(ETSFunctionType const *const func1, 21883af6ab5fSopenharmony_ci ETSFunctionType const *const func2) noexcept 21893af6ab5fSopenharmony_ci{ 21903af6ab5fSopenharmony_ci for (auto const *sig1 : func1->CallSignatures()) { 21913af6ab5fSopenharmony_ci for (auto const *sig2 : func2->CallSignatures()) { 21923af6ab5fSopenharmony_ci if (HasSameAssemblySignature(sig1, sig2)) { 21933af6ab5fSopenharmony_ci return true; 21943af6ab5fSopenharmony_ci } 21953af6ab5fSopenharmony_ci } 21963af6ab5fSopenharmony_ci } 21973af6ab5fSopenharmony_ci return false; 21983af6ab5fSopenharmony_ci} 21993af6ab5fSopenharmony_ci} // namespace ark::es2panda::checker 2200