1/** 2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "utils/logger.h" 17#include "varbinder/ETSBinder.h" 18#include "checker/ETSchecker.h" 19#include "checker/ets/castingContext.h" 20#include "checker/ets/function_helpers.h" 21#include "checker/ets/typeRelationContext.h" 22#include "checker/types/ets/etsAsyncFuncReturnType.h" 23#include "checker/types/ets/etsObjectType.h" 24#include "ir/base/catchClause.h" 25#include "ir/base/classDefinition.h" 26#include "ir/base/classProperty.h" 27#include "ir/base/methodDefinition.h" 28#include "ir/base/scriptFunction.h" 29#include "ir/base/spreadElement.h" 30#include "ir/ets/etsFunctionType.h" 31#include "ir/ets/etsParameterExpression.h" 32#include "ir/ets/etsTypeReference.h" 33#include "ir/ets/etsTypeReferencePart.h" 34#include "ir/ets/etsUnionType.h" 35#include "ir/expressions/arrowFunctionExpression.h" 36#include "ir/expressions/assignmentExpression.h" 37#include "ir/expressions/callExpression.h" 38#include "ir/expressions/functionExpression.h" 39#include "ir/expressions/identifier.h" 40#include "ir/expressions/literals/numberLiteral.h" 41#include "ir/expressions/literals/undefinedLiteral.h" 42#include "ir/expressions/memberExpression.h" 43#include "ir/expressions/objectExpression.h" 44#include "ir/expressions/thisExpression.h" 45#include "ir/statements/blockStatement.h" 46#include "ir/statements/doWhileStatement.h" 47#include "ir/statements/expressionStatement.h" 48#include "ir/statements/forInStatement.h" 49#include "ir/statements/forOfStatement.h" 50#include "ir/statements/forUpdateStatement.h" 51#include "ir/statements/returnStatement.h" 52#include "ir/statements/switchStatement.h" 53#include "ir/statements/whileStatement.h" 54#include "ir/ts/tsTypeAliasDeclaration.h" 55#include "ir/ts/tsTypeParameter.h" 56#include "ir/ts/tsTypeParameterInstantiation.h" 57#include "parser/program/program.h" 58#include "util/helpers.h" 59#include "util/language.h" 60 61namespace ark::es2panda::checker { 62 63// NOTE: #14993 merge with InstantiationContext::ValidateTypeArg 64bool ETSChecker::IsCompatibleTypeArgument(ETSTypeParameter *typeParam, Type *typeArgument, 65 const Substitution *substitution) 66{ 67 if (typeArgument->IsWildcardType()) { 68 return true; 69 } 70 ASSERT(IsReferenceType(typeArgument) || typeArgument->IsETSVoidType()); 71 auto *constraint = typeParam->GetConstraintType()->Substitute(Relation(), substitution); 72 bool retVal = false; 73 if (typeArgument->IsETSVoidType()) { 74 retVal = Relation()->IsSupertypeOf(constraint, GlobalETSUndefinedType()); 75 } else if (typeArgument->IsETSFunctionType()) { 76 retVal = Relation()->IsSupertypeOf( 77 constraint, 78 this->FunctionTypeToFunctionalInterfaceType(typeArgument->AsETSFunctionType()->CallSignatures().front())); 79 } else { 80 retVal = Relation()->IsSupertypeOf(constraint, typeArgument); 81 } 82 83 return retVal; 84} 85 86bool ETSChecker::HasTypeArgsOfObject(Type *argType, Type *paramType) 87{ 88 return paramType->IsETSObjectType() && argType->IsETSObjectType() && 89 !argType->AsETSObjectType()->TypeArguments().empty() && 90 !paramType->AsETSObjectType()->TypeArguments().empty(); 91} 92 93bool ETSChecker::InsertTypeIntoSubstitution(const ArenaVector<Type *> &typeParams, const Type *typeParam, 94 const size_t index, Substitution *substitution, Type *objectParam) 95{ 96 // Check if the type parameter is in the signature, and the type argument is not already in the return vector 97 if (typeParams.size() > index && 98 IsCompatibleTypeArgument(typeParams[index]->AsETSTypeParameter(), objectParam, substitution) && 99 std::find(typeParams.begin(), typeParams.end(), typeParam) != typeParams.end()) { 100 substitution->emplace(typeParams[index]->AsETSTypeParameter(), objectParam); 101 return true; 102 } 103 104 return false; 105} 106 107bool ETSChecker::EnhanceSubstitutionForGenericType(const ArenaVector<Type *> &typeParams, const Type *argType, 108 const Type *paramType, Substitution *substitution) 109{ 110 ArenaVector<Type *> objectParams(Allocator()->Adapter()); 111 112 if (!argType->AsETSObjectType()->GetDeclNode()->IsClassDefinition()) { 113 return false; 114 } 115 116 const auto paramTypeArgs = paramType->AsETSObjectType()->TypeArguments(); 117 118 for (const auto it : typeParams) { 119 bool found = false; 120 121 for (size_t i = 0; i < paramTypeArgs.size() && !found; i++) { 122 if (paramTypeArgs[i] == it) { 123 objectParams.push_back(argType->AsETSObjectType()->TypeArguments()[i]); 124 found = true; 125 } 126 } 127 128 if (!found) { 129 objectParams.push_back(nullptr); 130 } 131 } 132 133 if (objectParams.size() < paramTypeArgs.size()) { 134 return false; 135 } 136 137 bool res = true; 138 for (size_t j = 0; j < paramTypeArgs.size() && res; ++j) { 139 if (objectParams[j] != nullptr) { 140 res = InsertTypeIntoSubstitution(typeParams, paramTypeArgs[j], j, substitution, objectParams[j]); 141 } else { 142 res = EnhanceSubstitutionForType(typeParams, paramTypeArgs[j], 143 argType->AsETSObjectType()->TypeArguments()[j], substitution); 144 } 145 } 146 147 return res; 148} 149 150bool ETSChecker::EnhanceSubstitutionForReadonly(const ArenaVector<Type *> &typeParams, ETSReadonlyType *paramType, 151 Type *argumentType, Substitution *substitution) 152{ 153 return EnhanceSubstitutionForType(typeParams, paramType->GetUnderlying(), GetReadonlyType(argumentType), 154 substitution); 155} 156 157/* A very rough and imprecise partial type inference */ 158bool ETSChecker::EnhanceSubstitutionForType(const ArenaVector<Type *> &typeParams, Type *paramType, Type *argumentType, 159 Substitution *substitution) 160{ 161 if (argumentType->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) { 162 argumentType = PrimitiveTypeAsETSBuiltinType(argumentType); 163 } 164 if (paramType->IsETSTypeParameter()) { 165 auto *const tparam = paramType->AsETSTypeParameter(); 166 auto *const originalTparam = tparam->GetOriginal(); 167 if (std::find(typeParams.begin(), typeParams.end(), originalTparam) != typeParams.end() && 168 substitution->count(originalTparam) == 0) { 169 if (!IsReferenceType(argumentType)) { 170 LogTypeError({argumentType, " is not compatible with type ", tparam}, tparam->GetDeclNode()->Start()); 171 return false; 172 } 173 174 ETSChecker::EmplaceSubstituted(substitution, originalTparam, argumentType); 175 return IsCompatibleTypeArgument(tparam, argumentType, substitution); 176 } 177 } 178 179 if (paramType->IsETSReadonlyType()) { 180 return EnhanceSubstitutionForReadonly(typeParams, paramType->AsETSReadonlyType(), argumentType, substitution); 181 } 182 if (paramType->IsETSUnionType()) { 183 return EnhanceSubstitutionForUnion(typeParams, paramType->AsETSUnionType(), argumentType, substitution); 184 } 185 if (paramType->IsETSObjectType()) { 186 if (HasTypeArgsOfObject(argumentType, paramType) && 187 EnhanceSubstitutionForGenericType(typeParams, argumentType, paramType, substitution)) { 188 return true; 189 } 190 return EnhanceSubstitutionForObject(typeParams, paramType->AsETSObjectType(), argumentType, substitution); 191 } 192 if (paramType->IsETSArrayType()) { 193 return EnhanceSubstitutionForArray(typeParams, paramType->AsETSArrayType(), argumentType, substitution); 194 } 195 196 return true; 197} 198 199bool ETSChecker::EnhanceSubstitutionForUnion(const ArenaVector<Type *> &typeParams, ETSUnionType *paramUn, 200 Type *argumentType, Substitution *substitution) 201{ 202 if (!argumentType->IsETSUnionType()) { 203 return std::any_of( 204 paramUn->ConstituentTypes().begin(), paramUn->ConstituentTypes().end(), 205 [this, typeParams, argumentType, substitution](Type *ctype) { 206 return EnhanceSubstitutionForType(typeParams, ctype, argumentType, substitution) && 207 (!ctype->IsETSTypeParameter() || 208 (substitution->find(ctype->AsETSTypeParameter()) != substitution->end() && 209 Relation()->IsAssignableTo(argumentType, substitution->at(ctype->AsETSTypeParameter())))); 210 }); 211 } 212 auto *const argUn = argumentType->AsETSUnionType(); 213 214 ArenaVector<Type *> paramWlist(Allocator()->Adapter()); 215 ArenaVector<Type *> argWlist(Allocator()->Adapter()); 216 217 for (auto *pc : paramUn->ConstituentTypes()) { 218 for (auto *ac : argUn->ConstituentTypes()) { 219 if (ETSChecker::GetOriginalBaseType(pc) != ETSChecker::GetOriginalBaseType(ac)) { 220 paramWlist.push_back(pc); 221 argWlist.push_back(ac); 222 continue; 223 } 224 if (!EnhanceSubstitutionForType(typeParams, pc, ac, substitution)) { 225 return false; 226 } 227 } 228 } 229 auto *const newArg = CreateETSUnionType(std::move(argWlist)); 230 231 for (auto *pc : paramWlist) { 232 if (!EnhanceSubstitutionForType(typeParams, pc, newArg, substitution)) { 233 return false; 234 } 235 } 236 return true; 237} 238 239bool ETSChecker::EnhanceSubstitutionForObject(const ArenaVector<Type *> &typeParams, ETSObjectType *paramType, 240 Type *argumentType, Substitution *substitution) 241{ 242 auto *paramObjType = paramType->AsETSObjectType(); 243 244 auto const enhance = [this, typeParams, substitution](Type *ptype, Type *atype) { 245 return EnhanceSubstitutionForType(typeParams, ptype, atype, substitution); 246 }; 247 248 if (argumentType->IsETSObjectType()) { 249 auto *argObjType = argumentType->AsETSObjectType(); 250 if (GetOriginalBaseType(argObjType) != GetOriginalBaseType(paramObjType)) { 251 return true; // don't attempt anything fancy for now 252 } 253 bool res = true; 254 for (size_t i = 0; i < argObjType->TypeArguments().size(); i++) { 255 res &= enhance(paramObjType->TypeArguments()[i], argObjType->TypeArguments()[i]); 256 } 257 return res; 258 } 259 260 if (argumentType->IsETSFunctionType() && paramObjType->HasObjectFlag(ETSObjectFlags::FUNCTIONAL_INTERFACE)) { 261 auto ¶meterSignatures = 262 paramObjType 263 ->GetOwnProperty<checker::PropertyType::INSTANCE_METHOD>(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME) 264 ->TsType() 265 ->AsETSFunctionType() 266 ->CallSignatures(); 267 auto &argumentSignatures = argumentType->AsETSFunctionType()->CallSignatures(); 268 ASSERT(argumentSignatures.size() == 1); 269 ASSERT(parameterSignatures.size() == 1); 270 auto *argumentSignature = argumentSignatures[0]; 271 auto *parameterSignature = parameterSignatures[0]; 272 // NOTE(gogabr): handle rest parameter for argumentSignature 273 if (parameterSignature->GetSignatureInfo()->params.size() != 274 argumentSignature->GetSignatureInfo()->params.size()) { 275 return false; 276 } 277 bool res = true; 278 for (size_t idx = 0; idx < argumentSignature->GetSignatureInfo()->params.size(); idx++) { 279 res &= enhance(parameterSignature->GetSignatureInfo()->params[idx]->TsType(), 280 argumentSignature->GetSignatureInfo()->params[idx]->TsType()); 281 } 282 res &= enhance(parameterSignature->ReturnType(), argumentSignature->ReturnType()); 283 return res; 284 } 285 286 return true; 287} 288 289bool ETSChecker::EnhanceSubstitutionForArray(const ArenaVector<Type *> &typeParams, ETSArrayType *const paramType, 290 Type *const argumentType, Substitution *const substitution) 291{ 292 auto *const elementType = 293 argumentType->IsETSArrayType() ? argumentType->AsETSArrayType()->ElementType() : argumentType; 294 295 return EnhanceSubstitutionForType(typeParams, paramType->ElementType(), elementType, substitution); 296} 297 298Signature *ETSChecker::ValidateParameterlessConstructor(Signature *signature, const lexer::SourcePosition &pos, 299 TypeRelationFlag flags) 300{ 301 std::size_t const parameterCount = signature->MinArgCount(); 302 auto const reportError = (flags & TypeRelationFlag::NO_THROW) == 0; 303 304 if (parameterCount != 0) { 305 if (reportError) { 306 LogTypeError({"No Matching Parameterless Constructor, parameter count ", parameterCount}, pos); 307 } 308 return nullptr; 309 } 310 return signature; 311} 312 313bool ETSChecker::CheckOptionalLambdaFunction(ir::Expression *argument, Signature *substitutedSig, std::size_t index) 314{ 315 if (argument->IsArrowFunctionExpression()) { 316 auto *const arrowFuncExpr = argument->AsArrowFunctionExpression(); 317 318 if (ir::ScriptFunction *const lambda = arrowFuncExpr->Function(); 319 CheckLambdaAssignable(substitutedSig->Function()->Params()[index], lambda)) { 320 if (arrowFuncExpr->TsTypeOrError() != nullptr) { 321 arrowFuncExpr->Check(this); 322 return true; 323 } 324 } 325 } 326 327 return false; 328} 329 330bool ETSChecker::ValidateArgumentAsIdentifier(const ir::Identifier *identifier) 331{ 332 auto result = Scope()->Find(identifier->Name()); 333 return result.variable != nullptr && (result.variable->HasFlag(varbinder::VariableFlags::CLASS_OR_INTERFACE)); 334} 335 336bool ETSChecker::ValidateSignatureRequiredParams(Signature *substitutedSig, 337 const ArenaVector<ir::Expression *> &arguments, TypeRelationFlag flags, 338 const std::vector<bool> &argTypeInferenceRequired, bool reportError) 339{ 340 std::size_t const argumentCount = arguments.size(); 341 std::size_t const parameterCount = substitutedSig->MinArgCount(); 342 auto count = std::min(parameterCount, argumentCount); 343 for (std::size_t index = 0; index < count; ++index) { 344 auto &argument = arguments[index]; 345 346 if (argument->IsObjectExpression()) { 347 if (substitutedSig->Params()[index]->TsType()->IsETSObjectType()) { 348 // No chance to check the argument at this point 349 continue; 350 } 351 return false; 352 } 353 354 if (argument->IsMemberExpression()) { 355 SetArrayPreferredTypeForNestedMemberExpressions(arguments[index]->AsMemberExpression(), 356 substitutedSig->Params()[index]->TsType()); 357 } else if (argument->IsSpreadElement()) { 358 if (reportError) { 359 LogTypeError("Spread argument cannot be passed for ordinary parameter.", argument->Start()); 360 } 361 return false; 362 } 363 364 if (argTypeInferenceRequired[index]) { 365 ASSERT(argument->IsArrowFunctionExpression()); 366 auto *const arrowFuncExpr = argument->AsArrowFunctionExpression(); 367 ir::ScriptFunction *const lambda = arrowFuncExpr->Function(); 368 if (CheckLambdaAssignable(substitutedSig->Function()->Params()[index], lambda)) { 369 continue; 370 } 371 return false; 372 } 373 374 if (argument->IsArrayExpression()) { 375 argument->AsArrayExpression()->GetPrefferedTypeFromFuncParam( 376 this, substitutedSig->Function()->Params()[index], flags); 377 } 378 379 if (!CheckInvokable(substitutedSig, argument, index, flags)) { 380 return false; 381 } 382 383 if (argument->IsIdentifier() && ValidateArgumentAsIdentifier(argument->AsIdentifier())) { 384 LogTypeError("Class name can't be the argument of function or method.", argument->Start()); 385 return false; 386 } 387 388 // clang-format off 389 if (!ValidateSignatureInvocationContext( 390 substitutedSig, argument, 391 TryGettingFunctionTypeFromInvokeFunction(substitutedSig->Params()[index]->TsType()), index, flags)) { 392 // clang-format on 393 return false; 394 } 395 } 396 397 return true; 398} 399 400bool ETSChecker::CheckInvokable(Signature *substitutedSig, ir::Expression *argument, std::size_t index, 401 TypeRelationFlag flags) 402{ 403 auto *argumentType = argument->Check(this); 404 auto *targetType = substitutedSig->Params()[index]->TsType(); 405 406 auto const invocationCtx = 407 checker::InvocationContext(Relation(), argument, argumentType, targetType, argument->Start(), 408 {"Type '", argumentType, "' is not compatible with type '", 409 TryGettingFunctionTypeFromInvokeFunction(targetType), "' at index ", index + 1}, 410 flags); 411 return invocationCtx.IsInvocable() || CheckOptionalLambdaFunction(argument, substitutedSig, index); 412} 413 414bool ETSChecker::ValidateSignatureInvocationContext(Signature *substitutedSig, ir::Expression *argument, 415 const Type *targetType, std::size_t index, TypeRelationFlag flags) 416{ 417 Type *argumentType = argument->Check(this); 418 auto const invocationCtx = checker::InvocationContext( 419 Relation(), argument, argumentType, substitutedSig->Params()[index]->TsType(), argument->Start(), 420 {"Type '", argumentType, "' is not compatible with type '", targetType, "' at index ", index + 1}, flags); 421 if (!invocationCtx.IsInvocable()) { 422 return CheckOptionalLambdaFunction(argument, substitutedSig, index); 423 } 424 425 return true; 426} 427 428bool ETSChecker::ValidateSignatureRestParams(Signature *substitutedSig, const ArenaVector<ir::Expression *> &arguments, 429 TypeRelationFlag flags, bool reportError) 430{ 431 std::size_t const argumentCount = arguments.size(); 432 std::size_t const parameterCount = substitutedSig->MinArgCount(); 433 auto count = std::min(parameterCount, argumentCount); 434 auto const restCount = argumentCount - count; 435 436 for (std::size_t index = count; index < argumentCount; ++index) { 437 auto &argument = arguments[index]; 438 439 if (!argument->IsSpreadElement()) { 440 auto *const argumentType = argument->Check(this); 441 const Type *targetType = TryGettingFunctionTypeFromInvokeFunction( 442 substitutedSig->RestVar()->TsType()->AsETSArrayType()->ElementType()); 443 const Type *sourceType = TryGettingFunctionTypeFromInvokeFunction(argumentType); 444 auto const invocationCtx = checker::InvocationContext( 445 Relation(), argument, argumentType, 446 substitutedSig->RestVar()->TsType()->AsETSArrayType()->ElementType(), argument->Start(), 447 {"Type '", sourceType, "' is not compatible with rest parameter type '", targetType, "' at index ", 448 index + 1}, 449 flags); 450 if (!invocationCtx.IsInvocable()) { 451 return false; 452 } 453 continue; 454 } 455 456 if (restCount > 1U) { 457 if (reportError) { 458 LogTypeError("Spread argument for the rest parameter can be only one.", argument->Start()); 459 } 460 return false; 461 } 462 463 auto *const restArgument = argument->AsSpreadElement()->Argument(); 464 auto *const argumentType = restArgument->Check(this); 465 const Type *targetType = TryGettingFunctionTypeFromInvokeFunction(substitutedSig->RestVar()->TsType()); 466 const Type *sourceType = TryGettingFunctionTypeFromInvokeFunction(argumentType); 467 468 auto const invocationCtx = checker::InvocationContext( 469 Relation(), restArgument, argumentType, substitutedSig->RestVar()->TsType(), argument->Start(), 470 {"Type '", sourceType, "' is not compatible with rest parameter type '", targetType, "' at index ", 471 index + 1}, 472 flags); 473 if (!invocationCtx.IsInvocable()) { 474 return false; 475 } 476 } 477 478 return true; 479} 480 481void ETSChecker::MaybeSubstituteLambdaArgumentsInFunctionCall(ir::CallExpression *callExpr) 482{ 483 ir::AstNode *expr = callExpr; 484 485 while (!expr->IsFunctionExpression()) { 486 if (expr->Parent() == nullptr || expr->Parent()->IsClassDefinition()) { 487 return; 488 } 489 expr = expr->Parent(); 490 } 491 492 for (const auto it : expr->AsFunctionExpression()->Function()->Params()) { 493 if (const auto ident = it->AsETSParameterExpression()->Ident(); 494 callExpr->Callee()->IsIdentifier() && ident->Name() == callExpr->Callee()->AsIdentifier()->Name() && 495 ident->IsAnnotatedExpression()) { 496 if (ident->AsAnnotatedExpression()->TypeAnnotation()->IsETSFunctionType()) { 497 MaybeSubstituteLambdaArguments( 498 ident->AsAnnotatedExpression()->TypeAnnotation()->AsETSFunctionType()->Params(), callExpr); 499 } 500 } 501 } 502} 503 504void ETSChecker::MaybeSubstituteLambdaArgumentsInFunctionCallHelper(ir::CallExpression *callExpr, ir::Identifier *ident) 505{ 506 ir::ETSFunctionType *funcType = nullptr; 507 ir::TypeNode *typeAnnotation = ident->TypeAnnotation(); 508 509 if (typeAnnotation->IsETSTypeReference()) { 510 auto typeAnnotationIdentifier = ident->TypeAnnotation()->AsETSTypeReference()->Part()->Name()->Variable(); 511 typeAnnotation = typeAnnotationIdentifier->Declaration()->Node()->AsTSTypeAliasDeclaration()->TypeAnnotation(); 512 } 513 514 if (typeAnnotation->IsETSFunctionType()) { 515 funcType = typeAnnotation->AsETSFunctionType(); 516 } else if (typeAnnotation->IsETSUnionType()) { 517 auto found = std::find_if(typeAnnotation->AsETSUnionType()->Types().begin(), 518 typeAnnotation->AsETSUnionType()->Types().end(), 519 [](ir::TypeNode *const type) { return type->IsETSFunctionType(); }); 520 if (found != typeAnnotation->AsETSUnionType()->Types().end()) { 521 funcType = (*found)->AsETSFunctionType(); 522 } 523 } 524 525 if (funcType == nullptr) { 526 return; 527 } 528 529 MaybeSubstituteLambdaArguments(funcType->AsETSFunctionType()->Params(), callExpr); 530} 531 532void ETSChecker::MaybeSubstituteLambdaArguments(const ArenaVector<ir::Expression *> ¶ms, 533 ir::CallExpression *callExpr) 534{ 535 for (size_t i = 0; i < params.size(); i++) { 536 if (params[i]->AsETSParameterExpression()->IsDefault() && callExpr->Arguments().size() <= i && 537 params[i]->AsETSParameterExpression()->Initializer() != nullptr) { 538 callExpr->Arguments().push_back( 539 params[i]->AsETSParameterExpression()->Initializer()->Clone(Allocator(), callExpr)->AsExpression()); 540 } 541 } 542} 543 544Signature *ETSChecker::ValidateSignature( 545 std::tuple<Signature *, const ir::TSTypeParameterInstantiation *, TypeRelationFlag> info, 546 const ArenaVector<ir::Expression *> &arguments, const lexer::SourcePosition &pos, 547 const std::vector<bool> &argTypeInferenceRequired) 548{ 549 auto [signature, typeArguments, flags] = info; 550 Signature *substitutedSig = MaybeSubstituteTypeParameters(this, signature, typeArguments, arguments, pos, flags); 551 if (substitutedSig == nullptr) { 552 return nullptr; 553 } 554 555 fflush(stdout); 556 557 auto const hasRestParameter = substitutedSig->RestVar() != nullptr; 558 std::size_t const argumentCount = arguments.size(); 559 std::size_t const parameterCount = substitutedSig->MinArgCount(); 560 auto const reportError = (flags & TypeRelationFlag::NO_THROW) == 0; 561 562 if (argumentCount < parameterCount || (argumentCount > parameterCount && !hasRestParameter)) { 563 if (reportError) { 564 LogTypeError({"Expected ", parameterCount, " arguments, got ", argumentCount, "."}, pos); 565 } 566 return nullptr; 567 } 568 569 if (argumentCount > parameterCount && hasRestParameter && (flags & TypeRelationFlag::IGNORE_REST_PARAM) != 0) { 570 return nullptr; 571 } 572 573 auto count = std::min(parameterCount, argumentCount); 574 // Check all required formal parameter(s) first 575 if (!ValidateSignatureRequiredParams(substitutedSig, arguments, flags, argTypeInferenceRequired, reportError)) { 576 return nullptr; 577 } 578 579 // Check rest parameter(s) if any exists 580 if (!hasRestParameter || count >= argumentCount) { 581 return substitutedSig; 582 } 583 if (!ValidateSignatureRestParams(substitutedSig, arguments, flags, reportError)) { 584 return nullptr; 585 } 586 587 return substitutedSig; 588} 589 590Signature *ETSChecker::CollectParameterlessConstructor(ArenaVector<Signature *> &signatures, 591 const lexer::SourcePosition &pos, TypeRelationFlag resolveFlags) 592{ 593 Signature *compatibleSignature = nullptr; 594 595 auto collectSignatures = [&](TypeRelationFlag relationFlags) { 596 for (auto *sig : signatures) { 597 if (auto *concreteSig = ValidateParameterlessConstructor(sig, pos, relationFlags); concreteSig != nullptr) { 598 compatibleSignature = concreteSig; 599 break; 600 } 601 } 602 }; 603 604 // We are able to provide more specific error messages. 605 if (signatures.size() == 1) { 606 collectSignatures(resolveFlags); 607 } else { 608 collectSignatures(resolveFlags | TypeRelationFlag::NO_THROW); 609 } 610 611 if (compatibleSignature == nullptr) { 612 if ((resolveFlags & TypeRelationFlag::NO_THROW) == 0) { 613 LogTypeError({"No matching parameterless constructor"}, pos); 614 } 615 } 616 return compatibleSignature; 617} 618 619bool IsSignatureAccessible(Signature *sig, ETSObjectType *containingClass, TypeRelation *relation) 620{ 621 // NOTE(vivienvoros): this check can be removed if signature is implicitly declared as public according to the spec. 622 if (!sig->HasSignatureFlag(SignatureFlags::PUBLIC | SignatureFlags::PROTECTED | SignatureFlags::PRIVATE | 623 SignatureFlags::INTERNAL)) { 624 return true; 625 } 626 627 // NOTE(vivienvoros): take care of SignatureFlags::INTERNAL and SignatureFlags::INTERNAL_PROTECTED 628 if (sig->HasSignatureFlag(SignatureFlags::INTERNAL) && !sig->HasSignatureFlag(SignatureFlags::PROTECTED)) { 629 return true; 630 } 631 632 if (sig->HasSignatureFlag(SignatureFlags::PUBLIC) || sig->Owner() == containingClass || 633 (sig->HasSignatureFlag(SignatureFlags::PROTECTED) && relation->IsSupertypeOf(sig->Owner(), containingClass))) { 634 return true; 635 } 636 637 return false; 638} 639 640// NOLINTNEXTLINE(readability-magic-numbers) 641std::array<TypeRelationFlag, 9U> GetFlagVariants() 642{ 643 // NOTE(boglarkahaag): Not in sync with specification, but solves the issues with rest params for now (#17483) 644 return { 645 TypeRelationFlag::NO_THROW | TypeRelationFlag::NO_UNBOXING | TypeRelationFlag::NO_BOXING | 646 TypeRelationFlag::IGNORE_REST_PARAM, 647 TypeRelationFlag::NO_THROW | TypeRelationFlag::NO_UNBOXING | TypeRelationFlag::NO_BOXING, 648 TypeRelationFlag::NO_THROW | TypeRelationFlag::IGNORE_REST_PARAM, 649 TypeRelationFlag::NO_THROW, 650 TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING | TypeRelationFlag::NO_UNBOXING | 651 TypeRelationFlag::NO_BOXING | TypeRelationFlag::IGNORE_REST_PARAM, 652 TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING | TypeRelationFlag::NO_UNBOXING | 653 TypeRelationFlag::NO_BOXING, 654 TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING | TypeRelationFlag::IGNORE_REST_PARAM, 655 TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING, 656 TypeRelationFlag::NO_THROW | TypeRelationFlag::STRING_TO_CHAR, 657 }; 658} 659ArenaVector<Signature *> ETSChecker::CollectSignatures(ArenaVector<Signature *> &signatures, 660 const ir::TSTypeParameterInstantiation *typeArguments, 661 const ArenaVector<ir::Expression *> &arguments, 662 const lexer::SourcePosition &pos, TypeRelationFlag resolveFlags) 663{ 664 ArenaVector<Signature *> compatibleSignatures(Allocator()->Adapter()); 665 std::vector<bool> argTypeInferenceRequired = FindTypeInferenceArguments(arguments); 666 Signature *notVisibleSignature = nullptr; 667 668 auto collectSignatures = [&](TypeRelationFlag relationFlags) { 669 for (auto *sig : signatures) { 670 if (notVisibleSignature != nullptr && 671 !IsSignatureAccessible(sig, Context().ContainingClass(), Relation())) { 672 continue; 673 } 674 auto *concreteSig = ValidateSignature(std::make_tuple(sig, typeArguments, relationFlags), arguments, pos, 675 argTypeInferenceRequired); 676 if (concreteSig == nullptr) { 677 continue; 678 } 679 if (notVisibleSignature == nullptr && 680 !IsSignatureAccessible(sig, Context().ContainingClass(), Relation())) { 681 notVisibleSignature = concreteSig; 682 } else { 683 compatibleSignatures.push_back(concreteSig); 684 } 685 } 686 }; 687 688 // If there's only one signature, we don't need special checks for boxing/unboxing/widening. 689 // We are also able to provide more specific error messages. 690 if (signatures.size() == 1) { 691 TypeRelationFlag flags = TypeRelationFlag::WIDENING | TypeRelationFlag::STRING_TO_CHAR | resolveFlags; 692 collectSignatures(flags); 693 } else { 694 for (auto flags : GetFlagVariants()) { 695 flags = flags | resolveFlags; 696 collectSignatures(flags); 697 if (!compatibleSignatures.empty()) { 698 break; 699 } 700 } 701 } 702 703 if (compatibleSignatures.empty() && notVisibleSignature != nullptr) { 704 LogTypeError( 705 {"Signature ", notVisibleSignature->Function()->Id()->Name(), notVisibleSignature, " is not visible here."}, 706 pos); 707 } 708 return compatibleSignatures; 709} 710 711Signature *ETSChecker::GetMostSpecificSignature(ArenaVector<Signature *> &compatibleSignatures, 712 const ArenaVector<ir::Expression *> &arguments, 713 const lexer::SourcePosition &pos, TypeRelationFlag resolveFlags) 714{ 715 std::vector<bool> argTypeInferenceRequired = FindTypeInferenceArguments(arguments); 716 Signature *mostSpecificSignature = ChooseMostSpecificSignature(compatibleSignatures, argTypeInferenceRequired, pos); 717 718 if (mostSpecificSignature == nullptr) { 719 LogTypeError({"Reference to ", compatibleSignatures.front()->Function()->Id()->Name(), " is ambiguous"}, pos); 720 return nullptr; 721 } 722 723 if (!TypeInference(mostSpecificSignature, arguments, resolveFlags)) { 724 return nullptr; 725 } 726 727 return mostSpecificSignature; 728} 729 730Signature *ETSChecker::ValidateSignatures(ArenaVector<Signature *> &signatures, 731 const ir::TSTypeParameterInstantiation *typeArguments, 732 const ArenaVector<ir::Expression *> &arguments, 733 const lexer::SourcePosition &pos, std::string_view signatureKind, 734 TypeRelationFlag resolveFlags) 735{ 736 auto compatibleSignatures = CollectSignatures(signatures, typeArguments, arguments, pos, resolveFlags); 737 if (!compatibleSignatures.empty()) { 738 return GetMostSpecificSignature(compatibleSignatures, arguments, pos, resolveFlags); 739 } 740 741 if ((resolveFlags & TypeRelationFlag::NO_THROW) == 0 && !arguments.empty() && !signatures.empty()) { 742 std::stringstream ss; 743 744 if (signatures[0]->Function()->IsConstructor()) { 745 ss << util::Helpers::GetClassDefiniton(signatures[0]->Function())->PrivateId().Mutf8(); 746 } else { 747 ss << signatures[0]->Function()->Id()->Name().Mutf8(); 748 } 749 750 ss << "("; 751 752 for (uint32_t index = 0; index < arguments.size(); ++index) { 753 if (arguments[index]->IsArrowFunctionExpression()) { 754 // NOTE(peterseres): Refactor this case and add test case 755 break; 756 } 757 758 arguments[index]->Check(this); 759 arguments[index]->TsType()->ToString(ss); 760 761 if (index == arguments.size() - 1) { 762 ss << ")"; 763 LogTypeError({"No matching ", signatureKind, " signature for ", ss.str().c_str()}, pos); 764 return nullptr; 765 } 766 767 ss << ", "; 768 } 769 } 770 771 if ((resolveFlags & TypeRelationFlag::NO_THROW) == 0) { 772 LogTypeError({"No matching ", signatureKind, " signature"}, pos); 773 } 774 775 return nullptr; 776} 777 778Signature *ETSChecker::FindMostSpecificSignature(const ArenaVector<Signature *> &signatures, 779 const ArenaMultiMap<size_t, Signature *> &bestSignaturesForParameter, 780 size_t paramCount) 781{ 782 Signature *mostSpecificSignature = nullptr; 783 784 for (auto *sig : signatures) { 785 bool mostSpecific = true; 786 787 for (size_t paramIdx = 0; paramIdx < paramCount; ++paramIdx) { 788 const auto range = bestSignaturesForParameter.equal_range(paramIdx); 789 // Check if signature is most specific for i. parameter type. 790 mostSpecific = std::any_of(range.first, range.second, [&sig](auto entry) { return entry.second == sig; }); 791 if (!mostSpecific) { 792 break; 793 } 794 } 795 796 if (!mostSpecific) { 797 continue; 798 } 799 if (mostSpecificSignature == nullptr) { 800 mostSpecificSignature = sig; 801 continue; 802 } 803 if (mostSpecificSignature->Owner() == sig->Owner()) { 804 // NOTE: audovichenko. Remove this 'if' when #12443 gets resolved 805 if (mostSpecificSignature->Function() == sig->Function()) { 806 // The same signature 807 continue; 808 } 809 return nullptr; 810 } 811 } 812 return mostSpecificSignature; 813} 814 815static void InitMostSpecificType(const ArenaVector<Signature *> &signatures, [[maybe_unused]] Type *&mostSpecificType, 816 [[maybe_unused]] Signature *&prevSig, const size_t idx) 817{ 818 for (auto *sig : signatures) { 819 if (Type *sigType = sig->Params().at(idx)->TsType(); 820 sigType->IsETSObjectType() && !sigType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INTERFACE)) { 821 mostSpecificType = sigType; 822 prevSig = sig; 823 return; 824 } 825 } 826} 827 828void ETSChecker::SearchAmongMostSpecificTypes( 829 Type *&mostSpecificType, Signature *&prevSig, 830 std::tuple<const lexer::SourcePosition &, size_t, size_t, size_t, Signature *> info, bool lookForClassType) 831{ 832 auto [pos, argumentsSize, paramCount, idx, sig] = info; 833 if (lookForClassType && argumentsSize == ULONG_MAX) { 834 [[maybe_unused]] const bool equalParamSize = sig->Params().size() == paramCount; 835 ASSERT(equalParamSize); 836 } 837 Type *sigType = sig->Params().at(idx)->TsType(); 838 const bool isClassType = 839 sigType->IsETSObjectType() && !sigType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INTERFACE); 840 if (isClassType == lookForClassType) { 841 if (Relation()->IsIdenticalTo(sigType, mostSpecificType)) { 842 return; 843 } 844 if (Relation()->IsAssignableTo(sigType, mostSpecificType)) { 845 mostSpecificType = sigType; 846 prevSig = sig; 847 } else if (sigType->IsETSObjectType() && mostSpecificType->IsETSObjectType() && 848 !Relation()->IsAssignableTo(mostSpecificType, sigType)) { 849 auto funcName = sig->Function()->Id()->Name(); 850 LogTypeError({"Call to `", funcName, "` is ambiguous as `2` versions of `", funcName, "` are available: `", 851 funcName, prevSig, "` and `", funcName, sig, "`"}, 852 pos); 853 } 854 } 855} 856 857ArenaMultiMap<size_t, Signature *> ETSChecker::GetSuitableSignaturesForParameter( 858 const std::vector<bool> &argTypeInferenceRequired, size_t paramCount, ArenaVector<Signature *> &signatures, 859 const lexer::SourcePosition &pos, size_t argumentsSize) 860{ 861 // Collect which signatures are most specific for each parameter. 862 ArenaMultiMap<size_t /* parameter index */, Signature *> bestSignaturesForParameter(Allocator()->Adapter()); 863 864 const checker::SavedTypeRelationFlagsContext savedTypeRelationFlagCtx(Relation(), 865 TypeRelationFlag::ONLY_CHECK_WIDENING); 866 867 for (size_t i = 0; i < paramCount; ++i) { 868 if (argTypeInferenceRequired[i]) { 869 for (auto *sig : signatures) { 870 bestSignaturesForParameter.insert({i, sig}); 871 } 872 continue; 873 } 874 // 1st step: check which is the most specific parameter type for i. parameter. 875 Type *mostSpecificType = signatures.front()->Params().at(i)->TsType(); 876 Signature *prevSig = signatures.front(); 877 878 InitMostSpecificType(signatures, mostSpecificType, prevSig, i); 879 for (auto *sig : signatures) { 880 SearchAmongMostSpecificTypes(mostSpecificType, prevSig, 881 std::make_tuple(pos, argumentsSize, paramCount, i, sig), true); 882 } 883 for (auto *sig : signatures) { 884 SearchAmongMostSpecificTypes(mostSpecificType, prevSig, 885 std::make_tuple(pos, argumentsSize, paramCount, i, sig), false); 886 } 887 888 for (auto *sig : signatures) { 889 Type *sigType = sig->Params().at(i)->TsType(); 890 if (Relation()->IsIdenticalTo(sigType, mostSpecificType)) { 891 bestSignaturesForParameter.insert({i, sig}); 892 } 893 } 894 } 895 return bestSignaturesForParameter; 896} 897 898Signature *ETSChecker::ChooseMostSpecificSignature(ArenaVector<Signature *> &signatures, 899 const std::vector<bool> &argTypeInferenceRequired, 900 const lexer::SourcePosition &pos, size_t argumentsSize) 901{ 902 ASSERT(signatures.empty() == false); 903 904 if (signatures.size() == 1) { 905 return signatures.front(); 906 } 907 908 size_t paramCount = signatures.front()->Params().size(); 909 if (argumentsSize != ULONG_MAX) { 910 paramCount = argumentsSize; 911 } 912 // Multiple signatures with zero parameter because of inheritance. 913 // Return the closest one in inheritance chain that is defined at the beginning of the vector. 914 if (paramCount == 0) { 915 auto zeroParamSignature = std::find_if(signatures.begin(), signatures.end(), 916 [](auto *signature) { return signature->RestVar() == nullptr; }); 917 // If there is a zero parameter signature, return that 918 if (zeroParamSignature != signatures.end()) { 919 return *zeroParamSignature; 920 } 921 // If there are multiple rest parameter signatures with different argument types, throw error 922 if (signatures.size() > 1 && std::any_of(signatures.begin(), signatures.end(), [signatures](const auto *param) { 923 return param->RestVar()->TsType() != signatures.front()->RestVar()->TsType(); 924 })) { 925 ThrowTypeError({"Call to `", signatures.front()->Function()->Id()->Name(), "` is ambiguous "}, pos); 926 } 927 // Else return the signature with the rest parameter 928 auto restParamSignature = std::find_if(signatures.begin(), signatures.end(), 929 [](auto *signature) { return signature->RestVar() != nullptr; }); 930 return *restParamSignature; 931 } 932 933 ArenaMultiMap<size_t /* parameter index */, Signature *> bestSignaturesForParameter = 934 GetSuitableSignaturesForParameter(argTypeInferenceRequired, paramCount, signatures, pos, argumentsSize); 935 // Find the signature that are most specific for all parameters. 936 Signature *mostSpecificSignature = FindMostSpecificSignature(signatures, bestSignaturesForParameter, paramCount); 937 938 return mostSpecificSignature; 939} 940 941Signature *ETSChecker::ResolveCallExpressionAndTrailingLambda(ArenaVector<Signature *> &signatures, 942 ir::CallExpression *callExpr, 943 const lexer::SourcePosition &pos, 944 const TypeRelationFlag reportFlag) 945{ 946 Signature *sig = nullptr; 947 if (callExpr->TrailingBlock() == nullptr) { 948 for (auto it : signatures) { 949 MaybeSubstituteLambdaArguments(it->Function()->Params(), callExpr); 950 951 if (callExpr->Arguments().size() != it->Function()->Params().size()) { 952 MaybeSubstituteLambdaArgumentsInFunctionCall(callExpr); 953 } 954 } 955 956 sig = ValidateSignatures(signatures, callExpr->TypeParams(), callExpr->Arguments(), pos, "call", reportFlag); 957 return sig; 958 } 959 960 // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 961 auto arguments = ExtendArgumentsWithFakeLamda(callExpr); 962 sig = ValidateSignatures(signatures, callExpr->TypeParams(), arguments, pos, "call", 963 TypeRelationFlag::NO_THROW | TypeRelationFlag::NO_CHECK_TRAILING_LAMBDA); 964 if (sig != nullptr) { 965 // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 966 TransformTraillingLambda(callExpr); 967 TypeInference(sig, callExpr->Arguments()); 968 return sig; 969 } 970 971 sig = ValidateSignatures(signatures, callExpr->TypeParams(), callExpr->Arguments(), pos, "call", reportFlag); 972 if (sig != nullptr) { 973 EnsureValidCurlyBrace(callExpr); 974 } 975 976 return sig; 977} 978 979Signature *ETSChecker::ResolveConstructExpression(ETSObjectType *type, const ArenaVector<ir::Expression *> &arguments, 980 const lexer::SourcePosition &pos) 981{ 982 return ValidateSignatures(type->ConstructSignatures(), nullptr, arguments, pos, "construct"); 983} 984 985/* 986 * Object literals do not get checked in the process of call resolution; we need to check them separately 987 * afterwards. 988 */ 989void ETSChecker::CheckObjectLiteralArguments(Signature *signature, ArenaVector<ir::Expression *> const &arguments) 990{ 991 for (uint32_t index = 0; index < arguments.size(); index++) { 992 if (!arguments[index]->IsObjectExpression()) { 993 continue; 994 } 995 996 Type *tp; 997 if (index >= signature->MinArgCount()) { 998 ASSERT(signature->RestVar()); 999 tp = signature->RestVar()->TsType(); 1000 } else { 1001 tp = signature->Params()[index]->TsType(); 1002 } 1003 1004 arguments[index]->AsObjectExpression()->SetPreferredType(tp); 1005 arguments[index]->Check(this); 1006 } 1007} 1008 1009checker::ETSFunctionType *ETSChecker::BuildMethodSignature(ir::MethodDefinition *method) 1010{ 1011 if (method->TsTypeOrError() != nullptr) { 1012 return method->TsTypeOrError()->AsETSFunctionType(); 1013 } 1014 1015 bool isConstructSig = method->IsConstructor(); 1016 1017 method->Function()->Id()->SetVariable(method->Id()->Variable()); 1018 BuildFunctionSignature(method->Function(), isConstructSig); 1019 if (method->Function()->Signature() == nullptr) { 1020 return nullptr; 1021 } 1022 auto *funcType = BuildNamedFunctionType(method->Function()); 1023 std::vector<checker::ETSFunctionType *> overloads; 1024 1025 for (ir::MethodDefinition *const currentFunc : method->Overloads()) { 1026 currentFunc->Function()->Id()->SetVariable(currentFunc->Id()->Variable()); 1027 BuildFunctionSignature(currentFunc->Function(), isConstructSig); 1028 if (currentFunc->Function()->Signature() == nullptr) { 1029 return nullptr; 1030 } 1031 auto *const overloadType = BuildNamedFunctionType(currentFunc->Function()); 1032 CheckIdenticalOverloads(funcType, overloadType, currentFunc); 1033 currentFunc->SetTsType(overloadType); 1034 funcType->AddCallSignature(currentFunc->Function()->Signature()); 1035 overloads.push_back(overloadType); 1036 } 1037 for (size_t baseFuncCounter = 0; baseFuncCounter < overloads.size(); ++baseFuncCounter) { 1038 auto *overloadType = overloads.at(baseFuncCounter); 1039 for (size_t compareFuncCounter = baseFuncCounter + 1; compareFuncCounter < overloads.size(); 1040 compareFuncCounter++) { 1041 auto *compareOverloadType = overloads.at(compareFuncCounter); 1042 CheckIdenticalOverloads(overloadType, compareOverloadType, method->Overloads()[compareFuncCounter]); 1043 } 1044 } 1045 1046 method->Id()->Variable()->SetTsType(funcType); 1047 return funcType; 1048} 1049 1050void ETSChecker::CheckIdenticalOverloads(ETSFunctionType *func, ETSFunctionType *overload, 1051 const ir::MethodDefinition *const currentFunc) 1052{ 1053 SavedTypeRelationFlagsContext savedFlagsCtx(Relation(), TypeRelationFlag::NO_RETURN_TYPE_CHECK); 1054 1055 Relation()->IsIdenticalTo(func, overload); 1056 if (Relation()->IsTrue() && func->CallSignatures()[0]->GetSignatureInfo()->restVar == 1057 overload->CallSignatures()[0]->GetSignatureInfo()->restVar) { 1058 LogTypeError("Function " + func->Name().Mutf8() + " is already declared.", currentFunc->Start()); 1059 return; 1060 } 1061 if (HasSameAssemblySignatures(func, overload)) { 1062 LogTypeError("Function " + func->Name().Mutf8() + " with this assembly signature already declared.", 1063 currentFunc->Start()); 1064 } 1065} 1066 1067Signature *ETSChecker::ComposeSignature(ir::ScriptFunction *func, SignatureInfo *signatureInfo, Type *returnType, 1068 varbinder::Variable *nameVar) 1069{ 1070 auto *signature = CreateSignature(signatureInfo, returnType, func); 1071 signature->SetOwner(Context().ContainingClass()); 1072 signature->SetOwnerVar(nameVar); 1073 1074 const auto *returnTypeAnnotation = func->ReturnTypeAnnotation(); 1075 if (returnTypeAnnotation == nullptr && ((func->Flags() & ir::ScriptFunctionFlags::HAS_RETURN) != 0)) { 1076 signature->AddSignatureFlag(SignatureFlags::NEED_RETURN_TYPE); 1077 } 1078 1079 if (returnTypeAnnotation != nullptr && returnTypeAnnotation->IsTSThisType()) { 1080 signature->AddSignatureFlag(SignatureFlags::THIS_RETURN_TYPE); 1081 } 1082 1083 if (func->IsAbstract()) { 1084 signature->AddSignatureFlag(SignatureFlags::ABSTRACT); 1085 signature->AddSignatureFlag(SignatureFlags::VIRTUAL); 1086 } 1087 1088 if (func->IsStatic()) { 1089 signature->AddSignatureFlag(SignatureFlags::STATIC); 1090 } 1091 1092 if (func->IsConstructor()) { 1093 signature->AddSignatureFlag(SignatureFlags::CONSTRUCTOR); 1094 } 1095 1096 if (signature->Owner()->GetDeclNode()->IsFinal() || func->IsFinal()) { 1097 signature->AddSignatureFlag(SignatureFlags::FINAL); 1098 } 1099 1100 if (func->IsPublic()) { 1101 signature->AddSignatureFlag(SignatureFlags::PUBLIC); 1102 } else if (func->IsInternal()) { 1103 if (func->IsProtected()) { 1104 signature->AddSignatureFlag(SignatureFlags::INTERNAL_PROTECTED); 1105 } else { 1106 signature->AddSignatureFlag(SignatureFlags::INTERNAL); 1107 } 1108 } else if (func->IsProtected()) { 1109 signature->AddSignatureFlag(SignatureFlags::PROTECTED); 1110 } else if (func->IsPrivate()) { 1111 signature->AddSignatureFlag(SignatureFlags::PRIVATE); 1112 } 1113 1114 return signature; 1115} 1116 1117Type *ETSChecker::ComposeReturnType(ir::ScriptFunction *func) 1118{ 1119 auto *const returnTypeAnnotation = func->ReturnTypeAnnotation(); 1120 checker::Type *returnType {}; 1121 1122 if (returnTypeAnnotation == nullptr) { 1123 // implicit void return type 1124 returnType = GlobalVoidType(); 1125 1126 if (func->IsAsyncFunc()) { 1127 auto implicitPromiseVoid = [this]() { 1128 const auto &promiseGlobal = GlobalBuiltinPromiseType()->AsETSObjectType(); 1129 auto promiseType = 1130 promiseGlobal->Instantiate(Allocator(), Relation(), GetGlobalTypesHolder())->AsETSObjectType(); 1131 promiseType->AddTypeFlag(checker::TypeFlag::GENERIC); 1132 promiseType->TypeArguments().clear(); 1133 promiseType->TypeArguments().emplace_back(GlobalVoidType()); 1134 return promiseType; 1135 }; 1136 1137 returnType = implicitPromiseVoid(); 1138 } 1139 } else if (func->IsEntryPoint() && returnTypeAnnotation->GetType(this) == GlobalVoidType()) { 1140 returnType = GlobalVoidType(); 1141 } else { 1142 returnType = returnTypeAnnotation->GetType(this); 1143 returnTypeAnnotation->SetTsType(returnType); 1144 } 1145 1146 return returnType; 1147} 1148 1149SignatureInfo *ETSChecker::ComposeSignatureInfo(ir::ScriptFunction *func) 1150{ 1151 auto *signatureInfo = CreateSignatureInfo(); 1152 signatureInfo->restVar = nullptr; 1153 signatureInfo->minArgCount = 0; 1154 1155 if ((func->IsConstructor() || !func->IsStatic()) && !func->IsArrow()) { 1156 auto *thisVar = func->Scope()->ParamScope()->Params().front(); 1157 thisVar->SetTsType(Context().ContainingClass()); 1158 } 1159 1160 if (func->TypeParams() != nullptr) { 1161 auto [typeParamTypes, ok] = CreateUnconstrainedTypeParameters(func->TypeParams()); 1162 signatureInfo->typeParams = std::move(typeParamTypes); 1163 if (ok) { 1164 AssignTypeParameterConstraints(func->TypeParams()); 1165 } 1166 } 1167 1168 for (auto *const it : func->Params()) { 1169 auto *const param = it->AsETSParameterExpression(); 1170 1171 if (param->IsRestParameter()) { 1172 auto const *const restIdent = param->Ident(); 1173 1174 ASSERT(restIdent->Variable()); 1175 signatureInfo->restVar = restIdent->Variable()->AsLocalVariable(); 1176 1177 auto *const restParamTypeAnnotation = param->TypeAnnotation(); 1178 ASSERT(restParamTypeAnnotation); 1179 1180 signatureInfo->restVar->SetTsType(restParamTypeAnnotation->GetType(this)); 1181 auto arrayType = signatureInfo->restVar->TsType()->AsETSArrayType(); 1182 CreateBuiltinArraySignature(arrayType, arrayType->Rank()); 1183 } else { 1184 auto *const paramIdent = param->Ident(); 1185 1186 varbinder::Variable *const paramVar = paramIdent->Variable(); 1187 ASSERT(paramVar); 1188 1189 auto *const paramTypeAnnotation = param->TypeAnnotation(); 1190 if (paramIdent->TsType() == nullptr && paramTypeAnnotation == nullptr) { 1191 LogTypeError({"The type of parameter '", paramIdent->Name(), "' cannot be determined"}, param->Start()); 1192 return nullptr; 1193 } 1194 1195 if (paramIdent->TsType() == nullptr) { 1196 ASSERT(paramTypeAnnotation); 1197 1198 paramVar->SetTsType(paramTypeAnnotation->GetType(this)); 1199 } else { 1200 paramVar->SetTsType(paramIdent->TsTypeOrError()); 1201 } 1202 signatureInfo->params.push_back(paramVar->AsLocalVariable()); 1203 ++signatureInfo->minArgCount; 1204 } 1205 } 1206 1207 return signatureInfo; 1208} 1209 1210ArenaVector<SignatureInfo *> ETSChecker::ComposeSignatureInfosForArrowFunction( 1211 ir::ArrowFunctionExpression *arrowFuncExpr) 1212{ 1213 ArenaVector<SignatureInfo *> signatureInfos(Allocator()->Adapter()); 1214 1215 for (size_t i = arrowFuncExpr->Function()->DefaultParamIndex(); i < arrowFuncExpr->Function()->Params().size(); 1216 i++) { 1217 auto *signatureInfo = CreateSignatureInfo(); 1218 signatureInfo->restVar = nullptr; 1219 signatureInfo->minArgCount = 0; 1220 1221 if (arrowFuncExpr->Function()->TypeParams() != nullptr) { 1222 signatureInfo->typeParams = 1223 CreateUnconstrainedTypeParameters(arrowFuncExpr->Function()->TypeParams()).first; 1224 } 1225 1226 for (size_t j = 0; j < i; j++) { 1227 SetParamForSignatureInfoOfArrowFunction(signatureInfo, 1228 arrowFuncExpr->Function()->Params()[j]->AsETSParameterExpression()); 1229 } 1230 1231 signatureInfos.push_back(signatureInfo); 1232 } 1233 1234 return signatureInfos; 1235} 1236 1237void ETSChecker::SetParamForSignatureInfoOfArrowFunction(SignatureInfo *signatureInfo, 1238 ir::ETSParameterExpression *param) 1239{ 1240 if (param->IsRestParameter()) { 1241 auto const *const restIdent = param->Ident(); 1242 1243 ASSERT(restIdent->Variable()); 1244 signatureInfo->restVar = restIdent->Variable()->AsLocalVariable(); 1245 1246 auto *const restParamTypeAnnotation = param->TypeAnnotation(); 1247 ASSERT(restParamTypeAnnotation); 1248 1249 signatureInfo->restVar->SetTsType(restParamTypeAnnotation->GetType(this)); 1250 auto arrayType = signatureInfo->restVar->TsType()->AsETSArrayType(); 1251 CreateBuiltinArraySignature(arrayType, arrayType->Rank()); 1252 } else { 1253 auto *const paramIdent = param->Ident(); 1254 1255 varbinder::Variable *const paramVar = paramIdent->Variable(); 1256 ASSERT(paramVar); 1257 1258 auto *const paramTypeAnnotation = param->TypeAnnotation(); 1259 if (paramIdent->TsType() == nullptr) { 1260 ASSERT(paramTypeAnnotation); 1261 1262 paramVar->SetTsType(paramTypeAnnotation->GetType(this)); 1263 } else { 1264 paramVar->SetTsType(paramIdent->TsType()); 1265 } 1266 signatureInfo->params.push_back(paramVar->AsLocalVariable()); 1267 ++signatureInfo->minArgCount; 1268 } 1269} 1270 1271void ETSChecker::ValidateMainSignature(ir::ScriptFunction *func) 1272{ 1273 if (func->Params().size() >= 2U) { 1274 LogTypeError("0 or 1 argument are allowed", func->Start()); 1275 return; 1276 } 1277 1278 if (func->Params().size() == 1) { 1279 auto const *const param = func->Params()[0]->AsETSParameterExpression(); 1280 1281 if (param->IsRestParameter()) { 1282 LogTypeError("Rest parameter is not allowed in the 'main' function.", param->Start()); 1283 } 1284 1285 const auto paramType = param->Variable()->TsType(); 1286 if (!paramType->IsETSArrayType() || !paramType->AsETSArrayType()->ElementType()->IsETSStringType()) { 1287 LogTypeError("Only 'string[]' type argument is allowed.", param->Start()); 1288 } 1289 } 1290} 1291 1292static void AddSignatureFlags(const ir::ScriptFunction *const func, Signature *const signature) 1293{ 1294 if (func->IsAbstract()) { 1295 signature->AddSignatureFlag(SignatureFlags::ABSTRACT); 1296 signature->AddSignatureFlag(SignatureFlags::VIRTUAL); 1297 } 1298 1299 if (func->IsStatic()) { 1300 signature->AddSignatureFlag(SignatureFlags::STATIC); 1301 } 1302 1303 if (func->IsConstructor()) { 1304 signature->AddSignatureFlag(SignatureFlags::CONSTRUCTOR); 1305 } 1306 1307 if (func->Signature()->Owner()->GetDeclNode()->IsFinal() || func->IsFinal()) { 1308 signature->AddSignatureFlag(SignatureFlags::FINAL); 1309 } 1310 1311 if (func->IsPublic()) { 1312 signature->AddSignatureFlag(SignatureFlags::PUBLIC); 1313 } else if (func->IsInternal()) { 1314 if (func->IsProtected()) { 1315 signature->AddSignatureFlag(SignatureFlags::INTERNAL_PROTECTED); 1316 } else { 1317 signature->AddSignatureFlag(SignatureFlags::INTERNAL); 1318 } 1319 } else if (func->IsProtected()) { 1320 signature->AddSignatureFlag(SignatureFlags::PROTECTED); 1321 } else if (func->IsPrivate()) { 1322 signature->AddSignatureFlag(SignatureFlags::PRIVATE); 1323 } 1324 1325 if (func->IsSetter()) { 1326 signature->AddSignatureFlag(SignatureFlags::SETTER); 1327 } else if (func->IsGetter()) { 1328 signature->AddSignatureFlag(SignatureFlags::GETTER); 1329 } 1330} 1331 1332void ETSChecker::BuildFunctionSignature(ir::ScriptFunction *func, bool isConstructSig) 1333{ 1334 bool isArrow = func->IsArrow(); 1335 auto *nameVar = isArrow ? nullptr : func->Id()->Variable(); 1336 auto funcName = nameVar == nullptr ? util::StringView() : nameVar->Name(); 1337 1338 auto *signatureInfo = ComposeSignatureInfo(func); 1339 if (signatureInfo == nullptr) { 1340 return; 1341 } 1342 1343 if (funcName.Is(compiler::Signatures::MAIN) && 1344 func->Scope()->Name().Utf8().find(compiler::Signatures::ETS_GLOBAL) != std::string::npos) { 1345 func->AddFlag(ir::ScriptFunctionFlags::ENTRY_POINT); 1346 } 1347 if (func->IsEntryPoint()) { 1348 ValidateMainSignature(func); 1349 } 1350 1351 auto *returnType = ComposeReturnType(func); 1352 auto *signature = ComposeSignature(func, signatureInfo, returnType, nameVar); 1353 if (isConstructSig) { 1354 signature->AddSignatureFlag(SignatureFlags::CONSTRUCT); 1355 } else { 1356 signature->AddSignatureFlag(SignatureFlags::CALL); 1357 } 1358 func->SetSignature(signature); 1359 AddSignatureFlags(func, signature); 1360 VarBinder()->AsETSBinder()->BuildFunctionName(func); 1361} 1362 1363checker::ETSFunctionType *ETSChecker::BuildNamedFunctionType(ir::ScriptFunction *func) 1364{ 1365 ASSERT(!func->IsArrow()); 1366 auto *nameVar = func->Id()->Variable(); 1367 auto *funcType = CreateETSFunctionType(func, func->Signature(), nameVar->Name()); 1368 funcType->SetVariable(nameVar); 1369 return funcType; 1370} 1371 1372Signature *ETSChecker::CheckEveryAbstractSignatureIsOverridden(ETSFunctionType *target, ETSFunctionType *source) 1373{ 1374 for (auto targetSig = target->CallSignatures().begin(); targetSig != target->CallSignatures().end();) { 1375 if (!(*targetSig)->HasSignatureFlag(SignatureFlags::ABSTRACT)) { 1376 continue; 1377 } 1378 1379 bool isOverridden = false; 1380 for (auto sourceSig : source->CallSignatures()) { 1381 if ((*targetSig)->Function()->Id()->Name() == sourceSig->Function()->Id()->Name() && 1382 Relation()->IsCompatibleTo(*targetSig, sourceSig)) { 1383 target->CallSignatures().erase(targetSig); 1384 isOverridden = true; 1385 break; 1386 } 1387 sourceSig++; 1388 } 1389 1390 if (!isOverridden) { 1391 return *targetSig; 1392 } 1393 } 1394 1395 return nullptr; 1396} 1397 1398bool ETSChecker::IsOverridableIn(Signature *signature) 1399{ 1400 if (signature->HasSignatureFlag(SignatureFlags::PRIVATE)) { 1401 return false; 1402 } 1403 1404 // NOTE: #15095 workaround, separate internal visibility check 1405 if (signature->HasSignatureFlag(SignatureFlags::PUBLIC | SignatureFlags::INTERNAL)) { 1406 return true; 1407 } 1408 1409 return signature->HasSignatureFlag(SignatureFlags::PROTECTED); 1410} 1411 1412bool ETSChecker::IsMethodOverridesOther(Signature *base, Signature *derived) 1413{ 1414 if (derived->Function()->IsConstructor()) { 1415 return false; 1416 } 1417 1418 if (base == derived) { 1419 return true; 1420 } 1421 1422 if (derived->HasSignatureFlag(SignatureFlags::STATIC) != base->HasSignatureFlag(SignatureFlags::STATIC)) { 1423 return false; 1424 } 1425 1426 if (IsOverridableIn(base)) { 1427 SavedTypeRelationFlagsContext savedFlagsCtx(Relation(), TypeRelationFlag::NO_RETURN_TYPE_CHECK | 1428 TypeRelationFlag::OVERRIDING_CONTEXT); 1429 if (Relation()->IsCompatibleTo(base, derived)) { 1430 CheckThrowMarkers(base, derived); 1431 1432 if (derived->HasSignatureFlag(SignatureFlags::STATIC)) { 1433 return false; 1434 } 1435 1436 derived->Function()->SetOverride(); 1437 return true; 1438 } 1439 } 1440 1441 return false; 1442} 1443 1444bool ETSChecker::CheckThrowMarkers(Signature *source, Signature *target) 1445{ 1446 ir::ScriptFunctionFlags throwMarkers = ir::ScriptFunctionFlags::THROWS | ir::ScriptFunctionFlags::RETHROWS; 1447 if ((source->Function()->Flags() & throwMarkers) == (target->Function()->Flags() & throwMarkers)) { 1448 return true; 1449 } 1450 1451 if ((source->Function()->IsRethrowing() && target->Function()->IsThrowing()) || 1452 (!source->Function()->IsThrowing() && 1453 (target->Function()->IsRethrowing() || target->Function()->IsThrowing()))) { 1454 ThrowTypeError( 1455 "A method that overrides or hides another method cannot change throw or rethrow clauses of the " 1456 "overridden " 1457 "or hidden method.", 1458 target->Function()->Body() == nullptr ? target->Function()->Start() : target->Function()->Body()->Start()); 1459 return false; 1460 } 1461 return true; 1462} 1463 1464OverrideErrorCode ETSChecker::CheckOverride(Signature *signature, Signature *other) 1465{ 1466 if (other->HasSignatureFlag(SignatureFlags::STATIC)) { 1467 ASSERT(signature->HasSignatureFlag(SignatureFlags::STATIC)); 1468 return OverrideErrorCode::NO_ERROR; 1469 } 1470 1471 if (other->IsFinal()) { 1472 return OverrideErrorCode::OVERRIDDEN_FINAL; 1473 } 1474 1475 if (!other->ReturnType()->IsETSTypeParameter()) { 1476 if (!IsReturnTypeSubstitutable(signature, other)) { 1477 return OverrideErrorCode::INCOMPATIBLE_RETURN; 1478 } 1479 } else { 1480 // We need to have this branch to allow generic overriding of the form: 1481 // foo<T>(x: T): T -> foo<someClass>(x: someClass): someClass 1482 if (!signature->ReturnType()->IsETSReferenceType()) { 1483 return OverrideErrorCode::INCOMPATIBLE_RETURN; 1484 } 1485 } 1486 1487 if (signature->ProtectionFlag() > other->ProtectionFlag()) { 1488 return OverrideErrorCode::OVERRIDDEN_WEAKER; 1489 } 1490 1491 return OverrideErrorCode::NO_ERROR; 1492} 1493 1494Signature *ETSChecker::AdjustForTypeParameters(Signature *source, Signature *target) 1495{ 1496 auto &sourceTypeParams = source->GetSignatureInfo()->typeParams; 1497 auto &targetTypeParams = target->GetSignatureInfo()->typeParams; 1498 if (sourceTypeParams.size() != targetTypeParams.size()) { 1499 return nullptr; 1500 } 1501 if (sourceTypeParams.empty()) { 1502 return target; 1503 } 1504 auto *substitution = NewSubstitution(); 1505 for (size_t ix = 0; ix < sourceTypeParams.size(); ix++) { 1506 if (!targetTypeParams[ix]->IsETSTypeParameter()) { 1507 continue; 1508 } 1509 ETSChecker::EmplaceSubstituted(substitution, targetTypeParams[ix]->AsETSTypeParameter(), sourceTypeParams[ix]); 1510 } 1511 return target->Substitute(Relation(), substitution); 1512} 1513 1514void ETSChecker::ReportOverrideError(Signature *signature, Signature *overriddenSignature, 1515 const OverrideErrorCode &errorCode) 1516{ 1517 const char *reason {}; 1518 switch (errorCode) { 1519 case OverrideErrorCode::OVERRIDDEN_FINAL: { 1520 reason = "overridden method is final."; 1521 break; 1522 } 1523 case OverrideErrorCode::INCOMPATIBLE_RETURN: { 1524 reason = "overriding return type is not compatible with the other return type."; 1525 break; 1526 } 1527 case OverrideErrorCode::OVERRIDDEN_WEAKER: { 1528 reason = "overridden method has weaker access privilege."; 1529 break; 1530 } 1531 default: { 1532 UNREACHABLE(); 1533 } 1534 } 1535 1536 LogTypeError({signature->Function()->Id()->Name(), signature, " in ", signature->Owner(), " cannot override ", 1537 overriddenSignature->Function()->Id()->Name(), overriddenSignature, " in ", 1538 overriddenSignature->Owner(), " because ", reason}, 1539 signature->Function()->Start()); 1540} 1541 1542bool ETSChecker::CheckOverride(Signature *signature, ETSObjectType *site) 1543{ 1544 auto *target = site->GetProperty(signature->Function()->Id()->Name(), PropertySearchFlags::SEARCH_METHOD); 1545 bool isOverridingAnySignature = false; 1546 1547 if (target == nullptr) { 1548 return isOverridingAnySignature; 1549 } 1550 1551 for (auto *it : target->TsType()->AsETSFunctionType()->CallSignatures()) { 1552 auto *itSubst = AdjustForTypeParameters(signature, it); 1553 1554 if (itSubst == nullptr) { 1555 continue; 1556 } 1557 1558 if (itSubst->HasSignatureFlag(SignatureFlags::ABSTRACT) || site->HasObjectFlag(ETSObjectFlags::INTERFACE)) { 1559 if (site->HasObjectFlag(ETSObjectFlags::INTERFACE) && !CheckThrowMarkers(itSubst, signature)) { 1560 return false; 1561 } 1562 1563 if ((itSubst->Function()->IsSetter() && !signature->Function()->IsSetter()) || 1564 (itSubst->Function()->IsGetter() && !signature->Function()->IsGetter())) { 1565 continue; 1566 } 1567 } 1568 1569 if (!IsMethodOverridesOther(itSubst, signature)) { 1570 continue; 1571 } 1572 1573 if (auto err = CheckOverride(signature, itSubst); err != OverrideErrorCode::NO_ERROR) { 1574 ReportOverrideError(signature, it, err); 1575 return false; 1576 } 1577 1578 if (signature->Owner()->HasObjectFlag(ETSObjectFlags::INTERFACE) && 1579 Relation()->IsIdenticalTo(itSubst->Owner(), GlobalETSObjectType()) && 1580 !itSubst->HasSignatureFlag(SignatureFlags::PRIVATE)) { 1581 LogTypeError("Cannot override non-private method of the class Object from an interface.", 1582 signature->Function()->Start()); 1583 return false; 1584 } 1585 1586 isOverridingAnySignature = true; 1587 it->AddSignatureFlag(SignatureFlags::VIRTUAL); 1588 } 1589 1590 return isOverridingAnySignature; 1591} 1592 1593void ETSChecker::CheckOverride(Signature *signature) 1594{ 1595 auto *owner = signature->Owner(); 1596 bool isOverriding = false; 1597 1598 if (!owner->HasObjectFlag(ETSObjectFlags::CLASS | ETSObjectFlags::INTERFACE)) { 1599 return; 1600 } 1601 1602 for (auto *const interface : owner->Interfaces()) { 1603 isOverriding |= CheckInterfaceOverride(this, interface, signature); 1604 } 1605 1606 ETSObjectType *iter = owner->SuperType(); 1607 while (iter != nullptr) { 1608 isOverriding |= CheckOverride(signature, iter); 1609 1610 for (auto *const interface : iter->Interfaces()) { 1611 isOverriding |= CheckInterfaceOverride(this, interface, signature); 1612 } 1613 1614 iter = iter->SuperType(); 1615 } 1616 1617 if (!isOverriding && signature->Function()->IsOverride()) { 1618 LogTypeError({"Method ", signature->Function()->Id()->Name(), signature, " in ", signature->Owner(), 1619 " not overriding any method"}, 1620 signature->Function()->Start()); 1621 } 1622} 1623 1624Signature *ETSChecker::GetSignatureFromMethodDefinition(const ir::MethodDefinition *methodDef) 1625{ 1626 if (methodDef->TsTypeOrError()->IsTypeError()) { 1627 return nullptr; 1628 } 1629 ASSERT(methodDef->TsType() && methodDef->TsType()->IsETSFunctionType()); 1630 for (auto *it : methodDef->TsType()->AsETSFunctionType()->CallSignatures()) { 1631 if (it->Function() == methodDef->Function()) { 1632 return it; 1633 } 1634 } 1635 1636 return nullptr; 1637} 1638 1639void ETSChecker::ValidateSignatureAccessibility(ETSObjectType *callee, const ir::CallExpression *callExpr, 1640 Signature *signature, const lexer::SourcePosition &pos, 1641 char const *errorMessage) 1642{ 1643 if ((Context().Status() & CheckerStatus::IGNORE_VISIBILITY) != 0U || 1644 (!signature->HasSignatureFlag(SignatureFlags::PRIVATE) && 1645 !signature->HasSignatureFlag(SignatureFlags::PROTECTED))) { 1646 return; 1647 } 1648 const auto *declNode = callee->GetDeclNode(); 1649 auto *containingClass = Context().ContainingClass(); 1650 bool isContainingSignatureInherited = containingClass->IsSignatureInherited(signature); 1651 ASSERT(declNode && (declNode->IsClassDefinition() || declNode->IsTSInterfaceDeclaration())); 1652 1653 if (declNode->IsTSInterfaceDeclaration()) { 1654 const auto *enclosingFunc = 1655 util::Helpers::FindAncestorGivenByType(callExpr, ir::AstNodeType::SCRIPT_FUNCTION)->AsScriptFunction(); 1656 if (callExpr->Callee()->IsMemberExpression() && 1657 callExpr->Callee()->AsMemberExpression()->Object()->IsThisExpression() && 1658 signature->Function()->IsPrivate() && !enclosingFunc->IsPrivate()) { 1659 LogTypeError({"Cannot reference 'this' in this context."}, enclosingFunc->Start()); 1660 } 1661 1662 if (containingClass == declNode->AsTSInterfaceDeclaration()->TsType() && isContainingSignatureInherited) { 1663 return; 1664 } 1665 } 1666 if (containingClass == declNode->AsClassDefinition()->TsType() && isContainingSignatureInherited) { 1667 return; 1668 } 1669 1670 bool isSignatureInherited = callee->IsSignatureInherited(signature); 1671 const auto *currentOutermost = containingClass->OutermostClass(); 1672 if (!signature->HasSignatureFlag(SignatureFlags::PRIVATE) && 1673 ((signature->HasSignatureFlag(SignatureFlags::PROTECTED) && containingClass->IsDescendantOf(callee)) || 1674 (currentOutermost != nullptr && currentOutermost == callee->OutermostClass())) && 1675 isSignatureInherited) { 1676 return; 1677 } 1678 1679 if (errorMessage == nullptr) { 1680 LogTypeError({"Signature ", signature->Function()->Id()->Name(), signature, " is not visible here."}, pos); 1681 return; 1682 } 1683 LogTypeError(errorMessage, pos); 1684} 1685 1686void ETSChecker::CheckCapturedVariable(ir::AstNode *const node, varbinder::Variable *const var) 1687{ 1688 if (node->IsIdentifier()) { 1689 const auto *const parent = node->Parent(); 1690 1691 if (parent->IsUpdateExpression() || 1692 (parent->IsAssignmentExpression() && parent->AsAssignmentExpression()->Left() == node)) { 1693 const auto *const identNode = node->AsIdentifier(); 1694 1695 const auto *resolved = identNode->Variable(); 1696 1697 if (resolved == nullptr) { 1698 resolved = 1699 FindVariableInFunctionScope(identNode->Name(), varbinder::ResolveBindingOptions::ALL_NON_TYPE); 1700 } 1701 1702 if (resolved == nullptr) { 1703 resolved = FindVariableInGlobal(identNode, varbinder::ResolveBindingOptions::ALL_NON_TYPE); 1704 } 1705 1706 if (resolved == var) { 1707 // For mutable captured variable [possible] smart-cast is senseless (or even erroneous) 1708 Context().RemoveSmartCast(var); 1709 } 1710 } 1711 } 1712 1713 CheckCapturedVariableInSubnodes(node, var); 1714} 1715 1716void ETSChecker::CheckCapturedVariableInSubnodes(ir::AstNode *node, varbinder::Variable *var) 1717{ 1718 if (!node->IsClassDefinition()) { 1719 node->Iterate([this, var](ir::AstNode *childNode) { CheckCapturedVariable(childNode, var); }); 1720 } 1721} 1722 1723void ETSChecker::CheckCapturedVariables() 1724{ 1725 // If we want to capture non constant local variables, we should wrap them in a generic reference class 1726 for (auto [var, _] : Context().CapturedVars()) { 1727 (void)_; 1728 if ((var->Declaration() == nullptr) || var->Declaration()->IsConstDecl() || 1729 !var->HasFlag(varbinder::VariableFlags::LOCAL) || var->GetScope()->Node()->IsArrowFunctionExpression()) { 1730 continue; 1731 } 1732 1733 auto *searchNode = var->Declaration()->Node()->Parent(); 1734 1735 if (searchNode->IsVariableDeclarator()) { 1736 searchNode = searchNode->Parent()->Parent(); 1737 } 1738 1739 CheckCapturedVariableInSubnodes(searchNode, var); 1740 } 1741} 1742 1743bool ETSChecker::AreOverrideEquivalent(Signature *const s1, Signature *const s2) 1744{ 1745 // Two functions, methods or constructors M and N have the same signature if 1746 // their names and type parameters (if any) are the same, and their formal parameter 1747 // types are also the same (after the formal parameter types of N are adapted to the type parameters of M). 1748 // Signatures s1 and s2 are override-equivalent only if s1 and s2 are the same. 1749 1750 SavedTypeRelationFlagsContext savedFlagsCtx(Relation(), TypeRelationFlag::OVERRIDING_CONTEXT); 1751 return s1->Function()->Id()->Name() == s2->Function()->Id()->Name() && Relation()->IsCompatibleTo(s1, s2); 1752} 1753 1754bool ETSChecker::IsReturnTypeSubstitutable(Signature *const s1, Signature *const s2) 1755{ 1756 auto *const r1 = s1->ReturnType(); 1757 auto *const r2 = s2->ReturnType(); 1758 1759 // A method declaration d1 with return type R1 is return-type-substitutable for another method d2 with return 1760 // type R2 if any of the following is true: 1761 1762 // - If R1 is a primitive type then R2 is identical to R1. 1763 if (r1->HasTypeFlag(TypeFlag::ETS_PRIMITIVE | TypeFlag::ETS_INT_ENUM | TypeFlag::ETS_STRING_ENUM | 1764 TypeFlag::ETS_VOID)) { 1765 return Relation()->IsIdenticalTo(r2, r1); 1766 } 1767 1768 // - If R1 is a reference type then R1, adapted to the type parameters of d2 (link to generic methods), is a 1769 // subtype of R2. 1770 ASSERT(IsReferenceType(r1)); 1771 1772 if (Relation()->IsSupertypeOf(r2, r1)) { 1773 return true; 1774 } 1775 1776 return s2->Function()->ReturnTypeAnnotation()->IsETSTypeReference() && 1777 Relation()->IsSupertypeOf( 1778 s2->Function()->ReturnTypeAnnotation()->GetType(this)->AsETSTypeParameter()->GetConstraintType(), r1); 1779} 1780 1781std::string ETSChecker::GetAsyncImplName(const util::StringView &name) 1782{ 1783 std::string implName(name); 1784 implName += "$asyncimpl"; 1785 return implName; 1786} 1787 1788std::string ETSChecker::GetAsyncImplName(ir::MethodDefinition *asyncMethod) 1789{ 1790 ir::Identifier *asyncName = asyncMethod->Function()->Id(); 1791 ASSERT(asyncName != nullptr); 1792 return GetAsyncImplName(asyncName->Name()); 1793} 1794 1795bool ETSChecker::IsAsyncImplMethod(ir::MethodDefinition const *method) 1796{ 1797 auto methodName = method->Key()->AsIdentifier()->Name().Utf8(); 1798 std::string_view asyncSuffix = "$asyncimpl"; 1799 if (methodName.size() < asyncSuffix.size()) { 1800 return false; 1801 } 1802 return methodName.substr(methodName.size() - asyncSuffix.size()) == asyncSuffix; 1803} 1804 1805ir::MethodDefinition *ETSChecker::CreateAsyncImplMethod(ir::MethodDefinition *asyncMethod, 1806 ir::ClassDefinition *classDef) 1807{ 1808 util::UString implName(GetAsyncImplName(asyncMethod), Allocator()); 1809 ir::ModifierFlags modifiers = asyncMethod->Modifiers(); 1810 // clear ASYNC flag for implementation 1811 modifiers &= ~ir::ModifierFlags::ASYNC; 1812 ir::ScriptFunction *asyncFunc = asyncMethod->Function(); 1813 ir::ScriptFunctionFlags flags = ir::ScriptFunctionFlags::METHOD; 1814 1815 if (asyncFunc->IsProxy()) { 1816 flags |= ir::ScriptFunctionFlags::PROXY; 1817 } 1818 1819 if (asyncFunc->HasReturnStatement()) { 1820 flags |= ir::ScriptFunctionFlags::HAS_RETURN; 1821 } 1822 1823 asyncMethod->AddModifier(ir::ModifierFlags::NATIVE); 1824 asyncFunc->AddModifier(ir::ModifierFlags::NATIVE); 1825 // Create async_impl method copied from CreateInvokeFunction 1826 auto scopeCtx = 1827 varbinder::LexicalScope<varbinder::ClassScope>::Enter(VarBinder(), classDef->Scope()->AsClassScope()); 1828 auto *body = asyncFunc->Body(); 1829 ArenaVector<ir::Expression *> params(Allocator()->Adapter()); 1830 // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 1831 varbinder::FunctionParamScope *paramScope = CopyParams(asyncFunc->Params(), params); 1832 1833 ir::ETSTypeReference *returnTypeAnn = nullptr; 1834 1835 if (!asyncFunc->Signature()->HasSignatureFlag(SignatureFlags::NEED_RETURN_TYPE)) { 1836 // Set impl method return type "Object" because it may return Promise as well as Promise parameter's type 1837 auto *objectId = AllocNode<ir::Identifier>(compiler::Signatures::BUILTIN_OBJECT_CLASS, Allocator()); 1838 objectId->SetReference(); 1839 VarBinder()->AsETSBinder()->LookupTypeReference(objectId, false); 1840 returnTypeAnn = 1841 AllocNode<ir::ETSTypeReference>(AllocNode<ir::ETSTypeReferencePart>(objectId, nullptr, nullptr)); 1842 objectId->SetParent(returnTypeAnn->Part()); 1843 returnTypeAnn->Part()->SetParent(returnTypeAnn); 1844 auto *asyncFuncRetTypeAnn = asyncFunc->ReturnTypeAnnotation(); 1845 auto *promiseType = [this](ir::TypeNode *type) { 1846 if (type != nullptr) { 1847 return type->GetType(this)->AsETSObjectType(); 1848 } 1849 1850 return GlobalBuiltinPromiseType()->AsETSObjectType(); 1851 }(asyncFuncRetTypeAnn); 1852 // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 1853 auto *retType = Allocator()->New<ETSAsyncFuncReturnType>(Allocator(), Relation(), promiseType); 1854 returnTypeAnn->SetTsType(retType); 1855 } 1856 1857 ir::MethodDefinition *implMethod = 1858 CreateMethod(implName.View(), modifiers, flags, std::move(params), paramScope, returnTypeAnn, body); 1859 asyncFunc->SetBody(nullptr); 1860 1861 if (returnTypeAnn != nullptr) { 1862 returnTypeAnn->SetParent(implMethod->Function()); 1863 } 1864 1865 implMethod->Function()->AddFlag(ir::ScriptFunctionFlags::ASYNC_IMPL); 1866 implMethod->SetParent(asyncMethod->Parent()); 1867 return implMethod; 1868} 1869 1870static void CreateFuncDecl(ETSChecker *checker, ir::MethodDefinition *func, varbinder::LocalScope *scope) 1871{ 1872 auto *allocator = checker->Allocator(); 1873 auto *varBinder = checker->VarBinder(); 1874 // Add the function declarations to the lambda class scope 1875 auto ctx = varbinder::LexicalScope<varbinder::LocalScope>::Enter(varBinder, scope); 1876 varbinder::Variable *var = scope->FindLocal(func->Id()->Name(), varbinder::ResolveBindingOptions::ALL_DECLARATION); 1877 if (var == nullptr) { 1878 var = std::get<1>( 1879 varBinder->NewVarDecl<varbinder::FunctionDecl>(func->Start(), allocator, func->Id()->Name(), func)); 1880 } 1881 var->AddFlag(varbinder::VariableFlags::METHOD); 1882 var->SetScope(ctx.GetScope()); 1883 func->Function()->Id()->SetVariable(var); 1884} 1885 1886ir::MethodDefinition *ETSChecker::CreateAsyncProxy(ir::MethodDefinition *asyncMethod, ir::ClassDefinition *classDef, 1887 bool createDecl) 1888{ 1889 ir::ScriptFunction *asyncFunc = asyncMethod->Function(); 1890 if (!asyncFunc->IsExternal()) { 1891 VarBinder()->AsETSBinder()->GetRecordTable()->Signatures().push_back(asyncFunc->Scope()); 1892 } 1893 1894 // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 1895 ir::MethodDefinition *implMethod = CreateAsyncImplMethod(asyncMethod, classDef); 1896 varbinder::FunctionScope *implFuncScope = implMethod->Function()->Scope(); 1897 for (auto *decl : asyncFunc->Scope()->Decls()) { 1898 auto res = asyncFunc->Scope()->Bindings().find(decl->Name()); 1899 ASSERT(res != asyncFunc->Scope()->Bindings().end()); 1900 auto *const var = std::get<1>(*res); 1901 var->SetScope(implFuncScope); 1902 implFuncScope->Decls().push_back(decl); 1903 implFuncScope->InsertBinding(decl->Name(), var); 1904 } 1905 1906 ReplaceScope(implMethod->Function()->Body(), asyncFunc, implFuncScope); 1907 1908 ArenaVector<varbinder::Variable *> captured(Allocator()->Adapter()); 1909 1910 bool isStatic = asyncMethod->IsStatic(); 1911 if (createDecl) { 1912 if (isStatic) { 1913 CreateFuncDecl(this, implMethod, classDef->Scope()->AsClassScope()->StaticMethodScope()); 1914 } else { 1915 CreateFuncDecl(this, implMethod, classDef->Scope()->AsClassScope()->InstanceMethodScope()); 1916 } 1917 implMethod->Id()->SetVariable(implMethod->Function()->Id()->Variable()); 1918 } 1919 VarBinder()->AsETSBinder()->BuildProxyMethod(implMethod->Function(), classDef->InternalName(), isStatic, 1920 asyncFunc->IsExternal()); 1921 implMethod->SetParent(asyncMethod->Parent()); 1922 1923 return implMethod; 1924} 1925 1926ir::MethodDefinition *ETSChecker::CreateMethod(const util::StringView &name, ir::ModifierFlags modifiers, 1927 ir::ScriptFunctionFlags flags, ArenaVector<ir::Expression *> &¶ms, 1928 varbinder::FunctionParamScope *paramScope, ir::TypeNode *returnType, 1929 ir::AstNode *body) 1930{ 1931 // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 1932 auto *nameId = AllocNode<ir::Identifier>(name, Allocator()); 1933 // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 1934 auto *scope = VarBinder()->Allocator()->New<varbinder::FunctionScope>(Allocator(), paramScope); 1935 // clang-format off 1936 auto *const func = AllocNode<ir::ScriptFunction>( 1937 Allocator(), ir::ScriptFunction::ScriptFunctionData { 1938 body, ir::FunctionSignature(nullptr, std::move(params), returnType), flags, modifiers}); 1939 // clang-format on 1940 func->SetScope(scope); 1941 func->SetIdent(nameId); 1942 if (body != nullptr && body->IsBlockStatement()) { 1943 body->AsBlockStatement()->SetScope(scope); 1944 } 1945 scope->BindNode(func); 1946 paramScope->BindNode(func); 1947 scope->BindParamScope(paramScope); 1948 paramScope->BindFunctionScope(scope); 1949 // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 1950 auto *funcExpr = AllocNode<ir::FunctionExpression>(func); 1951 auto *nameClone = nameId->Clone(Allocator(), nullptr); 1952 // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 1953 auto *method = AllocNode<ir::MethodDefinition>(ir::MethodDefinitionKind::METHOD, nameClone, funcExpr, modifiers, 1954 Allocator(), false); 1955 return method; 1956} 1957 1958varbinder::FunctionParamScope *ETSChecker::CopyParams(const ArenaVector<ir::Expression *> ¶ms, 1959 ArenaVector<ir::Expression *> &outParams) 1960{ 1961 auto paramCtx = varbinder::LexicalScope<varbinder::FunctionParamScope>(VarBinder()); 1962 1963 for (auto *const it : params) { 1964 auto *const paramOld = it->AsETSParameterExpression(); 1965 // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 1966 auto *const paramNew = paramOld->Clone(Allocator(), paramOld->Parent())->AsETSParameterExpression(); 1967 1968 auto *const var = std::get<1>(VarBinder()->AddParamDecl(paramNew)); 1969 1970 var->SetTsType(paramOld->Ident()->Variable()->TsType()); 1971 var->SetScope(paramCtx.GetScope()); 1972 paramNew->SetVariable(var); 1973 1974 paramNew->SetTsType(paramOld->Ident()->Variable()->TsType()); 1975 1976 outParams.emplace_back(paramNew); 1977 } 1978 1979 return paramCtx.GetScope(); 1980} 1981 1982void ETSChecker::ReplaceScope(ir::AstNode *root, ir::AstNode *oldNode, varbinder::Scope *newScope) 1983{ 1984 if (root == nullptr) { 1985 return; 1986 } 1987 1988 root->Iterate([this, oldNode, newScope](ir::AstNode *child) { 1989 auto *scope = NodeScope(child); 1990 if (scope != nullptr) { 1991 while (scope->Parent() != nullptr && scope->Parent()->Node() != oldNode) { 1992 scope = scope->Parent(); 1993 } 1994 scope->SetParent(newScope); 1995 } else { 1996 ReplaceScope(child, oldNode, newScope); 1997 } 1998 }); 1999} 2000 2001void ETSChecker::MoveTrailingBlockToEnclosingBlockStatement(ir::CallExpression *callExpr) 2002{ 2003 if (callExpr == nullptr) { 2004 return; 2005 } 2006 2007 ir::AstNode *parent = callExpr->Parent(); 2008 ir::AstNode *current = callExpr; 2009 while (parent != nullptr) { 2010 if (!parent->IsBlockStatement()) { 2011 current = parent; 2012 parent = parent->Parent(); 2013 } else { 2014 // Collect trailing block, insert it only when block statements traversal ends to avoid order mismatch. 2015 parent->AsBlockStatement()->AddTrailingBlock(current, callExpr->TrailingBlock()); 2016 callExpr->TrailingBlock()->SetParent(parent); 2017 callExpr->SetTrailingBlock(nullptr); 2018 break; 2019 } 2020 } 2021} 2022 2023void ETSChecker::TransformTraillingLambda(ir::CallExpression *callExpr) 2024{ 2025 auto *trailingBlock = callExpr->TrailingBlock(); 2026 ASSERT(trailingBlock != nullptr); 2027 2028 auto *funcParamScope = varbinder::LexicalScope<varbinder::FunctionParamScope>(VarBinder()).GetScope(); 2029 auto paramCtx = varbinder::LexicalScope<varbinder::FunctionParamScope>::Enter(VarBinder(), funcParamScope, false); 2030 2031 auto funcCtx = varbinder::LexicalScope<varbinder::FunctionScope>(VarBinder()); 2032 auto *funcScope = funcCtx.GetScope(); 2033 funcScope->BindParamScope(funcParamScope); 2034 funcParamScope->BindFunctionScope(funcScope); 2035 funcParamScope->SetParent(trailingBlock->Scope()->Parent()); 2036 2037 for (auto [_, var] : trailingBlock->Scope()->Bindings()) { 2038 (void)_; 2039 if (var->GetScope() == trailingBlock->Scope()) { 2040 var->SetScope(funcScope); 2041 funcScope->InsertBinding(var->Name(), var); 2042 } 2043 } 2044 2045 ArenaVector<ir::Expression *> params(Allocator()->Adapter()); 2046 auto *funcNode = AllocNode<ir::ScriptFunction>( 2047 Allocator(), ir::ScriptFunction::ScriptFunctionData {trailingBlock, 2048 ir::FunctionSignature(nullptr, std::move(params), nullptr), 2049 ir::ScriptFunctionFlags::ARROW}); 2050 funcNode->SetScope(funcScope); 2051 funcScope->BindNode(funcNode); 2052 funcParamScope->BindNode(funcNode); 2053 2054 trailingBlock->SetScope(funcScope); 2055 ReplaceScope(funcNode->Body(), trailingBlock, funcScope); 2056 callExpr->SetTrailingBlock(nullptr); 2057 2058 // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 2059 auto *arrowFuncNode = AllocNode<ir::ArrowFunctionExpression>(funcNode); 2060 arrowFuncNode->SetRange(trailingBlock->Range()); 2061 arrowFuncNode->SetParent(callExpr); 2062 2063 callExpr->Arguments().push_back(arrowFuncNode); 2064} 2065 2066ArenaVector<ir::Expression *> ETSChecker::ExtendArgumentsWithFakeLamda(ir::CallExpression *callExpr) 2067{ 2068 auto funcCtx = varbinder::LexicalScope<varbinder::FunctionScope>(VarBinder()); 2069 auto *funcScope = funcCtx.GetScope(); 2070 ArenaVector<ir::Expression *> params(Allocator()->Adapter()); 2071 2072 ArenaVector<ir::Statement *> statements(Allocator()->Adapter()); 2073 // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) 2074 auto *body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements)); 2075 body->SetScope(funcScope); 2076 2077 auto *funcNode = AllocNode<ir::ScriptFunction>( 2078 Allocator(), 2079 ir::ScriptFunction::ScriptFunctionData {body, ir::FunctionSignature(nullptr, std::move(params), nullptr), 2080 ir::ScriptFunctionFlags::ARROW}); 2081 funcNode->SetScope(funcScope); 2082 funcScope->BindNode(funcNode); 2083 auto *arrowFuncNode = AllocNode<ir::ArrowFunctionExpression>(funcNode); 2084 arrowFuncNode->SetParent(callExpr); 2085 2086 ArenaVector<ir::Expression *> fakeArguments = callExpr->Arguments(); 2087 fakeArguments.push_back(arrowFuncNode); 2088 return fakeArguments; 2089} 2090 2091void ETSChecker::EnsureValidCurlyBrace(ir::CallExpression *callExpr) 2092{ 2093 if (callExpr->TrailingBlock() == nullptr) { 2094 return; 2095 } 2096 2097 if (callExpr->IsTrailingBlockInNewLine()) { 2098 MoveTrailingBlockToEnclosingBlockStatement(callExpr); 2099 return; 2100 } 2101 2102 LogTypeError({"No matching call signature with trailing lambda"}, callExpr->Start()); 2103} 2104 2105ETSObjectType *ETSChecker::GetCachedFunctionalInterface(ir::ETSFunctionType *type) 2106{ 2107 auto hash = GetHashFromFunctionType(type); 2108 auto it = functionalInterfaceCache_.find(hash); 2109 if (it == functionalInterfaceCache_.cend()) { 2110 return nullptr; 2111 } 2112 return it->second; 2113} 2114 2115void ETSChecker::CacheFunctionalInterface(ir::ETSFunctionType *type, ETSObjectType *ifaceType) 2116{ 2117 auto hash = GetHashFromFunctionType(type); 2118 ASSERT(functionalInterfaceCache_.find(hash) == functionalInterfaceCache_.cend()); 2119 functionalInterfaceCache_.emplace(hash, ifaceType); 2120} 2121 2122void ETSChecker::CollectReturnStatements(ir::AstNode *parent) 2123{ 2124 parent->Iterate([this](ir::AstNode *childNode) -> void { 2125 if (childNode->IsScriptFunction()) { 2126 return; 2127 } 2128 2129 if (childNode->IsReturnStatement()) { 2130 ir::ReturnStatement *returnStmt = childNode->AsReturnStatement(); 2131 returnStmt->Check(this); 2132 } 2133 2134 CollectReturnStatements(childNode); 2135 }); 2136} 2137 2138ArenaVector<ConstraintCheckRecord> &ETSChecker::PendingConstraintCheckRecords() 2139{ 2140 return pendingConstraintCheckRecords_; 2141} 2142 2143size_t &ETSChecker::ConstraintCheckScopesCount() 2144{ 2145 return constraintCheckScopesCount_; 2146} 2147 2148bool ETSChecker::CmpAssemblerTypesWithRank(Signature const *const sig1, Signature const *const sig2) noexcept 2149{ 2150 for (size_t ix = 0; ix < sig1->MinArgCount(); ix++) { 2151 std::stringstream s1; 2152 std::stringstream s2; 2153 sig1->Params()[ix]->TsType()->ToAssemblerTypeWithRank(s1); 2154 sig2->Params()[ix]->TsType()->ToAssemblerTypeWithRank(s2); 2155 if (s1.str() != s2.str()) { 2156 return false; 2157 break; 2158 } 2159 } 2160 return true; 2161} 2162 2163bool ETSChecker::HasSameAssemblySignature(Signature const *const sig1, Signature const *const sig2) noexcept 2164{ 2165 if (sig1->MinArgCount() != sig2->MinArgCount()) { 2166 return false; 2167 } 2168 2169 if (!CmpAssemblerTypesWithRank(sig1, sig2)) { 2170 return false; 2171 } 2172 auto *rv1 = sig1->RestVar(); 2173 auto *rv2 = sig2->RestVar(); 2174 if (rv1 == nullptr && rv2 == nullptr) { 2175 return true; 2176 } 2177 if (rv1 == nullptr || rv2 == nullptr) { // exactly one of them is null 2178 return false; 2179 } 2180 std::stringstream s1; 2181 std::stringstream s2; 2182 rv1->TsType()->ToAssemblerTypeWithRank(s1); 2183 rv2->TsType()->ToAssemblerTypeWithRank(s2); 2184 return s1.str() == s2.str(); 2185} 2186 2187bool ETSChecker::HasSameAssemblySignatures(ETSFunctionType const *const func1, 2188 ETSFunctionType const *const func2) noexcept 2189{ 2190 for (auto const *sig1 : func1->CallSignatures()) { 2191 for (auto const *sig2 : func2->CallSignatures()) { 2192 if (HasSameAssemblySignature(sig1, sig2)) { 2193 return true; 2194 } 2195 } 2196 } 2197 return false; 2198} 2199} // namespace ark::es2panda::checker 2200