diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 9943998a5ef27aa81d3814b4b90240752104aacf..d8d087c094a6d0bf5616b26a292be822ed695d17 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 e944b05b04bdd44312df44eb79cf4e12328985f0..96463d59ba4ed4f3c938d83f41499a1134094168 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 d8f74a0d2bc6ab2ee6ad83b096b96afef7c4549e..2ce7f0e30f105ea1619d16cd28d95a3e80b60edf 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 0000000000000000000000000000000000000000..b7051016a8b9613cff7ce9aa7589dc585c3b65d5 --- /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 0000000000000000000000000000000000000000..9f91a1fe204dd57a024b9c768f51b2d1ae9ca5f4 --- /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 045aaf46b1496574677a8c42db112eaba7a8ad02..19d5e3fed132ad6bca6c5ccef90ee6c703876f52 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 0000000000000000000000000000000000000000..5cbd994ced8fdee320b6fd726b543ec521ce629a --- /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 dc308f414bba189648b0a9176bc93be5ec68de4c..db1355f9969b492834761728a5ddc64388e54e6f 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