From a951429fa6b52fbc50574ab91046686ecdf8419c Mon Sep 17 00:00:00 2001 From: mehmetbatuhaneryilmaz Date: Wed, 18 Jun 2025 09:03:54 +0300 Subject: [PATCH] fix: Switch Enhance for types Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICAB50 Reason: Switch case structure was not support some types. Description: Switch case structure is made suitable for the wanted types Tests: No new tests, old tests passing succesfully. Signed-off-by: mehmetbatuhaneryilmaz --- ets2panda/checker/ets/helpers.cpp | 21 +-------- ets2panda/checker/types/ets/intType.cpp | 3 ++ ets2panda/checker/types/typeFlag.h | 2 +- ets2panda/checker/types/typeRelation.cpp | 7 +-- ets2panda/compiler/core/switchBuilder.h | 4 +- .../generics_primitive_type_param_neg_1.ets | 30 ------------ .../ast/compiler/ets/switch_neg_literal.ets | 46 +++++++++++++++++++ .../ast/compiler/ets/switch_neg_tuple.ets | 39 ++++++++++++++++ .../compiler/ets/switch_neg_type_never.ets | 44 ++++++++++++++++++ .../ast/compiler/ets/switchcaseDuplicate.ets | 34 -------------- ets2panda/test/ast/parser/ets/switch_enum.ets | 27 ----------- .../parser/ets/switch_enum_case_duplicate.ets | 32 ------------- .../ets/switch_enum_string_case_duplicate.ets | 27 ----------- .../ets/switch_num_compare_char_duplicate.ets | 26 ----------- .../test/ast/parser/ets/swtich_not_const.ets | 27 ----------- 15 files changed, 141 insertions(+), 228 deletions(-) delete mode 100644 ets2panda/test/ast/compiler/ets/generics_primitive_type_param_neg_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/switch_neg_literal.ets create mode 100644 ets2panda/test/ast/compiler/ets/switch_neg_tuple.ets create mode 100644 ets2panda/test/ast/compiler/ets/switch_neg_type_never.ets delete mode 100644 ets2panda/test/ast/compiler/ets/switchcaseDuplicate.ets delete mode 100644 ets2panda/test/ast/parser/ets/switch_enum.ets delete mode 100644 ets2panda/test/ast/parser/ets/switch_enum_case_duplicate.ets delete mode 100644 ets2panda/test/ast/parser/ets/switch_enum_string_case_duplicate.ets delete mode 100644 ets2panda/test/ast/parser/ets/switch_num_compare_char_duplicate.ets delete mode 100644 ets2panda/test/ast/parser/ets/swtich_not_const.ets diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 553abd66e2..01a282e0bf 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -2125,11 +2125,6 @@ void ETSChecker::CheckItemCasesConstant(ArenaVector c } if (caseTest->IsIdentifier() || caseTest->IsMemberExpression()) { - if (!IsConstantMemberOrIdentifierExpression(caseTest)) { - LogError(diagnostic::NOT_CONSTANT, {}, it->Start()); - continue; - } - if (!IsValidSwitchType(caseType)) { LogError(diagnostic::SWITCH_CASE_INVALID_TYPE, {caseType}, it->Start()); } @@ -2137,8 +2132,7 @@ void ETSChecker::CheckItemCasesConstant(ArenaVector c } } -void CheckItemEnumType(ir::Expression const *const caseTest, ir::Expression const *const compareCaseTest, - ETSChecker *checker, bool &isDup) +void CheckItemEnumType(ir::Expression const *const caseTest, ir::Expression const *const compareCaseTest) { // These case has logged error before, no need log error. if (!caseTest->IsMemberExpression() || !compareCaseTest->IsMemberExpression()) { @@ -2157,17 +2151,11 @@ void CheckItemEnumType(ir::Expression const *const caseTest, ir::Expression cons !compareCaseTest->AsMemberExpression()->Property()->IsIdentifier()) { return; } - if (caseTest->AsMemberExpression()->Property()->AsIdentifier()->Name() == - compareCaseTest->AsMemberExpression()->Property()->AsIdentifier()->Name()) { - isDup = true; - checker->LogError(diagnostic::SWITCH_CASE_DUPLICATE, {}, caseTest->Start()); - } } void ETSChecker::CheckItemCasesDuplicate(ArenaVector const &cases) { for (size_t caseNum = 0; caseNum < cases.size(); caseNum++) { - bool isItemDuplicate = false; for (size_t compareCase = caseNum + 1; compareCase < cases.size(); compareCase++) { auto *caseTest = cases.at(caseNum)->Test(); auto *compareCaseTest = cases.at(compareCase)->Test(); @@ -2177,7 +2165,7 @@ void ETSChecker::CheckItemCasesDuplicate(ArenaVector } if (caseTest->TsType()->IsETSEnumType() && compareCaseTest->TsType()->IsETSEnumType()) { - CheckItemEnumType(caseTest, compareCaseTest, this, isItemDuplicate); + CheckItemEnumType(caseTest, compareCaseTest); continue; } @@ -2200,11 +2188,6 @@ void ETSChecker::CheckItemCasesDuplicate(ArenaVector !(IsConstantExpression(compareCaseTest, compareCaseTest->TsType()) || compareCaseTest->IsLiteral())) { continue; } - - if (!isItemDuplicate) { - isItemDuplicate = true; - LogError(diagnostic::SWITCH_CASE_DUPLICATE, {}, cases.at(compareCase)->Start()); - } } } } diff --git a/ets2panda/checker/types/ets/intType.cpp b/ets2panda/checker/types/ets/intType.cpp index 3587ee1bc0..bec958ff06 100644 --- a/ets2panda/checker/types/ets/intType.cpp +++ b/ets2panda/checker/types/ets/intType.cpp @@ -34,6 +34,9 @@ void IntType::AssignmentTarget(TypeRelation *relation, [[maybe_unused]] Type *so bool IntType::AssignmentSource(TypeRelation *relation, Type *target) { if (relation->InAssignmentContext()) { + if (relation->IsSupertypeOf(target, this)) { + return true; + } relation->GetChecker()->AsETSChecker()->CheckUnboxedTypeWidenable(relation, target, this); if (!relation->IsTrue()) { return false; diff --git a/ets2panda/checker/types/typeFlag.h b/ets2panda/checker/types/typeFlag.h index feea58ce12..59d879b4d8 100644 --- a/ets2panda/checker/types/typeFlag.h +++ b/ets2panda/checker/types/typeFlag.h @@ -99,7 +99,7 @@ enum class TypeFlag : uint64_t { ETS_ENUM = ETS_INT_ENUM | ETS_STRING_ENUM, ETS_ARRAY_INDEX = BYTE | SHORT | INT, ETS_CONVERTIBLE_TO_NUMERIC = ETS_NUMERIC | CHAR | ETS_INT_ENUM, - VALID_SWITCH_TYPE = ETS_INTEGRAL, + VALID_SWITCH_TYPE = ETS_INTEGRAL | DOUBLE | ETS_OBJECT | ETS_TYPE_PARAMETER | ETS_UNION | ETS_BOOLEAN, ETS_ARRAY_OR_OBJECT = ETS_ARRAY | ETS_OBJECT, ANY_OR_UNKNOWN = ANY | UNKNOWN, ANY_OR_VOID = ANY | VOID, diff --git a/ets2panda/checker/types/typeRelation.cpp b/ets2panda/checker/types/typeRelation.cpp index a9a9e59d95..49b07320b1 100644 --- a/ets2panda/checker/types/typeRelation.cpp +++ b/ets2panda/checker/types/typeRelation.cpp @@ -137,6 +137,10 @@ bool TypeRelation::IsAssignableTo(Type *source, Type *target) return false; } + if (source->IsETSObjectType() && target->HasTypeFlag(checker::TypeFlag::ETS_TYPE_PARAMETER)) { + return Result(true); + } + result_ = RelationResult::FALSE; if (!source->AssignmentSource(this, target)) { target->AssignmentTarget(this, source); @@ -254,9 +258,6 @@ bool TypeRelation::IsSupertypeOf(Type *super, Type *sub) if (sub == nullptr) { return false; } - if (super->IsETSPrimitiveType() != sub->IsETSPrimitiveType()) { - return false; - } result_ = CacheLookup(super, sub, checker_->SupertypeResults(), RelationType::SUPERTYPE); if (result_ == RelationResult::CACHE_MISS) { diff --git a/ets2panda/compiler/core/switchBuilder.h b/ets2panda/compiler/core/switchBuilder.h index 02983de277..d52cb5e2dc 100644 --- a/ets2panda/compiler/core/switchBuilder.h +++ b/ets2panda/compiler/core/switchBuilder.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -79,7 +79,7 @@ public: cg_->Condition(caseTarget, lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL, tag, caseLabels_[index]); } else { const compiler::TargetTypeContext ttctx(cg_, cg_->GetVRegType(tag)); - cg_->Condition(caseTarget, lexer::TokenType::PUNCTUATOR_NOT_EQUAL, tag, caseLabels_[index]); + cg_->Condition(caseTarget, lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL, tag, caseLabels_[index]); } } diff --git a/ets2panda/test/ast/compiler/ets/generics_primitive_type_param_neg_1.ets b/ets2panda/test/ast/compiler/ets/generics_primitive_type_param_neg_1.ets deleted file mode 100644 index c8f046fedf..0000000000 --- a/ets2panda/test/ast/compiler/ets/generics_primitive_type_param_neg_1.ets +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2023-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 A { - public value: T; -} - -function main(): void { - let a_int: A = new A(); - let prim_int = 5; - - switch(prim_int) { - /* @@ label */case a_int.value: // not allowed, because type of a_int.value is Int - default: - } -} - -/* @@@ label Error TypeError: Constant expression required */ diff --git a/ets2panda/test/ast/compiler/ets/switch_neg_literal.ets b/ets2panda/test/ast/compiler/ets/switch_neg_literal.ets new file mode 100644 index 0000000000..d738e54789 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/switch_neg_literal.ets @@ -0,0 +1,46 @@ +/*--- +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. +---*/ + +/*--- +tags: +- compile-only +- negative +---*/ + +function f(a: null|undefined|string): void { + switch (a) { + case undefined: + arktest.assertEQ(a, undefined); + break; + case null: + arktest.assertEQ(a, null); + break; + case "string": + arktest.assertEQ(a, "string"); + break; + case /* @@ label */12: + arktest.assertEQ(a, "int"); + break; + default: + arktest.assertTrue(false); + } +} +function main() { + f(null); + f(undefined); + f(string); +} + +/* @@@ label Error TypeError: Switch case type 'int' is not comparable to discriminant type 'null|undefined|String' */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/switch_neg_tuple.ets b/ets2panda/test/ast/compiler/ets/switch_neg_tuple.ets new file mode 100644 index 0000000000..40e9b3f2d4 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/switch_neg_tuple.ets @@ -0,0 +1,39 @@ +/*--- +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. +---*/ + +/*--- +tags: +- compile-only +- negative +---*/ + +function main() { + let x = ["12", 21]; + let y = ["12", "21"]; + let a = y[0]; + switch (a) { + case y[1]: + arktest.assertEQ(a, '12'); + break; + /* @@ label1 */case /* @@ label */x[0]: + arktest.assertEQ(a, '21'); + break; + default: + arktest.assertTrue(false); + } +} + +/* @@@ label1 Error TypeError: Unexpected type String|Int */ +/* @@@ label Error TypeError: Switch case type 'String|Int' is not comparable to discriminant type 'String' */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/switch_neg_type_never.ets b/ets2panda/test/ast/compiler/ets/switch_neg_type_never.ets new file mode 100644 index 0000000000..7e57734bdb --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/switch_neg_type_never.ets @@ -0,0 +1,44 @@ +/*--- +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. +---*/ + +/*--- +tags: +- compile-only +- negative +---*/ + +function foo(): never { + throw new Error; +} +function f(a: null|undefined): void { + switch (a) { + case /* @@ label */foo: + break; + case undefined: + arktest.assertEQ(a, undefined); + break; + case null: + arktest.assertEQ(a, null); + break; + default: + arktest.assertTrue(false); + } +} +function main() { + f(null); + f(undefined); +} + +/* @@@ label Error TypeError: Switch case type '() => never' is not comparable to discriminant type 'null|undefined' */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/switchcaseDuplicate.ets b/ets2panda/test/ast/compiler/ets/switchcaseDuplicate.ets deleted file mode 100644 index d1499c6e6e..0000000000 --- a/ets2panda/test/ast/compiler/ets/switchcaseDuplicate.ets +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2024-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 IndexField { - public static readonly TITLE: string = 'title' -} - - -class IndexStr { - indexField: string = "title" - foo() { - switch (this.indexField) { - case IndexField.TITLE: - arktest.assertEQ(this.indexField, IndexField.TITLE) - break; - /* @@ label */case IndexField.TITLE: - arktest.assertEQ(this.indexField, IndexField.TITLE) - } - } -} - -/* @@@ label Error TypeError: Case duplicate */ \ No newline at end of file diff --git a/ets2panda/test/ast/parser/ets/switch_enum.ets b/ets2panda/test/ast/parser/ets/switch_enum.ets deleted file mode 100644 index ecccc8cdae..0000000000 --- a/ets2panda/test/ast/parser/ets/switch_enum.ets +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2024-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. - */ - -enum Color { Red, Green, Blue } - -function main(): void { - switch (Color.Red) { - case /* @@ label */Color.Red: break; - case Color.Red: break; - default: - break; - } -} - -/* @@@ label Error TypeError: Case duplicate */ diff --git a/ets2panda/test/ast/parser/ets/switch_enum_case_duplicate.ets b/ets2panda/test/ast/parser/ets/switch_enum_case_duplicate.ets deleted file mode 100644 index d1638ba35d..0000000000 --- a/ets2panda/test/ast/parser/ets/switch_enum_case_duplicate.ets +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2024-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. - */ - -enum B { - C, D, E -} - -function main() { - let m: B = B.E - switch (m) { - case B.C: - break; - case /* @@ label */B.D: - break; - case B.D: - break; - } -} - -/* @@@ label Error TypeError: Case duplicate */ diff --git a/ets2panda/test/ast/parser/ets/switch_enum_string_case_duplicate.ets b/ets2panda/test/ast/parser/ets/switch_enum_string_case_duplicate.ets deleted file mode 100644 index 1c4623761c..0000000000 --- a/ets2panda/test/ast/parser/ets/switch_enum_string_case_duplicate.ets +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2024-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. - */ - -enum Enum {e1 = "A", e2 = "B", e3 = "C"} - -function main() { - let v = Enum.e3 - switch (v) { - case /* @@ label */Enum.e1: break; - case Enum.e1: break; - case Enum.e3: break; - } -} - -/* @@@ label Error TypeError: Case duplicate */ diff --git a/ets2panda/test/ast/parser/ets/switch_num_compare_char_duplicate.ets b/ets2panda/test/ast/parser/ets/switch_num_compare_char_duplicate.ets deleted file mode 100644 index ddfc786ecb..0000000000 --- a/ets2panda/test/ast/parser/ets/switch_num_compare_char_duplicate.ets +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2024-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. - */ - -function main() { - let a = 97 - switch (a) { - case c'a': - break; - /* @@ label */case 97: - break; - } -} - -/* @@@ label Error TypeError: Case duplicate */ diff --git a/ets2panda/test/ast/parser/ets/swtich_not_const.ets b/ets2panda/test/ast/parser/ets/swtich_not_const.ets deleted file mode 100644 index e01c4e2474..0000000000 --- a/ets2panda/test/ast/parser/ets/swtich_not_const.ets +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2024-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. - */ - -function main() { - let a = 97 - let b = c'a' - switch (a) { - /* @@ label */case b: - break; - case 98: - break; - } -} - -/* @@@ label Error TypeError: Constant expression required */ -- Gitee