diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index ec155ee9ae943e62fede1007345ea4c72a11717a..7cf964d3efba91dddbabc71c1f9aa866633d7cc0 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 685c1d8b4babed5725f0907ff8a4534da1651ced..57b2188e76d5c79346338106500434a76912551f 100644 --- a/ets2panda/checker/ets/validateHelpers.cpp +++ b/ets2panda/checker/ets/validateHelpers.cpp @@ -182,7 +182,7 @@ void ETSChecker::ValidateResolvedIdentifier(ir::Identifier *const ident) [[fallthrough]]; case ir::AstNodeType::UPDATE_EXPRESSION: case ir::AstNodeType::UNARY_EXPRESSION: - if (resolved != nullptr && !resolved->Declaration()->PossibleTDZ()) { + if (resolved != nullptr && !resolved->Declaration()->PossibleTDZ() && !resolvedType->IsETSFunctionType()) { WrongContextErrorClassifyByType(ident); } break; diff --git a/ets2panda/compiler/core/ETSemitter.cpp b/ets2panda/compiler/core/ETSemitter.cpp index 81a59f631085f223531026484b2d4ea169cc0513..6390fe959c2bf728e234c45ab5b237dd5e2d4fe1 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 5e4836e4453e634a260ee27a996f7162bed529f1..191bf1d729e69922369514acbd7c4ef17495dd6b 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/ast/parser/ets/wrong_context_function_3.ets b/ets2panda/test/ast/parser/ets/wrong_context_function_3.ets index 74b8296e569fb0bbdf09cd3004228e5ac4e7409f..d70bb4a19036be6f0188f25622904f1a293d8a97 100644 --- a/ets2panda/test/ast/parser/ets/wrong_context_function_3.ets +++ b/ets2panda/test/ast/parser/ets/wrong_context_function_3.ets @@ -22,5 +22,4 @@ function main() a++ } -/* @@? 22:5 Error TypeError: Function name 'a' used in the wrong context */ /* @@? 22:5 Error TypeError: Bad operand type, the type of the operand must be numeric type. */ diff --git a/ets2panda/test/runtime/ets/compare-method.ets b/ets2panda/test/runtime/ets/compare-method.ets new file mode 100644 index 0000000000000000000000000000000000000000..8ac5c996477557de2a997c7550fd244e1e79e6e3 --- /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 0000000000000000000000000000000000000000..b55854600a0564a958e500aca09094d33fa151e7 --- /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