diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 51bd4b1f22822180c11f0fcd9f080d6bcdf84ec9..a34a23d0eed7fbfa590672e7d3bca0355d99b9d1 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -715,7 +715,7 @@ private: std::pair GetTargetIdentifierAndType(ir::Identifier *ident); [[noreturn]] void ThrowError(ir::Identifier *ident); void WrongContextErrorClassifyByType(ir::Identifier *ident, varbinder::Variable *resolved); - void CheckEtsFunctionType(ir::Identifier *ident, ir::Identifier const *id, ir::TypeNode const *annotation); + void CheckEtsFunctionType(ir::Identifier *ident, ir::Identifier const *id); [[noreturn]] void NotResolvedError(ir::Identifier *const ident, const varbinder::Variable *classVar, const ETSObjectType *classType); void ValidateCallExpressionIdentifier(ir::Identifier *const ident, varbinder::Variable *const resolved, diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 6fde4aa6325eb30bcec4ff31014a876e46ee6215..130c48edc6aa7cb5af5cd91afc6a2b4f38a36d71 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -708,7 +708,9 @@ checker::Type *ETSChecker::CheckVariableDeclaration(ir::Identifier *ident, ir::T } if (typeAnnotation == nullptr && initType->IsETSFunctionType()) { - ASSERT(initType->AsETSFunctionType()->CallSignatures().size() == 1); + if (initType->AsETSFunctionType()->CallSignatures().size() != 1) { + ThrowTypeError("Ambiguous function initialization because of multiple overloads", init->Start()); + } annotationType = FunctionTypeToFunctionalInterfaceType(initType->AsETSFunctionType()->CallSignatures()[0]); bindingVar->SetTsType(annotationType); } diff --git a/ets2panda/checker/ets/typeCheckingHelpers.cpp b/ets2panda/checker/ets/typeCheckingHelpers.cpp index 156f758237e8ddb3da540272df282b4c361382d9..b99f2128a7d83411465392cd1d0492ae2ac49062 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -516,15 +516,8 @@ Type *ETSChecker::GuaranteedTypeForUncheckedCallReturn(Signature *sig) return GuaranteedTypeForUncheckedCast(baseSig->ReturnType(), sig->ReturnType()); } -void ETSChecker::CheckEtsFunctionType(ir::Identifier *const ident, ir::Identifier const *const id, - ir::TypeNode const *const annotation) +void ETSChecker::CheckEtsFunctionType(ir::Identifier *const ident, ir::Identifier const *const id) { - if (annotation == nullptr) { - ThrowTypeError( - {"Cannot infer type for ", id->Name(), " because method reference needs an explicit target type"}, - id->Start()); - } - const auto *const targetType = GetTypeOfVariable(id->Variable()); ASSERT(targetType != nullptr); diff --git a/ets2panda/checker/ets/validateHelpers.cpp b/ets2panda/checker/ets/validateHelpers.cpp index a98aaeb8f699689eb1894b1df7d5cf8a1483c271..d3f0b368129b49449ad5e0b8885a684b4e9f068d 100644 --- a/ets2panda/checker/ets/validateHelpers.cpp +++ b/ets2panda/checker/ets/validateHelpers.cpp @@ -141,7 +141,7 @@ void ETSChecker::ValidatePropertyOrDeclaratorIdentifier(ir::Identifier *const id const auto [target_ident, typeAnnotation] = GetTargetIdentifierAndType(ident); if ((resolved != nullptr) && resolved->TsType()->IsETSFunctionType()) { - CheckEtsFunctionType(ident, target_ident, typeAnnotation); + CheckEtsFunctionType(ident, target_ident); return; } diff --git a/ets2panda/test/compiler/ets/FunctionType5-expected.txt b/ets2panda/test/compiler/ets/FunctionType5-expected.txt index 1be708ce93c22ba4a3f62d8db58bcad6096c8488..907e83c1e0fdcb533b52fbc1d89a44674b073a2a 100644 --- a/ets2panda/test/compiler/ets/FunctionType5-expected.txt +++ b/ets2panda/test/compiler/ets/FunctionType5-expected.txt @@ -171,7 +171,7 @@ "operator": "=", "left": { "type": "Identifier", - "name": "cb", + "name": "f", "decorators": [], "loc": { "start": { @@ -180,7 +180,7 @@ }, "end": { "line": 20, - "column": 7 + "column": 6 } } }, @@ -191,11 +191,11 @@ "loc": { "start": { "line": 20, - "column": 10 + "column": 9 }, "end": { "line": 20, - "column": 13 + "column": 12 } } }, @@ -206,7 +206,7 @@ }, "end": { "line": 20, - "column": 13 + "column": 12 } } }, @@ -217,7 +217,7 @@ }, "end": { "line": 20, - "column": 13 + "column": 12 } } } @@ -276,11 +276,11 @@ "decorators": [], "loc": { "start": { - "line": 16, + "line": 17, "column": 10 }, "end": { - "line": 16, + "line": 17, "column": 13 } } @@ -300,11 +300,11 @@ "decorators": [], "loc": { "start": { - "line": 16, + "line": 17, "column": 10 }, "end": { - "line": 16, + "line": 17, "column": 13 } } @@ -317,172 +317,283 @@ "type": "ETSParameterExpression", "name": { "type": "Identifier", - "name": "a", + "name": "p", "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 16, - "column": 17 + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "String", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } }, - "end": { - "line": 16, - "column": 20 + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 25 + } } - } - }, - "decorators": [], - "loc": { - "start": { - "line": 16, - "column": 14 }, - "end": { - "line": 16, - "column": 20 - } - } - }, - "loc": { - "start": { - "line": 16, - "column": 14 - }, - "end": { - "line": 16, - "column": 20 - } - } - }, - { - "type": "ETSParameterExpression", - "name": { - "type": "Identifier", - "name": "b", - "typeAnnotation": { - "type": "ETSPrimitiveType", "loc": { "start": { - "line": 16, - "column": 25 + "line": 17, + "column": 18 }, "end": { - "line": 16, - "column": 28 + "line": 17, + "column": 25 } } }, "decorators": [], "loc": { "start": { - "line": 16, - "column": 22 + "line": 17, + "column": 15 }, "end": { - "line": 16, - "column": 28 + "line": 17, + "column": 25 } } }, "loc": { "start": { - "line": 16, - "column": 22 + "line": 17, + "column": 15 }, "end": { - "line": 16, - "column": 28 + "line": 17, + "column": 25 } } } ], - "returnType": { - "type": "ETSPrimitiveType", + "body": { + "type": "BlockStatement", + "statements": [], "loc": { "start": { - "line": 16, - "column": 31 + "line": 17, + "column": 25 }, "end": { - "line": 16, - "column": 34 + "line": 17, + "column": 27 } } }, - "body": { - "type": "BlockStatement", - "statements": [ - { - "type": "ReturnStatement", - "argument": { - "type": "NumberLiteral", - "value": 1, + "loc": { + "start": { + "line": 17, + "column": 13 + }, + "end": { + "line": 17, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 13 + }, + "end": { + "line": 17, + "column": 27 + } + } + }, + "overloads": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 10 + }, + "end": { + "line": 18, + "column": 13 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 10 + }, + "end": { + "line": 18, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "p", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 18 + }, + "end": { + "line": 18, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 18 + }, + "end": { + "line": 18, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 18 + }, + "end": { + "line": 18, + "column": 25 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 15 + }, + "end": { + "line": 18, + "column": 25 + } + } + }, "loc": { "start": { - "line": 17, - "column": 10 + "line": 18, + "column": 15 }, "end": { - "line": 17, - "column": 11 + "line": 18, + "column": 25 } } - }, + } + ], + "body": { + "type": "BlockStatement", + "statements": [], "loc": { "start": { - "line": 17, - "column": 3 + "line": 18, + "column": 25 }, "end": { - "line": 17, - "column": 12 + "line": 18, + "column": 27 } } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 27 + } } - ], + }, "loc": { "start": { - "line": 16, - "column": 35 + "line": 18, + "column": 13 }, "end": { "line": 18, - "column": 2 + "column": 27 } } }, + "overloads": [], + "decorators": [], "loc": { "start": { - "line": 16, - "column": 13 + "line": 18, + "column": 1 }, "end": { "line": 18, - "column": 2 + "column": 27 } } - }, - "loc": { - "start": { - "line": 16, - "column": 13 - }, - "end": { - "line": 18, - "column": 2 - } } - }, - "overloads": [], + ], "decorators": [], "loc": { "start": { - "line": 16, + "line": 17, "column": 1 }, "end": { - "line": 18, - "column": 2 + "line": 17, + "column": 27 } } }, @@ -490,7 +601,7 @@ "type": "ClassProperty", "key": { "type": "Identifier", - "name": "cb", + "name": "f", "decorators": [], "loc": { "start": { @@ -499,7 +610,7 @@ }, "end": { "line": 20, - "column": 7 + "column": 6 } } }, @@ -510,11 +621,11 @@ "loc": { "start": { "line": 20, - "column": 10 + "column": 9 }, "end": { "line": 20, - "column": 13 + "column": 12 } } }, @@ -533,7 +644,7 @@ }, "end": { "line": 20, - "column": 13 + "column": 12 } } } @@ -572,4 +683,4 @@ } } } -TypeError: Cannot infer type for cb because method reference needs an explicit target type [FunctionType5.sts:20:5] +TypeError: Ambiguous function initialization because of multiple overloads [FunctionType5.sts:20:9] diff --git a/ets2panda/test/compiler/ets/FunctionType5.sts b/ets2panda/test/compiler/ets/FunctionType5.sts index 5d6f3a10632fdc36e004d38e945b0d573a7f7f00..76748ed093eb2ff5c10da33c516788d6c26dfe10 100644 --- a/ets2panda/test/compiler/ets/FunctionType5.sts +++ b/ets2panda/test/compiler/ets/FunctionType5.sts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2024 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 @@ -13,8 +13,8 @@ * limitations under the License. */ -function foo(a: int, b: int): int { - return 1; -} -let cb = foo; +function foo (p: String){} +function foo (p: number){} + +let f = foo diff --git a/ets2panda/test/runtime/ets/function_type_inference.ets b/ets2panda/test/runtime/ets/function_type_inference.ets new file mode 100644 index 0000000000000000000000000000000000000000..e6e98d1247827e690e37064b95851fe4ec277d8e --- /dev/null +++ b/ets2panda/test/runtime/ets/function_type_inference.ets @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 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(): int { + return 1; +} + +function main(){ + let goo = foo; + assert goo() == 1 +}