From f0fdd10f993bbf460749aa2bd99f4e2e6dd982d6 Mon Sep 17 00:00:00 2001 From: Boglarka Haag Date: Mon, 15 Jan 2024 12:47:59 +0100 Subject: [PATCH] [ArkTS frontend] Methods with different rest params are not the same Problems with methods only different in rest parameters are solved. The rest parameter's type won't be ignored. Fixes #14496 internal issue. Signed-off-by: Haag Boglarka Change-Id: Iab255945a534dddd75485f35862bf8bea98bbba0 --- ets2panda/checker/ETSchecker.h | 8 + ets2panda/checker/ets/function.cpp | 206 +-- ets2panda/checker/types/signature.cpp | 4 + ets2panda/checker/types/typeRelation.h | 1 + ..._method_with_empty_rest_param-expected.txt | 1118 +++++++++++++++++ ..._specific_method_with_empty_rest_param.ets | 28 + ...most_specific_method_with_rest_param_1.ets | 29 + ...most_specific_method_with_rest_param_2.ets | 25 + ...most_specific_method_with_rest_param_3.ets | 20 + 9 files changed, 1352 insertions(+), 87 deletions(-) create mode 100644 ets2panda/test/compiler/ets/most_specific_method_with_empty_rest_param-expected.txt create mode 100644 ets2panda/test/compiler/ets/most_specific_method_with_empty_rest_param.ets create mode 100644 ets2panda/test/runtime/ets/most_specific_method_with_rest_param_1.ets create mode 100644 ets2panda/test/runtime/ets/most_specific_method_with_rest_param_2.ets create mode 100644 ets2panda/test/runtime/ets/most_specific_method_with_rest_param_3.ets diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 4bfd1cd011..b3b387a109 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -356,6 +356,14 @@ public: const ArenaVector &arguments, const lexer::SourcePosition &pos, std::string_view signatureKind, TypeRelationFlag resolveFlags = TypeRelationFlag::NONE); + Signature *FindMostSpecificSignature(const ArenaVector &signatures, + const ArenaMultiMap &bestSignaturesForParameter, + size_t paramCount); + void EvaluateMostSpecificSearch(Type *&mostSpecificType, Signature *&prevSig, const lexer::SourcePosition &pos, + Signature *sig, Type *sigType); + void SearchAmongMostSpecificTypes(Type *&mostSpecificType, Signature *&prevSig, const lexer::SourcePosition &pos, + size_t argumentsSize, size_t paramCount, size_t idx, Signature *sig, + bool lookForClassType); Signature *ChooseMostSpecificSignature(ArenaVector &signatures, const std::vector &argTypeInferenceRequired, const lexer::SourcePosition &pos, size_t argumentsSize = ULONG_MAX); diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index b1029acf50..1c18c8e60b 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -485,6 +485,10 @@ Signature *ETSChecker::ValidateSignature(Signature *signature, const ir::TSTypeP return nullptr; } + if (argumentCount > parameterCount && hasRestParameter && (flags & TypeRelationFlag::IGNORE_REST_PARAM) != 0) { + return nullptr; + } + auto count = std::min(parameterCount, argumentCount); // Check all required formal parameter(s) first if (!ValidateSignatureRequiredParams(substitutedSig, arguments, flags, argTypeInferenceRequired, throwError)) { @@ -553,7 +557,23 @@ bool IsSignatureAccessible(Signature *sig, ETSObjectType *containingClass, TypeR return false; } - +std::array GetFlagVariants() +{ + // NOTE(boglarkahaag): Not in sync with specification, but solves the issues with rest params for now (#17483) + return { + TypeRelationFlag::NO_THROW | TypeRelationFlag::NO_UNBOXING | TypeRelationFlag::NO_BOXING | + TypeRelationFlag::IGNORE_REST_PARAM, + TypeRelationFlag::NO_THROW | TypeRelationFlag::NO_UNBOXING | TypeRelationFlag::NO_BOXING, + TypeRelationFlag::NO_THROW | TypeRelationFlag::IGNORE_REST_PARAM, + TypeRelationFlag::NO_THROW, + TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING | TypeRelationFlag::NO_UNBOXING | + TypeRelationFlag::NO_BOXING | TypeRelationFlag::IGNORE_REST_PARAM, + TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING | TypeRelationFlag::NO_UNBOXING | + TypeRelationFlag::NO_BOXING, + TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING | TypeRelationFlag::IGNORE_REST_PARAM, + TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING, + }; +} ArenaVector ETSChecker::CollectSignatures(ArenaVector &signatures, const ir::TSTypeParameterInstantiation *typeArguments, const ArenaVector &arguments, @@ -589,13 +609,7 @@ ArenaVector ETSChecker::CollectSignatures(ArenaVector TypeRelationFlag flags = TypeRelationFlag::WIDENING | resolveFlags; collectSignatures(flags); } else { - std::array flagVariants {TypeRelationFlag::NO_THROW | TypeRelationFlag::NO_UNBOXING | - TypeRelationFlag::NO_BOXING, - TypeRelationFlag::NO_THROW, - TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING | - TypeRelationFlag::NO_UNBOXING | TypeRelationFlag::NO_BOXING, - TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING}; - for (auto flags : flagVariants) { + for (auto flags : GetFlagVariants()) { flags = flags | resolveFlags; collectSignatures(flags); if (!compatibleSignatures.empty()) { @@ -677,6 +691,91 @@ Signature *ETSChecker::ValidateSignatures(ArenaVector &signatures, return nullptr; } +Signature *ETSChecker::FindMostSpecificSignature(const ArenaVector &signatures, + const ArenaMultiMap &bestSignaturesForParameter, + size_t paramCount) +{ + Signature *mostSpecificSignature = nullptr; + + for (auto *sig : signatures) { + bool mostSpecific = true; + + for (size_t paramIdx = 0; paramIdx < paramCount; ++paramIdx) { + const auto range = bestSignaturesForParameter.equal_range(paramIdx); + // Check if signature is most specific for i. parameter type. + mostSpecific = std::any_of(range.first, range.second, [&sig](auto entry) { return entry.second == sig; }); + if (!mostSpecific) { + break; + } + } + + if (!mostSpecific) { + continue; + } + if (mostSpecificSignature == nullptr) { + mostSpecificSignature = sig; + continue; + } + if (mostSpecificSignature->Owner() == sig->Owner()) { + // NOTE: audovichenko. Remove this 'if' when #12443 gets resolved + if (mostSpecificSignature->Function() == sig->Function()) { + // The same signature + continue; + } + return nullptr; + } + } + return mostSpecificSignature; +} + +static void InitMostSpecificType(const ArenaVector &signatures, [[maybe_unused]] Type *&mostSpecificType, + [[maybe_unused]] Signature *&prevSig, const size_t idx) +{ + for (auto *sig : signatures) { + if (Type *sigType = sig->Params().at(idx)->TsType(); + sigType->IsETSObjectType() && !sigType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INTERFACE)) { + mostSpecificType = sigType; + prevSig = sig; + return; + } + } +} + +void ETSChecker::EvaluateMostSpecificSearch(Type *&mostSpecificType, Signature *&prevSig, + const lexer::SourcePosition &pos, Signature *sig, Type *sigType) +{ + if (Relation()->IsAssignableTo(sigType, mostSpecificType)) { + mostSpecificType = sigType; + prevSig = sig; + } else if (sigType->IsETSObjectType() && mostSpecificType->IsETSObjectType() && + !Relation()->IsAssignableTo(mostSpecificType, sigType)) { + auto funcName = sig->Function()->Id()->Name(); + ThrowTypeError({"Call to `", funcName, "` is ambiguous as `2` versions of `", funcName, "` are available: `", + funcName, prevSig, "` and `", funcName, sig, "`"}, + pos); + } +} + +void ETSChecker::SearchAmongMostSpecificTypes(Type *&mostSpecificType, Signature *&prevSig, + const lexer::SourcePosition &pos, const size_t argumentsSize, + const size_t paramCount, const size_t idx, Signature *sig, + const bool lookForClassType) +{ + if (lookForClassType && argumentsSize == ULONG_MAX) { + [[maybe_unused]] const bool equalParamSize = sig->Params().size() == paramCount; + ASSERT(equalParamSize); + } + Type *sigType = sig->Params().at(idx)->TsType(); + const bool isClassType = + sigType->IsETSObjectType() && !sigType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INTERFACE); + if (isClassType == lookForClassType) { + if (Relation()->IsIdenticalTo(sigType, mostSpecificType)) { + return; + } + EvaluateMostSpecificSearch(mostSpecificType, prevSig, pos, sig, sigType); + } +} + Signature *ETSChecker::ChooseMostSpecificSignature(ArenaVector &signatures, const std::vector &argTypeInferenceRequired, const lexer::SourcePosition &pos, size_t argumentsSize) @@ -694,7 +793,10 @@ Signature *ETSChecker::ChooseMostSpecificSignature(ArenaVector &sig // Multiple signatures with zero parameter because of inheritance. // Return the closest one in inheritance chain that is defined at the beginning of the vector. if (paramCount == 0) { - return signatures.front(); + if (signatures.front()->RestVar() == nullptr) { + return signatures.front(); + } + ThrowTypeError({"Call to `", signatures.front()->Function()->Id()->Name(), "` is ambiguous "}, pos); } // Collect which signatures are most specific for each parameter. @@ -714,51 +816,13 @@ Signature *ETSChecker::ChooseMostSpecificSignature(ArenaVector &sig Type *mostSpecificType = signatures.front()->Params().at(i)->TsType(); Signature *prevSig = signatures.front(); - auto initMostSpecificType = [&mostSpecificType, &prevSig, i](Signature *sig) { - if (Type *sigType = sig->Params().at(i)->TsType(); - sigType->IsETSObjectType() && !sigType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INTERFACE)) { - mostSpecificType = sigType; - prevSig = sig; - return true; - } - return false; - }; - - auto evaluateResult = [this, &mostSpecificType, &prevSig, pos](Signature *sig, Type *sigType) { - if (Relation()->IsAssignableTo(sigType, mostSpecificType)) { - mostSpecificType = sigType; - prevSig = sig; - } else if (sigType->IsETSObjectType() && mostSpecificType->IsETSObjectType() && - !Relation()->IsAssignableTo(mostSpecificType, sigType)) { - auto funcName = sig->Function()->Id()->Name(); - ThrowTypeError({"Call to `", funcName, "` is ambiguous as `2` versions of `", funcName, - "` are available: `", funcName, prevSig, "` and `", funcName, sig, "`"}, - pos); - } - }; - - auto searchAmongTypes = [this, &mostSpecificType, argumentsSize, paramCount, i, - &evaluateResult](Signature *sig, const bool lookForClassType) { - if (lookForClassType && argumentsSize == ULONG_MAX) { - [[maybe_unused]] const bool equalParamSize = sig->Params().size() == paramCount; - ASSERT(equalParamSize); - } - Type *sigType = sig->Params().at(i)->TsType(); - const bool isClassType = - sigType->IsETSObjectType() && !sigType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INTERFACE); - if (isClassType == lookForClassType) { - if (Relation()->IsIdenticalTo(sigType, mostSpecificType)) { - return; - } - evaluateResult(sig, sigType); - } - }; - - std::any_of(signatures.begin(), signatures.end(), initMostSpecificType); - std::for_each(signatures.begin(), signatures.end(), - [&searchAmongTypes](Signature *sig) mutable { searchAmongTypes(sig, true); }); - std::for_each(signatures.begin(), signatures.end(), - [&searchAmongTypes](Signature *sig) mutable { searchAmongTypes(sig, false); }); + InitMostSpecificType(signatures, mostSpecificType, prevSig, i); + for (auto *sig : signatures) { + SearchAmongMostSpecificTypes(mostSpecificType, prevSig, pos, argumentsSize, paramCount, i, sig, true); + } + for (auto *sig : signatures) { + SearchAmongMostSpecificTypes(mostSpecificType, prevSig, pos, argumentsSize, paramCount, i, sig, false); + } for (auto *sig : signatures) { Type *sigType = sig->Params().at(i)->TsType(); @@ -767,40 +831,8 @@ Signature *ETSChecker::ChooseMostSpecificSignature(ArenaVector &sig } } } - // Find the signature that are most specific for all parameters. - Signature *mostSpecificSignature = nullptr; - - for (auto *sig : signatures) { - bool mostSpecific = true; - - for (size_t paramIdx = 0; paramIdx < paramCount; ++paramIdx) { - const auto range = bestSignaturesForParameter.equal_range(paramIdx); - // Check if signature is most specific for i. parameter type. - const bool hasSignature = - std::any_of(range.first, range.second, [&sig](auto entry) { return entry.second == sig; }); - if (!hasSignature) { - mostSpecific = false; - break; - } - } - - if (!mostSpecific) { - continue; - } - if (mostSpecificSignature == nullptr) { - mostSpecificSignature = sig; - continue; - } - if (mostSpecificSignature->Owner() == sig->Owner()) { - // NOTE: audovichenko. Remove this 'if' when #12443 gets resolved - if (mostSpecificSignature->Function() == sig->Function()) { - // The same signature - continue; - } - return nullptr; - } - } + Signature *mostSpecificSignature = FindMostSpecificSignature(signatures, bestSignaturesForParameter, paramCount); return mostSpecificSignature; } diff --git a/ets2panda/checker/types/signature.cpp b/ets2panda/checker/types/signature.cpp index cb7f832a5c..6fa8c78594 100644 --- a/ets2panda/checker/types/signature.cpp +++ b/ets2panda/checker/types/signature.cpp @@ -298,6 +298,10 @@ void Signature::Compatible(TypeRelation *relation, Signature *other) 3. == this->Params().size(), must be < otherToCheckParametersNumber as described in 2, and we need to check the remaining mandatory parameters of "other" against the RestVar of "this". */ + if (other->RestVar() != nullptr && this->RestVar() != nullptr) { + relation->IsIdenticalTo(this->RestVar()->TsType(), other->RestVar()->TsType()); + } + if (i == toCheckParametersNumber) { return; } diff --git a/ets2panda/checker/types/typeRelation.h b/ets2panda/checker/types/typeRelation.h index d7af81d3a4..f1950ad2ab 100644 --- a/ets2panda/checker/types/typeRelation.h +++ b/ets2panda/checker/types/typeRelation.h @@ -58,6 +58,7 @@ enum class TypeRelationFlag : uint32_t { NO_CHECK_TRAILING_LAMBDA = 1U << 23U, NO_THROW_GENERIC_TYPEALIAS = 1U << 24U, OVERRIDING_CONTEXT = 1U << 25U, + IGNORE_REST_PARAM = 1U << 26U, ASSIGNMENT_CONTEXT = WIDENING | BOXING | UNBOXING, CASTING_CONTEXT = NARROWING | WIDENING | BOXING | UNBOXING | UNCHECKED_CAST, diff --git a/ets2panda/test/compiler/ets/most_specific_method_with_empty_rest_param-expected.txt b/ets2panda/test/compiler/ets/most_specific_method_with_empty_rest_param-expected.txt new file mode 100644 index 0000000000..8b3cc8c499 --- /dev/null +++ b/ets2panda/test/compiler/ets/most_specific_method_with_empty_rest_param-expected.txt @@ -0,0 +1,1118 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "C", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "met", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 12 + }, + "end": { + "line": 17, + "column": 15 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "met", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 12 + }, + "end": { + "line": 17, + "column": 15 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "rest parameter": { + "type": "RestElement", + "argument": { + "type": "Identifier", + "name": "p", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 22 + }, + "end": { + "line": 17, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 22 + }, + "end": { + "line": 17, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 22 + }, + "end": { + "line": 17, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 30 + }, + "end": { + "line": 17, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 16 + }, + "end": { + "line": 17, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 16 + }, + "end": { + "line": 17, + "column": 31 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 33 + }, + "end": { + "line": 17, + "column": 39 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 33 + }, + "end": { + "line": 17, + "column": 41 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 33 + }, + "end": { + "line": 17, + "column": 41 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "StringLiteral", + "value": "nR", + "loc": { + "start": { + "line": 18, + "column": 17 + }, + "end": { + "line": 18, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 10 + }, + "end": { + "line": 18, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 40 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + "overloads": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "met", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 12 + }, + "end": { + "line": 20, + "column": 15 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "met", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 12 + }, + "end": { + "line": 20, + "column": 15 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "rest parameter": { + "type": "RestElement", + "argument": { + "type": "Identifier", + "name": "p", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 19 + }, + "end": { + "line": 20, + "column": 20 + } + } + }, + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Number", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 31 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 33 + }, + "end": { + "line": 20, + "column": 39 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 33 + }, + "end": { + "line": 20, + "column": 41 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 33 + }, + "end": { + "line": 20, + "column": 41 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "StringLiteral", + "value": "NR", + "loc": { + "start": { + "line": 21, + "column": 16 + }, + "end": { + "line": 21, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 9 + }, + "end": { + "line": 21, + "column": 20 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 40 + }, + "end": { + "line": 22, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 15 + }, + "end": { + "line": 22, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 15 + }, + "end": { + "line": 22, + "column": 6 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 22, + "column": 6 + } + } + } + ], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 2 + }, + "end": { + "line": 23, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 23, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 23, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 10 + }, + "end": { + "line": 25, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 10 + }, + "end": { + "line": 25, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "c", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "C", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 12 + }, + "end": { + "line": 26, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 12 + }, + "end": { + "line": 26, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 12 + }, + "end": { + "line": 26, + "column": 15 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 9 + }, + "end": { + "line": 26, + "column": 10 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "C", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 20 + }, + "end": { + "line": 26, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 20 + }, + "end": { + "line": 26, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 20 + }, + "end": { + "line": 26, + "column": 22 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 26, + "column": 16 + }, + "end": { + "line": 27, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 9 + }, + "end": { + "line": 27, + "column": 6 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 27, + "column": 6 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 5 + }, + "end": { + "line": 27, + "column": 6 + } + } + }, + "property": { + "type": "Identifier", + "name": "met", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 7 + }, + "end": { + "line": 27, + "column": 10 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 27, + "column": 5 + }, + "end": { + "line": 27, + "column": 10 + } + } + }, + "arguments": [], + "optional": false, + "loc": { + "start": { + "line": 27, + "column": 5 + }, + "end": { + "line": 27, + "column": 12 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 5 + }, + "end": { + "line": 27, + "column": 12 + } + } + } + ], + "loc": { + "start": { + "line": 25, + "column": 17 + }, + "end": { + "line": 28, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 14 + }, + "end": { + "line": 28, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 14 + }, + "end": { + "line": 28, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 1 + }, + "end": { + "line": 28, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 29, + "column": 1 + } + } +} +TypeError: Call to `met` is ambiguous [most_specific_method_with_empty_rest_param.ets:27:5] diff --git a/ets2panda/test/compiler/ets/most_specific_method_with_empty_rest_param.ets b/ets2panda/test/compiler/ets/most_specific_method_with_empty_rest_param.ets new file mode 100644 index 0000000000..730268e39c --- /dev/null +++ b/ets2panda/test/compiler/ets/most_specific_method_with_empty_rest_param.ets @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class C { + public met(...p: number[]): string { + return "nR" + } + public met(...p: Number[]): string { + return "NR" + } +} + +function main() { + let c: C = new C() + c.met() +} diff --git a/ets2panda/test/runtime/ets/most_specific_method_with_rest_param_1.ets b/ets2panda/test/runtime/ets/most_specific_method_with_rest_param_1.ets new file mode 100644 index 0000000000..f818142af3 --- /dev/null +++ b/ets2panda/test/runtime/ets/most_specific_method_with_rest_param_1.ets @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class C { + public met(...p: number[]): string { + return "nR" + } + public met(...p: Number[]): string { + return "NR" + } +} + +function main() { + let c: C = new C() + assert c.met(0.0) == "nR" + assert c.met(new Number()) == "NR" +} diff --git a/ets2panda/test/runtime/ets/most_specific_method_with_rest_param_2.ets b/ets2panda/test/runtime/ets/most_specific_method_with_rest_param_2.ets new file mode 100644 index 0000000000..eab3c06fcf --- /dev/null +++ b/ets2panda/test/runtime/ets/most_specific_method_with_rest_param_2.ets @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + function foo(...x: string[]) { + return 1; +} + +function foo(...x: int[]) { + return 2; +} + +assert(foo("bar") == 1); +assert(foo(1) == 2); diff --git a/ets2panda/test/runtime/ets/most_specific_method_with_rest_param_3.ets b/ets2panda/test/runtime/ets/most_specific_method_with_rest_param_3.ets new file mode 100644 index 0000000000..d2ed4b1bab --- /dev/null +++ b/ets2panda/test/runtime/ets/most_specific_method_with_rest_param_3.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type B = Object | null; +function foo(...b : B[]) { return 1; } +function foo(str: String) { return 2; } + +assert(foo(new String()) == 2); -- Gitee