From e82e03e11714fa45d9f3ee08f59c3b01d62498c0 Mon Sep 17 00:00:00 2001 From: kaanfurkancakiroglu Date: Wed, 16 Jul 2025 13:25:42 +0300 Subject: [PATCH] Title: CrashWithEmit Issue: ICK4FY Test: Build Signed-off-by: kaanfurkancakiroglu --- ets2panda/compiler/core/ETSCompiler.cpp | 9 +++- .../compiler/lowering/ets/lambdaLowering.cpp | 17 +++++-- .../test/ast/compiler/ets/crash_with_emit.ets | 26 +++++++++++ .../ets/super_call_bound_function.ets | 44 +++++++++++++++++++ 4 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 ets2panda/test/ast/compiler/ets/crash_with_emit.ets create mode 100644 ets2panda/test/ast/compiler/ets/super_call_bound_function.ets diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index 75fd7d3de5..aae7fa9067 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -14,6 +14,7 @@ */ #include "ETSCompiler.h" +#include #include "compiler/base/catchTable.h" #include "compiler/base/condition.h" @@ -757,7 +758,13 @@ void ETSCompiler::Compile(const ir::CallExpression *expr) const auto const callee = expr->Callee(); checker::Signature *const signature = expr->Signature(); - ES2PANDA_ASSERT(!callee->TsType()->IsETSArrowType()); // should have been lowered + // std::cout << "call expression" << expr->DumpJSON() << std::endl; + // std::cout << "callee " << callee->DumpJSON() << std::endl; + if (callee->TsType()->IsETSArrowType()) { + std::cout << "CRASH: Callee still has ETSArrowType → " << callee->DumpEtsSrc() << std::endl; + } + + ES2PANDA_ASSERT(!callee->TsType()->IsETSArrowType()); // should have been lowered // bool const isStatic = signature->HasSignatureFlag(checker::SignatureFlags::STATIC); diff --git a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp index f621292487..aa6a595e02 100644 --- a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp +++ b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp @@ -14,6 +14,7 @@ */ #include "lambdaLowering.h" +#include #include #include "checker/ets/typeRelationContext.h" @@ -1013,7 +1014,11 @@ static ir::AstNode *ConvertLambda(public_lib::Context *ctx, ir::ArrowFunctionExp auto *callee = CreateCallee(ctx, lambda, &info); auto *lambdaType = lambda->TsType()->AsETSFunctionType(); auto *lambdaClass = CreateLambdaClass(ctx, lambdaType, callee, &info); - return CreateConstructorCall(ctx, lambda, lambdaClass, &info); + + auto *ctorCall = CreateConstructorCall(ctx, lambda, lambdaClass, &info); + + ctorCall->SetTsType(lambda->TsType()); + return ctorCall; } static ir::ScriptFunction *GetWrappingLambdaParentFunction(public_lib::Context *ctx, ir::Expression *funcRef, @@ -1076,6 +1081,8 @@ static ir::ArrowFunctionExpression *CreateWrappingLambda(public_lib::Context *ct ES2PANDA_ASSERT(lambda); lambda->SetParent(parent); + lambda->SetTsType(funcRef->TsType()); + auto *nearestScope = NearestScope(lambda); auto lexScope = varbinder::LexicalScope::Enter(varBinder, nearestScope); InitScopesPhaseETS::RunExternalNode(lambda, varBinder); @@ -1153,7 +1160,12 @@ static ir::AstNode *ConvertFunctionReference(public_lib::Context *ctx, ir::Expre // Direct reference to method will be impossible from the lambda class, so replace func ref with a lambda // that will translate to a proxy method auto *lam = CreateWrappingLambda(ctx, funcRef); - return lam == nullptr ? funcRef : ConvertLambda(ctx, lam); + auto node = lam == nullptr ? funcRef : ConvertLambda(ctx, lam); + if (funcRef->TsType() != nullptr && node->IsExpression()) { + node->AsExpression()->SetTsType(funcRef->TsType()); + } + + return node; } LambdaInfo info = GenerateLambdaInfoForFunctionReference(ctx, funcRef, method); @@ -1303,7 +1315,6 @@ static ir::AstNode *BuildLambdaClassWhenNeeded(public_lib::Context *ctx, ir::Ast if (node->IsArrowFunctionExpression()) { return ConvertLambda(ctx, node->AsArrowFunctionExpression()); } - if (node->IsIdentifier()) { auto *id = node->AsIdentifier(); auto *var = id->Variable(); diff --git a/ets2panda/test/ast/compiler/ets/crash_with_emit.ets b/ets2panda/test/ast/compiler/ets/crash_with_emit.ets new file mode 100644 index 0000000000..6c43ae6357 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/crash_with_emit.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. + */ + +class C { + protected privateM() {} //lambda function + publicM() {} + + getPrivateM(): ()=> void { + return this.privateM + } + getPublicM(): () => void { + return this.publicM + } +} diff --git a/ets2panda/test/ast/compiler/ets/super_call_bound_function.ets b/ets2panda/test/ast/compiler/ets/super_call_bound_function.ets new file mode 100644 index 0000000000..d8a4eb55d6 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/super_call_bound_function.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. + */ + +class A { + x(): void { + console.log("A.x"); + } + + y(): void { + console.log("A.y"); + } +} + +class B extends A { + // Use a standard property to store the bound function + private boundX: () => void; + + constructor() { + super(); + // Bind the implementation explicitly in the constructor + this.boundX = this.callParentXImpl; + this.boundX(); + } + + protected callParentXImpl(): void { + // super.x(); // Safe to call super in a method + } +} + +function main (){ + let b w= new B(); +} -- Gitee