From b91e3ab9caa017b28bac8d76af9123df7a0eacd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E5=AE=B6=E7=86=99?= Date: Tue, 10 Jun 2025 15:44:40 +0800 Subject: [PATCH] Fix several compile errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICE1XP Signed-off-by: 梁家熙 --- ets2panda/checker/ETSAnalyzer.cpp | 23 +++- ets2panda/checker/ets/function.cpp | 4 + ets2panda/checker/ets/helpers.cpp | 4 + ets2panda/compiler/base/lreference.cpp | 4 + .../lowering/ets/annotationCopyLowering.cpp | 2 +- .../ets/optionalArgumentsLowering.cpp | 5 + ets2panda/ir/brokenTypeNode.cpp | 9 ++ ets2panda/ir/brokenTypeNode.h | 2 + .../ets/anno_interface_invalid_error.ets | 50 ++++++++ .../ets/recursive_clousre_reference_error.ets | 23 ++++ .../ets/recursive_exported_structure.ets | 110 ++++++++++++++++++ .../ast/parser/ets/update_funcscope_error.ets | 41 +++++++ 12 files changed, 271 insertions(+), 6 deletions(-) create mode 100644 ets2panda/test/ast/parser/ets/anno_interface_invalid_error.ets create mode 100644 ets2panda/test/ast/parser/ets/recursive_clousre_reference_error.ets create mode 100644 ets2panda/test/ast/parser/ets/recursive_exported_structure.ets create mode 100644 ets2panda/test/ast/parser/ets/update_funcscope_error.ets diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 5028e1770e..a5f90c53b8 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -1469,6 +1469,10 @@ checker::Type *ETSAnalyzer::GetCallExpressionReturnType(ir::CallExpression *expr return returnType; } + if (!signature->HasFunction()) { + return checker->GlobalTypeError(); + } + auto owner = const_cast(util::Helpers::GetContainingObjectType(signature->Function())); SavedCheckerContext savedCtx(ReconstructOwnerClassContext(checker, owner)); @@ -1883,7 +1887,15 @@ static void SetTypeforRecordProperties(const ir::ObjectExpression *expr, checker auto *const valueType = typeArguments[1]; // Record type arguments for (auto *const recordProperty : recordProperties) { - auto *const recordPropertyExpr = recordProperty->AsProperty()->Value(); + ir::Expression *recordPropertyExpr = nullptr; + if (recordProperty->IsProperty()) { + recordPropertyExpr = recordProperty->AsProperty()->Value(); + } else if (recordProperty->IsSpreadElement()) { + recordPropertyExpr = recordProperty->AsSpreadElement()->Argument(); + } else { + ES2PANDA_UNREACHABLE(); + } + recordPropertyExpr->SetPreferredType(valueType); recordPropertyExpr->Check(checker); } @@ -2389,6 +2401,11 @@ checker::Type *ETSAnalyzer::Check(ir::SuperExpression *expr) const checker::Type *ETSAnalyzer::Check(ir::TemplateLiteral *expr) const { ETSChecker *checker = GetETSChecker(); + + for (auto *it : expr->Expressions()) { + it->Check(checker); + } + if (expr->TsType() != nullptr) { return expr->TsType(); } @@ -2399,10 +2416,6 @@ checker::Type *ETSAnalyzer::Check(ir::TemplateLiteral *expr) const return expr->TsType(); } - for (auto *it : expr->Expressions()) { - it->Check(checker); - } - for (auto *it : expr->Quasis()) { it->Check(checker); } diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index 22f1c94672..4c6a8d0d04 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -1218,6 +1218,10 @@ Signature *ETSChecker::ResolvePotentialTrailingLambdaWithReceiver(ir::CallExpres ArenaVector sigContainLambdaWithReceiverAsParam(ProgramAllocator()->Adapter()); Signature *signature = nullptr; for (auto sig : signatures) { + if (!sig->HasFunction()) { + continue; + } + if (!IsLastParameterLambdaWithReceiver(sig)) { normalSig.emplace_back(sig); continue; diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 8be037eadd..0ec9599d31 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -783,6 +783,10 @@ static void CheckRecordType(ir::Expression *init, checker::Type *annotationType, auto properties = objectExpr->Properties(); for (const auto &property : properties) { + if (!property->IsProperty()) { + checker->LogError(diagnostic::IMPROPER_NESTING_INTERFACE, {}, property->Start()); + continue; + } ES2PANDA_ASSERT(property->IsProperty()); auto p = property->AsProperty(); diff --git a/ets2panda/compiler/base/lreference.cpp b/ets2panda/compiler/base/lreference.cpp index 96572db071..00a2eec14f 100644 --- a/ets2panda/compiler/base/lreference.cpp +++ b/ets2panda/compiler/base/lreference.cpp @@ -69,6 +69,10 @@ LReference::LReferenceBase LReference::CreateBase(CodeGen *cg, const ir::AstNode case ir::AstNodeType::TS_NON_NULL_EXPRESSION: { return CreateBase(cg, node->AsTSNonNullExpression()->Expr(), isDeclaration); } + case ir::AstNodeType::ETS_NEW_CLASS_INSTANCE_EXPRESSION: { + ES2PANDA_ASSERT(node->AsETSNewClassInstanceExpression()->GetArguments().size() == 1); + return CreateBase(cg, node->AsETSNewClassInstanceExpression()->GetArguments()[0], isDeclaration); + } default: { ES2PANDA_UNREACHABLE(); } diff --git a/ets2panda/compiler/lowering/ets/annotationCopyLowering.cpp b/ets2panda/compiler/lowering/ets/annotationCopyLowering.cpp index d69ba30f65..7944383399 100644 --- a/ets2panda/compiler/lowering/ets/annotationCopyLowering.cpp +++ b/ets2panda/compiler/lowering/ets/annotationCopyLowering.cpp @@ -57,7 +57,7 @@ void CopyAnnotationProperties(public_lib::Context *ctx, ir::AnnotationUsage *st) for (auto *it : st->Properties()) { auto *param = it->AsClassProperty(); auto *property = findProperty(param->Id()->Name()); - if (property == nullptr) { + if (property == nullptr || property->TypeAnnotation() == nullptr) { // Will be handled in Checker continue; } diff --git a/ets2panda/compiler/lowering/ets/optionalArgumentsLowering.cpp b/ets2panda/compiler/lowering/ets/optionalArgumentsLowering.cpp index 94ce179427..69a92966aa 100644 --- a/ets2panda/compiler/lowering/ets/optionalArgumentsLowering.cpp +++ b/ets2panda/compiler/lowering/ets/optionalArgumentsLowering.cpp @@ -72,6 +72,11 @@ bool OptionalArgumentsLowering::PerformForModule(public_lib::Context *ctx, parse [ctx](ir::AstNode *const node) -> ir::AstNode * { if (node->IsCallExpression()) { auto callExpr = node->AsCallExpression(); + if (callExpr->Signature() == nullptr) { + ctx->parser->LogError(diagnostic::IMPROPER_NESTING_INTERFACE, {}, node->Start()); + return node; + } + callExpr->IsTrailingCall() ? TransformArgumentsForTrailingLambda(ctx, callExpr->AsCallExpression(), callExpr->Signature()) : TransformArguments(ctx, callExpr, callExpr->Signature(), callExpr->Arguments()); diff --git a/ets2panda/ir/brokenTypeNode.cpp b/ets2panda/ir/brokenTypeNode.cpp index 7194b87d8d..110222066d 100644 --- a/ets2panda/ir/brokenTypeNode.cpp +++ b/ets2panda/ir/brokenTypeNode.cpp @@ -68,4 +68,13 @@ checker::VerifiedType BrokenTypeNode::Check([[maybe_unused]] checker::ETSChecker { return {this, checker->GetAnalyzer()->Check(this)}; } + +BrokenTypeNode *BrokenTypeNode::Clone(ArenaAllocator *const allocator, AstNode *const parent) +{ + auto *const clone = allocator->New(allocator); + if (parent != nullptr) { + clone->SetParent(parent); + } + return clone; +} } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/brokenTypeNode.h b/ets2panda/ir/brokenTypeNode.h index 81df2eeea8..f4143f6adf 100644 --- a/ets2panda/ir/brokenTypeNode.h +++ b/ets2panda/ir/brokenTypeNode.h @@ -43,6 +43,8 @@ public: checker::VerifiedType Check([[maybe_unused]] checker::ETSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + [[nodiscard]] BrokenTypeNode *Clone(ArenaAllocator *allocator, AstNode *parent) override; + void Accept(ASTVisitorT *v) override { v->Accept(this); diff --git a/ets2panda/test/ast/parser/ets/anno_interface_invalid_error.ets b/ets2panda/test/ast/parser/ets/anno_interface_invalid_error.ets new file mode 100644 index 0000000000..69d61ed6c5 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/anno_interface_invalid_error.ets @@ -0,0 +1,50 @@ +/* + * 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. + */ + +const enum E { + A = 10, + B = 20, + C = 30 +} + +const enum E1 { + A = "A", + B = "B" +} + +@interface Anno { + a: number + b = [(10 + 3), E.A] + c: string + d: boolean + e: E[] = [E.A, E.B, E.C] + f: number[] + g: number[][][] + h: E + i: E[][][] + j: E1 + k: E1[][][] +} + + +@Anno({a: E.A + 10, c: "a" + "b", d: (1 === 1), f: [], g: [[[0]]], h: E.A, i: [], j: E1.B, k: []}) +class C{ + @Anno({a: 10, b: [1, 2, 3], c: "cde", d: true, f: [1], g:[[[0], [1]]], h: E.A, i: [[[E.A], [E.B]]], j: E1.B, k: [[[E1.A], [E1.B]]]}) + public foo() {} +} + +/* @@? 29:2 Error TypeError: Invalid annotation field type. Only numeric, boolean, string, enum, or arrays of these types are permitted for annotation fields. */ +/* @@? 29:4 Error SyntaxError: Missing type annotation for property 'b'. */ +/* @@? 42:11 Error TypeError: Invalid value for annotation field, expected a constant literal. */ diff --git a/ets2panda/test/ast/parser/ets/recursive_clousre_reference_error.ets b/ets2panda/test/ast/parser/ets/recursive_clousre_reference_error.ets new file mode 100644 index 0000000000..5f86308441 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/recursive_clousre_reference_error.ets @@ -0,0 +1,23 @@ +/* + * 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 foo() { + let x = () => y(); + let y = () => x(); + x(); +} + +/* @@? 17:19 Error TypeError: Variable 'y' is accessed before it's initialization. */ +/* @@? 18:9 Error TypeError: Circular dependency detected for identifier: y */ diff --git a/ets2panda/test/ast/parser/ets/recursive_exported_structure.ets b/ets2panda/test/ast/parser/ets/recursive_exported_structure.ets new file mode 100644 index 0000000000..bf13d520c1 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/recursive_exported_structure.ets @@ -0,0 +1,110 @@ +/* + * 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. + */ + +const TopLevelSym: string = "TopLevelSym"; +const InnerSym: string = "InnerSym"; + +const _topLevelFunc = (x: number | undefined): number => { + if (x === undefined) { + return 12; + } + return x; +}; + +const _innerFunc = (arg: { x: number } | undefined): number => { + if (arg === undefined) { + return 12; + } + return arg.x; +}; + +type NumberFunc = () => number; + +// Indexable type for items +type IndexableType = Record; + +// Explicitly typed indexable object +const _items: IndexableType = {}; +const innerFunction: NumberFunc = () => { + return _innerFunc({ x: 12 }); +}; + +// Fix: Assign computed property safely (done after object creation) +_items[InnerSym] = innerFunction; + +const topLevelWrapper: NumberFunc = () => { + return _topLevelFunc(12); +}; + +// Inner map using the same indexable type +const innerMap: IndexableType = {}; +const innerMapFunction: NumberFunc = () => { + const result = _innerFunc({ x: 12 }); + return result; +}; + +innerMap[InnerSym] = innerMapFunction; + +// Define the exported structure explicitly +type ExportedType = Record & { + items: IndexableType; +}; + +// Create a base object without computed properties +class ExportedStructure implements ExportedType { + items: IndexableType; + + constructor() { + this.items = innerMap; + } + + [key: string]: NumberFunc | IndexableType; + + static createBase(): ExportedType { + return new ExportedStructure() as ExportedType; + } +} + +// Create the exported structure and assign dynamic keys safely +const baseExportedStructure: ExportedType = ExportedStructure.createBase(); +const _exportedStructure: ExportedType = { ...baseExportedStructure }; + +// Assign computed key after object creation (not in literal) +_exportedStructure[TopLevelSym] = topLevelWrapper; + +const _exported: ExportedType = _exportedStructure; + +export default _exported; + +/* @@? 26:26 Error SyntaxError: Invalid Type. */ +/* @@? 41:12 Error TypeError: No matching call signature for (...) */ +/* @@? 41:23 Error TypeError: need to specify target type for class composite */ +/* @@? 54:20 Error TypeError: No matching call signature for (...) */ +/* @@? 54:31 Error TypeError: need to specify target type for class composite */ +/* @@? 61:64 Error SyntaxError: Unexpected token '&'. */ +/* @@? 61:66 Error SyntaxError: Unexpected token '{'. */ +/* @@? 62:12 Error SyntaxError: Label must be followed by a loop statement. */ +/* @@? 62:12 Error TypeError: Type name 'IndexableType' used in the wrong context */ +/* @@? 66:36 Error TypeError: Interfaces cannot extend classes, only other interfaces. */ +/* @@? 73:6 Error SyntaxError: Unexpected token 'key'. */ +/* @@? 73:9 Error SyntaxError: Unexpected token ':'. */ +/* @@? 73:17 Error SyntaxError: Field type annotation expected. */ +/* @@? 73:17 Error SyntaxError: Unexpected token ']'. */ +/* @@? 73:18 Error SyntaxError: Unexpected token ':'. */ +/* @@? 73:31 Error SyntaxError: Unexpected token '|'. */ +/* @@? 73:31 Error SyntaxError: Field type annotation expected. */ +/* @@? 73:46 Error SyntaxError: Field type annotation expected. */ +/* @@? 76:16 Error TypeError: Cannot cast type 'ExportedStructure' to 'Record Double|Record Double>>' */ +/* @@? 82:44 Error SyntaxError: Property or signature expected. */ diff --git a/ets2panda/test/ast/parser/ets/update_funcscope_error.ets b/ets2panda/test/ast/parser/ets/update_funcscope_error.ets new file mode 100644 index 0000000000..6261ac4ff1 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/update_funcscope_error.ets @@ -0,0 +1,41 @@ +/* + * 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 UpdateFunc = (u: Record) => Record; +type ReducerFunc = (key: string) => Record; + +export const updateIfChanged = (t: Record) => { + const reducerFunc: ReducerFunc = (key) => { + const value = u[key]; + const reduceResult = reduce( + value as Record, + (v: Record) => { + const baseU = u; + const updatedU: Record = { + ...baseU, + [key]: v + }; + return update(updatedU); + } + ); + return reduceResult; + }; +}; + +/* @@? 21:19 Error TypeError: Unresolved reference u */ +/* @@? 21:19 Error TypeError: Indexed access is not supported for such expression type. */ +/* @@? 24:7 Error TypeError: Type '(v: Record) => Boolean' is not compatible with type '(previousValue: Boolean, currentValue: Boolean, index: Double, array: FixedArray) => Boolean' at index 2 */ +/* @@? 27:11 Error SyntaxError: Property or signature expected. */ +/* @@? 30:16 Error TypeError: Unresolved reference update */ -- Gitee