From eed8545d02acf5c061dbd0ce54ce058240478888 Mon Sep 17 00:00:00 2001 From: Boglarka Date: Mon, 26 May 2025 16:10:17 +0200 Subject: [PATCH] Ensure correct signature called after lowering Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/IC8XIP Reason: Object parameter type overload could hide the rest param Description: After rechecking the call argument in rest args lowering the new call would fit to Object parameter type signatures not only to rest params. Signed-off-by: Haag Boglarka --- ets2panda/checker/ets/function.cpp | 13 +++----- ets2panda/checker/types/ets/etsObjectType.cpp | 12 ++++--- ets2panda/checker/types/typeRelation.h | 1 + .../lowering/ets/restArgsLowering.cpp | 1 + ..._specific_method_with_empty_rest_param.ets | 2 ++ .../FixedArray/overload-resolution-rest.ets | 32 +++++++++++++++++++ ..._specific_method_with_empty_rest_param.ets | 1 + ...with_ambiguous_rest_parameter-expected.txt | 1 - ets2panda/util/diagnostic/semantic.yaml | 4 --- 9 files changed, 49 insertions(+), 18 deletions(-) create mode 100644 ets2panda/test/ast/compiler/ets/FixedArray/overload-resolution-rest.ets diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index de2fe9821a..9f0239c964 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -585,6 +585,10 @@ Signature *ETSChecker::ValidateSignature( size_t const argCount = arguments.size(); auto const hasRestParameter = signature->RestVar() != nullptr; auto const reportError = (flags & TypeRelationFlag::NO_THROW) == 0; + + if (((Relation()->GetTypeRelationFlags() & TypeRelationFlag::REST_ARGS_CONTEXT) != 0) && !hasRestParameter) { + return nullptr; + } size_t compareCount = argCount; if ((flags & TypeRelationFlag::NO_CHECK_TRAILING_LAMBDA) != 0 && !signature->Params().empty() && signature->Params().back()->Declaration()->Node()->AsETSParameterExpression()->IsOptional()) { @@ -1045,14 +1049,7 @@ Signature *ETSChecker::ChooseMostSpecificSignature(ArenaVector &sig return *zeroParamSignature; } // If there are multiple rest parameter signatures with different argument types, throw error - if (signatures.size() > 1 && - std::any_of(signatures.begin(), signatures.end(), [signatures, this](const auto *param) { - auto left = MaybeBoxType(GetElementTypeOfArray(param->RestVar()->TsType())); - auto right = MaybeBoxType(GetElementTypeOfArray(signatures.front()->RestVar()->TsType())); - Relation()->IsIdenticalTo(left, right); - return !Relation()->IsTrue(); - })) { - LogError(diagnostic::AMBIGUOUS_CALL_2, {signatures.front()->Function()->Id()->Name()}, pos); + if (signatures.size() > 1) { return nullptr; } // Else return the signature with the rest parameter diff --git a/ets2panda/checker/types/ets/etsObjectType.cpp b/ets2panda/checker/types/ets/etsObjectType.cpp index 733f658a53..64f21c5796 100644 --- a/ets2panda/checker/types/ets/etsObjectType.cpp +++ b/ets2panda/checker/types/ets/etsObjectType.cpp @@ -214,11 +214,13 @@ static void AddSignature(std::vector &signatures, PropertySearchFla if (((flags & PropertySearchFlags::IGNORE_ABSTRACT) != 0) && it->HasSignatureFlag(SignatureFlags::ABSTRACT)) { continue; } - if (std::any_of(signatures.begin(), signatures.end(), [&it, &checker](auto sig) { - return checker->AreOverrideCompatible(sig, it) && - it->Owner()->HasObjectFlag(ETSObjectFlags::INTERFACE) && - (checker->Relation()->IsSupertypeOf(it->Owner(), sig->Owner()) || - !sig->Owner()->HasObjectFlag(ETSObjectFlags::INTERFACE)); + if (!(it->IsFinal() || it->HasSignatureFlag(SignatureFlags::STATIC)) && + std::any_of(signatures.begin(), signatures.end(), [&it, &checker](auto sig) { + return checker->AreOverrideCompatible(it, sig) && + ((checker->Relation()->IsSupertypeOf(it->Owner(), sig->Owner()) && + !checker->Relation()->IsIdenticalTo(it->Owner(), sig->Owner())) || + (it->Owner()->HasObjectFlag(ETSObjectFlags::INTERFACE) && + !sig->Owner()->HasObjectFlag(ETSObjectFlags::INTERFACE))); })) { continue; } diff --git a/ets2panda/checker/types/typeRelation.h b/ets2panda/checker/types/typeRelation.h index ae65dc1229..a3329d5765 100644 --- a/ets2panda/checker/types/typeRelation.h +++ b/ets2panda/checker/types/typeRelation.h @@ -63,6 +63,7 @@ enum class TypeRelationFlag : uint32_t { OVERRIDING_CONTEXT = 1U << 25U, IGNORE_REST_PARAM = 1U << 26U, STRING_TO_CHAR = 1U << 27U, + REST_ARGS_CONTEXT = 1U << 28U, ASSIGNMENT_CONTEXT = WIDENING | BOXING | UNBOXING, BRIDGE_CHECK = OVERRIDING_CONTEXT | IGNORE_TYPE_PARAMETERS | NO_RETURN_TYPE_CHECK, diff --git a/ets2panda/compiler/lowering/ets/restArgsLowering.cpp b/ets2panda/compiler/lowering/ets/restArgsLowering.cpp index 224e980335..1969a16d48 100644 --- a/ets2panda/compiler/lowering/ets/restArgsLowering.cpp +++ b/ets2panda/compiler/lowering/ets/restArgsLowering.cpp @@ -143,6 +143,7 @@ static ir::CallExpression *RebuildCallExpression(public_lib::Context *context, i auto *scope = NearestScope(newCall->Parent()); auto bscope = varbinder::LexicalScope::Enter(varbinder, scope); + context->checker->Relation()->SetFlags(checker::TypeRelationFlag::REST_ARGS_CONTEXT); CheckLoweredNode(context->checker->VarBinder()->AsETSBinder(), context->checker->AsETSChecker(), newCall); newCall->RemoveAstNodeFlags(ir::AstNodeFlags::RESIZABLE_REST); return newCall; diff --git a/ets2panda/test/ast/compiler/ets/FixedArray/most_specific_method_with_empty_rest_param.ets b/ets2panda/test/ast/compiler/ets/FixedArray/most_specific_method_with_empty_rest_param.ets index e53edf414f..1c31c6eb2b 100644 --- a/ets2panda/test/ast/compiler/ets/FixedArray/most_specific_method_with_empty_rest_param.ets +++ b/ets2panda/test/ast/compiler/ets/FixedArray/most_specific_method_with_empty_rest_param.ets @@ -26,3 +26,5 @@ function main() { let c: C = new C() c.met() } + +/* @@? 27:5 Error TypeError: Reference to met is ambiguous */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/FixedArray/overload-resolution-rest.ets b/ets2panda/test/ast/compiler/ets/FixedArray/overload-resolution-rest.ets new file mode 100644 index 0000000000..9dcd5b6a74 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/FixedArray/overload-resolution-rest.ets @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 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. + */ + +let res: number = 0 + +function foo(a: NullishType) { + res = 1 +} + +function foo(...a: NullishType[]) { + res = 2 +} + +function foo(...a: FixedArray) { + res = 3 +} + +/* @@ label */foo("a", "b", "c", "d") + +/* @@@ label Error TypeError: Reference to foo is ambiguous */ diff --git a/ets2panda/test/ast/compiler/ets/most_specific_method_with_empty_rest_param.ets b/ets2panda/test/ast/compiler/ets/most_specific_method_with_empty_rest_param.ets index 7ec8ba7d89..f18d5f6150 100644 --- a/ets2panda/test/ast/compiler/ets/most_specific_method_with_empty_rest_param.ets +++ b/ets2panda/test/ast/compiler/ets/most_specific_method_with_empty_rest_param.ets @@ -28,3 +28,4 @@ function main() { } /* @@? 20:5 Error TypeError: Function met with this assembly signature already declared. */ +/* @@? 27:5 Error TypeError: Reference to met is ambiguous */ diff --git a/ets2panda/test/compiler/ets/functions_with_ambiguous_rest_parameter-expected.txt b/ets2panda/test/compiler/ets/functions_with_ambiguous_rest_parameter-expected.txt index 74d45b5f1b..8984eeaef5 100644 --- a/ets2panda/test/compiler/ets/functions_with_ambiguous_rest_parameter-expected.txt +++ b/ets2panda/test/compiler/ets/functions_with_ambiguous_rest_parameter-expected.txt @@ -904,5 +904,4 @@ } } TypeError: Function foo with this assembly signature already declared. [functions_with_ambiguous_rest_parameter.ets:20:1] -TypeError: Call to `foo` is ambiguous [functions_with_ambiguous_rest_parameter.ets:25:5] TypeError: Reference to foo is ambiguous [functions_with_ambiguous_rest_parameter.ets:25:5] diff --git a/ets2panda/util/diagnostic/semantic.yaml b/ets2panda/util/diagnostic/semantic.yaml index 6cb4ab1b32..d97f7a59c4 100644 --- a/ets2panda/util/diagnostic/semantic.yaml +++ b/ets2panda/util/diagnostic/semantic.yaml @@ -523,10 +523,6 @@ semantic: id: 128 message: "No matching {} signature" -- name: AMBIGUOUS_CALL_2 - id: 129 - message: "Call to `{}` is ambiguous " - - name: FUNCTION_REDECL_BY_TYPE_SIG id: 130 message: "Function {} is already declared." -- Gitee