From 1d4b9d641b1895d7ab9661c322787765c25f9af3 Mon Sep 17 00:00:00 2001 From: gizembusraturan Date: Wed, 25 Jun 2025 08:43:14 +0300 Subject: [PATCH] Title: union type crash Issue: ICG6QA Testing: Build Signed-off-by: gizembusraturan --- ets2panda/checker/ETSAnalyzer.cpp | 4 +- ets2panda/checker/types/ets/etsUnionType.cpp | 1 + ets2panda/ir/statements/forOfStatement.cpp | 16 +++--- .../forof_iterator_doesnt_return_iteartor.ets | 54 +++++++++++++++++++ .../ets/forof_iterator_missing_next.ets | 40 ++++++++++++++ .../ets/forof_missing_iterator_method.ets | 31 +++++++++++ ...forof_missing_iterator_method_with_sig.ets | 37 +++++++++++++ .../ast/compiler/ets/forof_prop_is_static.ets | 47 ++++++++++++++++ .../ast/compiler/ets/union_types_forof_1.ets | 34 ++++++++++++ 9 files changed, 254 insertions(+), 10 deletions(-) create mode 100644 ets2panda/test/ast/compiler/ets/forof_iterator_doesnt_return_iteartor.ets create mode 100644 ets2panda/test/ast/compiler/ets/forof_iterator_missing_next.ets create mode 100644 ets2panda/test/ast/compiler/ets/forof_missing_iterator_method.ets create mode 100644 ets2panda/test/ast/compiler/ets/forof_missing_iterator_method_with_sig.ets create mode 100644 ets2panda/test/ast/compiler/ets/forof_prop_is_static.ets create mode 100644 ets2panda/test/ast/compiler/ets/union_types_forof_1.ets diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 2c0fd6a3fc..86485d23f6 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -2980,7 +2980,7 @@ checker::Type *ETSAnalyzer::Check(ir::ForOfStatement *const st) const return checker->GlobalTypeError(); } - checker::Type *elemType = nullptr; + checker::Type *elemType = checker->GlobalTypeError(); if (exprType->IsETSStringType()) { elemType = checker->GetGlobalTypesHolder()->GlobalCharType(); @@ -2990,7 +2990,7 @@ checker::Type *ETSAnalyzer::Check(ir::ForOfStatement *const st) const elemType = st->CheckIteratorMethod(checker); } - if (elemType == nullptr) { + if (elemType == checker->GlobalTypeError()) { checker->LogError(diagnostic::FOROF_SOURCE_NONITERABLE, {}, st->Right()->Start()); return checker->GlobalTypeError(); } diff --git a/ets2panda/checker/types/ets/etsUnionType.cpp b/ets2panda/checker/types/ets/etsUnionType.cpp index 2bbdf54442..7893a517a9 100644 --- a/ets2panda/checker/types/ets/etsUnionType.cpp +++ b/ets2panda/checker/types/ets/etsUnionType.cpp @@ -265,6 +265,7 @@ void ETSUnionType::LinearizeAndEraseIdentical(TypeRelation *relation, ArenaVecto size_t const initialSz = types.size(); for (size_t i = 0; i < initialSz; ++i) { auto ct = types[i]; + ES2PANDA_ASSERT(ct != nullptr); if (ct->IsETSUnionType()) { auto const &otherTypes = ct->AsETSUnionType()->ConstituentTypes(); types.insert(types.end(), otherTypes.begin(), otherTypes.end()); diff --git a/ets2panda/ir/statements/forOfStatement.cpp b/ets2panda/ir/statements/forOfStatement.cpp index 31198b09a9..d6eee195c8 100644 --- a/ets2panda/ir/statements/forOfStatement.cpp +++ b/ets2panda/ir/statements/forOfStatement.cpp @@ -35,7 +35,7 @@ checker::Type *ForOfStatement::CreateUnionIteratorTypes(checker::ETSChecker *che checker->GetGlobalTypesHolder())); types.back()->RemoveTypeFlag(checker::TypeFlag::CONSTANT); } else { - return nullptr; + return checker->GlobalTypeError(); } } @@ -158,7 +158,7 @@ checker::Type *ForOfStatement::CheckIteratorMethodForObject(checker::ETSChecker auto *const method = sourceType->GetProperty(compiler::Signatures::ITERATOR_METHOD, searchFlag); if (method == nullptr || !method->HasFlag(varbinder::VariableFlags::METHOD)) { checker->LogError(diagnostic::MISSING_ITERATOR_METHOD, {}, position); - return nullptr; + return checker->GlobalTypeError(); } ArenaVector arguments {checker->Allocator()->Adapter()}; @@ -167,27 +167,27 @@ checker::Type *ForOfStatement::CheckIteratorMethodForObject(checker::ETSChecker checker::TypeRelationFlag::NO_THROW); if (signature == nullptr) { checker->LogError(diagnostic::MISSING_ITERATOR_METHOD_WITH_SIG, {}, position); - return nullptr; + return checker->GlobalTypeError(); } checker->ValidateSignatureAccessibility(sourceType, signature, position, {{diagnostic::INVISIBLE_ITERATOR, {}}}); ES2PANDA_ASSERT(signature->Function() != nullptr); if (!CheckReturnTypeOfIteratorMethod(checker, sourceType, signature, position)) { - return nullptr; + return checker->GlobalTypeError(); } if (checker->IsClassStaticMethod(sourceType, signature)) { checker->LogError(diagnostic::PROP_IS_STATIC, {compiler::Signatures::ITERATOR_METHOD, sourceType->Name()}, position); - return nullptr; + return checker->GlobalTypeError(); } auto *const nextMethod = signature->ReturnType()->AsETSObjectType()->GetProperty(ITERATOR_INTERFACE_METHOD, searchFlag); if (nextMethod == nullptr || !nextMethod->HasFlag(varbinder::VariableFlags::METHOD)) { checker->LogError(diagnostic::ITERATOR_MISSING_NEXT, {}, position); - return nullptr; + return checker->GlobalTypeError(); } auto &nextSignatures = checker->GetTypeOfVariable(nextMethod)->AsETSFunctionType()->CallSignatures(); @@ -200,7 +200,7 @@ checker::Type *ForOfStatement::CheckIteratorMethodForObject(checker::ETSChecker } } - return nullptr; + return checker->GlobalTypeError(); } bool ForOfStatement::CheckReturnTypeOfIteratorMethod(checker::ETSChecker *checker, checker::ETSObjectType *sourceType, @@ -251,6 +251,6 @@ checker::Type *ForOfStatement::CheckIteratorMethod(checker::ETSChecker *const ch } } - return nullptr; + return checker->GlobalTypeError(); } } // namespace ark::es2panda::ir diff --git a/ets2panda/test/ast/compiler/ets/forof_iterator_doesnt_return_iteartor.ets b/ets2panda/test/ast/compiler/ets/forof_iterator_doesnt_return_iteartor.ets new file mode 100644 index 0000000000..e340e0579b --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/forof_iterator_doesnt_return_iteartor.ets @@ -0,0 +1,54 @@ +/* + * 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 A { + data: FixedArray = [1,2,3]; + $_iterator() : CIterator | undefined { + return new CIterator(this); + } +} + +class CIterator implements Iterator { + index = 0; + base: A; + constructor (base: A) { + this.base = base; + } + next(): IteratorResult { + if (this.index >= this.base.data.length) { + return { + done: true, + value: undefined + } + } + return { + done: this.index >= this.base.data.length, + value: this.base.data[this.index++] + } + } +} + +function main(): void { + let res = 0; + let a = new A(); + for (let x of a) res += x; + arktest.assertEQ(res, 6); +} + + +/* @@? 18:15 Error TypeError: The return type of '$_iterator' must be a type that implements Iterator interface.*/ +/* @@? 46:19 Error TypeError: Iterator method must return an object which implements Iterator */ +/* @@? 46:19 Error TypeError: 'For-of' statement source expression is not of iterable type. */ + diff --git a/ets2panda/test/ast/compiler/ets/forof_iterator_missing_next.ets b/ets2panda/test/ast/compiler/ets/forof_iterator_missing_next.ets new file mode 100644 index 0000000000..f513a77c6e --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/forof_iterator_missing_next.ets @@ -0,0 +1,40 @@ +/* + * 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 A { + data: FixedArray = [1,2,3]; + $_iterator() : CIterator | undefined { + return new CIterator(this); + } +} + +class CIterator { + index = 0; + base: A; + constructor (base: A) { + this.base = base; + } +} + +function main(): void { + let res = 0; + let a = new A(); + for (let x of a) res += x; + arktest.assertEQ(res, 6); +} + +/* @@? 18:15 Error TypeError: The return type of '$_iterator' must be a type that implements Iterator interface.*/ +/* @@? 34:19 Error TypeError: Iterator method must return an object which implements Iterator */ +/* @@? 34:19 Error TypeError: 'For-of' statement source expression is not of iterable type. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/forof_missing_iterator_method.ets b/ets2panda/test/ast/compiler/ets/forof_missing_iterator_method.ets new file mode 100644 index 0000000000..8952030938 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/forof_missing_iterator_method.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 C { + index = 0 +} + +function main(): int { + let c = new C() + let res = '' + for (let x of c) { + res += x + } + if (res != '6') return 1 + return 0 +} + +/* @@? 23:17 Error TypeError: Object type doesn't have proper iterator method. */ +/* @@? 23:17 Error TypeError: 'For-of' statement source expression is not of iterable type. */ diff --git a/ets2panda/test/ast/compiler/ets/forof_missing_iterator_method_with_sig.ets b/ets2panda/test/ast/compiler/ets/forof_missing_iterator_method_with_sig.ets new file mode 100644 index 0000000000..0adcb03bf1 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/forof_missing_iterator_method_with_sig.ets @@ -0,0 +1,37 @@ +/* + * 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 C { + $_iterator(param: int): string { + return "notAnIterator"; + } +} + +function main(): int { + let c = new C(); + let res = ""; + + for (let x of c) { + res += x; + } + + if (res != "6") return 1; + return 0; +} + +/* @@? 17:3 Error SyntaxError: The special predefined method '$_iterator' should not have parameters. */ +/* @@? 17:13 Error TypeError: The return type of '$_iterator' must be a type that implements Iterator interface. */ +/* @@? 26:17 Error TypeError: Cannot find iterator method with the required signature. */ +/* @@? 26:17 Error TypeError: 'For-of' statement source expression is not of iterable type. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/forof_prop_is_static.ets b/ets2panda/test/ast/compiler/ets/forof_prop_is_static.ets new file mode 100644 index 0000000000..ff9986cb41 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/forof_prop_is_static.ets @@ -0,0 +1,47 @@ +/* + * 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 C { + data: int[] = [1,2,3] + static $_iterator() { + return new CIterator(new C()) + } +} +class CIterator implements Iterator { + index = 0 + base: C + constructor (base: C) { + this.base = base + } + next(): IteratorResult { + return { + done: this.index >= this.base.data.length, + value: this.index >= this.base.data.length ? undefined : this.base.data[this.index++] + } + } +} + +function main(): int { + let c = new C() + let res = '' + for (let x of c) { + res += x + } + if (res != '6') return 1 + return 0 +} + +/* @@? 39:17 Error TypeError: '$_iterator' is a static property of 'C' */ +/* @@? 39:17 Error TypeError: 'For-of' statement source expression is not of iterable type. */ diff --git a/ets2panda/test/ast/compiler/ets/union_types_forof_1.ets b/ets2panda/test/ast/compiler/ets/union_types_forof_1.ets new file mode 100644 index 0000000000..b13724b2d1 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/union_types_forof_1.ets @@ -0,0 +1,34 @@ +/* + * 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. + */ + +function processValue(value: string | number): void { + if (typeof value === 'string') { + // Handle string case + for (const it of value) { + console.log(it); + } + } else { + // Handle number case + console.log(value.toString()); + } +} + +const testValues: (string | number)[] = ['hello', 42, 'world', 7]; + +for (const item of testValues) { + processValue(item); +} + +/* @@? 19:26 Error TypeError: Object type doesn't have proper iterator method. */ -- Gitee