From 39f82346b5a494e7d0895ac59e5da2b38ab3bbb7 Mon Sep 17 00:00:00 2001 From: oh-rgx Date: Tue, 24 Jun 2025 15:50:18 +0800 Subject: [PATCH] Fix static method compare Issue: #ICHFR9 Signed-off-by: oh-rgx --- ets2panda/checker/ETSchecker.h | 2 +- ets2panda/checker/ets/validateHelpers.cpp | 5 ++- ets2panda/compiler/core/ETSemitter.cpp | 4 ++- .../compiler/lowering/ets/lambdaLowering.cpp | 21 ++++++----- ets2panda/test/runtime/ets/compare-method.ets | 26 ++++++++++++++ .../ets/overload-static-method.ets.ets | 35 +++++++++++++++++++ 6 files changed, 81 insertions(+), 12 deletions(-) create mode 100644 ets2panda/test/runtime/ets/compare-method.ets create mode 100644 ets2panda/test/runtime/ets/overload-static-method.ets.ets diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index ec155ee9ae..7cf964d3ef 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -858,6 +858,7 @@ public: ir::MethodDefinition *CreateClassMethod(std::string_view name, ir::ScriptFunctionFlags funcFlags, ir::ModifierFlags modifierFlags, const MethodBuilder &builder); ir::ClassDeclaration *BuildClass(util::StringView name, const ClassBuilder &builder); + const varbinder::Variable *GetTargetRef(const ir::MemberExpression *memberExpr); void LogUnresolvedReferenceError(ir::Identifier *ident); void WrongContextErrorClassifyByType(ir::Identifier *ident); @@ -971,7 +972,6 @@ private: std::tuple IsResolvedAndValue(const ir::Expression *expr, Type *type) const; PropertySearchFlags GetSearchFlags(const ir::MemberExpression *memberExpr, const varbinder::Variable *targetRef); PropertySearchFlags GetInitialSearchFlags(const ir::MemberExpression *memberExpr); - const varbinder::Variable *GetTargetRef(const ir::MemberExpression *memberExpr); Type *GetTypeOfSetterGetter([[maybe_unused]] varbinder::Variable *var); void IterateInVariableContext([[maybe_unused]] varbinder::Variable *const var); bool CheckInit(ir::Identifier *ident, ir::TypeNode *typeAnnotation, ir::Expression *init, diff --git a/ets2panda/checker/ets/validateHelpers.cpp b/ets2panda/checker/ets/validateHelpers.cpp index 685c1d8b4b..ca0b5daccf 100644 --- a/ets2panda/checker/ets/validateHelpers.cpp +++ b/ets2panda/checker/ets/validateHelpers.cpp @@ -179,7 +179,10 @@ void ETSChecker::ValidateResolvedIdentifier(ir::Identifier *const ident) if (ValidateBinaryExpressionIdentifier(ident, resolvedType)) { return; } - [[fallthrough]]; + if (resolved != nullptr && !resolved->Declaration()->PossibleTDZ() && !resolvedType->IsETSFunctionType()) { + WrongContextErrorClassifyByType(ident); + } + break; case ir::AstNodeType::UPDATE_EXPRESSION: case ir::AstNodeType::UNARY_EXPRESSION: if (resolved != nullptr && !resolved->Declaration()->PossibleTDZ()) { diff --git a/ets2panda/compiler/core/ETSemitter.cpp b/ets2panda/compiler/core/ETSemitter.cpp index 81a59f6310..6390fe959c 100644 --- a/ets2panda/compiler/core/ETSemitter.cpp +++ b/ets2panda/compiler/core/ETSemitter.cpp @@ -1009,6 +1009,7 @@ pandasm::AnnotationData ETSEmitter::GenAnnotationFunctionalReference(const ir::C { GenAnnotationRecord(Signatures::ETS_ANNOTATION_FUNCTIONAL_REFERENCE); pandasm::AnnotationData functionalReference(Signatures::ETS_ANNOTATION_FUNCTIONAL_REFERENCE); + bool isStatic = classDef->FunctionalReferenceReferencedMethod()->IsStatic(); pandasm::AnnotationElement value( Signatures::ANNOTATION_KEY_VALUE, std::make_unique( @@ -1017,7 +1018,8 @@ pandasm::AnnotationData ETSEmitter::GenAnnotationFunctionalReference(const ir::C ->Function() ->Scope() ->InternalName() - .Mutf8()))); + .Mutf8(), + isStatic))); functionalReference.AddElement(std::move(value)); return functionalReference; } diff --git a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp index 5e4836e445..191bf1d729 100644 --- a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp +++ b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp @@ -1064,11 +1064,17 @@ static ir::AstNode *ConvertFunctionReference(public_lib::Context *ctx, ir::Expre } else { auto *mexpr = funcRef->AsMemberExpression(); // NOTE(gogabr): mexpr->PropVar() is a synthetic variable wwith no reference to the method definition. Why? - var = mexpr->Object()->TsType()->AsETSObjectType()->GetProperty( - mexpr->Property()->AsIdentifier()->Name(), - checker::PropertySearchFlags::SEARCH_INSTANCE_METHOD | checker::PropertySearchFlags::SEARCH_STATIC_METHOD | - checker::PropertySearchFlags::SEARCH_IN_BASE | - checker::PropertySearchFlags::DISALLOW_SYNTHETIC_METHOD_CREATION); + auto refVar = ctx->GetChecker()->AsETSChecker()->GetTargetRef(mexpr); + auto flags = checker::PropertySearchFlags::SEARCH_IN_BASE | + checker::PropertySearchFlags::DISALLOW_SYNTHETIC_METHOD_CREATION; + if (refVar != nullptr && refVar->HasFlag(varbinder::VariableFlags::CLASS)) { + flags |= checker::PropertySearchFlags::SEARCH_STATIC_METHOD; + } else { + flags |= (checker::PropertySearchFlags::SEARCH_INSTANCE_METHOD | + checker::PropertySearchFlags::SEARCH_STATIC_METHOD); + } + var = + mexpr->Object()->TsType()->AsETSObjectType()->GetProperty(mexpr->Property()->AsIdentifier()->Name(), flags); ES2PANDA_ASSERT(var != nullptr); } @@ -1079,10 +1085,7 @@ 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); - if (lam == nullptr) { - return funcRef; - } - return ConvertLambda(ctx, lam); + return lam == nullptr ? funcRef : ConvertLambda(ctx, lam); } LambdaInfo info; diff --git a/ets2panda/test/runtime/ets/compare-method.ets b/ets2panda/test/runtime/ets/compare-method.ets new file mode 100644 index 0000000000..8ac5c99647 --- /dev/null +++ b/ets2panda/test/runtime/ets/compare-method.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. + */ + +function foo() {} +function bar() {} +function goo(a: number) {} + +function main() { + arktest.assertEQ(foo == foo, true); + arktest.assertEQ(foo == bar, false); + arktest.assertEQ(foo == goo, false); + arktest.assertEQ(bar == goo, false); + arktest.assertEQ(goo == goo, true); +} \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/overload-static-method.ets.ets b/ets2panda/test/runtime/ets/overload-static-method.ets.ets new file mode 100644 index 0000000000..b55854600a --- /dev/null +++ b/ets2panda/test/runtime/ets/overload-static-method.ets.ets @@ -0,0 +1,35 @@ +/* + * 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 { + method() {} + static method(){} +} + +class B { + foo() {} + static foo(){} +} + +function main() { + let a = new A(); + let b = new B(); + arktest.assertEQ(a.method == a.method, true); + arktest.assertEQ(A.method == A.method, true); + arktest.assertEQ(b.foo == A.method, false); + arktest.assertEQ(B.foo == A.method, false); + arktest.assertEQ(B.foo == a.method, false); + arktest.assertEQ(b.foo == a.method, false); +} \ No newline at end of file -- Gitee