From 7cc9f5a6490ee8523a4c81009d6e4387dfb69f66 Mon Sep 17 00:00:00 2001 From: zengzengran Date: Thu, 14 Aug 2025 11:21:43 +0800 Subject: [PATCH] Fix lambda parameter error interception Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICSSQH Description: The error occurred in the CheckLambdaAssignableUnion method. When determining whether assignment, it requires that lambda->params().size() == type->AsETSFunctionType()->params().size(). In reality, it only needs to be lambda->params().size() <= type->AsETSFunctionType()->params().size(). Tested-by: ninja tests (passed) ets_testrunner (passed) Signed-off-by: zengzengran # --- ets2panda/checker/ets/helpers.cpp | 4 +- .../ast/compiler/ets/lambda_type_infer_2.ets | 38 +++++++++++ .../test/runtime/ets/lambda_type_infer_2.ets | 66 +++++++++++++++++++ 3 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 ets2panda/test/ast/compiler/ets/lambda_type_infer_2.ets create mode 100644 ets2panda/test/runtime/ets/lambda_type_infer_2.ets diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index d6db109207..c51f8fad4d 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -2584,14 +2584,14 @@ bool ETSChecker::CheckLambdaAssignableUnion(ir::AstNode *typeAnn, ir::ScriptFunc bool assignable = false; for (auto *type : typeAnn->AsETSUnionType()->Types()) { if (type->IsETSFunctionType()) { - assignable |= lambda->Params().size() == type->AsETSFunctionType()->Params().size(); + assignable |= lambda->Params().size() <= type->AsETSFunctionType()->Params().size(); continue; } if (type->IsETSTypeReference()) { auto aliasType = util::Helpers::DerefETSTypeReference(type); assignable |= aliasType->IsETSFunctionType() && - lambda->Params().size() == aliasType->AsETSFunctionType()->Params().size(); + lambda->Params().size() <= aliasType->AsETSFunctionType()->Params().size(); } } diff --git a/ets2panda/test/ast/compiler/ets/lambda_type_infer_2.ets b/ets2panda/test/ast/compiler/ets/lambda_type_infer_2.ets new file mode 100644 index 0000000000..26421b1023 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/lambda_type_infer_2.ets @@ -0,0 +1,38 @@ +/* + * 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. + */ + +type Callback = (a:T1,b:T2)=>R; + +function foo(fun:((a:number,b:number)=>void)|undefined){} +function foo2(fun:Callback|undefined){} + +foo((a:string,b:number)=>{}) +foo((a:number,b:string)=>{}) +foo((a:string)=>{}) +foo(():string=>{return "abc"}) + +foo2((a:string,b:number)=>{}) +foo2((a:number,b:string)=>{}) +foo2((a:string)=>{}) +foo2(():string=>{return "abc"}) + +/* @@? 21:5 Error TypeError: Type '(a: String, b: Double) => void' is not compatible with type '(a: Double, b: Double) => void|undefined' at index 1 */ +/* @@? 22:5 Error TypeError: Type '(a: Double, b: String) => void' is not compatible with type '(a: Double, b: Double) => void|undefined' at index 1 */ +/* @@? 23:5 Error TypeError: Type '(a: String) => void' is not compatible with type '(a: Double, b: Double) => void|undefined' at index 1 */ +/* @@? 24:5 Error TypeError: Type '() => String' is not compatible with type '(a: Double, b: Double) => void|undefined' at index 1 */ +/* @@? 26:6 Error TypeError: Type '(a: String, b: Double) => void' is not compatible with type '(a: Double, b: Double) => void|undefined' at index 1 */ +/* @@? 27:6 Error TypeError: Type '(a: Double, b: String) => void' is not compatible with type '(a: Double, b: Double) => void|undefined' at index 1 */ +/* @@? 28:6 Error TypeError: Type '(a: String) => void' is not compatible with type '(a: Double, b: Double) => void|undefined' at index 1 */ +/* @@? 29:6 Error TypeError: Type '() => String' is not compatible with type '(a: Double, b: Double) => void|undefined' at index 1 */ diff --git a/ets2panda/test/runtime/ets/lambda_type_infer_2.ets b/ets2panda/test/runtime/ets/lambda_type_infer_2.ets new file mode 100644 index 0000000000..2bdd6a1aa3 --- /dev/null +++ b/ets2panda/test/runtime/ets/lambda_type_infer_2.ets @@ -0,0 +1,66 @@ +/* + * 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. + */ + +type Callback = (a:T1,b:T2)=>R; + +let testString = "" + +class A{ + foo(fun:((a:number,b:number)=>void)|undefined){ + fun?.(1,2) + } +} + +function foo(fun:((a:number,b:number,c:number)=>void)|undefined){ + fun?.(1,2,3) +} + +function foo2(fun:Callback|undefined){ + fun?.(1,2) +} + +function main(){ + foo((a:number,b:number,c:number)=>{testString = "invoke1"}) + arktest.assertEQ(testString,"invoke1") + foo((a:number,b,c:number)=>{testString = "invoke2"}) + arktest.assertEQ(testString,"invoke2") + foo((a:number,b)=>{testString = "invoke3"}) + arktest.assertEQ(testString,"invoke3") + foo((a)=>{testString = "invoke4"}) + arktest.assertEQ(testString,"invoke4") + foo(()=>{testString = "invoke5"}) + arktest.assertEQ(testString,"invoke5") + + + foo2((a:number,b:number)=>{testString = "callback_invoke1"}) + arktest.assertEQ(testString,"callback_invoke1") + foo2((a:number,b)=>{testString = "callback_invoke2"}) + arktest.assertEQ(testString,"callback_invoke2") + foo2((a)=>{testString = "callback_invoke3"}) + arktest.assertEQ(testString,"callback_invoke3") + foo2(()=>{testString = "callback_invoke4"}) + arktest.assertEQ(testString,"callback_invoke4") + + let a = new A(); + a.foo((a:number,b:number)=>{testString = "method_invoke1"}) + arktest.assertEQ(testString,"method_invoke1") + a.foo((a:number,b)=>{testString = "method_invoke2"}) + arktest.assertEQ(testString,"method_invoke2") + a.foo((a:number)=>{testString = "method_invoke3"}) + arktest.assertEQ(testString,"method_invoke3") + a.foo(()=>{testString = "method_invoke4"}) + arktest.assertEQ(testString,"method_invoke4") +} + \ No newline at end of file -- Gitee