From c48953b0e1e91a1ace2adf4c6a17e879342e13ce Mon Sep 17 00:00:00 2001 From: xuxinjie4 Date: Tue, 24 Jun 2025 16:38:56 +0800 Subject: [PATCH] Fixed type alias with default typeParam bug Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICHGPX?from=project-issue Signed-off-by: xuxinjie4 --- ets2panda/checker/ets/helpers.cpp | 29 +++++++++------ ets2panda/checker/ets/validateHelpers.cpp | 2 +- .../compiler/ets/generic_typealias_2_neg.ets | 4 +-- .../ets/typealias_default_type_01.ets | 26 ++++++++++++++ .../ets/typealias_default_type_02.ets | 36 +++++++++++++++++++ .../parser/ets/typenode_clone_primitives.ets | 7 ++-- .../runtime/ets/typealias_default_type.ets | 31 ++++++++++++++++ ets2panda/util/diagnostic/semantic.yaml | 2 +- 8 files changed, 117 insertions(+), 20 deletions(-) create mode 100644 ets2panda/test/ast/compiler/ets/typealias_default_type_01.ets create mode 100644 ets2panda/test/ast/compiler/ets/typealias_default_type_02.ets create mode 100644 ets2panda/test/runtime/ets/typealias_default_type.ets diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 9943998a5e..d8d087c094 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -1615,7 +1615,7 @@ bool ETSChecker::CheckMinimumTypeArgsPresent(const ir::TSTypeAliasDeclaration *t ir::TypeNode *ETSChecker::ResolveTypeNodeForTypeArg(const ir::TSTypeAliasDeclaration *typeAliasNode, const ir::TSTypeParameterInstantiation *typeParams, size_t idx) { - if (typeParams->Params().size() > idx) { + if (typeParams != nullptr && typeParams->Params().size() > idx) { return typeParams->Params().at(idx); } @@ -1625,34 +1625,41 @@ ir::TypeNode *ETSChecker::ResolveTypeNodeForTypeArg(const ir::TSTypeAliasDeclara Type *ETSChecker::HandleTypeAlias(ir::Expression *const name, const ir::TSTypeParameterInstantiation *const typeParams, ir::TSTypeAliasDeclaration *const typeAliasNode) { - // NOTE (mmartin): modify for default params - if ((typeParams == nullptr) != (typeAliasNode->TypeParams() == nullptr)) { - if (typeParams == nullptr) { + if (typeParams == nullptr && typeAliasNode->TypeParams() != nullptr) { + auto declTypeParams = typeAliasNode->TypeParams()->Params(); + auto isAllTypeParamsHasDefaultType = + std::find_if(declTypeParams.begin(), declTypeParams.end(), [](ir::TSTypeParameter *param) { + return param->DefaultType() == nullptr; + }) == declTypeParams.end(); + if (!isAllTypeParamsHasDefaultType) { LogError(diagnostic::GENERIC_ALIAS_WITHOUT_PARAMS, {}, name->Start()); return GlobalTypeError(); } + } + if (typeParams != nullptr && typeAliasNode->TypeParams() == nullptr) { LogError(diagnostic::NON_GENERIC_ALIAS_WITH_PARAMS, {}, typeParams->Start()); return GlobalTypeError(); } - if (typeParams == nullptr) { + if (typeParams == nullptr && typeAliasNode->TypeParams() == nullptr) { // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) return GetReferencedTypeBase(name); } - for (auto *const origTypeParam : typeParams->Params()) { - origTypeParam->Check(this); + if (typeParams != nullptr) { + for (auto *const origTypeParam : typeParams->Params()) { + origTypeParam->Check(this); + } + if (CheckMinimumTypeArgsPresent(typeAliasNode, typeParams)) { + return GlobalTypeError(); + } } // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) Type *const aliasType = GetReferencedTypeBase(name); auto substitution = Substitution {}; - if (CheckMinimumTypeArgsPresent(typeAliasNode, typeParams)) { - return GlobalTypeError(); - } - std::set parametersNeedToBeBoxed; auto expandedAliasType = aliasType->Substitute(Relation(), &substitution); CollectAliasParametersForBoxing(expandedAliasType, parametersNeedToBeBoxed, false); diff --git a/ets2panda/checker/ets/validateHelpers.cpp b/ets2panda/checker/ets/validateHelpers.cpp index e944b05b04..96463d59ba 100644 --- a/ets2panda/checker/ets/validateHelpers.cpp +++ b/ets2panda/checker/ets/validateHelpers.cpp @@ -273,7 +273,7 @@ void ETSChecker::ValidateGenericTypeAliasForClonedNode(ir::TSTypeAliasDeclaratio ir::TypeNode *typeParamType = nullptr; - if (exactTypeParams->Params().size() > typeParamIdx) { + if (exactTypeParams != nullptr && exactTypeParams->Params().size() > typeParamIdx) { typeParamType = exactTypeParams->Params().at(typeParamIdx); } else { typeParamType = typeAliasNode->TypeParams()->Params().at(typeParamIdx)->DefaultType(); diff --git a/ets2panda/test/ast/compiler/ets/generic_typealias_2_neg.ets b/ets2panda/test/ast/compiler/ets/generic_typealias_2_neg.ets index d8f74a0d2b..2ce7f0e30f 100644 --- a/ets2panda/test/ast/compiler/ets/generic_typealias_2_neg.ets +++ b/ets2panda/test/ast/compiler/ets/generic_typealias_2_neg.ets @@ -17,7 +17,7 @@ type my_type = T; function main(): void { - let a: /* @@ label */my_type = new Int(); + let a: my_type = new Int(); } -/* @@@ label Error TypeError: Type alias declaration is generic, but no type parameters were provided */ +/* @@? 20:12 Error TypeError: Type alias declaration is generic, but too few type arguments were provided */ diff --git a/ets2panda/test/ast/compiler/ets/typealias_default_type_01.ets b/ets2panda/test/ast/compiler/ets/typealias_default_type_01.ets new file mode 100644 index 0000000000..b7051016a8 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/typealias_default_type_01.ets @@ -0,0 +1,26 @@ +/* + * 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 ErrorCallBack1 = (err: T) => void + +type ErrorCallBack2 = (err: T) => void + +function test1(call: ErrorCallBack1) { } // should be ok + +function test2(call: ErrorCallBack2) { } // should be error because typeParam has no default type + +function test3(call: ErrorCallBack2) { } // should be ok because we have explicitly provided a type. + +/* @@? 22:22 Error TypeError: Type alias declaration is generic, but too few type arguments were provided */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/typealias_default_type_02.ets b/ets2panda/test/ast/compiler/ets/typealias_default_type_02.ets new file mode 100644 index 0000000000..9f91a1fe20 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/typealias_default_type_02.ets @@ -0,0 +1,36 @@ +/* + * 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 ErrorCallBack1 = (err: T) => R + +type ErrorCallBack2 = (err: T) => R + +type ErrorCallBack3 = (err: T) => R + +function test1(call: ErrorCallBack1) { } // should be ok + +function test2(call: ErrorCallBack2) { } // should be error because typeParam has no default type + +function test3(call: ErrorCallBack2) { } // should be error because we have not provided all types. + +function test4(call: ErrorCallBack2) { } // should be ok because we have provided all types. + +function test5(call: ErrorCallBack3) { } // should be ok because the second type param has a default type + +function test6(call: ErrorCallBack3) { } // should be error + +/* @@? 24:22 Error TypeError: Type alias declaration is generic, but too few type arguments were provided */ +/* @@? 26:36 Error TypeError: Expected at least 2 type arguments, but got 1. */ +/* @@? 32:22 Error TypeError: Type alias declaration is generic, but too few type arguments were provided */ \ No newline at end of file diff --git a/ets2panda/test/ast/parser/ets/typenode_clone_primitives.ets b/ets2panda/test/ast/parser/ets/typenode_clone_primitives.ets index 045aaf46b1..19d5e3fed1 100644 --- a/ets2panda/test/ast/parser/ets/typenode_clone_primitives.ets +++ b/ets2panda/test/ast/parser/ets/typenode_clone_primitives.ets @@ -18,7 +18,7 @@ // Simple primitive type aliases that exercise Clone type NumAlias = T; -type StrAlias = T; +type StrAlias = T; type BoolAlias = T; type VoidAlias = T; @@ -46,7 +46,6 @@ declare const num: NumAlias<42>; declare const str: StrAlias<"test">; declare const bool: BoolAlias; -/* Expected syntax errors (normal for ETS): */ /* @@? 37:73 Error SyntaxError: Invalid Type. */ /* @@? 38:15 Error SyntaxError: Label must be followed by a loop statement. */ /* @@? 38:15 Error TypeError: Unresolved reference N */ @@ -59,12 +58,10 @@ declare const bool: BoolAlias; /* @@? 40:17 Error SyntaxError: Unexpected token ','. */ /* @@? 41:17 Error SyntaxError: Label must be followed by a loop statement. */ /* @@? 41:23 Error SyntaxError: Unexpected token 'void'. */ -/* @@? 45:20 Error TypeError: Type alias declaration is generic, but no type parameters were provided */ +/* @@? 45:29 Error SyntaxError: Invalid Type. */ /* @@? 45:29 Error SyntaxError: Unexpected token, expected '>'. */ /* @@? 45:29 Error SyntaxError: Unexpected token '>'. */ -/* @@? 45:29 Error SyntaxError: Invalid Type. */ /* @@? 45:32 Error SyntaxError: Unexpected token ';'. */ -/* @@? 47:21 Error TypeError: Type alias declaration is generic, but no type parameters were provided */ /* @@? 47:31 Error SyntaxError: Invalid Type. */ /* @@? 47:31 Error SyntaxError: Unexpected token, expected '>'. */ /* @@? 47:31 Error SyntaxError: Unexpected token '>'. */ diff --git a/ets2panda/test/runtime/ets/typealias_default_type.ets b/ets2panda/test/runtime/ets/typealias_default_type.ets new file mode 100644 index 0000000000..5cbd994ced --- /dev/null +++ b/ets2panda/test/runtime/ets/typealias_default_type.ets @@ -0,0 +1,31 @@ +/* + * 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. + */ + +class BusinessError extends Error { + constructor(message?: String) { + super(message) + } +} + +type ErrorCallBack = (err: T) => void +function test(call: ErrorCallBack) { // type of typeAnnotation should be `(err: BusinessError) => void` + call(new BusinessError("I am a error")) +} + +function main() { + test((err: BusinessError) => { + arktest.assertEQ(err.message, "I am a error") + }) // ok +} diff --git a/ets2panda/util/diagnostic/semantic.yaml b/ets2panda/util/diagnostic/semantic.yaml index dc308f414b..db1355f996 100644 --- a/ets2panda/util/diagnostic/semantic.yaml +++ b/ets2panda/util/diagnostic/semantic.yaml @@ -622,7 +622,7 @@ semantic: - name: GENERIC_ALIAS_WITHOUT_PARAMS id: 155 - message: "Type alias declaration is generic, but no type parameters were provided" + message: "Type alias declaration is generic, but too few type arguments were provided" - name: NON_GENERIC_ALIAS_WITH_PARAMS id: 156 -- Gitee