From 4c6a5bd68fb96191f9796c05c57292ffd52d12fb Mon Sep 17 00:00:00 2001 From: Konstantin Baladurin Date: Tue, 7 Nov 2023 14:09:27 +0300 Subject: [PATCH] Support lambdas subtyping Change-Id: I6d5fcbcd395ac35ad121da684046e6d29f9266b0 Signed-off-by: Konstantin Baladurin Signed-off-by: Georgy Bronnikov --- ets2panda/checker/ETSAnalyzer.cpp | 85 +- ets2panda/checker/ETSchecker.cpp | 114 +- ets2panda/checker/ETSchecker.h | 38 +- ets2panda/checker/ets/function.cpp | 551 +++-- ets2panda/checker/ets/function_helpers.h | 11 +- ets2panda/checker/ets/helpers.cpp | 101 +- ets2panda/checker/ets/object.cpp | 35 +- ets2panda/checker/types/ets/byteType.h | 4 +- ets2panda/checker/types/ets/charType.h | 2 +- ets2panda/checker/types/ets/doubleType.h | 2 +- ets2panda/checker/types/ets/etsArrayType.cpp | 11 +- ets2panda/checker/types/ets/etsArrayType.h | 2 +- .../types/ets/etsAsyncFuncReturnType.cpp | 6 +- .../types/ets/etsAsyncFuncReturnType.h | 2 +- ets2panda/checker/types/ets/etsBigIntType.h | 2 +- ets2panda/checker/types/ets/etsBooleanType.h | 2 +- ets2panda/checker/types/ets/etsEnumType.cpp | 2 +- ets2panda/checker/types/ets/etsEnumType.h | 2 +- .../types/ets/etsExtensionFuncHelperType.cpp | 6 +- .../types/ets/etsExtensionFuncHelperType.h | 2 +- .../checker/types/ets/etsFunctionType.cpp | 96 +- ets2panda/checker/types/ets/etsFunctionType.h | 5 +- ets2panda/checker/types/ets/etsObjectType.cpp | 270 ++- ets2panda/checker/types/ets/etsObjectType.h | 39 +- ets2panda/checker/types/ets/etsStringType.h | 4 +- ets2panda/checker/types/ets/etsTupleType.cpp | 6 +- ets2panda/checker/types/ets/etsTupleType.h | 2 +- .../checker/types/ets/etsTypeParameter.cpp | 7 +- .../checker/types/ets/etsTypeParameter.h | 2 +- ets2panda/checker/types/ets/etsUnionType.cpp | 4 +- ets2panda/checker/types/ets/etsUnionType.h | 2 +- ets2panda/checker/types/ets/etsVoidType.h | 2 +- ets2panda/checker/types/ets/floatType.h | 2 +- ets2panda/checker/types/ets/intType.h | 2 +- ets2panda/checker/types/ets/longType.h | 2 +- ets2panda/checker/types/ets/shortType.h | 2 +- ets2panda/checker/types/ets/wildcardType.cpp | 2 +- ets2panda/checker/types/ets/wildcardType.h | 2 +- ets2panda/checker/types/globalTypesHolder.cpp | 26 + ets2panda/checker/types/globalTypesHolder.h | 23 + ets2panda/checker/types/signature.cpp | 44 +- ets2panda/checker/types/signature.h | 7 +- ets2panda/checker/types/ts/anyType.cpp | 2 +- ets2panda/checker/types/ts/anyType.h | 2 +- ets2panda/checker/types/ts/arrayType.cpp | 4 +- ets2panda/checker/types/ts/arrayType.h | 2 +- .../checker/types/ts/bigintLiteralType.cpp | 2 +- .../checker/types/ts/bigintLiteralType.h | 2 +- ets2panda/checker/types/ts/bigintType.cpp | 2 +- ets2panda/checker/types/ts/bigintType.h | 2 +- .../checker/types/ts/booleanLiteralType.cpp | 2 +- .../checker/types/ts/booleanLiteralType.h | 2 +- ets2panda/checker/types/ts/booleanType.cpp | 2 +- ets2panda/checker/types/ts/booleanType.h | 2 +- .../checker/types/ts/constructorType.cpp | 2 +- ets2panda/checker/types/ts/constructorType.h | 2 +- .../checker/types/ts/enumLiteralType.cpp | 2 +- ets2panda/checker/types/ts/enumLiteralType.h | 2 +- ets2panda/checker/types/ts/enumType.cpp | 2 +- ets2panda/checker/types/ts/enumType.h | 3 +- ets2panda/checker/types/ts/functionType.cpp | 2 +- ets2panda/checker/types/ts/functionType.h | 2 +- ets2panda/checker/types/ts/interfaceType.cpp | 2 +- ets2panda/checker/types/ts/interfaceType.h | 2 +- ets2panda/checker/types/ts/neverType.cpp | 2 +- ets2panda/checker/types/ts/neverType.h | 2 +- .../checker/types/ts/nonPrimitiveType.cpp | 2 +- ets2panda/checker/types/ts/nonPrimitiveType.h | 2 +- ets2panda/checker/types/ts/nullType.cpp | 2 +- ets2panda/checker/types/ts/nullType.h | 2 +- .../checker/types/ts/numberLiteralType.cpp | 2 +- .../checker/types/ts/numberLiteralType.h | 2 +- ets2panda/checker/types/ts/numberType.cpp | 2 +- ets2panda/checker/types/ts/numberType.h | 2 +- .../checker/types/ts/objectLiteralType.cpp | 2 +- .../checker/types/ts/objectLiteralType.h | 2 +- .../checker/types/ts/stringLiteralType.cpp | 2 +- .../checker/types/ts/stringLiteralType.h | 2 +- ets2panda/checker/types/ts/stringType.cpp | 2 +- ets2panda/checker/types/ts/stringType.h | 2 +- ets2panda/checker/types/ts/tupleType.cpp | 6 +- ets2panda/checker/types/ts/tupleType.h | 2 +- ets2panda/checker/types/ts/typeParameter.cpp | 2 +- ets2panda/checker/types/ts/typeParameter.h | 2 +- ets2panda/checker/types/ts/typeReference.cpp | 4 +- ets2panda/checker/types/ts/typeReference.h | 2 +- ets2panda/checker/types/ts/undefinedType.cpp | 2 +- ets2panda/checker/types/ts/undefinedType.h | 2 +- ets2panda/checker/types/ts/unionType.cpp | 4 +- ets2panda/checker/types/ts/unionType.h | 2 +- ets2panda/checker/types/ts/unknownType.cpp | 2 +- ets2panda/checker/types/ts/unknownType.h | 2 +- ets2panda/checker/types/ts/voidType.cpp | 2 +- ets2panda/checker/types/ts/voidType.h | 2 +- ets2panda/checker/types/type.cpp | 27 + ets2panda/checker/types/type.h | 7 +- ets2panda/checker/types/typeFlag.h | 2 +- ets2panda/compiler/core/ETSCompiler.cpp | 94 +- ets2panda/compiler/core/ETSCompiler.h | 3 +- ets2panda/compiler/core/ETSGen.cpp | 9 +- ets2panda/compiler/core/ETSGen.h | 27 +- ets2panda/compiler/scripts/signatures.yaml | 60 +- ets2panda/ir/ets/etsFunctionType.h | 5 + ets2panda/ir/ts/tsAsExpression.h | 5 + .../compiler/ets/FunctionType1-expected.txt | 2 +- .../compiler/ets/FunctionType3-expected.txt | 2 +- .../ets/etsObjectToString4-expected.txt | 2 +- .../ets/etsObjectToString5-expected.txt | 2 +- .../ets/function_subtyping_1-expected.txt | 997 +++++++++ .../compiler/ets/function_subtyping_1.ets | 21 + .../ets/function_subtyping_2-expected.txt | 998 +++++++++ .../compiler/ets/function_subtyping_2.ets | 21 + .../ets/function_subtyping_3-expected.txt | 998 +++++++++ .../compiler/ets/function_subtyping_3.ets | 21 + .../ets/generic_variance_1-expected.txt | 1973 +++++++++++++++++ .../test/compiler/ets/generic_variance_1.ets | 28 + .../ets/generic_variance_2-expected.txt | 1218 ++++++++++ .../test/compiler/ets/generic_variance_2.ets | 24 + .../ets/generic_variance_3-expected.txt | 1218 ++++++++++ .../test/compiler/ets/generic_variance_3.ets | 24 + .../ets/generic_variance_4-expected.txt | 1178 ++++++++++ .../test/compiler/ets/generic_variance_4.ets | 24 + .../ets/generic_variance_5-expected.txt | 1178 ++++++++++ .../test/compiler/ets/generic_variance_5.ets | 24 + .../ets/identifierReference2-expected.txt | 2 +- ...utBlockStatementDifferentType-expected.txt | 2 +- .../compiler/ets/lambdaFunction3-expected.txt | 2 +- .../compiler/ets/lambdaFunction5-expected.txt | 2 +- ...mbda_cast_infer_type_widening-expected.txt | 96 +- .../lambda_cast_infer_type_widening.ets | 4 +- ...odOverrideCovariantReturnType-expected.txt | 1 - ...ullableTypeParamToNonNullable-expected.txt | 2 +- ...ericWithNullableTypeParamToNonNullable.ets | 2 +- .../ets/overload_with_generics-expected.txt | 1209 ++++++++++ .../compiler/ets/overload_with_generics.ets | 25 + .../test/compiler/ets/override16-expected.txt | 2 +- ...unction_implicit_return_type2-expected.txt | 2 +- ...unction_implicit_return_type3-expected.txt | 2 +- .../test/parser/ets/interface-expected.txt | 4 +- ets2panda/test/parser/ets/interface.ets | 2 +- .../lambda-type-inference-neg-expected.txt | 2 +- ...a-type-inference-overloaded-1-expected.txt | 2 +- .../runtime/ets/conversion-char-boolean.ets | 2 +- .../runtime/ets/unboxingBooleanConversion.ets | 3 +- .../ets-runtime/ets-runtime-ignored.txt | 9 + .../test-lists/parser/parser-ets-ignored.txt | 14 + .../test-lists/parser/parser-js-ignored.txt | 7 +- ets2panda/util/declgenEts2Ts.cpp | 3 +- ets2panda/varbinder/ETSBinder.cpp | 59 +- ets2panda/varbinder/ETSBinder.h | 2 - 150 files changed, 12565 insertions(+), 735 deletions(-) create mode 100644 ets2panda/test/compiler/ets/function_subtyping_1-expected.txt create mode 100644 ets2panda/test/compiler/ets/function_subtyping_1.ets create mode 100644 ets2panda/test/compiler/ets/function_subtyping_2-expected.txt create mode 100644 ets2panda/test/compiler/ets/function_subtyping_2.ets create mode 100644 ets2panda/test/compiler/ets/function_subtyping_3-expected.txt create mode 100644 ets2panda/test/compiler/ets/function_subtyping_3.ets create mode 100644 ets2panda/test/compiler/ets/generic_variance_1-expected.txt create mode 100644 ets2panda/test/compiler/ets/generic_variance_1.ets create mode 100644 ets2panda/test/compiler/ets/generic_variance_2-expected.txt create mode 100644 ets2panda/test/compiler/ets/generic_variance_2.ets create mode 100644 ets2panda/test/compiler/ets/generic_variance_3-expected.txt create mode 100644 ets2panda/test/compiler/ets/generic_variance_3.ets create mode 100644 ets2panda/test/compiler/ets/generic_variance_4-expected.txt create mode 100644 ets2panda/test/compiler/ets/generic_variance_4.ets create mode 100644 ets2panda/test/compiler/ets/generic_variance_5-expected.txt create mode 100644 ets2panda/test/compiler/ets/generic_variance_5.ets create mode 100644 ets2panda/test/compiler/ets/overload_with_generics-expected.txt create mode 100644 ets2panda/test/compiler/ets/overload_with_generics.ets diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 810934b8e5..050613b400 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -411,57 +411,50 @@ checker::Type *ETSAnalyzer::Check(ir::ETSClassLiteral *expr) const checker::Type *ETSAnalyzer::Check(ir::ETSFunctionType *node) const { ETSChecker *checker = GetETSChecker(); - checker->CreateFunctionalInterfaceForFunctionType(node); - auto *interfaceType = - checker->CreateETSObjectType(node->FunctionalInterface()->Id()->Name(), node->FunctionalInterface(), - checker::ETSObjectFlags::FUNCTIONAL_INTERFACE); - interfaceType->SetSuperType(checker->GlobalETSObjectType()); - - auto *invokeFunc = node->FunctionalInterface()->Body()->Body()[0]->AsMethodDefinition()->Function(); - auto *signatureInfo = checker->Allocator()->New(checker->Allocator()); - - for (auto *it : invokeFunc->Params()) { - auto *const param = it->AsETSParameterExpression(); - if (param->IsRestParameter()) { - auto *restIdent = param->Ident(); - - ASSERT(restIdent->Variable()); - signatureInfo->restVar = restIdent->Variable()->AsLocalVariable(); - - ASSERT(param->TypeAnnotation()); - signatureInfo->restVar->SetTsType(checker->GetTypeFromTypeAnnotation(param->TypeAnnotation())); - - auto arrayType = signatureInfo->restVar->TsType()->AsETSArrayType(); - checker->CreateBuiltinArraySignature(arrayType, arrayType->Rank()); - } else { - auto *paramIdent = param->Ident(); - - ASSERT(paramIdent->Variable()); - varbinder::Variable *paramVar = paramIdent->Variable(); + auto *genericInterfaceType = checker->GlobalBuiltinFunctionType(node->Params().size()); + node->SetFunctionalInterface(genericInterfaceType->GetDeclNode()->AsTSInterfaceDeclaration()); + + auto *tsType = checker->GetCachedFunctionlInterface(node); + node->SetTsType(tsType); + if (tsType != nullptr) { + return tsType; + } + + auto *substitution = checker->NewSubstitution(); + + auto maxParamsNum = checker->GlobalBuiltinFunctionTypeVariadicThreshold(); + + auto const ¶ms = node->Params(); + size_t i = 0; + if (params.size() < maxParamsNum) { + for (; i < params.size(); i++) { + auto *paramType = + checker->GetTypeFromTypeAnnotation(params[i]->AsETSParameterExpression()->TypeAnnotation()); + if (paramType->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + checker->Relation()->SetNode(params[i]); + auto *const boxedTypeArg = checker->PrimitiveTypeAsETSBuiltinType(paramType); + ASSERT(boxedTypeArg); + paramType = boxedTypeArg->Instantiate(checker->Allocator(), checker->Relation(), + checker->GetGlobalTypesHolder()); + } - ASSERT(param->TypeAnnotation()); - paramVar->SetTsType(checker->GetTypeFromTypeAnnotation(param->TypeAnnotation())); - signatureInfo->params.push_back(paramVar->AsLocalVariable()); - ++signatureInfo->minArgCount; + checker::ETSChecker::EmplaceSubstituted( + substitution, genericInterfaceType->TypeArguments()[i]->AsETSTypeParameter()->GetOriginal(), paramType); } } - invokeFunc->ReturnTypeAnnotation()->Check(checker); - auto *signature = - checker->Allocator()->New(signatureInfo, node->ReturnType()->GetType(checker), invokeFunc); - signature->SetOwnerVar(invokeFunc->Id()->Variable()->AsLocalVariable()); - signature->AddSignatureFlag(checker::SignatureFlags::FUNCTIONAL_INTERFACE_SIGNATURE); - signature->SetOwner(interfaceType); + auto *returnType = node->ReturnType()->GetType(checker); + if (returnType->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + checker->Relation()->SetNode(node->ReturnType()); + auto *const boxedTypeRet = checker->PrimitiveTypeAsETSBuiltinType(returnType); + returnType = + boxedTypeRet->Instantiate(checker->Allocator(), checker->Relation(), checker->GetGlobalTypesHolder()); + } - auto *funcType = checker->CreateETSFunctionType(signature); - invokeFunc->SetSignature(signature); - invokeFunc->Id()->Variable()->SetTsType(funcType); - interfaceType->AddProperty(invokeFunc->Id()->Variable()->AsLocalVariable()); - node->FunctionalInterface()->SetTsType(interfaceType); + checker::ETSChecker::EmplaceSubstituted( + substitution, genericInterfaceType->TypeArguments()[i]->AsETSTypeParameter()->GetOriginal(), returnType); - auto *thisVar = invokeFunc->Scope()->ParamScope()->Params().front(); - thisVar->SetTsType(interfaceType); - checker->BuildFunctionalInterfaceName(node); + auto *interfaceType = genericInterfaceType->Substitute(checker->Relation(), substitution)->AsETSObjectType(); node->SetTsType(interfaceType); return interfaceType; @@ -1016,7 +1009,7 @@ ArenaVector &ChooseSignatures(ETSChecker *checker, checker } if (isFunctionalInterface) { return calleeType->AsETSObjectType() - ->GetOwnProperty("invoke") + ->GetOwnProperty(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME) ->TsType() ->AsETSFunctionType() ->CallSignatures(); diff --git a/ets2panda/checker/ETSchecker.cpp b/ets2panda/checker/ETSchecker.cpp index 834464fcb7..e111deca28 100644 --- a/ets2panda/checker/ETSchecker.cpp +++ b/ets2panda/checker/ETSchecker.cpp @@ -29,6 +29,73 @@ #include "util/helpers.h" namespace panda::es2panda::checker { + +static util::StringView InitBuiltin(ETSChecker *checker, std::string_view signature) +{ + const auto varMap = checker->VarBinder()->TopScope()->Bindings(); + const auto iterator = varMap.find(signature); + ASSERT(iterator != varMap.end()); + auto *var = iterator->second; + Type *type {nullptr}; + if (var->Declaration()->Node()->IsClassDefinition()) { + type = checker->BuildBasicClassProperties(var->Declaration()->Node()->AsClassDefinition()); + } else { + ASSERT(var->Declaration()->Node()->IsTSInterfaceDeclaration()); + type = checker->BuildBasicInterfaceProperties(var->Declaration()->Node()->AsTSInterfaceDeclaration()); + } + checker->GetGlobalTypesHolder()->InitializeBuiltin(iterator->first, type); + return iterator->first; +} + +static void SetupFunctionalInterface(ETSChecker *checker, ETSObjectType *type) +{ + auto savedContext = SavedCheckerContext(checker, checker::CheckerStatus::IN_INTERFACE, type); + checker::ScopeContext scopeCtx(checker, type->GetDeclNode()->Scope()); + checker->ResolveDeclaredMembersOfObject(type); + type->AddObjectFlag(ETSObjectFlags::FUNCTIONAL); + auto *invoke = type->GetOwnProperty(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME); + auto *invokeType = invoke->TsType()->AsETSFunctionType(); + ASSERT(invokeType->CallSignatures().size() == 1); + auto *signature = invokeType->CallSignatures()[0]; + signature->AddSignatureFlag(SignatureFlags::FUNCTIONAL_INTERFACE_SIGNATURE); +} + +static void SetupBuiltinMember(ETSChecker *checker, varbinder::Variable *var) +{ + auto *type = var->TsType(); + if (type == nullptr || !type->IsETSObjectType()) { + return; + } + auto *objType = type->AsETSObjectType(); + auto *declNode = var->Declaration()->Node(); + if (declNode->IsClassDefinition()) { + auto savedContext = SavedCheckerContext(checker, checker::CheckerStatus::IN_CLASS, objType); + checker::ScopeContext scopeCtx(checker, declNode->Scope()); + checker->ResolveDeclaredMembersOfObject(objType); + } else if (declNode->IsTSInterfaceDeclaration()) { + auto savedContext = SavedCheckerContext(checker, checker::CheckerStatus::IN_INTERFACE, objType); + checker::ScopeContext scopeCtx(checker, declNode->Scope()); + checker->ResolveDeclaredMembersOfObject(objType); + } +} + +// NOLINTNEXTLINE(modernize-avoid-c-arrays) +static constexpr std::string_view BUILTINS_TO_INIT[] = { + compiler::Signatures::BUILTIN_BOOLEAN_CLASS, compiler::Signatures::BUILTIN_BYTE_CLASS, + compiler::Signatures::BUILTIN_CHAR_CLASS, compiler::Signatures::BUILTIN_SHORT_CLASS, + compiler::Signatures::BUILTIN_INT_CLASS, compiler::Signatures::BUILTIN_LONG_CLASS, + compiler::Signatures::BUILTIN_FLOAT_CLASS, compiler::Signatures::BUILTIN_DOUBLE_CLASS, + compiler::Signatures::BUILTIN_FUNCTION0_CLASS, compiler::Signatures::BUILTIN_FUNCTION1_CLASS, + compiler::Signatures::BUILTIN_FUNCTION2_CLASS, compiler::Signatures::BUILTIN_FUNCTION3_CLASS, + compiler::Signatures::BUILTIN_FUNCTION4_CLASS, compiler::Signatures::BUILTIN_FUNCTION5_CLASS, + compiler::Signatures::BUILTIN_FUNCTION6_CLASS, compiler::Signatures::BUILTIN_FUNCTION7_CLASS, + compiler::Signatures::BUILTIN_FUNCTION8_CLASS, compiler::Signatures::BUILTIN_FUNCTION9_CLASS, + compiler::Signatures::BUILTIN_FUNCTION10_CLASS, compiler::Signatures::BUILTIN_FUNCTION11_CLASS, + compiler::Signatures::BUILTIN_FUNCTION12_CLASS, compiler::Signatures::BUILTIN_FUNCTION13_CLASS, + compiler::Signatures::BUILTIN_FUNCTION14_CLASS, compiler::Signatures::BUILTIN_FUNCTION15_CLASS, + compiler::Signatures::BUILTIN_FUNCTION16_CLASS, compiler::Signatures::BUILTIN_FUNCTIONN_CLASS, +}; + void ETSChecker::InitializeBuiltins(varbinder::ETSBinder *varbinder) { if (HasStatus(CheckerStatus::BUILTINS_INITIALIZED)) { @@ -37,17 +104,23 @@ void ETSChecker::InitializeBuiltins(varbinder::ETSBinder *varbinder) const auto varMap = varbinder->TopScope()->Bindings(); - auto initBuiltin = [varMap](ETSChecker *checker, std::string_view signature) -> util::StringView { - const auto iterator = varMap.find(signature); - ASSERT(iterator != varMap.end()); - checker->GetGlobalTypesHolder()->InitializeBuiltin( - iterator->first, - checker->BuildClassProperties(iterator->second->Declaration()->Node()->AsClassDefinition())); - return iterator->first; - }; + auto const objectName = InitBuiltin(this, compiler::Signatures::BUILTIN_OBJECT_CLASS); + auto const voidName = InitBuiltin(this, compiler::Signatures::BUILTIN_VOID_CLASS); + + for (auto sig : BUILTINS_TO_INIT) { + InitBuiltin(this, sig); + } - auto const objectName = initBuiltin(this, compiler::Signatures::BUILTIN_OBJECT_CLASS); - auto const voidName = initBuiltin(this, compiler::Signatures::BUILTIN_VOID_CLASS); + for (size_t id = static_cast(GlobalTypeId::ETS_FUNCTION0_CLASS), nargs = 0; + id <= static_cast(GlobalTypeId::ETS_FUNCTIONN_CLASS); id++, nargs++) { + auto *type = GetGlobalTypesHolder()->GlobalFunctionBuiltinType(nargs)->AsETSObjectType(); + SetupFunctionalInterface(this, type); + } + + for (const auto &[name, var] : varMap) { + (void)name; + SetupBuiltinMember(this, var); + } for (const auto &[name, var] : varMap) { if (name == objectName || name == voidName) { @@ -55,7 +128,11 @@ void ETSChecker::InitializeBuiltins(varbinder::ETSBinder *varbinder) } if (var->HasFlag(varbinder::VariableFlags::BUILTIN_TYPE)) { - InitializeBuiltin(var, name); + if (var->TsType() == nullptr) { + InitializeBuiltin(var, name); + } else { + GetGlobalTypesHolder()->InitializeBuiltin(name, var->TsType()); + } } } @@ -160,9 +237,10 @@ Type *ETSChecker::CheckTypeCached(ir::Expression *expr) return expr->TsType(); } -ETSObjectType *ETSChecker::AsETSObjectType(Type *(GlobalTypesHolder::*typeFunctor)()) const +template +ETSObjectType *ETSChecker::AsETSObjectType(Type *(GlobalTypesHolder::*typeFunctor)(Args...), Args... args) const { - auto *ret = (GetGlobalTypesHolder()->*typeFunctor)(); + auto *ret = (GetGlobalTypesHolder()->*typeFunctor)(args...); return ret != nullptr ? ret->AsETSObjectType() : nullptr; } @@ -296,6 +374,16 @@ ETSObjectType *ETSChecker::GlobalBuiltinVoidType() const return AsETSObjectType(&GlobalTypesHolder::GlobalBuiltinVoidType); } +ETSObjectType *ETSChecker::GlobalBuiltinFunctionType(size_t nargs) const +{ + return AsETSObjectType(&GlobalTypesHolder::GlobalFunctionBuiltinType, nargs); +} + +size_t ETSChecker::GlobalBuiltinFunctionTypeVariadicThreshold() const +{ + return GetGlobalTypesHolder()->VariadicFunctionTypeThreshold(); +} + ETSObjectType *ETSChecker::GlobalBuiltinDynamicType(Language lang) const { if (lang.GetId() == Language::Id::JS) { diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index e909286f93..710021b70f 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -63,6 +63,7 @@ using ArrayMap = ArenaUnorderedMap; using GlobalArraySignatureMap = ArenaUnorderedMap; using DynamicCallIntrinsicsMap = ArenaUnorderedMap>; using DynamicLambdaObjectSignatureMap = ArenaUnorderedMap; +using FunctionalInterfaceMap = ArenaUnorderedMap; class ETSChecker final : public Checker { public: @@ -75,7 +76,8 @@ public: cachedComputedAbstracts_(Allocator()->Adapter()), dynamicCallIntrinsics_(Allocator()->Adapter()), dynamicNewIntrinsics_(Allocator()->Adapter()), - dynamicLambdaSignatureCache_(Allocator()->Adapter()) + dynamicLambdaSignatureCache_(Allocator()->Adapter()), + functionalInterfaceCache_(Allocator()->Adapter()) { } @@ -118,6 +120,9 @@ public: ETSObjectType *GlobalBuiltinBoxType(const Type *contents) const; ETSObjectType *GlobalBuiltinVoidType() const; + ETSObjectType *GlobalBuiltinFunctionType(size_t nargs) const; + size_t GlobalBuiltinFunctionTypeVariadicThreshold() const; + ETSObjectType *GlobalBuiltinDynamicType(Language lang) const; const checker::WrapperDesc &PrimitiveWrapper() const; @@ -140,8 +145,10 @@ public: } // Object + ETSObjectType *BuildBasicClassProperties(ir::ClassDefinition *classDef); ETSObjectType *BuildClassProperties(ir::ClassDefinition *classDef); ETSObjectType *BuildAnonymousClassProperties(ir::ClassDefinition *classDef, ETSObjectType *superType); + ETSObjectType *BuildBasicInterfaceProperties(ir::TSInterfaceDeclaration *interfaceDecl); ETSObjectType *BuildInterfaceProperties(ir::TSInterfaceDeclaration *interfaceDecl); ETSObjectType *GetSuperType(ETSObjectType *type); ArenaVector GetInterfaces(ETSObjectType *type); @@ -395,7 +402,7 @@ public: ArenaVector &properties); std::tuple CreateLambdaCtorImplicitParam( ArenaVector ¶ms, const lexer::SourceRange &pos, bool isStaticReference); - ir::MethodDefinition *CreateLambdaInvokeProto(); + ir::MethodDefinition *CreateLambdaInvokeProto(util::StringView invokeName); void CreateLambdaFuncDecl(ir::MethodDefinition *func, varbinder::LocalScope *scope); void ResolveProxyMethod(ir::MethodDefinition *proxyMethod, ir::ArrowFunctionExpression *lambda); void ResolveLambdaObject(ir::ClassDefinition *lambdaObject, Signature *signature, @@ -404,18 +411,18 @@ public: ir::ArrowFunctionExpression *lambda, ir::MethodDefinition *proxyMethod, bool saveThis); void ResolveLambdaObjectCtor(ir::ClassDefinition *lambdaObject, bool isStaticReference); void ResolveLambdaObjectCtor(ir::ClassDefinition *lambdaObject); - void ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, Signature *signatureRef); + void ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, Signature *signatureRef, bool ifaceOverride); void ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, ir::ArrowFunctionExpression *lambda, - ir::MethodDefinition *proxyMethod, bool isStatic); - ir::Statement *ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition *lambdaObject, Signature *signatureRef); + ir::MethodDefinition *proxyMethod, bool isStatic, bool ifaceOverride); + ir::Statement *ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition *lambdaObject, Signature *signatureRef, + bool ifaceOverride); ir::Statement *ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition *lambdaObject, - ir::MethodDefinition *proxyMethod, bool isStatic); - void CreateFunctionalInterfaceForFunctionType(ir::ETSFunctionType *funcType); - ir::MethodDefinition *CreateInvokeFunction(ir::ETSFunctionType *funcType); + ir::ArrowFunctionExpression *lambda, + ir::MethodDefinition *proxyMethod, bool isStatic, + bool ifaceOverride); void CheckCapturedVariables(); void CheckCapturedVariableInSubnodes(ir::AstNode *node, varbinder::Variable *var); void CheckCapturedVariable(ir::AstNode *node, varbinder::Variable *var); - void BuildFunctionalInterfaceName(ir::ETSFunctionType *funcType); void CreateAsyncProxyMethods(ir::ClassDefinition *classDef); ir::MethodDefinition *CreateAsyncImplMethod(ir::MethodDefinition *asyncMethod, ir::ClassDefinition *classDef); ir::MethodDefinition *CreateAsyncProxy(ir::MethodDefinition *asyncMethod, ir::ClassDefinition *classDef, @@ -537,6 +544,7 @@ public: ETSObjectType *GetRelevantArgumentedTypeFromChild(ETSObjectType *child, ETSObjectType *target); util::StringView GetHashFromTypeArguments(const ArenaVector &typeArgTypes); util::StringView GetHashFromSubstitution(const Substitution *substitution); + util::StringView GetHashFromFunctionType(ir::ETSFunctionType *type); ETSObjectType *GetOriginalBaseType(Type *object); Type *GetTypeFromTypeAnnotation(ir::TypeNode *typeAnnotation); void AddUndefinedParamsForDefaultParams(const Signature *signature, @@ -549,9 +557,8 @@ public: Type *SelectGlobalIntegerTypeForNumeric(Type *type); const Type *TryGettingFunctionTypeFromInvokeFunction(const Type *type) const; - void GenerateGetterSetterBody(ETSChecker *checker, ArenaVector &stmts, - ArenaVector ¶ms, ir::ClassProperty *field, - varbinder::FunctionParamScope *paramScope, bool isSetter); + void GenerateGetterSetterBody(ArenaVector &stmts, ArenaVector ¶ms, + ir::ClassProperty *field, varbinder::FunctionParamScope *paramScope, bool isSetter); static ir::MethodDefinition *GenerateDefaultGetterSetter(ir::ClassProperty *field, varbinder::ClassScope *scope, bool isSetter, ETSChecker *checker); @@ -610,6 +617,9 @@ public: return ret; } + ETSObjectType *GetCachedFunctionlInterface(ir::ETSFunctionType *type); + void CacheFunctionalInterface(ir::ETSFunctionType *type, ETSObjectType *ifaceType); + private: using ClassBuilder = std::function *)>; using ClassInitializerBuilder = std::function *, @@ -688,7 +698,8 @@ private: template typename TargetType::UType GetOperand(Type *type); - ETSObjectType *AsETSObjectType(Type *(GlobalTypesHolder::*typeFunctor)()) const; + template + ETSObjectType *AsETSObjectType(Type *(GlobalTypesHolder::*typeFunctor)(Args...), Args... args) const; Signature *GetMostSpecificSignature(ArenaVector &compatibleSignatures, ArenaVector &proxySignatures, const ArenaVector &arguments, @@ -713,6 +724,7 @@ private: DynamicCallIntrinsicsMap dynamicCallIntrinsics_; DynamicCallIntrinsicsMap dynamicNewIntrinsics_; DynamicLambdaObjectSignatureMap dynamicLambdaSignatureCache_; + FunctionalInterfaceMap functionalInterfaceCache_; std::recursive_mutex mtx_; }; diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index e6476c47e5..9dffd8fd25 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -20,6 +20,7 @@ #include "varbinder/variable.h" #include "varbinder/variableFlags.h" #include "checker/ETSchecker.h" +#include "checker/ets/castingContext.h" #include "checker/ets/function_helpers.h" #include "checker/ets/typeRelationContext.h" #include "checker/types/ets/etsAsyncFuncReturnType.h" @@ -143,10 +144,12 @@ bool ETSChecker::EnhanceSubstitutionForObject(const ArenaVector &typePar } if (argumentType->IsETSFunctionType() && paramObjType->HasObjectFlag(ETSObjectFlags::FUNCTIONAL_INTERFACE)) { - auto ¶meterSignatures = paramObjType->GetOwnProperty("invoke") - ->TsType() - ->AsETSFunctionType() - ->CallSignatures(); + auto ¶meterSignatures = + paramObjType + ->GetOwnProperty(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME) + ->TsType() + ->AsETSFunctionType() + ->CallSignatures(); auto &argumentSignatures = argumentType->AsETSFunctionType()->CallSignatures(); ASSERT(argumentSignatures.size() == 1); ASSERT(parameterSignatures.size() == 1); @@ -1405,83 +1408,53 @@ void ETSChecker::CheckCapturedVariables() } } -void ETSChecker::BuildFunctionalInterfaceName(ir::ETSFunctionType *funcType) -{ - VarBinder()->AsETSBinder()->BuildFunctionalInterfaceName(funcType); -} +// Lambda creation for Lambda expressions -void ETSChecker::CreateFunctionalInterfaceForFunctionType(ir::ETSFunctionType *funcType) +// Chunk pulled out of CreateLambdaObjectForLambdaReference to appease Chinese code checker +static std::pair, bool> CreateLambdaObjectPropertiesForLambdaReference( + ETSChecker *checker, ir::ArrowFunctionExpression *lambda, varbinder::ClassScope *classScope) { - auto *identNode = Allocator()->New(util::StringView("FunctionalInterface"), Allocator()); - - auto interfaceCtx = varbinder::LexicalScope(VarBinder()); - auto *interfaceScope = interfaceCtx.GetScope(); - - ArenaVector members(Allocator()->Adapter()); - ir::MethodDefinition *invokeFunc = CreateInvokeFunction(funcType); - members.push_back(invokeFunc); - - auto methodCtx = - varbinder::LexicalScope::Enter(VarBinder(), interfaceScope->InstanceMethodScope()); - auto [_, var] = VarBinder()->NewVarDecl(invokeFunc->Start(), Allocator(), - invokeFunc->Id()->Name(), invokeFunc); - (void)_; - var->AddFlag(varbinder::VariableFlags::METHOD); - invokeFunc->Function()->Id()->SetVariable(var); + bool saveThis = false; + size_t idx = 0; + const auto &capturedVars = lambda->CapturedVars(); - if (funcType->IsThrowing()) { - invokeFunc->Function()->AddFlag(ir::ScriptFunctionFlags::THROWS); + // Create the synthetic class property nodes for the captured variables + ArenaVector properties(checker->Allocator()->Adapter()); + for (const auto *it : capturedVars) { + if (it->HasFlag(varbinder::VariableFlags::LOCAL)) { + properties.push_back(checker->CreateLambdaCapturedField(it, classScope, idx, lambda->Start())); + idx++; + } else if (!it->HasFlag(varbinder::VariableFlags::STATIC) && + !checker->Context().ContainingClass()->HasObjectFlag(ETSObjectFlags::GLOBAL)) { + saveThis = true; + } } - auto *body = Allocator()->New(std::move(members)); - - ArenaVector extends(Allocator()->Adapter()); - auto *interfaceDecl = Allocator()->New( - Allocator(), identNode, nullptr, body, std::move(extends), false, false, Language(Language::Id::ETS)); - interfaceDecl->SetScope(interfaceScope); - interfaceDecl->AddModifier(ir::ModifierFlags::FUNCTIONAL); - funcType->SetFunctionalInterface(interfaceDecl); - invokeFunc->SetParent(interfaceDecl); + // If the lambda captured a property in the current class, we have to make a synthetic class property to store + // 'this' in it + if (saveThis) { + properties.push_back(checker->CreateLambdaCapturedThis(classScope, idx, lambda->Start())); + idx++; + } - VarBinder()->AsETSBinder()->BuildFunctionType(funcType); + return {properties, saveThis}; } -ir::MethodDefinition *ETSChecker::CreateInvokeFunction(ir::ETSFunctionType *funcType) +static void HandleAsyncFuncInLambda(ETSChecker *checker, ir::ArrowFunctionExpression *lambda, + ir::MethodDefinition *proxyMethod, ir::ClassDefinition *currentClassDef) { - auto *identNode = Allocator()->New(util::StringView("invoke"), Allocator()); - - ArenaVector params(Allocator()->Adapter()); - auto *funcParamScope = CopyParams(funcType->Params(), params); - - auto paramCtx = varbinder::LexicalScope::Enter(VarBinder(), funcParamScope, false); - auto functionCtx = varbinder::LexicalScope(VarBinder()); - auto *functionScope = functionCtx.GetScope(); - functionScope->BindParamScope(funcParamScope); - funcParamScope->BindFunctionScope(functionScope); - - ir::ModifierFlags flags = ir::ModifierFlags::ABSTRACT | ir::ModifierFlags::PUBLIC; - auto *func = Allocator()->New( - ir::FunctionSignature(nullptr, std::move(params), funcType->ReturnType()), nullptr, - ir::ScriptFunctionFlags::METHOD, flags, false, Language(Language::Id::ETS)); - - func->SetScope(functionScope); - functionScope->BindNode(func); - funcParamScope->BindNode(func); - - auto *funcExpr = Allocator()->New(func); - func->SetIdent(identNode); - - auto *method = Allocator()->New(ir::MethodDefinitionKind::METHOD, identNode, funcExpr, flags, - Allocator(), false); - - funcExpr->SetParent(method); - func->SetParent(funcExpr); - - return method; + ir::MethodDefinition *asyncImpl = checker->CreateAsyncProxy(proxyMethod, currentClassDef); + ir::ScriptFunction *asyncImplFunc = asyncImpl->Function(); + currentClassDef->Body().push_back(asyncImpl); + asyncImpl->SetParent(currentClassDef); + checker->ReplaceIdentifierReferencesInProxyMethod(asyncImplFunc->Body(), asyncImplFunc->Params(), + lambda->Function()->Params(), lambda->CapturedVars()); + Signature *implSig = checker->CreateSignature(proxyMethod->Function()->Signature()->GetSignatureInfo(), + checker->GlobalETSObjectType(), asyncImplFunc); + asyncImplFunc->SetSignature(implSig); + checker->VarBinder()->AsETSBinder()->BuildFunctionName(asyncImpl->Function()); } -// Lambda creation for Lambda expressions - void ETSChecker::CreateLambdaObjectForLambdaReference(ir::ArrowFunctionExpression *lambda, ETSObjectType *functionalInterface) { @@ -1489,33 +1462,12 @@ void ETSChecker::CreateLambdaObjectForLambdaReference(ir::ArrowFunctionExpressio return; } - bool saveThis = false; - size_t idx = 0; - const auto &capturedVars = lambda->CapturedVars(); - auto *currentClassDef = Context().ContainingClass()->GetDeclNode()->AsClassDefinition(); - // Create the class scope for the synthetic lambda class node auto classCtx = varbinder::LexicalScope(VarBinder()); auto *classScope = classCtx.GetScope(); - // Create the synthetic class property nodes for the captured variables - ArenaVector properties(Allocator()->Adapter()); - for (const auto *it : capturedVars) { - if (it->HasFlag(varbinder::VariableFlags::LOCAL)) { - properties.push_back(CreateLambdaCapturedField(it, classScope, idx, lambda->Start())); - idx++; - } else if (!it->HasFlag(varbinder::VariableFlags::STATIC) && - !Context().ContainingClass()->HasObjectFlag(ETSObjectFlags::GLOBAL)) { - saveThis = true; - } - } - - // If the lambda captured a property in the current class, we have to make a synthetic class property to store - // 'this' in it - if (saveThis) { - properties.push_back(CreateLambdaCapturedThis(classScope, idx, lambda->Start())); - idx++; - } + auto [properties, saveThis] = CreateLambdaObjectPropertiesForLambdaReference(this, lambda, classScope); + auto *currentClassDef = Context().ContainingClass()->GetDeclNode()->AsClassDefinition(); // Create the synthetic proxy method node for the current class definiton, which we will use in the lambda // 'invoke' method to propagate the function call to the current class @@ -1526,16 +1478,18 @@ void ETSChecker::CreateLambdaObjectForLambdaReference(ir::ArrowFunctionExpressio properties.push_back(ctor); // Create the synthetic invoke node for the lambda class, which will propagate the call to the proxy method - auto *invokeFunc = CreateLambdaInvokeProto(); + auto *invoke0Func = CreateLambdaInvokeProto(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME); + auto *invokeFunc = CreateLambdaInvokeProto("invoke"); + properties.push_back(invoke0Func); properties.push_back(invokeFunc); // Create the declarations for the synthetic constructor and invoke method CreateLambdaFuncDecl(ctor, classScope->StaticMethodScope()); + CreateLambdaFuncDecl(invoke0Func, classScope->InstanceMethodScope()); CreateLambdaFuncDecl(invokeFunc, classScope->InstanceMethodScope()); // Create the synthetic lambda class node - ArenaVector implements(Allocator()->Adapter()); auto *identNode = Allocator()->New(util::StringView("LambdaObject"), Allocator()); auto *lambdaObject = Allocator()->New(Allocator(), identNode, std::move(properties), @@ -1553,6 +1507,7 @@ void ETSChecker::CreateLambdaObjectForLambdaReference(ir::ArrowFunctionExpressio // Set the parent nodes ctor->SetParent(lambdaObject); + invoke0Func->SetParent(lambdaObject); invokeFunc->SetParent(lambdaObject); classScope->BindNode(lambdaObject); @@ -1562,15 +1517,7 @@ void ETSChecker::CreateLambdaObjectForLambdaReference(ir::ArrowFunctionExpressio // Resolve the proxy method ResolveProxyMethod(proxyMethod, lambda); if (lambda->Function()->IsAsyncFunc()) { - ir::MethodDefinition *asyncImpl = CreateAsyncProxy(proxyMethod, currentClassDef); - ir::ScriptFunction *asyncImplFunc = asyncImpl->Function(); - currentClassDef->Body().push_back(asyncImpl); - ReplaceIdentifierReferencesInProxyMethod(asyncImplFunc->Body(), asyncImplFunc->Params(), - lambda->Function()->Params(), lambda->CapturedVars()); - Signature *implSig = CreateSignature(proxyMethod->Function()->Signature()->GetSignatureInfo(), - GlobalETSObjectType(), asyncImplFunc); - asyncImplFunc->SetSignature(implSig); - VarBinder()->AsETSBinder()->BuildFunctionName(asyncImpl->Function()); + HandleAsyncFuncInLambda(this, lambda, proxyMethod, currentClassDef); } // Resolve the lambda object @@ -1608,45 +1555,75 @@ void ETSChecker::ResolveLambdaObject(ir::ClassDefinition *lambdaObject, ETSObjec ResolveLambdaObjectCtor(lambdaObject); // Resolve the invoke function - ResolveLambdaObjectInvoke(lambdaObject, lambda, proxyMethod, !saveThis); + ResolveLambdaObjectInvoke(lambdaObject, lambda, proxyMethod, !saveThis, true); + ResolveLambdaObjectInvoke(lambdaObject, lambda, proxyMethod, !saveThis, false); } -void ETSChecker::ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, ir::ArrowFunctionExpression *lambda, - ir::MethodDefinition *proxyMethod, bool isStatic) +static Signature *CreateInvokeSignature(ETSChecker *checker, ir::ArrowFunctionExpression *lambda, + ir::ScriptFunction *invokeFunc, ETSObjectType *lambdaObjectType, + bool ifaceOverride) { - const auto &lambdaBody = lambdaObject->Body(); - auto *invokeFunc = lambdaBody[lambdaBody.size() - 1]->AsMethodDefinition()->Function(); - ETSObjectType *lambdaObjectType = lambdaObject->TsType()->AsETSObjectType(); - - // Set the implicit 'this' parameters type to the lambda object - auto *thisVar = invokeFunc->Scope()->ParamScope()->Params().front(); - thisVar->SetTsType(lambdaObjectType); + auto *allocator = checker->Allocator(); // Create the signature for the invoke function type - auto *invokeSignatureInfo = CreateSignatureInfo(); + auto *invokeSignatureInfo = checker->CreateSignatureInfo(); invokeSignatureInfo->restVar = nullptr; // Create the parameters for the invoke function, based on the lambda function's parameters - for (auto *it : lambda->Function()->Params()) { + auto maxParamsNum = checker->GlobalBuiltinFunctionTypeVariadicThreshold(); + auto paramsNum = lambda->Function()->Params().size(); + if (paramsNum < maxParamsNum || !ifaceOverride) { + for (auto *it : lambda->Function()->Params()) { + auto paramCtx = varbinder::LexicalScope::Enter( + checker->VarBinder(), invokeFunc->Scope()->ParamScope(), false); + auto *const param = it->Clone(allocator, it->Parent())->AsETSParameterExpression(); + auto [_, var] = checker->VarBinder()->AddParamDecl(param); + (void)_; + var->SetTsType(ifaceOverride ? checker->GlobalETSNullishObjectType() : param->Variable()->TsType()); + param->Ident()->SetVariable(var); + invokeFunc->Params().push_back(param); + invokeSignatureInfo->minArgCount++; + invokeSignatureInfo->params.push_back(var->AsLocalVariable()); + } + } else { auto paramCtx = varbinder::LexicalScope::Enter( - VarBinder(), invokeFunc->Scope()->ParamScope(), false); + checker->VarBinder(), invokeFunc->Scope()->ParamScope(), false); - auto *const param = it->AsETSParameterExpression(); - auto [_, var] = VarBinder()->AddParamDecl(param); + auto *id = checker->AllocNode("p", allocator); + auto *restElement = checker->AllocNode(ir::AstNodeType::REST_ELEMENT, allocator, id); + auto *const param = checker->AllocNode(restElement, nullptr); + auto [_, var] = checker->VarBinder()->AddParamDecl(param); (void)_; - var->SetTsType(param->Variable()->TsType()); + var->SetTsType(checker->CreateETSArrayType(checker->GlobalETSNullishObjectType())); param->Ident()->SetVariable(var); invokeFunc->Params().push_back(param); - invokeSignatureInfo->minArgCount++; - invokeSignatureInfo->params.push_back(var->AsLocalVariable()); + invokeSignatureInfo->restVar = var->AsLocalVariable(); } // Create the function type for the invoke method - auto *invokeSignature = - CreateSignature(invokeSignatureInfo, lambda->Function()->Signature()->ReturnType(), invokeFunc); + auto *invokeSignature = checker->CreateSignature(invokeSignatureInfo, + ifaceOverride ? checker->GlobalETSNullishObjectType() + : lambda->Function()->Signature()->ReturnType(), + invokeFunc); invokeSignature->SetOwner(lambdaObjectType); invokeSignature->AddSignatureFlag(checker::SignatureFlags::CALL); + return invokeSignature; +} + +void ETSChecker::ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, ir::ArrowFunctionExpression *lambda, + ir::MethodDefinition *proxyMethod, bool isStatic, bool ifaceOverride) +{ + const auto &lambdaBody = lambdaObject->Body(); + auto *invokeFunc = lambdaBody[lambdaBody.size() - (ifaceOverride ? 2 : 1)]->AsMethodDefinition()->Function(); + ETSObjectType *lambdaObjectType = lambdaObject->TsType()->AsETSObjectType(); + + // Set the implicit 'this' parameters type to the lambda object + auto *thisVar = invokeFunc->Scope()->ParamScope()->Params().front(); + thisVar->SetTsType(lambdaObjectType); + + // Create the function type for the invoke method + auto *invokeSignature = CreateInvokeSignature(this, lambda, invokeFunc, lambdaObjectType, ifaceOverride); auto *invokeType = CreateETSFunctionType(invokeSignature); invokeFunc->SetSignature(invokeSignature); invokeFunc->Id()->Variable()->SetTsType(invokeType); @@ -1655,7 +1632,8 @@ void ETSChecker::ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, ir invokeFunc->Id()->Variable()->AsLocalVariable()); // Fill out the type information for the body of the invoke function - auto *resolvedLambdaInvokeFunctionBody = ResolveLambdaObjectInvokeFuncBody(lambdaObject, proxyMethod, isStatic); + auto *resolvedLambdaInvokeFunctionBody = + ResolveLambdaObjectInvokeFuncBody(lambdaObject, lambda, proxyMethod, isStatic, ifaceOverride); if (invokeFunc->IsAsyncFunc()) { return; } @@ -1665,8 +1643,90 @@ void ETSChecker::ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, ir } } +/* Pulled out to appease the Chinese checker */ + +static void AddFieldRefsToCallParameters(ETSChecker *checker, ir::ClassDefinition *lambdaObject, bool isStatic, + ArenaVector &callParams) +{ + auto *allocator = checker->Allocator(); + auto &lambdaBody = lambdaObject->Body(); + size_t counter = isStatic ? lambdaBody.size() - 3 : lambdaBody.size() - 4; + for (size_t i = 0; i < counter; i++) { + if (lambdaBody[i]->IsMethodDefinition()) { + break; + } + + auto *classProp = lambdaBody[i]->AsClassProperty(); + auto *param = allocator->New(classProp->Key()->AsIdentifier()->Name(), allocator); + param->SetVariable(classProp->Key()->AsIdentifier()->Variable()); + param->SetIgnoreBox(); + param->SetTsType(checker->MaybeBoxedType(param->Variable())); + callParams.push_back(param); + } +} + +static ArenaVector ResolveCallParametersForLambdaFuncBody(ETSChecker *checker, + ir::ClassDefinition *lambdaObject, + ir::ArrowFunctionExpression *lambda, + ir::ScriptFunction *invokeFunc, + bool isStatic, bool ifaceOverride) +{ + auto *allocator = checker->Allocator(); + ArenaVector callParams(allocator->Adapter()); + + AddFieldRefsToCallParameters(checker, lambdaObject, isStatic, callParams); + + auto maxParamsNum = checker->GlobalBuiltinFunctionTypeVariadicThreshold(); + auto paramsNum = lambda->Function()->Params().size(); + if (!ifaceOverride) { + for (auto const *const it : invokeFunc->Params()) { + auto const *const param = it->AsETSParameterExpression(); + auto *const paramIdent = allocator->New(param->Ident()->Name(), allocator); + paramIdent->SetVariable(param->Variable()); + paramIdent->SetTsType(param->Variable()->TsType()); + callParams.push_back(paramIdent); + } + } else if (paramsNum < maxParamsNum) { + // Then we add the lambda functions parameters to the call + auto nargs = invokeFunc->Params().size(); + for (size_t i = 0; i < nargs; i++) { + auto const *const param = invokeFunc->Params()[i]->AsETSParameterExpression(); + auto *const paramIdent = allocator->New(param->Ident()->Name(), allocator); + paramIdent->SetVariable(param->Variable()); + paramIdent->SetTsType(param->Variable()->TsType()); + + auto *lambdaParam = lambda->Function()->Params()[i]->AsETSParameterExpression(); + auto *const paramCast = + allocator->New(paramIdent, lambdaParam->TypeAnnotation(), false); + paramCast->Check(checker); + callParams.push_back(paramCast); + } + } else { + ASSERT(invokeFunc->Params().size() == 1); + auto const *const param = invokeFunc->Params()[0]->AsETSParameterExpression(); + auto *const paramIdent = allocator->New(param->Ident()->Name(), allocator); + paramIdent->SetVariable(param->Variable()); + paramIdent->SetTsType(param->Variable()->TsType()); + + for (size_t i = 0; i < paramsNum; i++) { + auto *idx = allocator->New(lexer::Number(static_cast(i))); + auto *arg = allocator->New(paramIdent, idx, ir::MemberExpressionKind::ELEMENT_ACCESS, + true, false); + + auto *lambdaParam = lambda->Function()->Params()[i]->AsETSParameterExpression(); + auto *const paramCast = allocator->New(arg, lambdaParam->TypeAnnotation(), false); + paramCast->Check(checker); + callParams.push_back(paramCast); + } + } + + return callParams; +} + ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition *lambdaObject, - ir::MethodDefinition *proxyMethod, bool isStatic) + ir::ArrowFunctionExpression *lambda, + ir::MethodDefinition *proxyMethod, bool isStatic, + bool ifaceOverride) { const auto &lambdaBody = lambdaObject->Body(); auto *proxySignature = proxyMethod->Function()->Signature(); @@ -1681,7 +1741,7 @@ ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition fieldIdent->SetTsType(fieldPropType); } else { // Otherwise, we call the proxy method through the saved 'this' field - auto *savedThis = lambdaBody[lambdaBody.size() - 3]->AsClassProperty(); + auto *savedThis = lambdaBody[lambdaBody.size() - 4]->AsClassProperty(); auto *fieldProp = savedThis->Key()->AsIdentifier()->Variable(); fieldPropType = fieldProp->TsType()->AsETSObjectType(); fieldIdent = Allocator()->New(savedThis->Key()->AsIdentifier()->Name(), Allocator()); @@ -1698,30 +1758,9 @@ ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition callee->SetTsType(proxySignature->OwnerVar()->TsType()); // Resolve the proxy method call arguments, first we add the captured fields to the call - auto *invokeFunc = lambdaBody[lambdaBody.size() - 1]->AsMethodDefinition()->Function(); - ArenaVector callParams(Allocator()->Adapter()); - size_t counter = isStatic ? lambdaBody.size() - 2 : lambdaBody.size() - 3; - for (size_t i = 0; i < counter; i++) { - if (lambdaBody[i]->IsMethodDefinition()) { - break; - } - - auto *classProp = lambdaBody[i]->AsClassProperty(); - auto *param = Allocator()->New(classProp->Key()->AsIdentifier()->Name(), Allocator()); - param->SetVariable(classProp->Key()->AsIdentifier()->Variable()); - param->SetIgnoreBox(); - param->SetTsType(MaybeBoxedType(param->Variable())); - callParams.push_back(param); - } - - // Then we add the lambda functions parameters to the call - for (auto const *const it : invokeFunc->Params()) { - auto const *const param = it->AsETSParameterExpression(); - auto *const paramIdent = Allocator()->New(param->Ident()->Name(), Allocator()); - paramIdent->SetVariable(param->Variable()); - paramIdent->SetTsType(param->Variable()->TsType()); - callParams.push_back(paramIdent); - } + auto *invokeFunc = lambdaBody[lambdaBody.size() - (ifaceOverride ? 2 : 1)]->AsMethodDefinition()->Function(); + ArenaVector callParams = + ResolveCallParametersForLambdaFuncBody(this, lambdaObject, lambda, invokeFunc, isStatic, ifaceOverride); // Create the synthetic call expression to the proxy method auto *resolvedCall = Allocator()->New(callee, std::move(callParams), nullptr, false); @@ -1731,6 +1770,11 @@ ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition if (proxySignature->ReturnType()->IsETSVoidType()) { return Allocator()->New(resolvedCall); } + + if (ifaceOverride && resolvedCall->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + resolvedCall->AddBoxingUnboxingFlags(GetBoxingFlag(resolvedCall->TsType())); + } + return Allocator()->New(resolvedCall); } @@ -1738,7 +1782,7 @@ void ETSChecker::ResolveLambdaObjectCtor(ir::ClassDefinition *lambdaObject) { const auto &lambdaBody = lambdaObject->Body(); auto *lambdaObjectType = lambdaObject->TsType()->AsETSObjectType(); - auto *ctorFunc = lambdaBody[lambdaBody.size() - 2]->AsMethodDefinition()->Function(); + auto *ctorFunc = lambdaBody[lambdaBody.size() - 3]->AsMethodDefinition()->Function(); // Set the implicit 'this' parameters type to the lambda object auto *thisVar = ctorFunc->Scope()->ParamScope()->Params().front(); @@ -2210,10 +2254,13 @@ void ETSChecker::CreateLambdaObjectForFunctionReference(ir::AstNode *refNode, Si return; } + /* signature has been converted through BpxPrimitives, we need to call the original one */ + auto *trueSignature = signature->Function()->Signature(); + // Create the class scope for the synthetic lambda class node auto classCtx = varbinder::LexicalScope(VarBinder()); auto *classScope = classCtx.GetScope(); - bool isStaticReference = signature->HasSignatureFlag(SignatureFlags::STATIC); + bool isStaticReference = trueSignature->HasSignatureFlag(SignatureFlags::STATIC); // Create the synthetic field where we will store the instance object which we are trying to obtain the function // reference through, if the referenced function is static, we won't need to store the instance object @@ -2229,15 +2276,17 @@ void ETSChecker::CreateLambdaObjectForFunctionReference(ir::AstNode *refNode, Si // Create the template for the synthetic invoke function which will propagate the function call to the saved // instance's referenced function, or the class static function, if this is a static reference - auto *invokeFunc = CreateLambdaInvokeProto(); + auto *invoke0Func = CreateLambdaInvokeProto(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME); + auto *invokeFunc = CreateLambdaInvokeProto("invoke"); + properties.push_back(invoke0Func); properties.push_back(invokeFunc); // Create the declarations for the synthetic constructor and invoke method CreateLambdaFuncDecl(ctor, classScope->StaticMethodScope()); + CreateLambdaFuncDecl(invoke0Func, classScope->InstanceMethodScope()); CreateLambdaFuncDecl(invokeFunc, classScope->InstanceMethodScope()); // Create the synthetic lambda class node - ArenaVector implements(Allocator()->Adapter()); auto *identNode = Allocator()->New(util::StringView("LambdaObject"), Allocator()); auto *lambdaObject = Allocator()->New(Allocator(), identNode, std::move(properties), @@ -2245,14 +2294,15 @@ void ETSChecker::CreateLambdaObjectForFunctionReference(ir::AstNode *refNode, Si lambdaObject->SetScope(classScope); // Set the parent nodes ctor->SetParent(lambdaObject); + invoke0Func->SetParent(lambdaObject); invokeFunc->SetParent(lambdaObject); classScope->BindNode(lambdaObject); // Build the lambda object in the binder - VarBinder()->AsETSBinder()->BuildLambdaObject(refNode, lambdaObject, signature); + VarBinder()->AsETSBinder()->BuildLambdaObject(refNode, lambdaObject, trueSignature); // Resolve the lambda object - ResolveLambdaObject(lambdaObject, signature, functionalInterface, refNode); + ResolveLambdaObject(lambdaObject, trueSignature, functionalInterface, refNode); } ir::AstNode *ETSChecker::CreateLambdaImplicitField(varbinder::ClassScope *scope, const lexer::SourcePosition &pos) @@ -2340,11 +2390,11 @@ std::tuple ETSChecker::C return {paramCtx.GetScope(), nullptr}; } -ir::MethodDefinition *ETSChecker::CreateLambdaInvokeProto() +ir::MethodDefinition *ETSChecker::CreateLambdaInvokeProto(util::StringView invokeName) { // Create the template for the synthetic 'invoke' method, which will be used when the function type will be // called - auto *name = Allocator()->New("invoke", Allocator()); + auto *name = Allocator()->New(invokeName, Allocator()); auto *paramScope = VarBinder()->Allocator()->New(Allocator(), VarBinder()->GetScope()); auto *scope = VarBinder()->Allocator()->New(Allocator(), paramScope); @@ -2426,13 +2476,14 @@ void ETSChecker::ResolveLambdaObject(ir::ClassDefinition *lambdaObject, Signatur ResolveLambdaObjectCtor(lambdaObject, isStaticReference); // Resolve the invoke function - ResolveLambdaObjectInvoke(lambdaObject, signature); + ResolveLambdaObjectInvoke(lambdaObject, signature, true); + ResolveLambdaObjectInvoke(lambdaObject, signature, false); } void ETSChecker::ResolveLambdaObjectCtor(ir::ClassDefinition *lambdaObject, bool isStaticReference) { const auto &lambdaBody = lambdaObject->Body(); - auto *ctorFunc = lambdaBody[lambdaBody.size() - 2]->AsMethodDefinition()->Function(); + auto *ctorFunc = lambdaBody[lambdaBody.size() - 3]->AsMethodDefinition()->Function(); ETSObjectType *lambdaObjectType = lambdaObject->TsType()->AsETSObjectType(); varbinder::Variable *fieldVar {}; @@ -2490,41 +2541,70 @@ void ETSChecker::ResolveLambdaObjectCtor(ir::ClassDefinition *lambdaObject, bool fieldinit->Right()->SetTsType(ctorSignature->Params()[0]->TsType()); } -void ETSChecker::ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, Signature *signatureRef) +static Signature *CreateInvokeSignature(ETSChecker *checker, Signature *signatureRef, ir::ScriptFunction *invokeFunc, + ETSObjectType *lambdaObjectType, bool ifaceOverride) { - const auto &lambdaBody = lambdaObject->Body(); - auto *invokeFunc = lambdaBody[lambdaBody.size() - 1]->AsMethodDefinition()->Function(); - ETSObjectType *lambdaObjectType = lambdaObject->TsType()->AsETSObjectType(); - - // Set the implicit 'this' parameters type to the lambda object - auto *thisVar = invokeFunc->Scope()->ParamScope()->Params().front(); - thisVar->SetTsType(lambdaObjectType); + auto *allocator = checker->Allocator(); // Create the signature for the invoke function type - auto *invokeSignatureInfo = CreateSignatureInfo(); + auto *invokeSignatureInfo = checker->CreateSignatureInfo(); invokeSignatureInfo->restVar = nullptr; // Create the parameters for the invoke function, based on the referenced function's signature - for (auto *it : signatureRef->Params()) { + auto maxParamsNum = checker->GlobalBuiltinFunctionTypeVariadicThreshold(); + auto paramsNum = signatureRef->Params().size(); + if (paramsNum < maxParamsNum || !ifaceOverride) { + for (auto *it : signatureRef->Params()) { + auto paramCtx = varbinder::LexicalScope::Enter( + checker->VarBinder(), invokeFunc->Scope()->ParamScope(), false); + + auto *paramIdent = allocator->New(it->Name(), allocator); + auto *param = allocator->New(paramIdent, nullptr); + auto [_, var] = checker->VarBinder()->AddParamDecl(param); + (void)_; + var->SetTsType(ifaceOverride ? checker->GlobalETSObjectType() : it->TsType()); + paramIdent->SetVariable(var); + invokeFunc->Params().push_back(param); + invokeSignatureInfo->minArgCount++; + invokeSignatureInfo->params.push_back(var->AsLocalVariable()); + } + } else { auto paramCtx = varbinder::LexicalScope::Enter( - VarBinder(), invokeFunc->Scope()->ParamScope(), false); + checker->VarBinder(), invokeFunc->Scope()->ParamScope(), false); - auto *paramIdent = Allocator()->New(it->Name(), Allocator()); - auto *param = Allocator()->New(paramIdent, nullptr); - auto [_, var] = VarBinder()->AddParamDecl(param); + auto *id = checker->AllocNode("p", allocator); + auto *restElement = checker->AllocNode(ir::AstNodeType::REST_ELEMENT, allocator, id); + auto *const param = checker->AllocNode(restElement, nullptr); + auto [_, var] = checker->VarBinder()->AddParamDecl(param); (void)_; - var->SetTsType(it->TsType()); - paramIdent->SetVariable(var); + var->SetTsType(checker->CreateETSArrayType(checker->GlobalETSObjectType())); + param->Ident()->SetVariable(var); invokeFunc->Params().push_back(param); - invokeSignatureInfo->minArgCount++; - invokeSignatureInfo->params.push_back(var->AsLocalVariable()); + invokeSignatureInfo->restVar = var->AsLocalVariable(); } // Create the function type for the constructor - auto *invokeSignature = CreateSignature(invokeSignatureInfo, signatureRef->ReturnType(), invokeFunc); + auto *invokeSignature = checker->CreateSignature( + invokeSignatureInfo, ifaceOverride ? checker->GlobalETSObjectType() : signatureRef->ReturnType(), invokeFunc); invokeSignature->SetOwner(lambdaObjectType); invokeSignature->AddSignatureFlag(checker::SignatureFlags::CALL); + return invokeSignature; +} + +void ETSChecker::ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, Signature *signatureRef, + bool ifaceOverride) +{ + const auto &lambdaBody = lambdaObject->Body(); + auto *invokeFunc = lambdaBody[lambdaBody.size() - (ifaceOverride ? 2 : 1)]->AsMethodDefinition()->Function(); + ETSObjectType *lambdaObjectType = lambdaObject->TsType()->AsETSObjectType(); + + // Set the implicit 'this' parameters type to the lambda object + auto *thisVar = invokeFunc->Scope()->ParamScope()->Params().front(); + thisVar->SetTsType(lambdaObjectType); + + auto *invokeSignature = CreateInvokeSignature(this, signatureRef, invokeFunc, lambdaObjectType, ifaceOverride); + auto *invokeType = CreateETSFunctionType(invokeSignature); invokeFunc->SetSignature(invokeSignature); invokeFunc->Id()->Variable()->SetTsType(invokeType); @@ -2534,7 +2614,8 @@ void ETSChecker::ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, Si // Fill out the type information for the body of the invoke function - auto *resolvedLambdaInvokeFunctionBody = ResolveLambdaObjectInvokeFuncBody(lambdaObject, signatureRef); + auto *resolvedLambdaInvokeFunctionBody = + ResolveLambdaObjectInvokeFuncBody(lambdaObject, signatureRef, ifaceOverride); invokeFunc->Body()->AsBlockStatement()->Statements().push_back(resolvedLambdaInvokeFunctionBody); if (resolvedLambdaInvokeFunctionBody->IsExpressionStatement()) { @@ -2542,7 +2623,80 @@ void ETSChecker::ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, Si } } -ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition *lambdaObject, Signature *signatureRef) +static ir::Expression *BuildParamExpression(ETSChecker *checker, ir::Identifier *paramIdent, Type *type) +{ + if (type->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + auto *boxedType = checker->PrimitiveTypeAsETSBuiltinType(type); + auto *boxedTypeNode = checker->AllocNode(boxedType); + boxedTypeNode->SetTsType(boxedType); + auto *paramAsExpr = checker->AllocNode(paramIdent, boxedTypeNode, false); + paramAsExpr->SetTsType(boxedType); + paramAsExpr->AddBoxingUnboxingFlags(checker->GetUnboxingFlag(type)); + return paramAsExpr; + } + checker::CastingContext ctx(checker->Relation(), paramIdent, paramIdent->TsType(), type, paramIdent->Start(), {}); + auto *const paramCast = checker->Allocator()->New(paramIdent, nullptr, false); + paramCast->SetUncheckedCast(ctx.UncheckedCast()); + paramCast->SetTsType(type); + return paramCast; +} + +static ArenaVector ResolveCallParametersForLambdaFuncBody(ETSChecker *checker, + Signature *signatureRef, + ir::ScriptFunction *invokeFunc, + bool ifaceOverride) +{ + auto *allocator = checker->Allocator(); + ArenaVector callParams(allocator->Adapter()); + + auto maxParamsNum = checker->GlobalBuiltinFunctionTypeVariadicThreshold(); + auto paramsNum = signatureRef->Params().size(); + if (!ifaceOverride) { + for (size_t idx = 0; idx != paramsNum; idx++) { + auto *paramIdent = allocator->New(signatureRef->Params()[idx]->Name(), allocator); + paramIdent->SetVariable(invokeFunc->Params()[idx]->AsETSParameterExpression()->Variable()); + paramIdent->SetTsType(invokeFunc->Params()[idx]->AsETSParameterExpression()->Variable()->TsType()); + callParams.push_back(paramIdent); + } + } else if (paramsNum < maxParamsNum) { + // Then we add the lambda functions parameters to the call + auto nargs = invokeFunc->Params().size(); + for (size_t i = 0; i < nargs; i++) { + auto const *const param = invokeFunc->Params()[i]->AsETSParameterExpression(); + auto *const paramIdent = allocator->New(param->Ident()->Name(), allocator); + paramIdent->SetVariable(param->Variable()); + paramIdent->SetTsType(param->Variable()->TsType()); + callParams.push_back(BuildParamExpression(checker, paramIdent, signatureRef->Params()[i]->TsType())); + } + } else { + ASSERT(invokeFunc->Params().size() == 1); + auto const *const param = invokeFunc->Params()[0]->AsETSParameterExpression(); + auto *const paramIdent = allocator->New(param->Ident()->Name(), allocator); + paramIdent->SetVariable(param->Variable()); + paramIdent->SetTsType(param->Variable()->TsType()); + + for (size_t i = 0; i < paramsNum; i++) { + auto *idx = allocator->New(lexer::Number(static_cast(i))); + auto *arg = allocator->New(paramIdent, idx, ir::MemberExpressionKind::ELEMENT_ACCESS, + true, false); + + auto *type = signatureRef->Params()[i]->TsType(); + if (type->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + arg->AddBoxingUnboxingFlags(checker->GetUnboxingFlag(type)); + callParams.push_back(arg); + } else { + auto *const paramCast = allocator->New(arg, nullptr, false); + paramCast->SetTsType(type); + callParams.push_back(paramCast); + } + } + } + + return callParams; +} + +ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition *lambdaObject, Signature *signatureRef, + bool ifaceOverride) { const auto &lambdaBody = lambdaObject->Body(); bool isStaticReference = signatureRef->HasSignatureFlag(SignatureFlags::STATIC); @@ -2574,14 +2728,9 @@ ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition callee->SetTsType(signatureRef->OwnerVar()->TsType()); // Create the parameters for the referenced function call - auto *invokeFunc = lambdaBody[lambdaBody.size() - 1]->AsMethodDefinition()->Function(); - ArenaVector callParams(Allocator()->Adapter()); - for (size_t idx = 0; idx != signatureRef->Params().size(); idx++) { - auto *paramIdent = Allocator()->New(signatureRef->Params()[idx]->Name(), Allocator()); - paramIdent->SetVariable(invokeFunc->Params()[idx]->AsETSParameterExpression()->Variable()); - paramIdent->SetTsType(invokeFunc->Params()[idx]->AsETSParameterExpression()->Variable()->TsType()); - callParams.push_back(paramIdent); - } + auto *invokeFunc = lambdaBody[lambdaBody.size() - (ifaceOverride ? 2 : 1)]->AsMethodDefinition()->Function(); + ArenaVector callParams = + ResolveCallParametersForLambdaFuncBody(this, signatureRef, invokeFunc, ifaceOverride); // Create the synthetic call expression to the referenced function auto *resolvedCall = Allocator()->New(callee, std::move(callParams), nullptr, false); @@ -2592,6 +2741,10 @@ ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition return Allocator()->New(resolvedCall); } + if (ifaceOverride && resolvedCall->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + resolvedCall->AddBoxingUnboxingFlags(GetBoxingFlag(resolvedCall->TsType())); + } + return Allocator()->New(resolvedCall); } @@ -2893,4 +3046,22 @@ void ETSChecker::EnsureValidCurlyBrace(ir::CallExpression *callExpr) ThrowTypeError({"No matching call signature with trailing lambda"}, callExpr->Start()); } + +ETSObjectType *ETSChecker::GetCachedFunctionlInterface(ir::ETSFunctionType *type) +{ + auto hash = GetHashFromFunctionType(type); + auto it = functionalInterfaceCache_.find(hash); + if (it == functionalInterfaceCache_.cend()) { + return nullptr; + } + return it->second; +} + +void ETSChecker::CacheFunctionalInterface(ir::ETSFunctionType *type, ETSObjectType *ifaceType) +{ + auto hash = GetHashFromFunctionType(type); + ASSERT(functionalInterfaceCache_.find(hash) == functionalInterfaceCache_.cend()); + functionalInterfaceCache_.emplace(hash, ifaceType); +} + } // namespace panda::es2panda::checker diff --git a/ets2panda/checker/ets/function_helpers.h b/ets2panda/checker/ets/function_helpers.h index 2fa3713186..ed07549bbc 100644 --- a/ets2panda/checker/ets/function_helpers.h +++ b/ets2panda/checker/ets/function_helpers.h @@ -96,7 +96,9 @@ static const Substitution *BuildImplicitSubstitutionForArguments(ETSChecker *che } auto *argType = arg->Check(checker); argType = MaybeBoxedType(checker, argType, arg); - auto *paramType = (ix < signature->MinArgCount()) ? sigInfo->params[ix]->TsType() : sigInfo->restVar->TsType(); + auto *paramType = (ix < signature->MinArgCount()) ? sigInfo->params[ix]->TsType() + : sigInfo->restVar != nullptr ? sigInfo->restVar->TsType() + : nullptr; if (paramType == nullptr) { continue; } @@ -161,7 +163,10 @@ static Signature *MaybeSubstituteTypeParameters(ETSChecker *checker, Signature * const Substitution *substitution = (typeArguments != nullptr) ? BuildExplicitSubstitutionForArguments(checker, signature, typeArguments->Params(), pos, flags) - : BuildImplicitSubstitutionForArguments(checker, signature, arguments); + : (signature->GetSignatureInfo()->params.empty() + ? nullptr + : BuildImplicitSubstitutionForArguments(checker, signature, arguments)); + return (substitution == nullptr) ? nullptr : signature->Substitute(checker->Relation(), substitution); } @@ -260,4 +265,4 @@ static varbinder::Scope *NodeScope(ir::AstNode *ast) } // namespace panda::es2panda::checker -#endif \ No newline at end of file +#endif diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 41e52fafab..46f52f19bd 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -89,7 +89,7 @@ void ETSChecker::CheckTruthinessOfType(ir::Expression *expr) ThrowTypeError("Condition must be of possible condition type", expr->Start()); } - if (unboxedType != nullptr && unboxedType->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) { + if (unboxedType->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) { FlagExpressionWithUnboxing(type, unboxedType, expr); } expr->SetTsType(unboxedType); @@ -886,7 +886,7 @@ std::tuple ETSChecker::IsResolvedAndValue(const ir::Expression *expr IsNullLikeOrVoidExpression(expr) ? std::make_tuple(true, false) : type->ResolveConditionExpr(); const Type *tsType = expr->TsType(); - if (!tsType->ContainsUndefined() && !tsType->ContainsNull() && !tsType->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) { + if (!tsType->ContainsUndefined() && !tsType->ContainsNull() && !type->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) { isResolve = true; isValue = true; } @@ -1780,6 +1780,10 @@ Type *ETSChecker::ETSBuiltinTypeAsConditionalType(Type *objectType) return nullptr; } + if (auto *unboxed = ETSBuiltinTypeAsPrimitiveType(objectType); unboxed != nullptr) { + return unboxed; + } + return objectType; } @@ -2294,38 +2298,6 @@ ETSObjectType *ETSChecker::GetRelevantArgumentedTypeFromChild(ETSObjectType *con return GetRelevantArgumentedTypeFromChild(child->SuperType(), target); } -static void TypeToString(std::stringstream &ss, Type *tp) -{ - if (tp->IsETSTypeParameter()) { - ss << tp->AsETSTypeParameter()->GetDeclNode()->Start().index; - ss << "."; - } - if (!tp->IsETSObjectType()) { - tp->ToString(ss); - return; - } - auto *const objType = tp->AsETSObjectType(); - ss << objType->Name(); - - if (!objType->TypeArguments().empty()) { - auto typeArgs = objType->TypeArguments(); - ss << "<"; - for (auto *ta : typeArgs) { - TypeToString(ss, ta); - ss << ";"; - } - ss << ">"; - } - - if (tp->ContainsNull()) { - ss << "|null"; - } - - if (tp->ContainsUndefined()) { - ss << "|undefined"; - } -} - void ETSChecker::EmplaceSubstituted(Substitution *substitution, ETSTypeParameter *tparam, Type *typeArg) { substitution->emplace(tparam, typeArg); @@ -2336,7 +2308,7 @@ util::StringView ETSChecker::GetHashFromTypeArguments(const ArenaVector std::stringstream ss; for (auto *it : typeArgTypes) { - TypeToString(ss, it); + it->ToString(ss, true); ss << compiler::Signatures::MANGLE_SEPARATOR; } @@ -2348,9 +2320,9 @@ util::StringView ETSChecker::GetHashFromSubstitution(const Substitution *substit std::vector fields; for (auto [k, v] : *substitution) { std::stringstream ss; - TypeToString(ss, k); + k->ToString(ss, true); ss << ":"; - TypeToString(ss, v); + v->ToString(ss, true); fields.push_back(ss.str()); } std::sort(fields.begin(), fields.end()); @@ -2363,6 +2335,29 @@ util::StringView ETSChecker::GetHashFromSubstitution(const Substitution *substit return util::UString(ss.str(), Allocator()).View(); } +util::StringView ETSChecker::GetHashFromFunctionType(ir::ETSFunctionType *type) +{ + std::stringstream ss; + for (auto *p : type->Params()) { + auto *const param = p->AsETSParameterExpression(); + GetTypeFromTypeAnnotation(param->TypeAnnotation())->ToString(ss, true); + ss << ";"; + } + + type->ReturnType()->GetType(this)->ToString(ss, true); + ss << ";"; + + if (type->IsThrowing()) { + ss << "throws;"; + } + + if (type->IsRethrowing()) { + ss << "rethrows;"; + } + + return util::UString(ss.str(), Allocator()).View(); +} + ETSObjectType *ETSChecker::GetOriginalBaseType(Type *const object) { if (object == nullptr || !object->IsETSObjectType()) { @@ -2419,6 +2414,10 @@ void ETSChecker::CheckNumberOfTypeArguments(ETSObjectType *const type, ir::TSTyp return; } + if (typeArgs == nullptr) { + return; + } + size_t minimumTypeArgs = std::count_if(typeParams.begin(), typeParams.end(), [](Type *param) { return param->AsETSTypeParameter()->GetDefaultType() == nullptr; }); @@ -2638,35 +2637,35 @@ std::string GenerateImplicitInstantiateArg(varbinder::LocalVariable *instantiate return implicitInstantiateArgument; } -void ETSChecker::GenerateGetterSetterBody(ETSChecker *checker, ArenaVector &stmts, - ArenaVector ¶ms, ir::ClassProperty *const field, - varbinder::FunctionParamScope *paramScope, bool isSetter) +void ETSChecker::GenerateGetterSetterBody(ArenaVector &stmts, ArenaVector ¶ms, + ir::ClassProperty *const field, varbinder::FunctionParamScope *paramScope, + bool isSetter) { if (!isSetter) { - stmts.push_back(checker->Allocator()->New(field->Key())); + stmts.push_back(Allocator()->New(field->Key())); return; } - auto *paramIdent = field->Key()->AsIdentifier()->Clone(checker->Allocator()); - paramIdent->SetTsTypeAnnotation(field->TypeAnnotation()->Clone(checker->Allocator())); + auto *paramIdent = field->Key()->AsIdentifier()->Clone(Allocator()); + paramIdent->SetTsTypeAnnotation(field->TypeAnnotation()->Clone(Allocator())); paramIdent->TypeAnnotation()->SetParent(paramIdent); - auto *paramExpression = checker->AllocNode(paramIdent, nullptr); + auto *paramExpression = AllocNode(paramIdent, nullptr); paramExpression->SetRange(paramIdent->Range()); - auto *const paramVar = std::get<2>(paramScope->AddParamDecl(checker->Allocator(), paramExpression)); + auto *const paramVar = std::get<2>(paramScope->AddParamDecl(Allocator(), paramExpression)); paramIdent->SetVariable(paramVar); paramExpression->SetVariable(paramVar); params.push_back(paramExpression); - auto *assignmentExpression = checker->AllocNode( - field->Key(), paramExpression, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + auto *assignmentExpression = + AllocNode(field->Key(), paramExpression, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); assignmentExpression->SetRange({field->Start(), field->End()}); - stmts.push_back(checker->AllocNode(assignmentExpression)); - stmts.push_back(checker->Allocator()->New(nullptr)); + stmts.push_back(AllocNode(assignmentExpression)); + stmts.push_back(Allocator()->New(nullptr)); } ir::MethodDefinition *ETSChecker::GenerateDefaultGetterSetter(ir::ClassProperty *const field, @@ -2683,7 +2682,7 @@ ir::MethodDefinition *ETSChecker::GenerateDefaultGetterSetter(ir::ClassProperty ArenaVector params(checker->Allocator()->Adapter()); ArenaVector stmts(checker->Allocator()->Adapter()); - checker->GenerateGetterSetterBody(checker, stmts, params, field, paramScope, isSetter); + checker->GenerateGetterSetterBody(stmts, params, field, paramScope, isSetter); auto *body = checker->AllocNode(checker->Allocator(), std::move(stmts)); auto funcFlags = isSetter ? ir::ScriptFunctionFlags::SETTER : ir::ScriptFunctionFlags::GETTER; @@ -2730,7 +2729,7 @@ ir::MethodDefinition *ETSChecker::GenerateDefaultGetterSetter(ir::ClassProperty const Type *ETSChecker::TryGettingFunctionTypeFromInvokeFunction(const Type *type) const { if (type->IsETSObjectType() && type->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::FUNCTIONAL)) { - auto const propInvoke = type->AsETSObjectType()->GetProperty(util::StringView("invoke"), + auto const propInvoke = type->AsETSObjectType()->GetProperty(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME, PropertySearchFlags::SEARCH_INSTANCE_METHOD); ASSERT(propInvoke != nullptr); diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index 8c06deccbc..24e9928347 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -285,9 +285,10 @@ void ETSChecker::CreateTypeForClassOrInterfaceTypeParameters(ETSObjectType *type : type->GetDeclNode()->AsTSInterfaceDeclaration()->TypeParams(); type->SetTypeArguments(CreateTypeForTypeParameters(typeParams)); type->AddObjectFlag(ETSObjectFlags::RESOLVED_TYPE_PARAMS); + type->AddObjectFlag(ETSObjectFlags::INCOMPLETE_INSTANTIATION); } -ETSObjectType *ETSChecker::BuildInterfaceProperties(ir::TSInterfaceDeclaration *interfaceDecl) +ETSObjectType *ETSChecker::BuildBasicInterfaceProperties(ir::TSInterfaceDeclaration *interfaceDecl) { auto *var = interfaceDecl->Id()->Variable(); ASSERT(var); @@ -309,6 +310,14 @@ ETSObjectType *ETSChecker::BuildInterfaceProperties(ir::TSInterfaceDeclaration * GetInterfacesOfInterface(interfaceType); + interfaceType->SetSuperType(GlobalETSObjectType()); + + return interfaceType; +} + +ETSObjectType *ETSChecker::BuildInterfaceProperties(ir::TSInterfaceDeclaration *interfaceDecl) +{ + auto *interfaceType = BuildBasicInterfaceProperties(interfaceDecl); checker::ScopeContext scopeCtx(this, interfaceDecl->Scope()); auto savedContext = checker::SavedCheckerContext(this, checker::CheckerStatus::IN_INTERFACE, interfaceType); @@ -317,7 +326,7 @@ ETSObjectType *ETSChecker::BuildInterfaceProperties(ir::TSInterfaceDeclaration * return interfaceType; } -ETSObjectType *ETSChecker::BuildClassProperties(ir::ClassDefinition *classDef) +ETSObjectType *ETSChecker::BuildBasicClassProperties(ir::ClassDefinition *classDef) { if (classDef->IsFinal() && classDef->IsAbstract()) { ThrowTypeError("Cannot use both 'final' and 'abstract' modifiers.", classDef->Start()); @@ -327,7 +336,6 @@ ETSObjectType *ETSChecker::BuildClassProperties(ir::ClassDefinition *classDef) ASSERT(var); const util::StringView &className = classDef->Ident()->Name(); - auto *classScope = classDef->Scope(); checker::ETSObjectType *classType {}; if (var->TsType() == nullptr) { @@ -368,10 +376,17 @@ ETSObjectType *ETSChecker::BuildClassProperties(ir::ClassDefinition *classDef) return classType; } - checker::ScopeContext scopeCtx(this, classScope); + return classType; +} - ResolveDeclaredMembersOfObject(classType); +ETSObjectType *ETSChecker::BuildClassProperties(ir::ClassDefinition *classDef) +{ + auto *classType = BuildBasicClassProperties(classDef); + auto savedContext = checker::SavedCheckerContext(this, checker::CheckerStatus::IN_CLASS, classType); + checker::ScopeContext scopeCtx(this, classDef->Scope()); + + ResolveDeclaredMembersOfObject(classType); return classType; } @@ -1586,7 +1601,8 @@ void ETSChecker::AddElementsToModuleObject(ETSObjectType *moduleObj, const util: Type *ETSChecker::FindLeastUpperBound(Type *source, Type *target) { - ASSERT(source->HasTypeFlag(TypeFlag::ETS_ARRAY_OR_OBJECT) && target->HasTypeFlag(TypeFlag::ETS_ARRAY_OR_OBJECT)); + ASSERT(source->HasTypeFlag(TypeFlag::ETS_ARRAY_OR_OBJECT | TypeFlag::ETS_TYPE_PARAMETER)); + ASSERT(target->HasTypeFlag(TypeFlag::ETS_ARRAY_OR_OBJECT | TypeFlag::ETS_TYPE_PARAMETER)); // GetCommonClass(GenA, GenB) => LUB(GenA, GenB) auto commonClass = GetCommonClass(source, target); @@ -1695,7 +1711,12 @@ ETSObjectType *ETSChecker::GetTypeargumentedLUB(ETSObjectType *const source, ETS return source; } - ETSObjectType *templateType = source->GetDeclNode()->AsClassDefinition()->TsType()->AsETSObjectType(); + ETSObjectType *templateType; + if (source->GetDeclNode()->IsClassDefinition()) { + templateType = source->GetDeclNode()->AsClassDefinition()->TsType()->AsETSObjectType(); + } else { + templateType = source->GetDeclNode()->AsTSInterfaceDeclaration()->TsType()->AsETSObjectType(); + } auto *lubType = templateType->GetInstantiatedType(hash); diff --git a/ets2panda/checker/types/ets/byteType.h b/ets2panda/checker/types/ets/byteType.h index cd81d91cd3..3bc9deb36d 100644 --- a/ets2panda/checker/types/ets/byteType.h +++ b/ets2panda/checker/types/ets/byteType.h @@ -37,12 +37,12 @@ public: void Cast(TypeRelation *relation, Type *target) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << "byte"; } - void ToAssemblerType([[maybe_unused]] std::stringstream &ss) const override + void ToAssemblerType(std::stringstream &ss) const override { ss << compiler::Signatures::PRIMITIVE_BYTE; } diff --git a/ets2panda/checker/types/ets/charType.h b/ets2panda/checker/types/ets/charType.h index f917156bcf..54641c35d1 100644 --- a/ets2panda/checker/types/ets/charType.h +++ b/ets2panda/checker/types/ets/charType.h @@ -37,7 +37,7 @@ public: void Cast(TypeRelation *relation, Type *target) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << "char"; } diff --git a/ets2panda/checker/types/ets/doubleType.h b/ets2panda/checker/types/ets/doubleType.h index ddf7cc3e41..57579724f2 100644 --- a/ets2panda/checker/types/ets/doubleType.h +++ b/ets2panda/checker/types/ets/doubleType.h @@ -37,7 +37,7 @@ public: void Cast(TypeRelation *relation, Type *target) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << "double"; } diff --git a/ets2panda/checker/types/ets/etsArrayType.cpp b/ets2panda/checker/types/ets/etsArrayType.cpp index 9b0e9403aa..ec422c7e12 100644 --- a/ets2panda/checker/types/ets/etsArrayType.cpp +++ b/ets2panda/checker/types/ets/etsArrayType.cpp @@ -21,9 +21,16 @@ #include "checker/types/typeRelation.h" namespace panda::es2panda::checker { -void ETSArrayType::ToString(std::stringstream &ss) const +void ETSArrayType::ToString(std::stringstream &ss, bool precise) const { - element_->ToString(ss); + bool needParens = (element_->IsETSUnionType() || element_->IsETSFunctionType() || element_->IsNullish()); + if (needParens) { + ss << "("; + } + element_->ToString(ss, precise); + if (needParens) { + ss << ")"; + } ss << "[]"; if (IsNullish()) { diff --git a/ets2panda/checker/types/ets/etsArrayType.h b/ets2panda/checker/types/ets/etsArrayType.h index f4f90331b9..edd0ddde3c 100644 --- a/ets2panda/checker/types/ets/etsArrayType.h +++ b/ets2panda/checker/types/ets/etsArrayType.h @@ -38,7 +38,7 @@ public: return {false, false}; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void ToAssemblerType(std::stringstream &ss) const override; void ToAssemblerTypeWithRank(std::stringstream &ss) const override; void ToDebugInfoType(std::stringstream &ss) const override; diff --git a/ets2panda/checker/types/ets/etsAsyncFuncReturnType.cpp b/ets2panda/checker/types/ets/etsAsyncFuncReturnType.cpp index 71738ebf7c..38550b5097 100644 --- a/ets2panda/checker/types/ets/etsAsyncFuncReturnType.cpp +++ b/ets2panda/checker/types/ets/etsAsyncFuncReturnType.cpp @@ -18,11 +18,11 @@ #include "checker/types/ets/etsAsyncFuncReturnType.h" namespace panda::es2panda::checker { -void ETSAsyncFuncReturnType::ToString(std::stringstream &ss) const +void ETSAsyncFuncReturnType::ToString(std::stringstream &ss, bool precise) const { - promiseType_->ToString(ss); + promiseType_->ToString(ss, precise); ss << " | "; - GetPromiseTypeArg()->ToString(ss); + GetPromiseTypeArg()->ToString(ss, precise); } void ETSAsyncFuncReturnType::Identical(TypeRelation *relation, Type *other) diff --git a/ets2panda/checker/types/ets/etsAsyncFuncReturnType.h b/ets2panda/checker/types/ets/etsAsyncFuncReturnType.h index 339a3b1d1f..07c9ecf6bd 100644 --- a/ets2panda/checker/types/ets/etsAsyncFuncReturnType.h +++ b/ets2panda/checker/types/ets/etsAsyncFuncReturnType.h @@ -30,7 +30,7 @@ public: SetAssemblerName(compiler::Signatures::BUILTIN_OBJECT); } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; bool AssignmentSource(TypeRelation *relation, Type *target) override; diff --git a/ets2panda/checker/types/ets/etsBigIntType.h b/ets2panda/checker/types/ets/etsBigIntType.h index befbfb3de9..a8b4fa3ecc 100644 --- a/ets2panda/checker/types/ets/etsBigIntType.h +++ b/ets2panda/checker/types/ets/etsBigIntType.h @@ -43,7 +43,7 @@ public: void AssignmentTarget(TypeRelation *relation, Type *source) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << lexer::TokenToString(lexer::TokenType::KEYW_BIGINT); } diff --git a/ets2panda/checker/types/ets/etsBooleanType.h b/ets2panda/checker/types/ets/etsBooleanType.h index 5127daf1fa..4a9f175ea8 100644 --- a/ets2panda/checker/types/ets/etsBooleanType.h +++ b/ets2panda/checker/types/ets/etsBooleanType.h @@ -36,7 +36,7 @@ public: return value_; } - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << "boolean"; } diff --git a/ets2panda/checker/types/ets/etsEnumType.cpp b/ets2panda/checker/types/ets/etsEnumType.cpp index 2a779b6a18..45d4cdce0f 100644 --- a/ets2panda/checker/types/ets/etsEnumType.cpp +++ b/ets2panda/checker/types/ets/etsEnumType.cpp @@ -87,7 +87,7 @@ void ETSEnumInterface::ToDebugInfoType(std::stringstream &ss) const ToDebugInfoTypeImpl(ss); } -void ETSEnumInterface::ToString(std::stringstream &ss) const +void ETSEnumInterface::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << decl_->Key()->Name(); } diff --git a/ets2panda/checker/types/ets/etsEnumType.h b/ets2panda/checker/types/ets/etsEnumType.h index 2bd8c99d3e..0ccfa56d29 100644 --- a/ets2panda/checker/types/ets/etsEnumType.h +++ b/ets2panda/checker/types/ets/etsEnumType.h @@ -60,7 +60,7 @@ public: void ToAssemblerType(std::stringstream &ss) const override; void ToDebugInfoType(std::stringstream &ss) const override; - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; [[nodiscard]] const ir::TSEnumDeclaration *GetDecl() const noexcept; diff --git a/ets2panda/checker/types/ets/etsExtensionFuncHelperType.cpp b/ets2panda/checker/types/ets/etsExtensionFuncHelperType.cpp index b737bd39b4..687496405e 100644 --- a/ets2panda/checker/types/ets/etsExtensionFuncHelperType.cpp +++ b/ets2panda/checker/types/ets/etsExtensionFuncHelperType.cpp @@ -27,11 +27,11 @@ namespace panda::es2panda::checker { in order to figure out a representation for case 3, we need the etsExtensionFuncHelperType */ -void ETSExtensionFuncHelperType::ToString(std::stringstream &ss) const +void ETSExtensionFuncHelperType::ToString(std::stringstream &ss, bool precise) const { - classMethodType_->ToString(ss); + classMethodType_->ToString(ss, precise); ss << " | "; - extensionFunctionType_->ToString(ss); + extensionFunctionType_->ToString(ss, precise); } void ETSExtensionFuncHelperType::AssignmentTarget(TypeRelation *relation, Type *source) diff --git a/ets2panda/checker/types/ets/etsExtensionFuncHelperType.h b/ets2panda/checker/types/ets/etsExtensionFuncHelperType.h index a646bec143..8e4b85c913 100644 --- a/ets2panda/checker/types/ets/etsExtensionFuncHelperType.h +++ b/ets2panda/checker/types/ets/etsExtensionFuncHelperType.h @@ -38,7 +38,7 @@ public: return extensionFunctionType_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void AssignmentTarget(TypeRelation *relation, Type *source) override; private: diff --git a/ets2panda/checker/types/ets/etsFunctionType.cpp b/ets2panda/checker/types/ets/etsFunctionType.cpp index a95e78d4d6..38b16d18e4 100644 --- a/ets2panda/checker/types/ets/etsFunctionType.cpp +++ b/ets2panda/checker/types/ets/etsFunctionType.cpp @@ -33,9 +33,9 @@ Signature *ETSFunctionType::FirstAbstractSignature() return nullptr; } -void ETSFunctionType::ToString(std::stringstream &ss) const +void ETSFunctionType::ToString(std::stringstream &ss, bool precise) const { - callSignatures_[0]->ToString(ss, nullptr); + callSignatures_[0]->ToString(ss, nullptr, false, precise); } void ETSFunctionType::Identical(TypeRelation *relation, Type *other) @@ -106,7 +106,7 @@ static Signature *ProcessSignatures(TypeRelation *relation, Signature *target, E size_t idx = 0; for (; idx != target->MinArgCount(); idx++) { - if (!relation->IsIdenticalTo(target->Params()[idx]->TsType(), it->Params()[idx]->TsType())) { + if (!relation->IsAssignableTo(target->Params()[idx]->TsType(), it->Params()[idx]->TsType())) { break; } } @@ -116,11 +116,11 @@ static Signature *ProcessSignatures(TypeRelation *relation, Signature *target, E } if (target->RestVar() != nullptr && - !relation->IsIdenticalTo(target->RestVar()->TsType(), it->RestVar()->TsType())) { + !relation->IsAssignableTo(target->RestVar()->TsType(), it->RestVar()->TsType())) { continue; } - if (!relation->IsAssignableTo(target->ReturnType(), it->ReturnType())) { + if (!relation->IsAssignableTo(it->ReturnType(), target->ReturnType())) { continue; } @@ -130,6 +130,27 @@ static Signature *ProcessSignatures(TypeRelation *relation, Signature *target, E return match; } +static ETSObjectType *SubstitutedFunctionalInterfaceForSignature(TypeRelation *relation, Signature *signature, + ETSObjectType *functionalInterface) +{ + auto &interfaceArgs = functionalInterface->TypeArguments(); + auto *checker = relation->GetChecker()->AsETSChecker(); + Substitution *substitution = checker->NewSubstitution(); + size_t i = 0; + for (auto *param : signature->Params()) { + auto *paramType = (param->TsType()->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) + ? checker->PrimitiveTypeAsETSBuiltinType(param->TsType()) + : param->TsType(); + substitution->emplace(interfaceArgs[i++]->AsETSTypeParameter(), paramType); + } + auto *retType = (signature->ReturnType()->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) + ? checker->PrimitiveTypeAsETSBuiltinType(signature->ReturnType()) + : signature->ReturnType(); + substitution->emplace(interfaceArgs[i]->AsETSTypeParameter(), retType); + + return functionalInterface->Substitute(relation, substitution); +} + void ETSFunctionType::AssignmentTarget(TypeRelation *relation, Type *source) { if (!source->IsETSFunctionType() && @@ -150,8 +171,9 @@ void ETSFunctionType::AssignmentTarget(TypeRelation *relation, Type *source) return; } - if (!target->Function()->IsThrowing()) { - if (match->Function()->IsThrowing() || match->Function()->IsRethrowing()) { + if (!(target->Function()->IsThrowing() || target->HasSignatureFlag(SignatureFlags::THROWS))) { + if (match->Function()->IsThrowing() || match->Function()->IsRethrowing() || + match->HasSignatureFlag(SignatureFlags::THROWS) || match->HasSignatureFlag(SignatureFlags::RETHROWS)) { relation->GetChecker()->ThrowTypeError( "Functions that can throw exceptions cannot be assigned to non throwing functions.", relation->GetNode()->Start()); @@ -160,12 +182,15 @@ void ETSFunctionType::AssignmentTarget(TypeRelation *relation, Type *source) ASSERT(relation->GetNode() != nullptr); if (!sourceIsFunctional) { + auto *substitutedFuncInterface = + SubstitutedFunctionalInterfaceForSignature(relation, match, callSignatures_[0]->Owner()); + if (relation->GetNode()->IsArrowFunctionExpression()) { relation->GetChecker()->AsETSChecker()->CreateLambdaObjectForLambdaReference( - relation->GetNode()->AsArrowFunctionExpression(), callSignatures_[0]->Owner()); + relation->GetNode()->AsArrowFunctionExpression(), substitutedFuncInterface); } else { relation->GetChecker()->AsETSChecker()->CreateLambdaObjectForFunctionReference(relation->GetNode(), match, - callSignatures_[0]->Owner()); + substitutedFuncInterface); } } @@ -206,19 +231,20 @@ ETSFunctionType *ETSFunctionType::Substitute(TypeRelation *relation, const Subst return anyChange ? copiedType : this; } -checker::RelationResult ETSFunctionType::CastFunctionParams(TypeRelation *relation, Type *target) +checker::RelationResult ETSFunctionType::CastFunctionParams(TypeRelation *relation, Signature *targetInvokeSig) { - auto *targetType = target->AsETSObjectType(); - auto *body = targetType->GetDeclNode()->AsTSInterfaceDeclaration()->Body(); - auto targetParams = body->AsTSInterfaceBody()->Body()[0]->AsMethodDefinition()->Function()->Params(); - for (size_t i = 0; i < targetType->TypeArguments().size(); i++) { + auto *ourSig = callSignatures_[0]; + auto &ourParams = ourSig->Params(); + auto &theirParams = targetInvokeSig->Params(); + if (ourParams.size() != theirParams.size()) { + return RelationResult::FALSE; + } + for (size_t i = 0; i < theirParams.size(); i++) { relation->Result(RelationResult::FALSE); - callSignatures_[0]->Function()->Params()[i]->TsType()->Cast( - relation, targetParams[i]->AsETSParameterExpression()->Check(relation->GetChecker()->AsETSChecker())); - if (relation->IsTrue()) { - continue; + ourParams[i]->TsType()->Cast(relation, theirParams[i]->TsType()); + if (!relation->IsTrue()) { + return RelationResult::FALSE; } - return RelationResult::FALSE; } return RelationResult::TRUE; } @@ -226,23 +252,37 @@ checker::RelationResult ETSFunctionType::CastFunctionParams(TypeRelation *relati void ETSFunctionType::Cast(TypeRelation *relation, Type *target) { ASSERT(relation->GetNode()->IsArrowFunctionExpression()); + auto *savedNode = relation->GetNode(); + conversion::Forbidden(relation); if (target->HasTypeFlag(TypeFlag::ETS_OBJECT)) { auto *targetType = target->AsETSObjectType(); - auto *body = targetType->GetDeclNode()->AsTSInterfaceDeclaration()->Body()->AsTSInterfaceBody(); - auto targetParams = body->AsTSInterfaceBody()->Body()[0]->AsMethodDefinition()->Function()->Params(); - if (targetType->HasObjectFlag(ETSObjectFlags::FUNCTIONAL_INTERFACE) && - targetParams.size() == callSignatures_[0]->Function()->Params().size()) { - relation->Result(CastFunctionParams(relation, target)); + if (targetType->HasObjectFlag(ETSObjectFlags::FUNCTIONAL)) { + auto *targetInvokeVar = targetType->GetProperty(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME, + PropertySearchFlags::SEARCH_INSTANCE_METHOD); + if (targetInvokeVar == nullptr || !targetInvokeVar->TsType()->IsETSFunctionType()) { + return; + } + auto *targetInvokeSig = targetInvokeVar->TsType()->AsETSFunctionType()->CallSignatures()[0]; + relation->Result(CastFunctionParams(relation, targetInvokeSig)); + auto *targetReturnType = targetInvokeSig->ReturnType(); + callSignatures_[0]->ReturnType()->Cast(relation, targetReturnType); } - relation->Result(RelationResult::FALSE); - auto targetReturnType = body->Body()[0]->AsMethodDefinition()->Function()->ReturnTypeAnnotation(); - callSignatures_[0]->ReturnType()->Cast(relation, targetReturnType->TsType()); if (relation->IsTrue()) { relation->GetChecker()->AsETSChecker()->CreateLambdaObjectForLambdaReference( relation->GetNode()->AsArrowFunctionExpression(), targetType->AsETSObjectType()); + relation->SetNode(savedNode); return; } } - conversion::Forbidden(relation); +} + +ETSFunctionType *ETSFunctionType::BoxPrimitives(ETSChecker *checker) +{ + auto *allocator = checker->Allocator(); + auto *ret = allocator->New(name_, allocator); + for (auto *sig : callSignatures_) { + ret->AddCallSignature(sig->BoxPrimitives(checker)); + } + return ret; } } // namespace panda::es2panda::checker diff --git a/ets2panda/checker/types/ets/etsFunctionType.h b/ets2panda/checker/types/ets/etsFunctionType.h index 2d79f87d3c..c275b1b730 100644 --- a/ets2panda/checker/types/ets/etsFunctionType.h +++ b/ets2panda/checker/types/ets/etsFunctionType.h @@ -112,14 +112,15 @@ public: } Signature *FirstAbstractSignature(); - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; bool AssignmentSource(TypeRelation *relation, Type *target) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; ETSFunctionType *Substitute(TypeRelation *relation, const Substitution *substitution) override; void Cast(TypeRelation *relation, Type *target) override; - checker::RelationResult CastFunctionParams(TypeRelation *relation, Type *target); + checker::RelationResult CastFunctionParams(TypeRelation *relation, Signature *targetInvokeSig); + ETSFunctionType *BoxPrimitives(ETSChecker *checker); private: ArenaVector callSignatures_; diff --git a/ets2panda/checker/types/ets/etsObjectType.cpp b/ets2panda/checker/types/ets/etsObjectType.cpp index 5891c50641..28e219d850 100644 --- a/ets2panda/checker/types/ets/etsObjectType.cpp +++ b/ets2panda/checker/types/ets/etsObjectType.cpp @@ -281,14 +281,16 @@ ArenaMap ETSObjectType::Coll return propMap; } -void ETSObjectType::ToString(std::stringstream &ss) const +void ETSObjectType::ToString(std::stringstream &ss, bool precise) const { if (HasObjectFlag(ETSObjectFlags::FUNCTIONAL)) { if (IsNullish() && this != GetConstOriginalBaseType() && !name_.Is("NullType") && !IsETSNullLike() && !name_.Empty()) { ss << lexer::TokenToString(lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); } - GetFunctionalInterfaceInvokeType()->ToString(ss); + GetFunctionalInterfaceInvokeType()->ToString(ss, precise); + } else if (precise) { + ss << assemblerName_; // NOTE(gogabr): need full qualified name } else { ss << name_; } @@ -296,7 +298,7 @@ void ETSObjectType::ToString(std::stringstream &ss) const if (!typeArguments_.empty()) { ss << compiler::Signatures::GENERIC_BEGIN; for (auto arg = typeArguments_.cbegin(); arg != typeArguments_.cend(); ++arg) { - (*arg)->ToString(ss); + (*arg)->ToString(ss, precise); if (next(arg) != typeArguments_.cend()) { ss << lexer::TokenToString(lexer::TokenType::PUNCTUATOR_COMMA); @@ -321,7 +323,7 @@ void ETSObjectType::ToString(std::stringstream &ss) const } } -void ETSObjectType::IdenticalUptoNullability(TypeRelation *relation, Type *other) +void ETSObjectType::IdenticalUptoNullabilityAndTypeArguments(TypeRelation *relation, Type *other) { relation->Result(false); if (!other->IsETSObjectType() || !CheckIdenticalFlags(other->AsETSObjectType()->ObjectFlags())) { @@ -339,57 +341,55 @@ void ETSObjectType::IdenticalUptoNullability(TypeRelation *relation, Type *other return; } - auto const otherTypeArguments = other->AsETSObjectType()->TypeArguments(); + if (IsNullish()) { + relation->Result(true); + return; + } - if (HasTypeFlag(TypeFlag::GENERIC) || IsNullish()) { - if (!HasTypeFlag(TypeFlag::GENERIC)) { - relation->Result(true); - return; - } - if (typeArguments_.empty() != otherTypeArguments.empty()) { - return; - } + auto const sourceTypeArguments = other->AsETSObjectType()->TypeArguments(); + if (typeArguments_.empty() != sourceTypeArguments.empty()) { + return; + } - auto const argsNumber = typeArguments_.size(); - ASSERT(argsNumber == otherTypeArguments.size()); + relation->Result(true); +} - for (size_t idx = 0U; idx < argsNumber; ++idx) { - if (typeArguments_[idx]->IsWildcardType() || otherTypeArguments[idx]->IsWildcardType()) { - continue; - } +void ETSObjectType::IdenticalUptoNullability(TypeRelation *relation, Type *other) +{ + IdenticalUptoNullabilityAndTypeArguments(relation, other); - // checking the nullishness of type args before getting their original base types - // because most probably GetOriginalBaseType will return the non-nullish version of the type - if (!typeArguments_[idx]->IsNullish() && otherTypeArguments[idx]->IsNullish()) { - return; - } + if (!relation->IsTrue() || !HasTypeFlag(TypeFlag::GENERIC)) { + return; + } + + auto const otherTypeArguments = other->AsETSObjectType()->TypeArguments(); - const auto getOriginalBaseTypeOrType = [&relation](Type *const originalType) { - auto *const baseType = relation->GetChecker()->AsETSChecker()->GetOriginalBaseType(originalType); - return baseType == nullptr ? originalType : baseType; - }; + auto const argsNumber = typeArguments_.size(); + ASSERT(argsNumber == otherTypeArguments.size()); - auto *const typeArgType = getOriginalBaseTypeOrType(typeArguments_[idx]); - auto *const otherTypeArgType = getOriginalBaseTypeOrType(otherTypeArguments[idx]); + for (size_t idx = 0U; idx < argsNumber; ++idx) { + if (typeArguments_[idx]->IsWildcardType() || otherTypeArguments[idx]->IsWildcardType()) { + continue; + } - typeArgType->Identical(relation, otherTypeArgType); - if (!relation->IsTrue()) { - return; - } + // checking the nullishness of type args before getting their original base types + // because most probably GetOriginalBaseType will return the non-nullish version of the type + if ((!typeArguments_[idx]->IsNullish() && otherTypeArguments[idx]->IsNullish()) || + (typeArguments_[idx]->IsNullish() && !otherTypeArguments[idx]->IsNullish())) { + relation->Result(false); + return; } - } else { - if (HasObjectFlag(ETSObjectFlags::FUNCTIONAL)) { - auto getInvokeSignature = [](const ETSObjectType *type) { - auto const propInvoke = - type->GetProperty(util::StringView("invoke"), PropertySearchFlags::SEARCH_INSTANCE_METHOD); - ASSERT(propInvoke != nullptr); - return propInvoke->TsType()->AsETSFunctionType()->CallSignatures()[0]; - }; - auto *const thisInvokeSignature = getInvokeSignature(this); - auto *const otherInvokeSignature = getInvokeSignature(other->AsETSObjectType()); + const auto getOriginalBaseTypeOrType = [&relation](Type *const originalType) { + auto *const baseType = relation->GetChecker()->AsETSChecker()->GetOriginalBaseType(originalType); + return baseType == nullptr ? originalType : baseType; + }; + + auto *const typeArgType = getOriginalBaseTypeOrType(typeArguments_[idx]); + auto *const otherTypeArgType = getOriginalBaseTypeOrType(otherTypeArguments[idx]); - relation->IsIdenticalTo(thisInvokeSignature, otherInvokeSignature); + typeArgType->Identical(relation, otherTypeArgType); + if (!relation->IsTrue()) { return; } } @@ -445,8 +445,12 @@ void ETSObjectType::AssignmentTarget(TypeRelation *const relation, Type *source) if (HasObjectFlag(ETSObjectFlags::FUNCTIONAL)) { EnsurePropertiesInstantiated(); - auto found = properties_[static_cast(PropertyType::INSTANCE_METHOD)].find("invoke"); + auto found = properties_[static_cast(PropertyType::INSTANCE_METHOD)].find( + FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME); ASSERT(found != properties_[static_cast(PropertyType::INSTANCE_METHOD)].end()); + if (source->IsETSFunctionType()) { + source = source->AsETSFunctionType()->BoxPrimitives(relation->GetChecker()->AsETSChecker()); + } relation->IsAssignableTo(source, found->second->TsType()); return; } @@ -474,10 +478,14 @@ bool ETSObjectType::CastWideningNarrowing(TypeRelation *const relation, Type *co bool ETSObjectType::CastNumericObject(TypeRelation *const relation, Type *const target) { - if (this->IsNullish()) { + if (!target->HasTypeFlag(TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT | TypeFlag::LONG | + TypeFlag::FLOAT | TypeFlag::DOUBLE | TypeFlag::ETS_BOOLEAN)) { return false; } - + IdenticalUptoNullability(relation, target); + if (relation->IsTrue()) { + return true; + } if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_BYTE)) { if (target->HasTypeFlag(TypeFlag::BYTE)) { conversion::Unboxing(relation, this); @@ -493,63 +501,42 @@ bool ETSObjectType::CastNumericObject(TypeRelation *const relation, Type *const return true; } } - TypeFlag unboxFlags = TypeFlag::NONE; - TypeFlag wideningFlags = TypeFlag::NONE; - TypeFlag narrowingFlags = TypeFlag::NONE; - if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_SHORT)) { - unboxFlags = TypeFlag::SHORT; - wideningFlags = TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE; - narrowingFlags = TypeFlag::BYTE | TypeFlag::CHAR; - if (CastWideningNarrowing(relation, target, unboxFlags, wideningFlags, narrowingFlags)) { - return true; - } + if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_SHORT) && + CastWideningNarrowing(relation, target, TypeFlag::SHORT, + TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE, + TypeFlag::BYTE | TypeFlag::CHAR)) { + return true; } - if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_CHAR)) { - unboxFlags = TypeFlag::CHAR; - wideningFlags = TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE; - narrowingFlags = TypeFlag::BYTE | TypeFlag::SHORT; - if (CastWideningNarrowing(relation, target, unboxFlags, wideningFlags, narrowingFlags)) { - return true; - } + if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_CHAR) && + CastWideningNarrowing(relation, target, TypeFlag::CHAR, + TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE, + TypeFlag::BYTE | TypeFlag::SHORT)) { + return true; } - if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_INT)) { - unboxFlags = TypeFlag::INT; - wideningFlags = TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE; - narrowingFlags = TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR; - if (CastWideningNarrowing(relation, target, unboxFlags, wideningFlags, narrowingFlags)) { - return true; - } + if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_INT) && + CastWideningNarrowing(relation, target, TypeFlag::INT, TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE, + TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR)) { + return true; } - if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_LONG)) { - unboxFlags = TypeFlag::LONG; - wideningFlags = TypeFlag::FLOAT | TypeFlag::DOUBLE; - narrowingFlags = TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT; - if (CastWideningNarrowing(relation, target, unboxFlags, wideningFlags, narrowingFlags)) { - return true; - } + if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_LONG) && + CastWideningNarrowing(relation, target, TypeFlag::LONG, TypeFlag::FLOAT | TypeFlag::DOUBLE, + TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT)) { + return true; } - if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_FLOAT)) { - unboxFlags = TypeFlag::FLOAT; - wideningFlags = TypeFlag::DOUBLE; - narrowingFlags = TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT | TypeFlag::LONG; - if (CastWideningNarrowing(relation, target, unboxFlags, wideningFlags, narrowingFlags)) { - return true; - } + if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_FLOAT) && + CastWideningNarrowing(relation, target, TypeFlag::FLOAT, TypeFlag::DOUBLE, + TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT | TypeFlag::LONG)) { + return true; } - if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_DOUBLE)) { - unboxFlags = TypeFlag::DOUBLE; - wideningFlags = TypeFlag::NONE; - narrowingFlags = + if (auto narrowingFlags = TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT; - if (CastWideningNarrowing(relation, target, unboxFlags, wideningFlags, narrowingFlags)) { - return true; - } + this->HasObjectFlag(ETSObjectFlags::BUILTIN_DOUBLE) && + CastWideningNarrowing(relation, target, TypeFlag::DOUBLE, TypeFlag::NONE, narrowingFlags)) { + return true; } - if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_BOOLEAN)) { - if (target->HasTypeFlag(TypeFlag::ETS_BOOLEAN)) { - conversion::Unboxing(relation, this); - return true; - } + if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_BOOLEAN) && target->HasTypeFlag(TypeFlag::ETS_BOOLEAN)) { + conversion::Unboxing(relation, this); + return true; } if (this->HasObjectFlag(ETSObjectFlags::UNBOXABLE_TYPE)) { if (target->HasTypeFlag(TypeFlag::ETS_OBJECT)) { @@ -649,23 +636,31 @@ bool ETSObjectType::DefaultObjectTypeChecks(const ETSChecker *const etsChecker, return true; } - IdenticalUptoNullability(relation, source); + IdenticalUptoNullabilityAndTypeArguments(relation, source); + if (relation->IsTrue() && HasTypeFlag(TypeFlag::GENERIC)) { + IsGenericSupertypeOf(relation, source); + } return relation->IsTrue(); } +static void IsSupertypeOfUnion(TypeRelation *relation, ETSObjectType *self, ETSUnionType *unionType) +{ + bool res = std::all_of(unionType->ConstituentTypes().begin(), unionType->ConstituentTypes().end(), + [self, relation](Type *ct) { + relation->Result(false); + self->IsSupertypeOf(relation, ct); + return relation->IsTrue(); + }); + relation->Result(res); +} + void ETSObjectType::IsSupertypeOf(TypeRelation *relation, Type *source) { relation->Result(false); auto *const etsChecker = relation->GetChecker()->AsETSChecker(); if (source->IsETSUnionType()) { - bool res = std::all_of(source->AsETSUnionType()->ConstituentTypes().begin(), - source->AsETSUnionType()->ConstituentTypes().end(), [this, relation](Type *ct) { - relation->Result(false); - IsSupertypeOf(relation, ct); - return relation->IsTrue(); - }); - relation->Result(res); + IsSupertypeOfUnion(relation, this, source->AsETSUnionType()); return; } @@ -689,6 +684,51 @@ void ETSObjectType::IsSupertypeOf(TypeRelation *relation, Type *source) } } +void ETSObjectType::IsGenericSupertypeOf(TypeRelation *relation, Type *source) +{ + ASSERT(HasTypeFlag(TypeFlag::GENERIC)); + + auto *sourceType = source->AsETSObjectType(); + auto const sourceTypeArguments = sourceType->TypeArguments(); + ASSERT(typeArguments_.size() == sourceTypeArguments.size()); + + ASSERT(declNode_ == sourceType->GetDeclNode()); + + auto *typeParamsDecl = GetTypeParams(); + ASSERT(typeParamsDecl != nullptr || typeArguments_.empty()); + + if (typeParamsDecl == nullptr) { + return; + } + + auto &typeParams = typeParamsDecl->Params(); + ASSERT(typeParams.size() == typeArguments_.size()); + + for (size_t idx = 0; idx < typeArguments_.size(); idx++) { + auto *typeArg = typeArguments_[idx]; + auto *sourceTypeArg = sourceTypeArguments[idx]; + auto *typeParam = typeParams[idx]; + + relation->Result(false); + + if (!(typeArg->IsWildcardType() || sourceTypeArg->IsWildcardType())) { + if (typeParam->IsOut()) { + typeArg->IsSupertypeOf(relation, sourceTypeArg); + } else if (typeParam->IsIn()) { + sourceTypeArg->IsSupertypeOf(relation, typeArg); + } else { + typeArg->Identical(relation, sourceTypeArg); + } + + if (!relation->IsTrue()) { + return; + } + } + } + + relation->Result(true); +} + Type *ETSObjectType::AsSuper(Checker *checker, varbinder::Variable *sourceVar) { if (sourceVar == nullptr) { @@ -845,7 +885,7 @@ void ETSObjectType::SetCopiedTypeProperties(TypeRelation *const relation, ETSObj copiedType->substitution_ = substitution; } -Type *ETSObjectType::Substitute(TypeRelation *relation, const Substitution *substitution) +ETSObjectType *ETSObjectType::Substitute(TypeRelation *relation, const Substitution *substitution, bool cache) { if (substitution == nullptr || substitution->empty()) { return this; @@ -864,8 +904,10 @@ Type *ETSObjectType::Substitute(TypeRelation *relation, const Substitution *subs } const util::StringView hash = checker->GetHashFromSubstitution(substitution); - if (auto *inst = GetInstantiatedType(hash); inst != nullptr) { - return inst; + if (cache) { + if (auto *inst = GetInstantiatedType(hash); inst != nullptr) { + return inst; + } } if (!relation->TypeInstantiationPossible(base) || IsETSNullLike()) { @@ -875,7 +917,10 @@ Type *ETSObjectType::Substitute(TypeRelation *relation, const Substitution *subs auto *const copiedType = checker->CreateNewETSObjectType(name_, declNode_, flags_); SetCopiedTypeProperties(relation, copiedType, newTypeArgs, substitution); - GetInstantiationMap().try_emplace(hash, copiedType); + + if (cache) { + GetInstantiationMap().try_emplace(hash, copiedType); + } if (superType_ != nullptr) { copiedType->SetSuperType(superType_->Substitute(relation, substitution)->AsETSObjectType()); @@ -890,6 +935,11 @@ Type *ETSObjectType::Substitute(TypeRelation *relation, const Substitution *subs return copiedType; } +ETSObjectType *ETSObjectType::Substitute(TypeRelation *relation, const Substitution *substitution) +{ + return Substitute(relation, substitution, true); +} + void ETSObjectType::InstantiateProperties() const { if (baseType_ == nullptr || baseType_ == this) { diff --git a/ets2panda/checker/types/ets/etsObjectType.h b/ets2panda/checker/types/ets/etsObjectType.h index c59e37eb67..b54010b006 100644 --- a/ets2panda/checker/types/ets/etsObjectType.h +++ b/ets2panda/checker/types/ets/etsObjectType.h @@ -112,6 +112,9 @@ enum class PropertyType { COUNT, }; +/* Invoke method name in functional interfaces */ +constexpr char const *FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME = "invoke0"; + class ETSObjectType : public Type { public: using PropertyMap = ArenaUnorderedMap; @@ -392,7 +395,7 @@ public: ETSFunctionType *GetFunctionalInterfaceInvokeType() const { ASSERT(HasObjectFlag(ETSObjectFlags::FUNCTIONAL)); - auto *invoke = GetOwnProperty("invoke"); + auto *invoke = GetOwnProperty(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME); ASSERT(invoke && invoke->TsType() && invoke->TsType()->IsETSFunctionType()); return invoke->TsType()->AsETSFunctionType(); } @@ -414,17 +417,11 @@ public: varbinder::Scope *GetTypeArgumentScope() const { - if (HasObjectFlag(ETSObjectFlags::ENUM) || !HasTypeFlag(TypeFlag::GENERIC)) { + auto *typeParams = GetTypeParams(); + if (typeParams == nullptr) { return nullptr; } - - if (HasObjectFlag(ETSObjectFlags::CLASS)) { - ASSERT(declNode_->IsClassDefinition() && declNode_->AsClassDefinition()->TypeParams()); - return declNode_->AsClassDefinition()->TypeParams()->Scope(); - } - - ASSERT(declNode_->IsTSInterfaceDeclaration() && declNode_->AsTSInterfaceDeclaration()->TypeParams()); - return declNode_->AsTSInterfaceDeclaration()->TypeParams()->Scope(); + return typeParams->Scope(); } InstantiationMap &GetInstantiationMap() @@ -471,7 +468,7 @@ public: bool CheckIdenticalVariable(varbinder::Variable *otherVar) const; void Iterate(const PropertyTraverser &cb) const; - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; bool AssignmentSource(TypeRelation *relation, Type *target) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; @@ -479,7 +476,8 @@ public: bool SubstituteTypeArgs(TypeRelation *relation, ArenaVector &newTypeArgs, const Substitution *substitution); void SetCopiedTypeProperties(TypeRelation *relation, ETSObjectType *copiedType, ArenaVector &newTypeArgs, const Substitution *substitution); - Type *Substitute(TypeRelation *relation, const Substitution *substitution) override; + ETSObjectType *Substitute(TypeRelation *relation, const Substitution *substitution) override; + ETSObjectType *Substitute(TypeRelation *relation, const Substitution *substitution, bool cache); void Cast(TypeRelation *relation, Type *target) override; bool CastNumericObject(TypeRelation *relation, Type *target); bool DefaultObjectTypeChecks(const ETSChecker *etsChecker, TypeRelation *relation, Type *source); @@ -549,6 +547,23 @@ private: void IdenticalUptoNullability(TypeRelation *relation, Type *other); bool CastWideningNarrowing(TypeRelation *relation, Type *target, TypeFlag unboxFlags, TypeFlag wideningFlags, TypeFlag narrowingFlags); + void IdenticalUptoNullabilityAndTypeArguments(TypeRelation *relation, Type *other); + void IsGenericSupertypeOf(TypeRelation *relation, Type *source); + + ir::TSTypeParameterDeclaration *GetTypeParams() const + { + if (HasObjectFlag(ETSObjectFlags::ENUM) || !HasTypeFlag(TypeFlag::GENERIC)) { + return nullptr; + } + + if (HasObjectFlag(ETSObjectFlags::CLASS)) { + ASSERT(declNode_->IsClassDefinition() && declNode_->AsClassDefinition()->TypeParams()); + return declNode_->AsClassDefinition()->TypeParams(); + } + + ASSERT(declNode_->IsTSInterfaceDeclaration() && declNode_->AsTSInterfaceDeclaration()->TypeParams()); + return declNode_->AsTSInterfaceDeclaration()->TypeParams(); + } ArenaAllocator *allocator_; util::StringView name_; diff --git a/ets2panda/checker/types/ets/etsStringType.h b/ets2panda/checker/types/ets/etsStringType.h index afc3c2dd9f..8b96db319e 100644 --- a/ets2panda/checker/types/ets/etsStringType.h +++ b/ets2panda/checker/types/ets/etsStringType.h @@ -43,12 +43,12 @@ public: void AssignmentTarget(TypeRelation *relation, Type *source) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << lexer::TokenToString(lexer::TokenType::KEYW_STRING); } - void ToAssemblerType([[maybe_unused]] std::stringstream &ss) const override + void ToAssemblerType(std::stringstream &ss) const override { ss << compiler::Signatures::BUILTIN_STRING; } diff --git a/ets2panda/checker/types/ets/etsTupleType.cpp b/ets2panda/checker/types/ets/etsTupleType.cpp index 1f79e6f997..2eea1c4084 100644 --- a/ets2panda/checker/types/ets/etsTupleType.cpp +++ b/ets2panda/checker/types/ets/etsTupleType.cpp @@ -20,12 +20,12 @@ #include "ir/ets/etsTuple.h" namespace panda::es2panda::checker { -void ETSTupleType::ToString(std::stringstream &ss) const +void ETSTupleType::ToString(std::stringstream &ss, bool precise) const { ss << "["; for (auto it = typeList_.begin(); it != typeList_.end(); it++) { - (*it)->ToString(ss); + (*it)->ToString(ss, precise); if (std::next(it) != typeList_.end()) { ss << ", "; @@ -34,7 +34,7 @@ void ETSTupleType::ToString(std::stringstream &ss) const if (spreadType_ != nullptr) { ss << ", ..."; - spreadType_->ToString(ss); + spreadType_->ToString(ss, precise); ss << "[]"; } diff --git a/ets2panda/checker/types/ets/etsTupleType.h b/ets2panda/checker/types/ets/etsTupleType.h index 249dbe58cf..ac3bc3ff79 100644 --- a/ets2panda/checker/types/ets/etsTupleType.h +++ b/ets2panda/checker/types/ets/etsTupleType.h @@ -80,7 +80,7 @@ public: [[nodiscard]] Type *GetTypeAtIndex(int32_t index) const; - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ets/etsTypeParameter.cpp b/ets2panda/checker/types/ets/etsTypeParameter.cpp index 302f9ce42f..3c1f5b76c9 100644 --- a/ets2panda/checker/types/ets/etsTypeParameter.cpp +++ b/ets2panda/checker/types/ets/etsTypeParameter.cpp @@ -20,8 +20,13 @@ #include "checker/ets/conversion.h" namespace panda::es2panda::checker { -void ETSTypeParameter::ToString(std::stringstream &ss) const + +void ETSTypeParameter::ToString(std::stringstream &ss, bool precise) const { + // Need source file name to avoid clashes + if (precise) { + ss << declNode_->Range().start.index << "." << declNode_->Range().start.line << "."; + } ss << declNode_->Name()->Name(); if (IsNullish()) { diff --git a/ets2panda/checker/types/ets/etsTypeParameter.h b/ets2panda/checker/types/ets/etsTypeParameter.h index 63dabb1358..f32f0305db 100644 --- a/ets2panda/checker/types/ets/etsTypeParameter.h +++ b/ets2panda/checker/types/ets/etsTypeParameter.h @@ -61,7 +61,7 @@ public: return constraint_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; bool AssignmentSource(TypeRelation *relation, Type *target) override; diff --git a/ets2panda/checker/types/ets/etsUnionType.cpp b/ets2panda/checker/types/ets/etsUnionType.cpp index b23981aed5..7f68b971ad 100644 --- a/ets2panda/checker/types/ets/etsUnionType.cpp +++ b/ets2panda/checker/types/ets/etsUnionType.cpp @@ -22,10 +22,10 @@ #include "ir/astNode.h" namespace panda::es2panda::checker { -void ETSUnionType::ToString(std::stringstream &ss) const +void ETSUnionType::ToString(std::stringstream &ss, bool precise) const { for (auto it = constituentTypes_.begin(); it != constituentTypes_.end(); it++) { - (*it)->ToString(ss); + (*it)->ToString(ss, precise); if (std::next(it) != constituentTypes_.end()) { ss << "|"; } diff --git a/ets2panda/checker/types/ets/etsUnionType.h b/ets2panda/checker/types/ets/etsUnionType.h index 216c2630c2..19336608aa 100644 --- a/ets2panda/checker/types/ets/etsUnionType.h +++ b/ets2panda/checker/types/ets/etsUnionType.h @@ -32,7 +32,7 @@ public: return constituentTypes_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void ToAssemblerType(std::stringstream &ss) const override; void ToDebugInfoType(std::stringstream &ss) const override; void Identical(TypeRelation *relation, Type *other) override; diff --git a/ets2panda/checker/types/ets/etsVoidType.h b/ets2panda/checker/types/ets/etsVoidType.h index ab280f7e2d..e6658fc53f 100644 --- a/ets2panda/checker/types/ets/etsVoidType.h +++ b/ets2panda/checker/types/ets/etsVoidType.h @@ -27,7 +27,7 @@ public: void AssignmentTarget(TypeRelation *relation, Type *source) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << "void"; } diff --git a/ets2panda/checker/types/ets/floatType.h b/ets2panda/checker/types/ets/floatType.h index 68da05d2d0..6c9b92c1c8 100644 --- a/ets2panda/checker/types/ets/floatType.h +++ b/ets2panda/checker/types/ets/floatType.h @@ -37,7 +37,7 @@ public: void Cast(TypeRelation *relation, Type *target) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << "float"; } diff --git a/ets2panda/checker/types/ets/intType.h b/ets2panda/checker/types/ets/intType.h index 2e9734ccc7..fab974a6f0 100644 --- a/ets2panda/checker/types/ets/intType.h +++ b/ets2panda/checker/types/ets/intType.h @@ -37,7 +37,7 @@ public: void Cast(TypeRelation *relation, Type *target) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << "int"; } diff --git a/ets2panda/checker/types/ets/longType.h b/ets2panda/checker/types/ets/longType.h index e2887d5374..85ee2db7d3 100644 --- a/ets2panda/checker/types/ets/longType.h +++ b/ets2panda/checker/types/ets/longType.h @@ -37,7 +37,7 @@ public: void Cast(TypeRelation *relation, Type *target) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << "long"; } diff --git a/ets2panda/checker/types/ets/shortType.h b/ets2panda/checker/types/ets/shortType.h index 85764fff83..7d0788b4bb 100644 --- a/ets2panda/checker/types/ets/shortType.h +++ b/ets2panda/checker/types/ets/shortType.h @@ -37,7 +37,7 @@ public: void Cast(TypeRelation *relation, Type *target) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << "short"; } diff --git a/ets2panda/checker/types/ets/wildcardType.cpp b/ets2panda/checker/types/ets/wildcardType.cpp index aab9ae80b4..7b99a7b06f 100644 --- a/ets2panda/checker/types/ets/wildcardType.cpp +++ b/ets2panda/checker/types/ets/wildcardType.cpp @@ -16,7 +16,7 @@ #include "wildcardType.h" namespace panda::es2panda::checker { -void WildcardType::ToString(std::stringstream &ss) const +void WildcardType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "wildcard"; } diff --git a/ets2panda/checker/types/ets/wildcardType.h b/ets2panda/checker/types/ets/wildcardType.h index 9db1b04df9..feb18636ec 100644 --- a/ets2panda/checker/types/ets/wildcardType.h +++ b/ets2panda/checker/types/ets/wildcardType.h @@ -23,7 +23,7 @@ class WildcardType : public Type { public: WildcardType() : Type(TypeFlag::WILDCARD) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; diff --git a/ets2panda/checker/types/globalTypesHolder.cpp b/ets2panda/checker/types/globalTypesHolder.cpp index 27115ca559..169afad7a8 100644 --- a/ets2panda/checker/types/globalTypesHolder.cpp +++ b/ets2panda/checker/types/globalTypesHolder.cpp @@ -158,6 +158,18 @@ GlobalTypesHolder::GlobalTypesHolder(ArenaAllocator *allocator) : builtinNameMap builtinNameMappings_.emplace("RegExp", GlobalTypeId::ETS_REGEXP_BUILTIN); builtinNameMappings_.emplace("Set", GlobalTypeId::ETS_SET_BUILTIN); + // ETS functional types + for (size_t id = static_cast(GlobalTypeId::ETS_FUNCTION0_CLASS), nargs = 0; + id < static_cast(GlobalTypeId::ETS_FUNCTIONN_CLASS); id++, nargs++) { + std::stringstream ss; + ss << "Function"; + ss << nargs; + + builtinNameMappings_.emplace(util::UString(ss.str(), allocator).View(), static_cast(id)); + } + + builtinNameMappings_.emplace("FunctionN", GlobalTypeId::ETS_FUNCTIONN_CLASS); + // ETS interop js specific types builtinNameMappings_.emplace("JSRuntime", GlobalTypeId::ETS_INTEROP_JSRUNTIME_BUILTIN); builtinNameMappings_.emplace("JSValue", GlobalTypeId::ETS_INTEROP_JSVALUE_BUILTIN); @@ -613,6 +625,20 @@ Type *GlobalTypesHolder::GlobalBuiltinNeverType() return globalTypes_.at(static_cast(GlobalTypeId::ETS_NEVER_BUILTIN)); } +size_t GlobalTypesHolder::VariadicFunctionTypeThreshold() +{ + return static_cast(GlobalTypeId::ETS_FUNCTIONN_CLASS) - + static_cast(GlobalTypeId::ETS_FUNCTION0_CLASS); +} + +Type *GlobalTypesHolder::GlobalFunctionBuiltinType(size_t nargs) +{ + if (nargs >= VariadicFunctionTypeThreshold()) { + return globalTypes_.at(static_cast(GlobalTypeId::ETS_FUNCTIONN_CLASS)); + } + return globalTypes_.at(static_cast(GlobalTypeId::ETS_FUNCTION0_CLASS) + nargs); +} + void GlobalTypesHolder::InitializeBuiltin(const util::StringView name, Type *type) { const auto typeId = builtinNameMappings_.find(name); diff --git a/ets2panda/checker/types/globalTypesHolder.h b/ets2panda/checker/types/globalTypesHolder.h index c79d375a25..3f3fb07465 100644 --- a/ets2panda/checker/types/globalTypesHolder.h +++ b/ets2panda/checker/types/globalTypesHolder.h @@ -112,6 +112,25 @@ enum class GlobalTypeId { ETS_BIG_INT_BUILTIN, ETS_BIG_INT, + ETS_FUNCTION0_CLASS, + ETS_FUNCTION1_CLASS, + ETS_FUNCTION2_CLASS, + ETS_FUNCTION3_CLASS, + ETS_FUNCTION4_CLASS, + ETS_FUNCTION5_CLASS, + ETS_FUNCTION6_CLASS, + ETS_FUNCTION7_CLASS, + ETS_FUNCTION8_CLASS, + ETS_FUNCTION9_CLASS, + ETS_FUNCTION10_CLASS, + ETS_FUNCTION11_CLASS, + ETS_FUNCTION12_CLASS, + ETS_FUNCTION13_CLASS, + ETS_FUNCTION14_CLASS, + ETS_FUNCTION15_CLASS, + ETS_FUNCTION16_CLASS, + ETS_FUNCTIONN_CLASS, + COUNT, }; @@ -204,6 +223,10 @@ public: Type *GlobalDoubleBoxBuiltinType(); Type *GlobalBuiltinNeverType(); + // Functional types + size_t VariadicFunctionTypeThreshold(); + Type *GlobalFunctionBuiltinType(size_t nargs); + // ETS escompat layer Type *GlobalArrayBuiltinType(); Type *GlobalClassOutOfMemoryErrorBuiltinType(); diff --git a/ets2panda/checker/types/signature.cpp b/ets2panda/checker/types/signature.cpp index c9e826acf8..01feb8044b 100644 --- a/ets2panda/checker/types/signature.cpp +++ b/ets2panda/checker/types/signature.cpp @@ -15,6 +15,7 @@ #include "signature.h" +#include "typeFlag.h" #include "varbinder/scope.h" #include "ir/base/scriptFunction.h" #include "ir/ts/tsTypeParameter.h" @@ -118,12 +119,13 @@ Signature *Signature::Copy(ArenaAllocator *allocator, TypeRelation *relation, Gl return copiedSignature; } -void Signature::ToString(std::stringstream &ss, const varbinder::Variable *variable, bool printAsMethod) const +void Signature::ToString(std::stringstream &ss, const varbinder::Variable *variable, bool printAsMethod, + bool precise) const { if (!signatureInfo_->typeParams.empty()) { ss << "<"; for (auto it = signatureInfo_->typeParams.begin(); it != signatureInfo_->typeParams.end(); ++it) { - (*it)->ToString(ss); + (*it)->ToString(ss, precise); if (std::next(it) != signatureInfo_->typeParams.end()) { ss << ", "; } @@ -142,7 +144,7 @@ void Signature::ToString(std::stringstream &ss, const varbinder::Variable *varia ss << ": "; - (*it)->TsType()->ToString(ss); + (*it)->TsType()->ToString(ss, precise); if (std::next(it) != signatureInfo_->params.end()) { ss << ", "; @@ -157,7 +159,8 @@ void Signature::ToString(std::stringstream &ss, const varbinder::Variable *varia ss << "..."; ss << signatureInfo_->restVar->Name(); ss << ": "; - signatureInfo_->restVar->TsType()->ToString(ss); + signatureInfo_->restVar->TsType()->ToString(ss, precise); + ss << "[]"; } @@ -169,7 +172,14 @@ void Signature::ToString(std::stringstream &ss, const varbinder::Variable *varia ss << " => "; } - returnType_->ToString(ss); + returnType_->ToString(ss, precise); +} + +std::string Signature::ToString() const +{ + std::stringstream ss; + ToString(ss, nullptr); + return ss.str(); } namespace { @@ -190,9 +200,7 @@ std::size_t GetToCheckParamCount(Signature *signature, bool isEts) bool Signature::IdenticalParameter(TypeRelation *relation, Type *type1, Type *type2) { - if (!CheckFunctionalInterfaces(relation, type1, type2)) { - relation->IsIdenticalTo(type1, type2); - } + relation->IsIdenticalTo(type1, type2); return relation->IsTrue(); } @@ -340,4 +348,24 @@ void Signature::AssignmentTarget(TypeRelation *relation, Signature *source) relation->IsAssignableTo(source->RestVar()->TsType(), signatureInfo_->restVar->TsType()); } } + +Signature *Signature::BoxPrimitives(ETSChecker *checker) +{ + auto *allocator = checker->Allocator(); + auto *sigInfo = allocator->New(signatureInfo_, allocator); + for (auto param : sigInfo->params) { + if (param->TsType()->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) { + param->SetTsType(checker->PrimitiveTypeAsETSBuiltinType(param->TsType())); + } + } + auto *retType = returnType_->HasTypeFlag(TypeFlag::ETS_PRIMITIVE) + ? checker->PrimitiveTypeAsETSBuiltinType(returnType_) + : returnType_; + + auto *resultSig = allocator->New(sigInfo, retType, func_); + resultSig->flags_ = flags_; + resultSig->SetOwner(Owner()); + resultSig->SetOwnerVar(OwnerVar()); + return resultSig; +} } // namespace panda::es2panda::checker diff --git a/ets2panda/checker/types/signature.h b/ets2panda/checker/types/signature.h index 295dd1111c..ab2bc277fc 100644 --- a/ets2panda/checker/types/signature.h +++ b/ets2panda/checker/types/signature.h @@ -81,6 +81,8 @@ enum class SignatureFlags : uint32_t { THIS_RETURN_TYPE = 1U << 15U, GETTER = 1U << 16U, SETTER = 1U << 17U, + THROWS = 1U << 18U, + RETHROWS = 1U << 19U, INTERNAL_PROTECTED = INTERNAL | PROTECTED, GETTER_OR_SETTER = GETTER | SETTER, @@ -245,10 +247,13 @@ public: Signature *Copy(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes); Signature *Substitute(TypeRelation *relation, const Substitution *substitution); - void ToString(std::stringstream &ss, const varbinder::Variable *variable, bool printAsMethod = false) const; + void ToString(std::stringstream &ss, const varbinder::Variable *variable, bool printAsMethod = false, + bool precise = false) const; + std::string ToString() const; void Identical(TypeRelation *relation, Signature *other); bool CheckFunctionalInterfaces(TypeRelation *relation, Type *source, Type *target); void AssignmentTarget(TypeRelation *relation, Signature *source); + Signature *BoxPrimitives(ETSChecker *checker); private: bool IdenticalParameter(TypeRelation *relation, Type *type1, Type *type2); diff --git a/ets2panda/checker/types/ts/anyType.cpp b/ets2panda/checker/types/ts/anyType.cpp index 8409060e97..db2c7f0420 100644 --- a/ets2panda/checker/types/ts/anyType.cpp +++ b/ets2panda/checker/types/ts/anyType.cpp @@ -16,7 +16,7 @@ #include "anyType.h" namespace panda::es2panda::checker { -void AnyType::ToString(std::stringstream &ss) const +void AnyType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "any"; } diff --git a/ets2panda/checker/types/ts/anyType.h b/ets2panda/checker/types/ts/anyType.h index 69c36c85f5..19633bc7a5 100644 --- a/ets2panda/checker/types/ts/anyType.h +++ b/ets2panda/checker/types/ts/anyType.h @@ -23,7 +23,7 @@ class AnyType : public Type { public: AnyType() : Type(TypeFlag::ANY) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; bool AssignmentSource(TypeRelation *relation, Type *target) override; diff --git a/ets2panda/checker/types/ts/arrayType.cpp b/ets2panda/checker/types/ts/arrayType.cpp index 8c4e2ac9b7..2e34572088 100644 --- a/ets2panda/checker/types/ts/arrayType.cpp +++ b/ets2panda/checker/types/ts/arrayType.cpp @@ -19,13 +19,13 @@ #include "checker/types/ts/objectType.h" namespace panda::es2panda::checker { -void ArrayType::ToString(std::stringstream &ss) const +void ArrayType::ToString(std::stringstream &ss, bool precise) const { bool elemIsUnion = (element_->TypeFlags() == TypeFlag::UNION); if (elemIsUnion) { ss << "("; } - ElementType()->ToString(ss); + ElementType()->ToString(ss, precise); if (elemIsUnion) { ss << ")"; } diff --git a/ets2panda/checker/types/ts/arrayType.h b/ets2panda/checker/types/ts/arrayType.h index 78f6c25994..d60de37a4d 100644 --- a/ets2panda/checker/types/ts/arrayType.h +++ b/ets2panda/checker/types/ts/arrayType.h @@ -33,7 +33,7 @@ public: return element_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; TypeFacts GetTypeFacts() const override; diff --git a/ets2panda/checker/types/ts/bigintLiteralType.cpp b/ets2panda/checker/types/ts/bigintLiteralType.cpp index b378c83fc5..6623505258 100644 --- a/ets2panda/checker/types/ts/bigintLiteralType.cpp +++ b/ets2panda/checker/types/ts/bigintLiteralType.cpp @@ -16,7 +16,7 @@ #include "bigintLiteralType.h" namespace panda::es2panda::checker { -void BigintLiteralType::ToString(std::stringstream &ss) const +void BigintLiteralType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << value_; } diff --git a/ets2panda/checker/types/ts/bigintLiteralType.h b/ets2panda/checker/types/ts/bigintLiteralType.h index 9e02187ffe..b3797e5aff 100644 --- a/ets2panda/checker/types/ts/bigintLiteralType.h +++ b/ets2panda/checker/types/ts/bigintLiteralType.h @@ -36,7 +36,7 @@ public: return negative_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void ToStringAsSrc(std::stringstream &ss) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/bigintType.cpp b/ets2panda/checker/types/ts/bigintType.cpp index 91e816019d..ee84c0717a 100644 --- a/ets2panda/checker/types/ts/bigintType.cpp +++ b/ets2panda/checker/types/ts/bigintType.cpp @@ -16,7 +16,7 @@ #include "bigintType.h" namespace panda::es2panda::checker { -void BigintType::ToString(std::stringstream &ss) const +void BigintType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "bigint"; } diff --git a/ets2panda/checker/types/ts/bigintType.h b/ets2panda/checker/types/ts/bigintType.h index 17b7526c60..e9b839d3e5 100644 --- a/ets2panda/checker/types/ts/bigintType.h +++ b/ets2panda/checker/types/ts/bigintType.h @@ -23,7 +23,7 @@ class BigintType : public Type { public: BigintType() : Type(TypeFlag::BIGINT) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; TypeFacts GetTypeFacts() const override; diff --git a/ets2panda/checker/types/ts/booleanLiteralType.cpp b/ets2panda/checker/types/ts/booleanLiteralType.cpp index b204f0b506..36a0689342 100644 --- a/ets2panda/checker/types/ts/booleanLiteralType.cpp +++ b/ets2panda/checker/types/ts/booleanLiteralType.cpp @@ -16,7 +16,7 @@ #include "booleanLiteralType.h" namespace panda::es2panda::checker { -void BooleanLiteralType::ToString(std::stringstream &ss) const +void BooleanLiteralType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { if (value_) { ss << "true"; diff --git a/ets2panda/checker/types/ts/booleanLiteralType.h b/ets2panda/checker/types/ts/booleanLiteralType.h index 381df49bc4..4c04e0cdea 100644 --- a/ets2panda/checker/types/ts/booleanLiteralType.h +++ b/ets2panda/checker/types/ts/booleanLiteralType.h @@ -28,7 +28,7 @@ public: return value_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void ToStringAsSrc(std::stringstream &ss) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/booleanType.cpp b/ets2panda/checker/types/ts/booleanType.cpp index 3ba7501e33..3855d633b1 100644 --- a/ets2panda/checker/types/ts/booleanType.cpp +++ b/ets2panda/checker/types/ts/booleanType.cpp @@ -16,7 +16,7 @@ #include "booleanType.h" namespace panda::es2panda::checker { -void BooleanType::ToString(std::stringstream &ss) const +void BooleanType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "boolean"; } diff --git a/ets2panda/checker/types/ts/booleanType.h b/ets2panda/checker/types/ts/booleanType.h index b0b54f2233..3dc6c1ece3 100644 --- a/ets2panda/checker/types/ts/booleanType.h +++ b/ets2panda/checker/types/ts/booleanType.h @@ -23,7 +23,7 @@ class BooleanType : public Type { public: BooleanType() : Type(TypeFlag::BOOLEAN) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; TypeFacts GetTypeFacts() const override; diff --git a/ets2panda/checker/types/ts/constructorType.cpp b/ets2panda/checker/types/ts/constructorType.cpp index 75596cb0b9..294d1a28a5 100644 --- a/ets2panda/checker/types/ts/constructorType.cpp +++ b/ets2panda/checker/types/ts/constructorType.cpp @@ -18,7 +18,7 @@ #include "checker/types/signature.h" namespace panda::es2panda::checker { -void ConstructorType::ToString(std::stringstream &ss) const +void ConstructorType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { if (desc_->constructSignatures.size() > 1) { ss << "{ "; diff --git a/ets2panda/checker/types/ts/constructorType.h b/ets2panda/checker/types/ts/constructorType.h index 4c930cee42..02389c7292 100644 --- a/ets2panda/checker/types/ts/constructorType.h +++ b/ets2panda/checker/types/ts/constructorType.h @@ -23,7 +23,7 @@ class ConstructorType : public ObjectType { public: explicit ConstructorType(ObjectDescriptor *desc) : ObjectType(ObjectType::ObjectTypeKind::FUNCTION, desc) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; TypeFacts GetTypeFacts() const override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; }; diff --git a/ets2panda/checker/types/ts/enumLiteralType.cpp b/ets2panda/checker/types/ts/enumLiteralType.cpp index 7cd7c05dc8..0618f2d1c9 100644 --- a/ets2panda/checker/types/ts/enumLiteralType.cpp +++ b/ets2panda/checker/types/ts/enumLiteralType.cpp @@ -19,7 +19,7 @@ #include "checker/types/ts/enumType.h" namespace panda::es2panda::checker { -void EnumLiteralType::ToString(std::stringstream &ss) const +void EnumLiteralType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << name_; } diff --git a/ets2panda/checker/types/ts/enumLiteralType.h b/ets2panda/checker/types/ts/enumLiteralType.h index 83a42455ef..19e4e8c9d5 100644 --- a/ets2panda/checker/types/ts/enumLiteralType.h +++ b/ets2panda/checker/types/ts/enumLiteralType.h @@ -47,7 +47,7 @@ public: return kind_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void ToStringAsSrc(std::stringstream &ss) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/enumType.cpp b/ets2panda/checker/types/ts/enumType.cpp index 0ee4cc675a..4a308dda73 100644 --- a/ets2panda/checker/types/ts/enumType.cpp +++ b/ets2panda/checker/types/ts/enumType.cpp @@ -18,7 +18,7 @@ #include "varbinder/variable.h" namespace panda::es2panda::checker { -void EnumType::ToString(std::stringstream &ss) const +void EnumType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << enumLiteralVar_->Name() << "." << enumVar_->Name(); } diff --git a/ets2panda/checker/types/ts/enumType.h b/ets2panda/checker/types/ts/enumType.h index c1a3a87882..ce3da03261 100644 --- a/ets2panda/checker/types/ts/enumType.h +++ b/ets2panda/checker/types/ts/enumType.h @@ -1,3 +1,4 @@ + /** * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,7 +41,7 @@ public: return enumVar_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; TypeFacts GetTypeFacts() const override; diff --git a/ets2panda/checker/types/ts/functionType.cpp b/ets2panda/checker/types/ts/functionType.cpp index 3e18974291..e8a10afe9d 100644 --- a/ets2panda/checker/types/ts/functionType.cpp +++ b/ets2panda/checker/types/ts/functionType.cpp @@ -18,7 +18,7 @@ #include "checker/types/signature.h" namespace panda::es2panda::checker { -void FunctionType::ToString(std::stringstream &ss) const +void FunctionType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { static std::unordered_set stack; diff --git a/ets2panda/checker/types/ts/functionType.h b/ets2panda/checker/types/ts/functionType.h index f1b465a54b..b8e36d821d 100644 --- a/ets2panda/checker/types/ts/functionType.h +++ b/ets2panda/checker/types/ts/functionType.h @@ -24,7 +24,7 @@ class FunctionType : public ObjectType { public: explicit FunctionType(ObjectDescriptor *desc) : ObjectType(ObjectType::ObjectTypeKind::FUNCTION, desc) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; TypeFacts GetTypeFacts() const override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; }; diff --git a/ets2panda/checker/types/ts/interfaceType.cpp b/ets2panda/checker/types/ts/interfaceType.cpp index 69b95e8ce3..633009c8a1 100644 --- a/ets2panda/checker/types/ts/interfaceType.cpp +++ b/ets2panda/checker/types/ts/interfaceType.cpp @@ -23,7 +23,7 @@ #include namespace panda::es2panda::checker { -void InterfaceType::ToString(std::stringstream &ss) const +void InterfaceType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << name_; diff --git a/ets2panda/checker/types/ts/interfaceType.h b/ets2panda/checker/types/ts/interfaceType.h index cfd1811e49..210129214b 100644 --- a/ets2panda/checker/types/ts/interfaceType.h +++ b/ets2panda/checker/types/ts/interfaceType.h @@ -128,7 +128,7 @@ public: return properties; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; TypeFacts GetTypeFacts() const override; void Identical(TypeRelation *relation, Type *other) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; diff --git a/ets2panda/checker/types/ts/neverType.cpp b/ets2panda/checker/types/ts/neverType.cpp index e4d75b6362..8add433de8 100644 --- a/ets2panda/checker/types/ts/neverType.cpp +++ b/ets2panda/checker/types/ts/neverType.cpp @@ -16,7 +16,7 @@ #include "neverType.h" namespace panda::es2panda::checker { -void NeverType::ToString(std::stringstream &ss) const +void NeverType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "never"; } diff --git a/ets2panda/checker/types/ts/neverType.h b/ets2panda/checker/types/ts/neverType.h index 0931b3ae44..5a5fb981c3 100644 --- a/ets2panda/checker/types/ts/neverType.h +++ b/ets2panda/checker/types/ts/neverType.h @@ -23,7 +23,7 @@ class NeverType : public Type { public: NeverType() : Type(TypeFlag::NEVER) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; TypeFacts GetTypeFacts() const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/nonPrimitiveType.cpp b/ets2panda/checker/types/ts/nonPrimitiveType.cpp index 3c37b7cebf..3fb42a30de 100644 --- a/ets2panda/checker/types/ts/nonPrimitiveType.cpp +++ b/ets2panda/checker/types/ts/nonPrimitiveType.cpp @@ -16,7 +16,7 @@ #include "nonPrimitiveType.h" namespace panda::es2panda::checker { -void NonPrimitiveType::ToString(std::stringstream &ss) const +void NonPrimitiveType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "object"; } diff --git a/ets2panda/checker/types/ts/nonPrimitiveType.h b/ets2panda/checker/types/ts/nonPrimitiveType.h index 2047f5df57..614a658ad5 100644 --- a/ets2panda/checker/types/ts/nonPrimitiveType.h +++ b/ets2panda/checker/types/ts/nonPrimitiveType.h @@ -23,7 +23,7 @@ class NonPrimitiveType : public Type { public: NonPrimitiveType() : Type(TypeFlag::NON_PRIMITIVE) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; TypeFacts GetTypeFacts() const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/nullType.cpp b/ets2panda/checker/types/ts/nullType.cpp index 786aed31c6..bcd90b3f70 100644 --- a/ets2panda/checker/types/ts/nullType.cpp +++ b/ets2panda/checker/types/ts/nullType.cpp @@ -16,7 +16,7 @@ #include "nullType.h" namespace panda::es2panda::checker { -void NullType::ToString(std::stringstream &ss) const +void NullType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "null"; } diff --git a/ets2panda/checker/types/ts/nullType.h b/ets2panda/checker/types/ts/nullType.h index c46dfccb24..5d40915809 100644 --- a/ets2panda/checker/types/ts/nullType.h +++ b/ets2panda/checker/types/ts/nullType.h @@ -23,7 +23,7 @@ class NullType : public Type { public: NullType() : Type(TypeFlag::NULL_TYPE) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; bool AssignmentSource(TypeRelation *relation, Type *target) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/numberLiteralType.cpp b/ets2panda/checker/types/ts/numberLiteralType.cpp index c4ccc26e37..3bc17ad8bc 100644 --- a/ets2panda/checker/types/ts/numberLiteralType.cpp +++ b/ets2panda/checker/types/ts/numberLiteralType.cpp @@ -20,7 +20,7 @@ #include "checker/types/ts/enumType.h" namespace panda::es2panda::checker { -void NumberLiteralType::ToString(std::stringstream &ss) const +void NumberLiteralType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << util::Helpers::ToString(value_); } diff --git a/ets2panda/checker/types/ts/numberLiteralType.h b/ets2panda/checker/types/ts/numberLiteralType.h index 360060a925..8b738425b7 100644 --- a/ets2panda/checker/types/ts/numberLiteralType.h +++ b/ets2panda/checker/types/ts/numberLiteralType.h @@ -28,7 +28,7 @@ public: return value_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void ToStringAsSrc(std::stringstream &ss) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/numberType.cpp b/ets2panda/checker/types/ts/numberType.cpp index 40916929fd..59e90af296 100644 --- a/ets2panda/checker/types/ts/numberType.cpp +++ b/ets2panda/checker/types/ts/numberType.cpp @@ -19,7 +19,7 @@ #include "checker/types/ts/enumType.h" namespace panda::es2panda::checker { -void NumberType::ToString(std::stringstream &ss) const +void NumberType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "number"; } diff --git a/ets2panda/checker/types/ts/numberType.h b/ets2panda/checker/types/ts/numberType.h index a30f48609f..eedbc33fe0 100644 --- a/ets2panda/checker/types/ts/numberType.h +++ b/ets2panda/checker/types/ts/numberType.h @@ -23,7 +23,7 @@ class NumberType : public Type { public: NumberType() : Type(TypeFlag::NUMBER) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; TypeFacts GetTypeFacts() const override; diff --git a/ets2panda/checker/types/ts/objectLiteralType.cpp b/ets2panda/checker/types/ts/objectLiteralType.cpp index 407454989d..0bedc56068 100644 --- a/ets2panda/checker/types/ts/objectLiteralType.cpp +++ b/ets2panda/checker/types/ts/objectLiteralType.cpp @@ -22,7 +22,7 @@ namespace panda::es2panda::checker { class TSChecker; -void ObjectLiteralType::ToString(std::stringstream &ss) const +void ObjectLiteralType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "{ "; diff --git a/ets2panda/checker/types/ts/objectLiteralType.h b/ets2panda/checker/types/ts/objectLiteralType.h index e9b5695c1c..85feba1c5c 100644 --- a/ets2panda/checker/types/ts/objectLiteralType.h +++ b/ets2panda/checker/types/ts/objectLiteralType.h @@ -24,7 +24,7 @@ public: explicit ObjectLiteralType(ObjectDescriptor *desc) : ObjectType(ObjectType::ObjectTypeKind::LITERAL, desc) {} ObjectLiteralType() : ObjectType(ObjectType::ObjectTypeKind::LITERAL) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; TypeFacts GetTypeFacts() const override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; }; diff --git a/ets2panda/checker/types/ts/stringLiteralType.cpp b/ets2panda/checker/types/ts/stringLiteralType.cpp index 87f8cea1c1..c5e6c80e2e 100644 --- a/ets2panda/checker/types/ts/stringLiteralType.cpp +++ b/ets2panda/checker/types/ts/stringLiteralType.cpp @@ -16,7 +16,7 @@ #include "stringLiteralType.h" namespace panda::es2panda::checker { -void StringLiteralType::ToString(std::stringstream &ss) const +void StringLiteralType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "\"" << value_ << "\""; } diff --git a/ets2panda/checker/types/ts/stringLiteralType.h b/ets2panda/checker/types/ts/stringLiteralType.h index f18e1cb63b..fbca9751a9 100644 --- a/ets2panda/checker/types/ts/stringLiteralType.h +++ b/ets2panda/checker/types/ts/stringLiteralType.h @@ -28,7 +28,7 @@ public: return value_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void ToStringAsSrc(std::stringstream &ss) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/stringType.cpp b/ets2panda/checker/types/ts/stringType.cpp index 9afedd90b6..e0b4a9182b 100644 --- a/ets2panda/checker/types/ts/stringType.cpp +++ b/ets2panda/checker/types/ts/stringType.cpp @@ -16,7 +16,7 @@ #include "stringType.h" namespace panda::es2panda::checker { -void StringType::ToString(std::stringstream &ss) const +void StringType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "string"; } diff --git a/ets2panda/checker/types/ts/stringType.h b/ets2panda/checker/types/ts/stringType.h index d37ae5b48d..2081adda40 100644 --- a/ets2panda/checker/types/ts/stringType.h +++ b/ets2panda/checker/types/ts/stringType.h @@ -23,7 +23,7 @@ class StringType : public Type { public: StringType() : Type(TypeFlag::STRING) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; TypeFacts GetTypeFacts() const override; diff --git a/ets2panda/checker/types/ts/tupleType.cpp b/ets2panda/checker/types/ts/tupleType.cpp index 9e5de1369e..9efd5ccb67 100644 --- a/ets2panda/checker/types/ts/tupleType.cpp +++ b/ets2panda/checker/types/ts/tupleType.cpp @@ -30,7 +30,7 @@ Type *TupleType::ConvertToArrayType(TSChecker *checker) return checker->Allocator()->New(arrayType); } -void TupleType::ToString(std::stringstream &ss) const +void TupleType::ToString(std::stringstream &ss, bool precise) const { if (readonly_) { ss << "readonly "; @@ -39,7 +39,7 @@ void TupleType::ToString(std::stringstream &ss) const if (namedMembers_.empty()) { for (auto it = desc_->properties.begin(); it != desc_->properties.end(); it++) { - (*it)->TsType()->ToString(ss); + (*it)->TsType()->ToString(ss, precise); if ((*it)->HasFlag(varbinder::VariableFlags::OPTIONAL)) { ss << "?"; } @@ -58,7 +58,7 @@ void TupleType::ToString(std::stringstream &ss) const } ss << ": "; - (*it)->TsType()->ToString(ss); + (*it)->TsType()->ToString(ss, precise); if (std::next(it) != desc_->properties.end()) { ss << ", "; } diff --git a/ets2panda/checker/types/ts/tupleType.h b/ets2panda/checker/types/ts/tupleType.h index 53fc5c47fc..b638dce06e 100644 --- a/ets2panda/checker/types/ts/tupleType.h +++ b/ets2panda/checker/types/ts/tupleType.h @@ -87,7 +87,7 @@ public: Type *ConvertToArrayType(TSChecker *checker); - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; TypeFacts GetTypeFacts() const override; diff --git a/ets2panda/checker/types/ts/typeParameter.cpp b/ets2panda/checker/types/ts/typeParameter.cpp index 516b284db4..fb297bfbf3 100644 --- a/ets2panda/checker/types/ts/typeParameter.cpp +++ b/ets2panda/checker/types/ts/typeParameter.cpp @@ -16,7 +16,7 @@ #include "typeParameter.h" namespace panda::es2panda::checker { -void TypeParameter::ToString([[maybe_unused]] std::stringstream &ss) const +void TypeParameter::ToString([[maybe_unused]] std::stringstream &ss, [[maybe_unused]] bool precise) const { UNREACHABLE(); } diff --git a/ets2panda/checker/types/ts/typeParameter.h b/ets2panda/checker/types/ts/typeParameter.h index bcc320265a..3de782e2c1 100644 --- a/ets2panda/checker/types/ts/typeParameter.h +++ b/ets2panda/checker/types/ts/typeParameter.h @@ -46,7 +46,7 @@ public: default_ = type; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; TypeFacts GetTypeFacts() const override; diff --git a/ets2panda/checker/types/ts/typeReference.cpp b/ets2panda/checker/types/ts/typeReference.cpp index 579f22f383..4ec359bb58 100644 --- a/ets2panda/checker/types/ts/typeReference.cpp +++ b/ets2panda/checker/types/ts/typeReference.cpp @@ -16,10 +16,10 @@ #include "typeReference.h" namespace panda::es2panda::checker { -void TypeReference::ToString(std::stringstream &ss) const +void TypeReference::ToString(std::stringstream &ss, bool precise) const { if (*ref_ != nullptr) { - (*ref_)->ToString(ss); + (*ref_)->ToString(ss, precise); } } diff --git a/ets2panda/checker/types/ts/typeReference.h b/ets2panda/checker/types/ts/typeReference.h index 2b4f33fc18..4e3022e7a4 100644 --- a/ets2panda/checker/types/ts/typeReference.h +++ b/ets2panda/checker/types/ts/typeReference.h @@ -33,7 +33,7 @@ public: return *ref_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; TypeFacts GetTypeFacts() const override; diff --git a/ets2panda/checker/types/ts/undefinedType.cpp b/ets2panda/checker/types/ts/undefinedType.cpp index 5e7f6aeae3..72e47c96e7 100644 --- a/ets2panda/checker/types/ts/undefinedType.cpp +++ b/ets2panda/checker/types/ts/undefinedType.cpp @@ -16,7 +16,7 @@ #include "undefinedType.h" namespace panda::es2panda::checker { -void UndefinedType::ToString(std::stringstream &ss) const +void UndefinedType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "undefined"; } diff --git a/ets2panda/checker/types/ts/undefinedType.h b/ets2panda/checker/types/ts/undefinedType.h index 79fbceeb63..93a0db73c9 100644 --- a/ets2panda/checker/types/ts/undefinedType.h +++ b/ets2panda/checker/types/ts/undefinedType.h @@ -23,7 +23,7 @@ class UndefinedType : public Type { public: UndefinedType() : Type(TypeFlag::UNDEFINED) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; bool AssignmentSource(TypeRelation *relation, Type *target) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/unionType.cpp b/ets2panda/checker/types/ts/unionType.cpp index 1d3f7e92f1..352436e9cf 100644 --- a/ets2panda/checker/types/ts/unionType.cpp +++ b/ets2panda/checker/types/ts/unionType.cpp @@ -19,10 +19,10 @@ #include "checker/types/globalTypesHolder.h" namespace panda::es2panda::checker { -void UnionType::ToString(std::stringstream &ss) const +void UnionType::ToString(std::stringstream &ss, bool precise) const { for (auto it = constituentTypes_.begin(); it != constituentTypes_.end(); it++) { - (*it)->ToString(ss); + (*it)->ToString(ss, precise); if (std::next(it) != constituentTypes_.end()) { ss << " | "; } diff --git a/ets2panda/checker/types/ts/unionType.h b/ets2panda/checker/types/ts/unionType.h index 95d81fc732..93ea3ced44 100644 --- a/ets2panda/checker/types/ts/unionType.h +++ b/ets2panda/checker/types/ts/unionType.h @@ -114,7 +114,7 @@ public: mergedObjectType_ = type; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; bool AssignmentSource(TypeRelation *relation, Type *target) override; diff --git a/ets2panda/checker/types/ts/unknownType.cpp b/ets2panda/checker/types/ts/unknownType.cpp index 554a3b8e0e..e3f0af57c5 100644 --- a/ets2panda/checker/types/ts/unknownType.cpp +++ b/ets2panda/checker/types/ts/unknownType.cpp @@ -16,7 +16,7 @@ #include "unknownType.h" namespace panda::es2panda::checker { -void UnknownType::ToString(std::stringstream &ss) const +void UnknownType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "unknown"; } diff --git a/ets2panda/checker/types/ts/unknownType.h b/ets2panda/checker/types/ts/unknownType.h index d1cb778f35..5a762dbe7f 100644 --- a/ets2panda/checker/types/ts/unknownType.h +++ b/ets2panda/checker/types/ts/unknownType.h @@ -23,7 +23,7 @@ class UnknownType : public Type { public: UnknownType() : Type(TypeFlag::UNKNOWN) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; TypeFacts GetTypeFacts() const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/voidType.cpp b/ets2panda/checker/types/ts/voidType.cpp index cb2b2fe403..edab990222 100644 --- a/ets2panda/checker/types/ts/voidType.cpp +++ b/ets2panda/checker/types/ts/voidType.cpp @@ -16,7 +16,7 @@ #include "voidType.h" namespace panda::es2panda::checker { -void VoidType::ToString(std::stringstream &ss) const +void VoidType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "void"; } diff --git a/ets2panda/checker/types/ts/voidType.h b/ets2panda/checker/types/ts/voidType.h index 47a5ceb807..e7b1b39b49 100644 --- a/ets2panda/checker/types/ts/voidType.h +++ b/ets2panda/checker/types/ts/voidType.h @@ -23,7 +23,7 @@ class VoidType : public Type { public: VoidType() : Type(TypeFlag::VOID) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; TypeFacts GetTypeFacts() const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/type.cpp b/ets2panda/checker/types/type.cpp index 81affaf07a..ddf5db1e18 100644 --- a/ets2panda/checker/types/type.cpp +++ b/ets2panda/checker/types/type.cpp @@ -83,11 +83,37 @@ bool Type::IsLambdaObject() const return false; } +void Type::ToString(std::stringstream &ss) const +{ + ToString(ss, false); +} + void Type::ToStringAsSrc(std::stringstream &ss) const { ToString(ss); } +std::string Type::ToString() const +{ + std::stringstream ss; + ToString(ss); + return ss.str(); +} + +std::string Type::ToStringAsSrc() const +{ + std::stringstream ss; + ToStringAsSrc(ss); + return ss.str(); +} + +std::string Type::ToStringPrecise() const +{ + std::stringstream ss; + ToString(ss, true); + return ss.str(); +} + void Type::Identical(TypeRelation *relation, Type *other) { relation->Result(typeFlags_ == other->TypeFlags()); @@ -140,4 +166,5 @@ Type *Type::Substitute([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] { return this; } + } // namespace panda::es2panda::checker diff --git a/ets2panda/checker/types/type.h b/ets2panda/checker/types/type.h index 455ec1e227..446da59ccb 100644 --- a/ets2panda/checker/types/type.h +++ b/ets2panda/checker/types/type.h @@ -224,8 +224,13 @@ public: } bool IsLambdaObject() const; - virtual void ToString(std::stringstream &ss) const = 0; + virtual void ToString(std::stringstream &ss, bool precise) const = 0; + void ToString(std::stringstream &ss) const; + std::string ToString() const; + std::string ToStringPrecise() const; virtual void ToStringAsSrc(std::stringstream &ss) const; + std::string ToStringAsSrc() const; + virtual TypeFacts GetTypeFacts() const; virtual void ToAssemblerType([[maybe_unused]] std::stringstream &ss) const {}; virtual void ToDebugInfoType([[maybe_unused]] std::stringstream &ss) const {}; diff --git a/ets2panda/checker/types/typeFlag.h b/ets2panda/checker/types/typeFlag.h index e4a973560d..821b89da24 100644 --- a/ets2panda/checker/types/typeFlag.h +++ b/ets2panda/checker/types/typeFlag.h @@ -129,7 +129,7 @@ enum class TypeFlag : uint64_t { VALID_ARITHMETIC_TYPE = ANY | NUMBER_LIKE | BIGINT_LIKE | ENUM, UNIT = LITERAL | UNIQUE_SYMBOL | NULLISH, GETTER_SETTER = GETTER | SETTER, - CONDITION_EXPRESSION_TYPE = NULLISH | CONSTANT | ETS_OBJECT | BYTE | SHORT | INT | LONG | FLOAT | DOUBLE | + CONDITION_EXPRESSION_TYPE = NULLISH | CONSTANT | ETS_OBJECT | BYTE | CHAR | SHORT | INT | LONG | FLOAT | DOUBLE | ETS_BOOLEAN | ETS_ARRAY | ETS_ENUM | ETS_STRING_ENUM }; diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index fd2476ce94..bd6143b251 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -15,8 +15,9 @@ #include "ETSCompiler.h" -#include "checker/types/ets/etsDynamicFunctionType.h" #include "compiler/base/catchTable.h" +#include "checker/types/ets/etsDynamicFunctionType.h" +#include "checker/types/ets/etsObjectType.h" #include "checker/types/ts/enumLiteralType.h" #include "compiler/base/condition.h" #include "compiler/base/lreference.h" @@ -328,9 +329,7 @@ void ETSCompiler::Compile(const ir::ETSNewClassInstanceExpression *expr) const etsg->InitObject(expr, expr->signature_, expr->GetArguments()); } - if (expr->GetBoxingUnboxingFlags() == ir::BoxingUnboxingFlags::NONE) { - etsg->SetAccumulatorType(expr->TsType()); - } + etsg->SetAccumulatorType(expr->TsType()); } void ETSCompiler::Compile(const ir::ETSNewMultiDimArrayInstanceExpression *expr) const @@ -659,11 +658,12 @@ void ETSCompiler::Compile(const ir::BinaryExpression *expr) const etsg->Binary(expr, expr->OperatorType(), lhs); } -static void ConvertRestArguments(checker::ETSChecker *const checker, const ir::CallExpression *expr) +static void ConvertRestArguments(checker::ETSChecker *const checker, const ir::CallExpression *expr, + checker::Signature *signature) { - if (expr->Signature()->RestVar() != nullptr) { + if (signature->RestVar() != nullptr) { std::size_t const argumentCount = expr->Arguments().size(); - std::size_t const parameterCount = expr->Signature()->MinArgCount(); + std::size_t const parameterCount = signature->MinArgCount(); ASSERT(argumentCount >= parameterCount); auto &arguments = const_cast &>(expr->Arguments()); @@ -678,13 +678,37 @@ static void ConvertRestArguments(checker::ETSChecker *const checker, const ir::C } auto *arrayExpression = checker->AllocNode(std::move(elements), checker->Allocator()); arrayExpression->SetParent(const_cast(expr)); - arrayExpression->SetTsType(expr->Signature()->RestVar()->TsType()); + arrayExpression->SetTsType(signature->RestVar()->TsType()); arguments.erase(expr->Arguments().begin() + parameterCount, expr->Arguments().end()); arguments.emplace_back(arrayExpression); } } } +void ConvertArgumentsForFunctionalCall(checker::ETSChecker *const checker, const ir::CallExpression *expr) +{ + std::size_t const argumentCount = expr->Arguments().size(); + auto &arguments = const_cast &>(expr->Arguments()); + auto *signature = expr->Signature(); + + for (size_t i = 0; i < argumentCount; i++) { + auto *paramType = checker->MaybeBoxedType( + i < signature->Params().size() ? signature->Params()[i] : signature->RestVar(), checker->Allocator()); + + auto *arg = arguments[i]; + auto *cast = checker->Allocator()->New(arg, nullptr, false); + arguments[i]->SetParent(cast); + cast->SetParent(const_cast(expr)); + cast->SetTsType(paramType); + + if (paramType->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + cast->AddBoxingUnboxingFlags(checker->GetBoxingFlag(paramType)); + } + + arguments[i] = cast; + } +} + void ETSCompiler::Compile(const ir::BlockExpression *expr) const { (void)expr; @@ -787,13 +811,15 @@ void ETSCompiler::CompileDynamic(const ir::CallExpression *expr, compiler::VReg etsg->StoreAccumulator(expr, dynParam2); etsg->CallDynamic(expr, calleeReg, dynParam2, expr->Signature(), expr->Arguments()); etsg->SetAccumulatorType(expr->Signature()->ReturnType()); + if (etsg->GetAccumulatorType() != expr->TsType()) { etsg->ApplyConversion(expr, expr->TsType()); } } // Helper function to avoid branching in non optional cases -void ETSCompiler::EmitCall(const ir::CallExpression *expr, compiler::VReg &calleeReg, bool isStatic) const +void ETSCompiler::EmitCall(const ir::CallExpression *expr, compiler::VReg &calleeReg, bool isStatic, + checker::Signature *signature, bool isReference) const { ETSGen *etsg = GetETSGen(); if (expr->Callee()->GetBoxingUnboxingFlags() != ir::BoxingUnboxingFlags::NONE) { @@ -804,14 +830,42 @@ void ETSCompiler::EmitCall(const ir::CallExpression *expr, compiler::VReg &calle } else if (expr->Signature()->HasSignatureFlag(checker::SignatureFlags::PRIVATE) || expr->IsETSConstructorCall() || (expr->Callee()->IsMemberExpression() && expr->Callee()->AsMemberExpression()->Object()->IsSuperExpression())) { - etsg->CallThisStatic(expr, calleeReg, expr->Signature(), expr->Arguments()); + etsg->CallThisStatic(expr, calleeReg, signature, expr->Arguments()); + } else { + etsg->CallThisVirtual(expr, calleeReg, signature, expr->Arguments()); + } + + if (isReference) { + etsg->CheckedReferenceNarrowing(expr, signature->ReturnType()); } else { - etsg->CallThisVirtual(expr, calleeReg, expr->Signature(), expr->Arguments()); + etsg->SetAccumulatorType(signature->ReturnType()); } etsg->GuardUncheckedType(expr, expr->UncheckedType(), expr->OptionalType()); } +static checker::Signature *ConvertArgumentsForFunctionReference(ETSGen *etsg, const ir::CallExpression *expr) +{ + checker::Signature *origSignature = expr->Signature(); + + auto *funcType = + origSignature->Owner() + ->GetOwnProperty(checker::FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME) + ->TsType() + ->AsETSFunctionType(); + ASSERT(funcType->CallSignatures().size() == 1); + checker::Signature *signature = funcType->CallSignatures()[0]; + + if (signature->ReturnType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + expr->AddBoxingUnboxingFlags(const_cast(etsg->Checker()->AsETSChecker()) + ->GetUnboxingFlag(signature->ReturnType())); + } + + ConvertArgumentsForFunctionalCall(const_cast(etsg->Checker()->AsETSChecker()), expr); + + return signature; +} + void ETSCompiler::Compile(const ir::CallExpression *expr) const { ETSGen *etsg = GetETSGen(); @@ -829,7 +883,12 @@ void ETSCompiler::Compile(const ir::CallExpression *expr) const bool isReference = expr->Signature()->HasSignatureFlag(checker::SignatureFlags::TYPE); bool isDynamic = expr->Callee()->TsType()->HasTypeFlag(checker::TypeFlag::ETS_DYNAMIC_FLAG); - ConvertRestArguments(const_cast(etsg->Checker()->AsETSChecker()), expr); + checker::Signature *signature = expr->Signature(); + if (isReference) { + signature = ConvertArgumentsForFunctionReference(etsg, expr); + } + + ConvertRestArguments(const_cast(etsg->Checker()->AsETSChecker()), expr, signature); if (isDynamic) { CompileDynamic(expr, calleeReg); @@ -838,24 +897,27 @@ void ETSCompiler::Compile(const ir::CallExpression *expr) const etsg->LoadThis(expr); etsg->StoreAccumulator(expr, calleeReg); } - EmitCall(expr, calleeReg, isStatic); + EmitCall(expr, calleeReg, isStatic, signature, isReference); } else if (!isReference && expr->Callee()->IsMemberExpression()) { if (!isStatic) { expr->Callee()->AsMemberExpression()->Object()->Compile(etsg); etsg->StoreAccumulator(expr, calleeReg); } - EmitCall(expr, calleeReg, isStatic); + EmitCall(expr, calleeReg, isStatic, signature, isReference); } else if (expr->Callee()->IsSuperExpression() || expr->Callee()->IsThisExpression()) { ASSERT(!isReference && expr->IsETSConstructorCall()); expr->Callee()->Compile(etsg); // ctor is not a value! etsg->SetVRegType(calleeReg, etsg->GetAccumulatorType()); - EmitCall(expr, calleeReg, isStatic); + EmitCall(expr, calleeReg, isStatic, signature, isReference); } else { ASSERT(isReference); etsg->CompileAndCheck(expr->Callee()); etsg->StoreAccumulator(expr, calleeReg); etsg->EmitMaybeOptional( - expr, [this, expr, isStatic, &calleeReg]() { this->EmitCall(expr, calleeReg, isStatic); }, + expr, + [this, expr, isStatic, &calleeReg, signature, isReference]() { + this->EmitCall(expr, calleeReg, isStatic, signature, isReference); + }, expr->IsOptional()); } } diff --git a/ets2panda/compiler/core/ETSCompiler.h b/ets2panda/compiler/core/ETSCompiler.h index 5421dde41f..4e0e04dbd3 100644 --- a/ets2panda/compiler/core/ETSCompiler.h +++ b/ets2panda/compiler/core/ETSCompiler.h @@ -38,7 +38,8 @@ private: void CompileDynamic(const ir::CallExpression *expr, compiler::VReg &calleeReg) const; void CompileCastUnboxable(const ir::TSAsExpression *expr) const; void CompileCast(const ir::TSAsExpression *expr) const; - void EmitCall(const ir::CallExpression *expr, compiler::VReg &calleeReg, bool isStatic) const; + void EmitCall(const ir::CallExpression *expr, compiler::VReg &calleeReg, bool isStatic, + checker::Signature *signature, bool isReference) const; ETSGen *GetETSGen() const; }; diff --git a/ets2panda/compiler/core/ETSGen.cpp b/ets2panda/compiler/core/ETSGen.cpp index 9274234954..c771dc9d13 100644 --- a/ets2panda/compiler/core/ETSGen.cpp +++ b/ets2panda/compiler/core/ETSGen.cpp @@ -1753,10 +1753,6 @@ void ETSGen::CastToDynamic(const ir::AstNode *node, const checker::ETSDynamicTyp methodName = compiler::Signatures::Dynamic::NewStringBuiltin(type->Language()); break; } - if (GetAccumulatorType()->IsLambdaObject()) { - methodName = Signatures::BUILTIN_JSRUNTIME_CREATE_LAMBDA_PROXY; - break; - } [[fallthrough]]; } case checker::TypeFlag::ETS_ARRAY: { @@ -2020,6 +2016,8 @@ void ETSGen::Condition(const ir::AstNode *node, lexer::TokenType op, VReg lhs, L void ETSGen::BranchIfNullish([[maybe_unused]] const ir::AstNode *node, [[maybe_unused]] Label *ifNullish) { #ifdef PANDA_WITH_ETS + RegScope rs(this); + auto *const type = GetAccumulatorType(); if (!Checker()->MayHaveNulllikeValue(type)) { @@ -2056,6 +2054,8 @@ void ETSGen::BranchIfNullish([[maybe_unused]] const ir::AstNode *node, [[maybe_u void ETSGen::BranchIfNotNullish([[maybe_unused]] const ir::AstNode *node, [[maybe_unused]] Label *ifNotNullish) { #ifdef PANDA_WITH_ETS + RegScope rs(this); + auto *const type = GetAccumulatorType(); if (!Checker()->MayHaveNulllikeValue(type)) { @@ -2117,6 +2117,7 @@ void ETSGen::EmitNullishGuardian(const ir::AstNode *node) void ETSGen::EmitNullishException(const ir::AstNode *node) { + RegScope ra(this); VReg exception = StoreException(node); NewObject(node, exception, Signatures::BUILTIN_NULLPOINTER_EXCEPTION); CallThisStatic0(node, exception, Signatures::BUILTIN_NULLPOINTER_EXCEPTION_CTOR); diff --git a/ets2panda/compiler/core/ETSGen.h b/ets2panda/compiler/core/ETSGen.h index b1c5907351..eddd5851d0 100644 --- a/ets2panda/compiler/core/ETSGen.h +++ b/ets2panda/compiler/core/ETSGen.h @@ -213,8 +213,7 @@ public: template void ResolveConditionalResult(const ir::AstNode *node, [[maybe_unused]] Label *ifFalse) { - auto type = node->IsExpression() && !node->AsExpression()->IsUnaryExpression() ? node->AsExpression()->TsType() - : GetAccumulatorType(); + auto type = GetAccumulatorType(); if (type->IsETSBooleanType()) { return; } @@ -233,11 +232,7 @@ public: BranchIfNullish(node, ifNullish); } } - if (type->IsETSArrayType()) { - compiler::VReg objReg = AllocReg(); - StoreAccumulator(node, objReg); - LoadArrayLength(node, objReg); - } else if (type->IsETSObjectType()) { + if (type->IsETSArrayType() || type->IsETSObjectType() || type->IsETSUnionType()) { ResolveConditionalResultObject(node); } else { ResolveConditionalResultNumeric(node, ifFalse, &end); @@ -937,7 +932,7 @@ private: arguments[idx]->Compile(this); \ VReg arg##idx = AllocReg(); \ ApplyConversion(arguments[idx], nullptr); \ - ApplyConversionAndStoreAccumulator(arguments[idx], arg##idx, paramType##idx); + ApplyConversionAndStoreAccumulator(arguments[idx], arg##idx, paramType##idx) template void CallThisImpl(const ir::AstNode *const node, const VReg ctor, checker::Signature *const signature, @@ -970,11 +965,8 @@ private: break; } default: { - for (const auto *arg : arguments) { - auto ttctx = TargetTypeContext(this, arg->TsType()); - VReg argReg = AllocReg(); - arg->Compile(this); - StoreAccumulator(node, argReg); + for (size_t idx = 0; idx < arguments.size(); idx++) { + COMPILE_ARG(idx); } Rra().Emit(node, ctor, arguments.size() + 1, name, ctor); @@ -1078,11 +1070,8 @@ private: default: { VReg argStart = NextReg(); - for (const auto *arg : arguments) { - auto ttctx = TargetTypeContext(this, arg->TsType()); - VReg argReg = AllocReg(); - arg->Compile(this); - StoreAccumulator(node, argReg); + for (size_t idx = 0; idx < arguments.size(); idx++) { + COMPILE_ARG(idx); } Rra().Emit(node, argStart, arguments.size(), name, argStart); @@ -1100,7 +1089,7 @@ private: auto ttctx##idx = TargetTypeContext(this, paramType##idx); \ VReg arg##idx = AllocReg(); \ arguments[idx]->Compile(this); \ - ApplyConversionAndStoreAccumulator(arguments[idx], arg##idx, paramType##idx); + ApplyConversionAndStoreAccumulator(arguments[idx], arg##idx, paramType##idx) template void CallDynamicImpl(const ir::AstNode *node, VReg &obj, VReg ¶m2, checker::Signature *signature, diff --git a/ets2panda/compiler/scripts/signatures.yaml b/ets2panda/compiler/scripts/signatures.yaml index c079795062..a4b5949abc 100644 --- a/ets2panda/compiler/scripts/signatures.yaml +++ b/ets2panda/compiler/scripts/signatures.yaml @@ -296,6 +296,60 @@ builtins: - name: DoubleBox package: PKG_STD_CORE ref: BUILTIN_DOUBLE_BOX + - name: Function0 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION0 + - name: Function1 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION1 + - name: Function2 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION2 + - name: Function3 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION3 + - name: Function4 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION4 + - name: Function5 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION5 + - name: Function6 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION6 + - name: Function7 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION7 + - name: Function8 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION8 + - name: Function9 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION9 + - name: Function10 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION10 + - name: Function11 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION11 + - name: Function12 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION12 + - name: Function13 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION13 + - name: Function14 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION14 + - name: Function15 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION15 + - name: Function16 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION16 + - name: FunctionN + package: PKG_STD_CORE + ref: BUILTIN_FUNCTIONN signatures: - callee: BUILTIN_OBJECT @@ -1030,12 +1084,6 @@ signatures: return_type: BUILTIN_VOID ref: BUILTIN_JSRUNTIME_INIT_DYNAMIC_NEW_CLASS - - callee: BUILTIN_JSRUNTIME - method_name: __createLambdaProxy - params: [BUILTIN_OBJECT] - return_type: BUILTIN_JSVALUE - ref: BUILTIN_JSRUNTIME_CREATE_LAMBDA_PROXY - - callee: BUILTIN_JSRUNTIME method_name: loadModule params: [BUILTIN_STRING] diff --git a/ets2panda/ir/ets/etsFunctionType.h b/ets2panda/ir/ets/etsFunctionType.h index 42f7323db5..a3245e053f 100644 --- a/ets2panda/ir/ets/etsFunctionType.h +++ b/ets2panda/ir/ets/etsFunctionType.h @@ -93,6 +93,11 @@ public: return (funcFlags_ & ir::ScriptFunctionFlags::THROWS) != 0; } + bool IsRethrowing() const + { + return (funcFlags_ & ir::ScriptFunctionFlags::RETHROWS) != 0; + } + void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; diff --git a/ets2panda/ir/ts/tsAsExpression.h b/ets2panda/ir/ts/tsAsExpression.h index ba4903adab..1fa6865140 100644 --- a/ets2panda/ir/ts/tsAsExpression.h +++ b/ets2panda/ir/ts/tsAsExpression.h @@ -49,6 +49,11 @@ public: return isConst_; } + void SetUncheckedCast(bool isUncheckedCast) + { + isUncheckedCast_ = isUncheckedCast; + } + void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; diff --git a/ets2panda/test/compiler/ets/FunctionType1-expected.txt b/ets2panda/test/compiler/ets/FunctionType1-expected.txt index eb64020f40..a62c8dd85d 100644 --- a/ets2panda/test/compiler/ets/FunctionType1-expected.txt +++ b/ets2panda/test/compiler/ets/FunctionType1-expected.txt @@ -1001,4 +1001,4 @@ } } } -TypeError: Type '(a: int, b: int) => int' cannot be assigned to type '(a: int, b: int) => void' [FunctionType1.ets:24:12] +TypeError: Type '(a: int, b: int) => int' cannot be assigned to type '(p1: Int, p2: Int) => void' [FunctionType1.ets:24:12] diff --git a/ets2panda/test/compiler/ets/FunctionType3-expected.txt b/ets2panda/test/compiler/ets/FunctionType3-expected.txt index bbb4c6e27b..0d0d88e229 100644 --- a/ets2panda/test/compiler/ets/FunctionType3-expected.txt +++ b/ets2panda/test/compiler/ets/FunctionType3-expected.txt @@ -809,4 +809,4 @@ } } } -TypeError: Type 'string' is not compatible with type 'int' at index 2 [FunctionType3.ets:23:16] +TypeError: Type 'string' is not compatible with type 'Int' at index 2 [FunctionType3.ets:23:16] diff --git a/ets2panda/test/compiler/ets/etsObjectToString4-expected.txt b/ets2panda/test/compiler/ets/etsObjectToString4-expected.txt index a92c603283..37dcab16ae 100644 --- a/ets2panda/test/compiler/ets/etsObjectToString4-expected.txt +++ b/ets2panda/test/compiler/ets/etsObjectToString4-expected.txt @@ -465,4 +465,4 @@ } } } -TypeError: Type 'int' cannot be assigned to type '() => int' [etsObjectToString4.ets:18:29] +TypeError: Type 'int' cannot be assigned to type '() => Int' [etsObjectToString4.ets:18:29] diff --git a/ets2panda/test/compiler/ets/etsObjectToString5-expected.txt b/ets2panda/test/compiler/ets/etsObjectToString5-expected.txt index c96da27d61..dbdd0fed4e 100644 --- a/ets2panda/test/compiler/ets/etsObjectToString5-expected.txt +++ b/ets2panda/test/compiler/ets/etsObjectToString5-expected.txt @@ -845,4 +845,4 @@ } } } -TypeError: Type '(y: A) => A|null' cannot be assigned to type '(y: A) => A|null' [etsObjectToString5.ets:18:42] +TypeError: Type '(y: A) => A|null' cannot be assigned to type '(p1: A) => A|null' [etsObjectToString5.ets:18:42] diff --git a/ets2panda/test/compiler/ets/function_subtyping_1-expected.txt b/ets2panda/test/compiler/ets/function_subtyping_1-expected.txt new file mode 100644 index 0000000000..ca68775f5e --- /dev/null +++ b/ets2panda/test/compiler/ets/function_subtyping_1-expected.txt @@ -0,0 +1,997 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSFunctionType", + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "p", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 13 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 13 + }, + "end": { + "line": 20, + "column": 18 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 12 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 10 + } + } + }, + "init": { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "p", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 27 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 27 + }, + "end": { + "line": 20, + "column": 32 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 34 + }, + "end": { + "line": 20, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 34 + }, + "end": { + "line": 20, + "column": 38 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 34 + }, + "end": { + "line": 20, + "column": 38 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 52 + }, + "end": { + "line": 20, + "column": 53 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 52 + }, + "end": { + "line": 20, + "column": 54 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 52 + }, + "end": { + "line": 20, + "column": 54 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 20, + "column": 48 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 41 + }, + "end": { + "line": 20, + "column": 57 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 39 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 26 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 26 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 57 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 57 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 21, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 21, + "column": 2 + } + } +} diff --git a/ets2panda/test/compiler/ets/function_subtyping_1.ets b/ets2panda/test/compiler/ets/function_subtyping_1.ets new file mode 100644 index 0000000000..0b2ffc867e --- /dev/null +++ b/ets2panda/test/compiler/ets/function_subtyping_1.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 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 {} +class B extends A {} + +function main(): void { + let x: (p: B) => A = (p: A): B => { return new B() } +} \ No newline at end of file diff --git a/ets2panda/test/compiler/ets/function_subtyping_2-expected.txt b/ets2panda/test/compiler/ets/function_subtyping_2-expected.txt new file mode 100644 index 0000000000..b49902e036 --- /dev/null +++ b/ets2panda/test/compiler/ets/function_subtyping_2-expected.txt @@ -0,0 +1,998 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSFunctionType", + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "p", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 13 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 13 + }, + "end": { + "line": 20, + "column": 18 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 12 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 10 + } + } + }, + "init": { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "p", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 27 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 27 + }, + "end": { + "line": 20, + "column": 32 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 34 + }, + "end": { + "line": 20, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 34 + }, + "end": { + "line": 20, + "column": 38 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 34 + }, + "end": { + "line": 20, + "column": 38 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 52 + }, + "end": { + "line": 20, + "column": 53 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 52 + }, + "end": { + "line": 20, + "column": 54 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 52 + }, + "end": { + "line": 20, + "column": 54 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 20, + "column": 48 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 41 + }, + "end": { + "line": 20, + "column": 57 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 39 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 26 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 26 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 57 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 57 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 21, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 21, + "column": 2 + } + } +} +TypeError: Type '(p: A) => A' cannot be assigned to type '(p1: B) => B' [function_subtyping_2.ets:20:26] diff --git a/ets2panda/test/compiler/ets/function_subtyping_2.ets b/ets2panda/test/compiler/ets/function_subtyping_2.ets new file mode 100644 index 0000000000..64860a92b8 --- /dev/null +++ b/ets2panda/test/compiler/ets/function_subtyping_2.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 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 {} +class B extends A {} + +function main(): void { + let x: (p: B) => B = (p: A): A => { return new B() } +} \ No newline at end of file diff --git a/ets2panda/test/compiler/ets/function_subtyping_3-expected.txt b/ets2panda/test/compiler/ets/function_subtyping_3-expected.txt new file mode 100644 index 0000000000..55e50a03bc --- /dev/null +++ b/ets2panda/test/compiler/ets/function_subtyping_3-expected.txt @@ -0,0 +1,998 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSFunctionType", + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "p", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 13 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 13 + }, + "end": { + "line": 20, + "column": 18 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 12 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 10 + } + } + }, + "init": { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "p", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 27 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 27 + }, + "end": { + "line": 20, + "column": 32 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 34 + }, + "end": { + "line": 20, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 34 + }, + "end": { + "line": 20, + "column": 38 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 34 + }, + "end": { + "line": 20, + "column": 38 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 52 + }, + "end": { + "line": 20, + "column": 53 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 52 + }, + "end": { + "line": 20, + "column": 54 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 52 + }, + "end": { + "line": 20, + "column": 54 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 20, + "column": 48 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 41 + }, + "end": { + "line": 20, + "column": 57 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 39 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 26 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 26 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 57 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 57 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 21, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 21, + "column": 2 + } + } +} +TypeError: Type '(p: B) => B' cannot be assigned to type '(p1: A) => A' [function_subtyping_3.ets:20:26] diff --git a/ets2panda/test/compiler/ets/function_subtyping_3.ets b/ets2panda/test/compiler/ets/function_subtyping_3.ets new file mode 100644 index 0000000000..4e57a855ae --- /dev/null +++ b/ets2panda/test/compiler/ets/function_subtyping_3.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 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 {} +class B extends A {} + +function main(): void { + let x: (p: A) => A = (p: B): B => { return new B() } +} \ No newline at end of file diff --git a/ets2panda/test/compiler/ets/generic_variance_1-expected.txt b/ets2panda/test/compiler/ets/generic_variance_1-expected.txt new file mode 100644 index 0000000000..abef87ab4c --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_1-expected.txt @@ -0,0 +1,1973 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "in": true, + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 15 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 16 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 7 + }, + "end": { + "line": 20, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 14 + }, + "end": { + "line": 20, + "column": 15 + } + } + }, + "out": true, + "loc": { + "start": { + "line": 20, + "column": 10 + }, + "end": { + "line": 20, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 16 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 19 + }, + "end": { + "line": 20, + "column": 19 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 10 + }, + "end": { + "line": 22, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 10 + }, + "end": { + "line": 22, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x1", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 15 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 15 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 11 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 27 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 27 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 23, + "column": 21 + }, + "end": { + "line": 24, + "column": 8 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 24, + "column": 8 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 24, + "column": 8 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x2", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 13 + }, + "end": { + "line": 24, + "column": 15 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 16 + }, + "end": { + "line": 24, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 16 + }, + "end": { + "line": 24, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 16 + }, + "end": { + "line": 24, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 24, + "column": 15 + }, + "end": { + "line": 24, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 13 + }, + "end": { + "line": 24, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 13 + }, + "end": { + "line": 24, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 24, + "column": 11 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 25 + }, + "end": { + "line": 24, + "column": 27 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 28 + }, + "end": { + "line": 24, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 28 + }, + "end": { + "line": 24, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 28 + }, + "end": { + "line": 24, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 24, + "column": 27 + }, + "end": { + "line": 24, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 25 + }, + "end": { + "line": 24, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 25 + }, + "end": { + "line": 24, + "column": 31 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 24, + "column": 21 + }, + "end": { + "line": 26, + "column": 8 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 26, + "column": 8 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 24, + "column": 5 + }, + "end": { + "line": 26, + "column": 8 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x3", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 13 + }, + "end": { + "line": 26, + "column": 15 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 16 + }, + "end": { + "line": 26, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 16 + }, + "end": { + "line": 26, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 16 + }, + "end": { + "line": 26, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 26, + "column": 15 + }, + "end": { + "line": 26, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 13 + }, + "end": { + "line": 26, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 13 + }, + "end": { + "line": 26, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 9 + }, + "end": { + "line": 26, + "column": 11 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 25 + }, + "end": { + "line": 26, + "column": 27 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 28 + }, + "end": { + "line": 26, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 28 + }, + "end": { + "line": 26, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 28 + }, + "end": { + "line": 26, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 26, + "column": 27 + }, + "end": { + "line": 26, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 25 + }, + "end": { + "line": 26, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 25 + }, + "end": { + "line": 26, + "column": 31 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 26, + "column": 21 + }, + "end": { + "line": 27, + "column": 8 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 9 + }, + "end": { + "line": 27, + "column": 8 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 27, + "column": 8 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x4", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 13 + }, + "end": { + "line": 27, + "column": 15 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 16 + }, + "end": { + "line": 27, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 16 + }, + "end": { + "line": 27, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 16 + }, + "end": { + "line": 27, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 27, + "column": 15 + }, + "end": { + "line": 27, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 13 + }, + "end": { + "line": 27, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 13 + }, + "end": { + "line": 27, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 9 + }, + "end": { + "line": 27, + "column": 11 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 25 + }, + "end": { + "line": 27, + "column": 27 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 28 + }, + "end": { + "line": 27, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 28 + }, + "end": { + "line": 27, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 28 + }, + "end": { + "line": 27, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 27, + "column": 27 + }, + "end": { + "line": 27, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 25 + }, + "end": { + "line": 27, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 25 + }, + "end": { + "line": 27, + "column": 31 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 27, + "column": 21 + }, + "end": { + "line": 28, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 9 + }, + "end": { + "line": 28, + "column": 2 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 27, + "column": 5 + }, + "end": { + "line": 28, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 23 + }, + "end": { + "line": 28, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 28, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 28, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 28, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 28, + "column": 2 + } + } +} diff --git a/ets2panda/test/compiler/ets/generic_variance_1.ets b/ets2panda/test/compiler/ets/generic_variance_1.ets new file mode 100644 index 0000000000..dee382251f --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_1.ets @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 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 {} +class B extends A {} + +class A1 {} +class A2 {} + +function main(): void { + let x1: A1 = new A1() + let x2: A1 = new A1() + + let x3: A2 = new A2() + let x4: A2 = new A2() +} \ No newline at end of file diff --git a/ets2panda/test/compiler/ets/generic_variance_2-expected.txt b/ets2panda/test/compiler/ets/generic_variance_2-expected.txt new file mode 100644 index 0000000000..227f565f38 --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_2-expected.txt @@ -0,0 +1,1218 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "in": true, + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 15 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 16 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 7 + }, + "end": { + "line": 20, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 14 + }, + "end": { + "line": 20, + "column": 15 + } + } + }, + "out": true, + "loc": { + "start": { + "line": 20, + "column": 10 + }, + "end": { + "line": 20, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 16 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 19 + }, + "end": { + "line": 20, + "column": 19 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 10 + }, + "end": { + "line": 22, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 10 + }, + "end": { + "line": 22, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x1", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 15 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 15 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 11 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 27 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 27 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 23, + "column": 21 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 23 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } +} +TypeError: Type 'A1' cannot be assigned to type 'A1' [generic_variance_2.ets:23:21] diff --git a/ets2panda/test/compiler/ets/generic_variance_2.ets b/ets2panda/test/compiler/ets/generic_variance_2.ets new file mode 100644 index 0000000000..a3bc04b211 --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_2.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 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 {} +class B extends A {} + +class A1 {} +class A2 {} + +function main(): void { + let x1: A1 = new A1() +} \ No newline at end of file diff --git a/ets2panda/test/compiler/ets/generic_variance_3-expected.txt b/ets2panda/test/compiler/ets/generic_variance_3-expected.txt new file mode 100644 index 0000000000..3bb1aa6f55 --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_3-expected.txt @@ -0,0 +1,1218 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "in": true, + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 15 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 16 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 7 + }, + "end": { + "line": 20, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 14 + }, + "end": { + "line": 20, + "column": 15 + } + } + }, + "out": true, + "loc": { + "start": { + "line": 20, + "column": 10 + }, + "end": { + "line": 20, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 16 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 19 + }, + "end": { + "line": 20, + "column": 19 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 10 + }, + "end": { + "line": 22, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 10 + }, + "end": { + "line": 22, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x1", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 15 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 15 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 11 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 27 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 27 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 23, + "column": 21 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 23 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } +} +TypeError: Type 'A2' cannot be assigned to type 'A2' [generic_variance_3.ets:23:21] diff --git a/ets2panda/test/compiler/ets/generic_variance_3.ets b/ets2panda/test/compiler/ets/generic_variance_3.ets new file mode 100644 index 0000000000..2b61cf9302 --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_3.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 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 {} +class B extends A {} + +class A1 {} +class A2 {} + +function main(): void { + let x1: A2 = new A2() +} \ No newline at end of file diff --git a/ets2panda/test/compiler/ets/generic_variance_4-expected.txt b/ets2panda/test/compiler/ets/generic_variance_4-expected.txt new file mode 100644 index 0000000000..a3be0edfd5 --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_4-expected.txt @@ -0,0 +1,1178 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "in": true, + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 15 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 16 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 7 + }, + "end": { + "line": 20, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 14 + }, + "end": { + "line": 20, + "column": 15 + } + } + }, + "out": true, + "loc": { + "start": { + "line": 20, + "column": 10 + }, + "end": { + "line": 20, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 16 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 19 + }, + "end": { + "line": 20, + "column": 19 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 10 + }, + "end": { + "line": 22, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 10 + }, + "end": { + "line": 22, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x2", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 15 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 15 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 11 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 27 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 27 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 23, + "column": 21 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 23 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } +} +TypeError: Type 'A1' cannot be assigned to type 'A1' [generic_variance_4.ets:23:21] diff --git a/ets2panda/test/compiler/ets/generic_variance_4.ets b/ets2panda/test/compiler/ets/generic_variance_4.ets new file mode 100644 index 0000000000..bc98518302 --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_4.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 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 {} +class B {} + +class A1 {} +class A2 {} + +function main(): void { + let x2: A1 = new A1() +} \ No newline at end of file diff --git a/ets2panda/test/compiler/ets/generic_variance_5-expected.txt b/ets2panda/test/compiler/ets/generic_variance_5-expected.txt new file mode 100644 index 0000000000..07709a6558 --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_5-expected.txt @@ -0,0 +1,1178 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "in": true, + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 15 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 16 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 7 + }, + "end": { + "line": 20, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 14 + }, + "end": { + "line": 20, + "column": 15 + } + } + }, + "out": true, + "loc": { + "start": { + "line": 20, + "column": 10 + }, + "end": { + "line": 20, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 16 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 19 + }, + "end": { + "line": 20, + "column": 19 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 10 + }, + "end": { + "line": 22, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 10 + }, + "end": { + "line": 22, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x4", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 15 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 15 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 11 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 27 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 27 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 23, + "column": 21 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 23 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } +} +TypeError: Type 'A2' cannot be assigned to type 'A2' [generic_variance_5.ets:23:21] diff --git a/ets2panda/test/compiler/ets/generic_variance_5.ets b/ets2panda/test/compiler/ets/generic_variance_5.ets new file mode 100644 index 0000000000..9e351ad8f9 --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_5.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 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 {} +class B {} + +class A1 {} +class A2 {} + +function main(): void { + let x4: A2 = new A2() +} \ No newline at end of file diff --git a/ets2panda/test/compiler/ets/identifierReference2-expected.txt b/ets2panda/test/compiler/ets/identifierReference2-expected.txt index c0fb2875ea..100cdc5d9d 100644 --- a/ets2panda/test/compiler/ets/identifierReference2-expected.txt +++ b/ets2panda/test/compiler/ets/identifierReference2-expected.txt @@ -398,4 +398,4 @@ } } } -TypeError: Type '(v: double, u: double) => double' cannot be assigned to type '(a: int, b: int) => void' [identifierReference2.ets:16:34] +TypeError: Type '(v: double, u: double) => double' cannot be assigned to type '(p1: Int, p2: Int) => void' [identifierReference2.ets:16:34] diff --git a/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentType-expected.txt b/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentType-expected.txt index a17df28bb3..d7fafa4654 100644 --- a/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentType-expected.txt +++ b/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentType-expected.txt @@ -515,4 +515,4 @@ } } } -TypeError: Type '() => String' cannot be assigned to type '() => int' [lambdaExpressionWithoutBlockStatementDifferentType.ets:17:28] +TypeError: Type '() => String' cannot be assigned to type '() => Int' [lambdaExpressionWithoutBlockStatementDifferentType.ets:17:28] diff --git a/ets2panda/test/compiler/ets/lambdaFunction3-expected.txt b/ets2panda/test/compiler/ets/lambdaFunction3-expected.txt index 22b2a3c2f2..1e358988d2 100644 --- a/ets2panda/test/compiler/ets/lambdaFunction3-expected.txt +++ b/ets2panda/test/compiler/ets/lambdaFunction3-expected.txt @@ -642,4 +642,4 @@ } } } -TypeError: Type '(b: int) => void' cannot be assigned to type '(b: String) => void' [lambdaFunction3.ets:18:39] +TypeError: Type '(b: int) => void' cannot be assigned to type '(p1: String) => void' [lambdaFunction3.ets:18:39] diff --git a/ets2panda/test/compiler/ets/lambdaFunction5-expected.txt b/ets2panda/test/compiler/ets/lambdaFunction5-expected.txt index 5737ced2b4..b82ab2b932 100644 --- a/ets2panda/test/compiler/ets/lambdaFunction5-expected.txt +++ b/ets2panda/test/compiler/ets/lambdaFunction5-expected.txt @@ -1705,4 +1705,4 @@ } } } -TypeError: Type 'string' is not compatible with type 'int' at index 2 [lambdaFunction5.ets:35:17] +TypeError: Type 'string' is not compatible with type 'Int' at index 2 [lambdaFunction5.ets:35:17] diff --git a/ets2panda/test/compiler/ets/lambda_infer_type/lambda_cast_infer_type_widening-expected.txt b/ets2panda/test/compiler/ets/lambda_infer_type/lambda_cast_infer_type_widening-expected.txt index 545b1715cf..21e87c7c1a 100644 --- a/ets2panda/test/compiler/ets/lambda_infer_type/lambda_cast_infer_type_widening-expected.txt +++ b/ets2panda/test/compiler/ets/lambda_infer_type/lambda_cast_infer_type_widening-expected.txt @@ -289,7 +289,7 @@ "type": "ETSTypeReferencePart", "name": { "type": "Identifier", - "name": "B", + "name": "A", "decorators": [], "loc": { "start": { @@ -354,9 +354,49 @@ { "type": "ReturnStatement", "argument": { - "type": "Identifier", - "name": "a", - "decorators": [], + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 41 + }, + "end": { + "line": 22, + "column": 42 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 41 + }, + "end": { + "line": 22, + "column": 44 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 41 + }, + "end": { + "line": 22, + "column": 44 + } + } + }, + "arguments": [], "loc": { "start": { "line": 22, @@ -364,7 +404,7 @@ }, "end": { "line": 22, - "column": 38 + "column": 44 } } }, @@ -375,7 +415,7 @@ }, "end": { "line": 22, - "column": 38 + "column": 44 } } } @@ -387,7 +427,7 @@ }, "end": { "line": 22, - "column": 39 + "column": 44 } } }, @@ -398,7 +438,7 @@ }, "end": { "line": 22, - "column": 39 + "column": 44 } } }, @@ -409,7 +449,7 @@ }, "end": { "line": 22, - "column": 39 + "column": 44 } } }, @@ -432,33 +472,33 @@ "loc": { "start": { "line": 22, - "column": 48 + "column": 53 }, "end": { "line": 22, - "column": 49 + "column": 54 } } }, "loc": { "start": { "line": 22, - "column": 48 + "column": 53 }, "end": { "line": 22, - "column": 50 + "column": 55 } } }, "loc": { "start": { "line": 22, - "column": 48 + "column": 53 }, "end": { "line": 22, - "column": 50 + "column": 55 } } }, @@ -466,22 +506,22 @@ "loc": { "start": { "line": 22, - "column": 44 + "column": 49 }, "end": { "line": 22, - "column": 50 + "column": 55 } } }, "loc": { "start": { "line": 22, - "column": 44 + "column": 49 }, "end": { "line": 22, - "column": 50 + "column": 55 } } } @@ -497,18 +537,18 @@ "loc": { "start": { "line": 22, - "column": 54 + "column": 59 }, "end": { "line": 22, - "column": 55 + "column": 60 } } }, "loc": { "start": { "line": 22, - "column": 54 + "column": 59 }, "end": { "line": 23, @@ -519,7 +559,7 @@ "loc": { "start": { "line": 22, - "column": 54 + "column": 59 }, "end": { "line": 23, @@ -530,7 +570,7 @@ "loc": { "start": { "line": 22, - "column": 43 + "column": 48 }, "end": { "line": 23, @@ -545,7 +585,7 @@ }, "end": { "line": 22, - "column": 39 + "column": 44 } } }, @@ -556,7 +596,7 @@ }, "end": { "line": 22, - "column": 39 + "column": 44 } } } @@ -569,7 +609,7 @@ }, "end": { "line": 22, - "column": 39 + "column": 44 } } }, @@ -595,7 +635,7 @@ "type": "ETSTypeReferencePart", "name": { "type": "Identifier", - "name": "A", + "name": "B", "decorators": [], "loc": { "start": { diff --git a/ets2panda/test/compiler/ets/lambda_infer_type/lambda_cast_infer_type_widening.ets b/ets2panda/test/compiler/ets/lambda_infer_type/lambda_cast_infer_type_widening.ets index cb90f223b6..2d5c270007 100644 --- a/ets2panda/test/compiler/ets/lambda_infer_type/lambda_cast_infer_type_widening.ets +++ b/ets2panda/test/compiler/ets/lambda_infer_type/lambda_cast_infer_type_widening.ets @@ -19,7 +19,7 @@ class A { class B extends A { main () { - let a = (a : B) => { return a} as (a : A) => A - let expected : (a : A) => A = a + let a = (a : A) => { return new B } as (a : A) => A + let expected : (a : B) => A = a } } diff --git a/ets2panda/test/compiler/ets/methodOverrideCovariantReturnType-expected.txt b/ets2panda/test/compiler/ets/methodOverrideCovariantReturnType-expected.txt index 186fa4c371..36610c08a0 100644 --- a/ets2panda/test/compiler/ets/methodOverrideCovariantReturnType-expected.txt +++ b/ets2panda/test/compiler/ets/methodOverrideCovariantReturnType-expected.txt @@ -2084,4 +2084,3 @@ } } } -TypeError: foo(a: int): C in B cannot override foo(): A in A because overriding return type is not compatible with the other return type. [methodOverrideCovariantReturnType.ets:42:8] diff --git a/ets2panda/test/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable-expected.txt b/ets2panda/test/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable-expected.txt index 218cfffdcb..50c023906d 100644 --- a/ets2panda/test/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable-expected.txt +++ b/ets2panda/test/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable-expected.txt @@ -1012,4 +1012,4 @@ } } } -TypeError: Type 'A' cannot be assigned to type 'A' [n_assignGenericWithNullableTypeParamToNonNullable.ets:21:19] +TypeError: Type 'A' cannot be assigned to type 'A' [n_assignGenericWithNullableTypeParamToNonNullable.ets:20:27] diff --git a/ets2panda/test/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable.ets b/ets2panda/test/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable.ets index 8dab208be0..bbe9f2aa80 100644 --- a/ets2panda/test/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable.ets +++ b/ets2panda/test/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable.ets @@ -17,6 +17,6 @@ class A {} class B {} function main(): void { - let abn : A = new A(); // should work: non nullable B is the subtype of nullable B + let abn : A = new A(); // should not work: non nullable B is the subtype of nullable B, but T has no variance mark let ab : A = abn; // should not work: nullable B (the type of abn) is not the subtype of non nullable B } diff --git a/ets2panda/test/compiler/ets/overload_with_generics-expected.txt b/ets2panda/test/compiler/ets/overload_with_generics-expected.txt new file mode 100644 index 0000000000..8b5703c149 --- /dev/null +++ b/ets2panda/test/compiler/ets/overload_with_generics-expected.txt @@ -0,0 +1,1209 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "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": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "arg", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 32 + }, + "end": { + "line": 17, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 32 + }, + "end": { + "line": 17, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 32 + }, + "end": { + "line": 17, + "column": 35 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 27 + }, + "end": { + "line": 17, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 27 + }, + "end": { + "line": 17, + "column": 35 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 37 + }, + "end": { + "line": 17, + "column": 41 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 37 + }, + "end": { + "line": 17, + "column": 43 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 37 + }, + "end": { + "line": 17, + "column": 43 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 17, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 17, + "column": 26 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 22 + }, + "end": { + "line": 17, + "column": 26 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 17, + "column": 42 + }, + "end": { + "line": 17, + "column": 44 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 22 + }, + "end": { + "line": 17, + "column": 44 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 22 + }, + "end": { + "line": 17, + "column": 44 + } + } + }, + "overloads": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 19 + }, + "end": { + "line": 18, + "column": 22 + } + } + }, + "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": 19 + }, + "end": { + "line": 18, + "column": 22 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "arg1", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 37 + }, + "end": { + "line": 18, + "column": 39 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 37 + }, + "end": { + "line": 18, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 37 + }, + "end": { + "line": 18, + "column": 40 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 31 + }, + "end": { + "line": 18, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 31 + }, + "end": { + "line": 18, + "column": 40 + } + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "arg2", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 47 + }, + "end": { + "line": 18, + "column": 49 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 47 + }, + "end": { + "line": 18, + "column": 50 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 47 + }, + "end": { + "line": 18, + "column": 50 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 41 + }, + "end": { + "line": 18, + "column": 50 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 41 + }, + "end": { + "line": 18, + "column": 50 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 52 + }, + "end": { + "line": 18, + "column": 56 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 52 + }, + "end": { + "line": 18, + "column": 58 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 52 + }, + "end": { + "line": 18, + "column": 58 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 23 + }, + "end": { + "line": 18, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 23 + }, + "end": { + "line": 18, + "column": 26 + } + } + }, + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 27 + }, + "end": { + "line": 18, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 27 + }, + "end": { + "line": 18, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 22 + }, + "end": { + "line": 18, + "column": 30 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 18, + "column": 57 + }, + "end": { + "line": 18, + "column": 59 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 22 + }, + "end": { + "line": 18, + "column": 59 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 22 + }, + "end": { + "line": 18, + "column": 59 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 59 + } + } + } + ], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 44 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 2 + }, + "end": { + "line": 19, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 10 + }, + "end": { + "line": 21, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 10 + }, + "end": { + "line": 21, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 21, + "column": 18 + }, + "end": { + "line": 21, + "column": 21 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 6 + } + } + }, + "property": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 7 + }, + "end": { + "line": 22, + "column": 10 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 10 + } + } + }, + "arguments": [ + { + "type": "StringLiteral", + "value": "lll", + "loc": { + "start": { + "line": 22, + "column": 11 + }, + "end": { + "line": 22, + "column": 16 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 17 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 23, + "column": 6 + } + } + }, + "property": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 7 + }, + "end": { + "line": 23, + "column": 10 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 23, + "column": 10 + } + } + }, + "arguments": [ + { + "type": "StringLiteral", + "value": "lll", + "loc": { + "start": { + "line": 23, + "column": 11 + }, + "end": { + "line": 23, + "column": 16 + } + } + }, + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 23, + "column": 18 + }, + "end": { + "line": 23, + "column": 19 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + { + "type": "ReturnStatement", + "argument": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 24, + "column": 12 + }, + "end": { + "line": 24, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 5 + }, + "end": { + "line": 24, + "column": 13 + } + } + } + ], + "loc": { + "start": { + "line": 21, + "column": 22 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 14 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 14 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 1 + }, + "end": { + "line": 25, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 26, + "column": 1 + } + } +} diff --git a/ets2panda/test/compiler/ets/overload_with_generics.ets b/ets2panda/test/compiler/ets/overload_with_generics.ets new file mode 100644 index 0000000000..b0c007e32a --- /dev/null +++ b/ets2panda/test/compiler/ets/overload_with_generics.ets @@ -0,0 +1,25 @@ +/** + * 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. + */ + +class A { + public static foo(arg: A1): void {} + public static foo(arg1: A1, arg2: A2): void {} +} + +function main(): int { + A.foo("lll") + A.foo("lll", 1) + return 0 +} diff --git a/ets2panda/test/compiler/ets/override16-expected.txt b/ets2panda/test/compiler/ets/override16-expected.txt index b1fa4f9c7e..cf234349f2 100644 --- a/ets2panda/test/compiler/ets/override16-expected.txt +++ b/ets2panda/test/compiler/ets/override16-expected.txt @@ -735,4 +735,4 @@ } } } -TypeError: Hiding method is not return-type-substitutable for other method. [override16.ets:23:5] +TypeError: fn(): float in B cannot override fn(): int in A because overridden method is static. [override16.ets:23:5] diff --git a/ets2panda/test/parser/ets/function_implicit_return_type2-expected.txt b/ets2panda/test/parser/ets/function_implicit_return_type2-expected.txt index b9803f021f..b6a70f9b2e 100644 --- a/ets2panda/test/parser/ets/function_implicit_return_type2-expected.txt +++ b/ets2panda/test/parser/ets/function_implicit_return_type2-expected.txt @@ -316,4 +316,4 @@ } } } -TypeError: Type '() => void' cannot be assigned to type '(i: int) => int' [function_implicit_return_type2.ets:17:27] +TypeError: Type '() => void' cannot be assigned to type '(p1: Int) => Int' [function_implicit_return_type2.ets:17:27] diff --git a/ets2panda/test/parser/ets/function_implicit_return_type3-expected.txt b/ets2panda/test/parser/ets/function_implicit_return_type3-expected.txt index 86af963d88..ef11ad3a75 100644 --- a/ets2panda/test/parser/ets/function_implicit_return_type3-expected.txt +++ b/ets2panda/test/parser/ets/function_implicit_return_type3-expected.txt @@ -465,4 +465,4 @@ } } } -TypeError: Type '(i: int) => void' cannot be assigned to type '(i: int) => int' [function_implicit_return_type3.ets:18:27] +TypeError: Type '(i: int) => void' cannot be assigned to type '(p1: Int) => Int' [function_implicit_return_type3.ets:18:27] diff --git a/ets2panda/test/parser/ets/interface-expected.txt b/ets2panda/test/parser/ets/interface-expected.txt index a84f38f68d..13e389abc2 100644 --- a/ets2panda/test/parser/ets/interface-expected.txt +++ b/ets2panda/test/parser/ets/interface-expected.txt @@ -156,7 +156,7 @@ "type": "ETSTypeReferencePart", "name": { "type": "Identifier", - "name": "Function", + "name": "FunctioN", "decorators": [], "loc": { "start": { @@ -375,4 +375,4 @@ } } } -SyntaxError: Cannot find type 'Function'. [interface.ets:17:39] +SyntaxError: Cannot find type 'FunctioN'. [interface.ets:17:39] diff --git a/ets2panda/test/parser/ets/interface.ets b/ets2panda/test/parser/ets/interface.ets index e43e384d53..80534bb52c 100644 --- a/ets2panda/test/parser/ets/interface.ets +++ b/ets2panda/test/parser/ets/interface.ets @@ -14,5 +14,5 @@ */ -interface G {} +interface G {} diff --git a/ets2panda/test/parser/ets/lambda-type-inference-neg-expected.txt b/ets2panda/test/parser/ets/lambda-type-inference-neg-expected.txt index b814441ff1..4ac2df4d2f 100644 --- a/ets2panda/test/parser/ets/lambda-type-inference-neg-expected.txt +++ b/ets2panda/test/parser/ets/lambda-type-inference-neg-expected.txt @@ -928,4 +928,4 @@ } } } -TypeError: Reference to foo is ambiguous [lambda-type-inference-neg.ets:23:5] +TypeError: Function with this assembly signature already declared. [lambda-type-inference-neg.ets:19:1] diff --git a/ets2panda/test/parser/ets/lambda-type-inference-overloaded-1-expected.txt b/ets2panda/test/parser/ets/lambda-type-inference-overloaded-1-expected.txt index 5c3f1759fa..898613c8c7 100644 --- a/ets2panda/test/parser/ets/lambda-type-inference-overloaded-1-expected.txt +++ b/ets2panda/test/parser/ets/lambda-type-inference-overloaded-1-expected.txt @@ -1963,4 +1963,4 @@ } } } -TypeError: Reference to foo is ambiguous [lambda-type-inference-overloaded-1.ets:32:5] +TypeError: Function with this assembly signature already declared. [lambda-type-inference-overloaded-1.ets:20:1] diff --git a/ets2panda/test/runtime/ets/conversion-char-boolean.ets b/ets2panda/test/runtime/ets/conversion-char-boolean.ets index 76f9ea8e29..2b8d23bc68 100644 --- a/ets2panda/test/runtime/ets/conversion-char-boolean.ets +++ b/ets2panda/test/runtime/ets/conversion-char-boolean.ets @@ -20,7 +20,7 @@ function check(): Boolean { function main(): void { let x: Boolean = false; - assert (x || check()); + assert (!x || check()); let y: Char = c'a'; assert (y != c'b'); diff --git a/ets2panda/test/runtime/ets/unboxingBooleanConversion.ets b/ets2panda/test/runtime/ets/unboxingBooleanConversion.ets index 7fb437eeda..8a865706f5 100644 --- a/ets2panda/test/runtime/ets/unboxingBooleanConversion.ets +++ b/ets2panda/test/runtime/ets/unboxingBooleanConversion.ets @@ -23,8 +23,9 @@ function returnRefBool(a: boolean): Boolean { function main(): void { let a: Boolean = false; + let a2: Boolean = true - let b: Boolean = a && returnTrue(); + let b: Boolean = a || a2; assert b == true let c: Boolean = returnRefBool(a || returnRefBool(returnRefBool(a))); diff --git a/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt b/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt index e8521c7c0b..c12cc9299c 100644 --- a/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt +++ b/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt @@ -47,3 +47,12 @@ struct-init.ets struct-init2.ets struct_implements.ets top_level_03.ets + +# Union with undefined +OptionalCall.ets + +# Functional type with rest parameter +lambdaExpressionWithRestParameter.ets + +# Non-trivial cast sequence +castSequence.ets diff --git a/ets2panda/test/test-lists/parser/parser-ets-ignored.txt b/ets2panda/test/test-lists/parser/parser-ets-ignored.txt index de27323be4..803f9a2c5e 100644 --- a/ets2panda/test/test-lists/parser/parser-ets-ignored.txt +++ b/ets2panda/test/test-lists/parser/parser-ets-ignored.txt @@ -11,3 +11,17 @@ parser/ets/import_tests/modules/struct_module.ets parser/ets/import_tests/check_exported_default_struct.ets parser/ets/import_tests/modules/struct_default_module.ets parser/ets/import_tests/check_exported_struct.ets + +# Throwing function types are not yet supported +parser/ets/lambdaThrowsRethrows.ets +parser/ets/variable_throw_function_1.ets +compiler/ets/rethrowingCheck5.ets +compiler/ets/rethrowingConstructorCheck1.ets +compiler/ets/rethrowingConstructorCheck2.ets +compiler/ets/rethrowingConstructorCheck3.ets +compiler/ets/rethrowingFunctionCheck1.ets +compiler/ets/rethrowingFunctionCheck2.ets +compiler/ets/rethrowingFunctionCheck3.ets +compiler/ets/rethrowingMethodCheck1.ets +compiler/ets/rethrowingMethodCheck2.ets +compiler/ets/rethrowingMethodCheck3.ets diff --git a/ets2panda/test/test-lists/parser/parser-js-ignored.txt b/ets2panda/test/test-lists/parser/parser-js-ignored.txt index a0cac35d0e..f6b8c9975e 100644 --- a/ets2panda/test/test-lists/parser/parser-js-ignored.txt +++ b/ets2panda/test/test-lists/parser/parser-js-ignored.txt @@ -71,10 +71,9 @@ parser/ets/trailing_lambda_tests/trailing_lambda_define_lambda_in_body_capture_v compiler/ets/override13.ets # 15095 -compiler/ets/methodOverrideCovariantReturnType.ets -compiler/ets/override16.ets compiler/ets/override17.ets parser/ets/static_function_hide_2.ets -# 14595 -compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable.ets +# Throwing function types +compiler/ets/throwingFunctionType2.ets +compiler/ets/throwingFunctionAsParameter2.ets diff --git a/ets2panda/util/declgenEts2Ts.cpp b/ets2panda/util/declgenEts2Ts.cpp index 89cb7e1e34..8e4d7c9c12 100644 --- a/ets2panda/util/declgenEts2Ts.cpp +++ b/ets2panda/util/declgenEts2Ts.cpp @@ -295,7 +295,8 @@ void TSDeclGen::GenEnumType(const checker::ETSEnumType *enumType) void TSDeclGen::GenObjectType(const checker::ETSObjectType *objectType) { if (objectType->HasObjectFlag(checker::ETSObjectFlags::FUNCTIONAL)) { - const auto *invoke = objectType->GetOwnProperty("invoke"); + const auto *invoke = objectType->GetOwnProperty( + checker::FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME); ASSERT(invoke && invoke->TsType() && invoke->TsType()->IsETSFunctionType()); GenType(invoke->TsType()); return; diff --git a/ets2panda/varbinder/ETSBinder.cpp b/ets2panda/varbinder/ETSBinder.cpp index 06d08f3553..1e6c232d01 100644 --- a/ets2panda/varbinder/ETSBinder.cpp +++ b/ets2panda/varbinder/ETSBinder.cpp @@ -400,8 +400,9 @@ void ETSBinder::BuildLambdaObject(ir::AstNode *refNode, ir::ClassDefinition *lam auto boundCtx = BoundContext(GetGlobalRecordTable(), lambdaObject); const auto &lambdaBody = lambdaObject->Body(); + AddLambdaFunctionThisParam(lambdaBody[lambdaBody.size() - 3U]->AsMethodDefinition()->Function()); AddLambdaFunctionThisParam(lambdaBody[lambdaBody.size() - 2U]->AsMethodDefinition()->Function()); - AddLambdaFunctionThisParam(lambdaBody[lambdaBody.size() - 1]->AsMethodDefinition()->Function()); + AddLambdaFunctionThisParam(lambdaBody[lambdaBody.size() - 1U]->AsMethodDefinition()->Function()); LambdaObjects().insert({refNode, {lambdaObject, signature}}); } @@ -876,16 +877,6 @@ void ETSBinder::FormLambdaName(util::UString &name, const util::StringView &sign name.Append(replaced); } -void ETSBinder::FormFunctionalInterfaceName(util::UString &name, const util::StringView &signature) -{ - auto replaced = std::string(signature.Utf8()); - std::replace(replaced.begin(), replaced.end(), '.', '-'); - std::replace(replaced.begin(), replaced.end(), ':', '-'); - std::replace(replaced.begin(), replaced.end(), ';', '-'); - replaced.append(std::to_string(0)); - name.Append(replaced); -} - void ETSBinder::BuildLambdaObjectName(const ir::AstNode *refNode) { auto found = lambdaObjects_.find(refNode); @@ -913,51 +904,17 @@ void ETSBinder::BuildLambdaObjectName(const ir::AstNode *refNode) lambdaObject->SetAssemblerName(lambdaClass->Ident()->Name()); const auto &lambdaBody = lambdaClass->Body(); - auto *ctorFunc = lambdaBody[lambdaBody.size() - 2]->AsMethodDefinition()->Function(); + auto *ctorFunc = lambdaBody[lambdaBody.size() - 3U]->AsMethodDefinition()->Function(); auto *ctorFuncScope = ctorFunc->Scope(); ctorFuncScope->BindName(lambdaClass->Ident()->Name()); - auto *invokeFunc = lambdaBody[lambdaBody.size() - 1]->AsMethodDefinition()->Function(); - auto *invokeFuncScope = invokeFunc->Scope(); - invokeFuncScope->BindName(lambdaClass->Ident()->Name()); -} - -void ETSBinder::BuildFunctionalInterfaceName(ir::ETSFunctionType *funcType) -{ - auto *functionalInterface = funcType->FunctionalInterface(); - auto *invokeFunc = functionalInterface->Body()->Body()[0]->AsMethodDefinition()->Function(); - util::UString functionalInterfaceName(functionalInterface->Id()->Name(), Allocator()); - std::stringstream ss; - invokeFunc->Signature()->ToAssemblerType(GetCompilerContext(), ss); - std::string signatureString = ss.str(); - util::StringView signatureName(signatureString); - FormFunctionalInterfaceName(functionalInterfaceName, signatureName); - functionalInterface->Id()->SetName(functionalInterfaceName.View()); - util::UString internalName(Program()->GetPackageName(), Allocator()); - if (!(internalName.View().Empty())) { - internalName.Append(compiler::Signatures::METHOD_SEPARATOR); - } - internalName.Append(functionalInterface->Id()->Name()); - functionalInterface->SetInternalName(internalName.View()); - - checker::ETSObjectType *functionalInterfaceType = functionalInterface->TsType()->AsETSObjectType(); - functionalInterfaceType->SetName(functionalInterface->Id()->Name()); - functionalInterfaceType->SetAssemblerName(internalName.View()); + auto *invoke0Func = lambdaBody[lambdaBody.size() - 2U]->AsMethodDefinition()->Function(); + auto *invoke0FuncScope = invoke0Func->Scope(); + invoke0FuncScope->BindName(lambdaClass->Ident()->Name()); + auto *invokeFunc = lambdaBody[lambdaBody.size() - 1U]->AsMethodDefinition()->Function(); auto *invokeFuncScope = invokeFunc->Scope(); - invokeFuncScope->BindName(functionalInterface->Id()->Name()); - - util::UString invokeInternalName(Program()->GetPackageName(), Allocator()); - if (!(invokeInternalName.View().Empty())) { - invokeInternalName.Append(compiler::Signatures::METHOD_SEPARATOR); - } - invokeInternalName.Append(invokeFuncScope->Name()); - invokeInternalName.Append(compiler::Signatures::METHOD_SEPARATOR); - invokeInternalName.Append(invokeFunc->Id()->Name()); - std::stringstream invokeSignatureSs; - invokeFunc->Signature()->ToAssemblerType(GetCompilerContext(), invokeSignatureSs); - invokeInternalName.Append(invokeSignatureSs.str()); - invokeFuncScope->BindInternalName(invokeInternalName.View()); + invokeFuncScope->BindName(lambdaClass->Ident()->Name()); } void ETSBinder::InitImplicitThisParam() diff --git a/ets2panda/varbinder/ETSBinder.h b/ets2panda/varbinder/ETSBinder.h index edd27f9a43..0f70577279 100644 --- a/ets2panda/varbinder/ETSBinder.h +++ b/ets2panda/varbinder/ETSBinder.h @@ -158,8 +158,6 @@ public: void AddInvokeFunctionThisParam(ir::ScriptFunction *func); void BuildLambdaObjectName(const ir::AstNode *refNode); void FormLambdaName(util::UString &name, const util::StringView &signature); - void FormFunctionalInterfaceName(util::UString &name, const util::StringView &signature); - void BuildFunctionalInterfaceName(ir::ETSFunctionType *funcType); void SetDefaultImports(ArenaVector defaultImports) { -- Gitee