diff --git a/ets2panda/checker/ETSchecker.cpp b/ets2panda/checker/ETSchecker.cpp index 911c0a1ea8be2d2e72f757fe08a11786dded1a5e..764abb07da69818085f33e71aaa65a3dfae42a3a 100644 --- a/ets2panda/checker/ETSchecker.cpp +++ b/ets2panda/checker/ETSchecker.cpp @@ -756,4 +756,11 @@ void ETSChecker::InsertExtensionGetterToMap(util::StringView name, ETSObjectType { GetGlobalTypesHolder()->InsertExtensionGetterToMap(name, type, sig); } + +bool ETSChecker::TypeHasDefaultValue(Type *tp) const +{ + return tp->IsBuiltinNumeric() || tp->IsETSBooleanType() || tp->IsETSCharType() || + Relation()->IsSupertypeOf(GlobalETSUndefinedType(), tp); +} + } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 57ef9dcf63abad9e9973d8a0fb6986fd78d5f1bf..0e7c496b133ea77c5751c71fcdb3e77dfb86f1d5 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -275,6 +275,8 @@ public: void VariableTypeFromInitializer(varbinder::Variable *variable, Type *annotationType, Type *initType); + bool TypeHasDefaultValue(Type *tp) const; + // Type creation ByteType *CreateByteType(int8_t value); ETSBooleanType *CreateETSBooleanType(bool value); diff --git a/ets2panda/checker/types/ets/etsFunctionType.cpp b/ets2panda/checker/types/ets/etsFunctionType.cpp index 1df9fd28eac9bc6271cff13c4bf63277ce2ae0d8..e547f07b47c46541a568264752fbb55cd77cb3c6 100644 --- a/ets2panda/checker/types/ets/etsFunctionType.cpp +++ b/ets2panda/checker/types/ets/etsFunctionType.cpp @@ -71,10 +71,18 @@ static ETSObjectType *FunctionTypeToFunctionalInterfaceType(ETSChecker *checker, bool isExtensionHack = signature->HasSignatureFlag(SignatureFlags::EXTENSION_FUNCTION); if (signature->RestVar() != nullptr) { - auto *functionN = checker->GlobalBuiltinFunctionType(arity, true)->AsETSObjectType(); + auto nPosParams = signature->Params().size(); + auto *functionN = checker->GlobalBuiltinFunctionType(nPosParams, true)->AsETSObjectType(); auto *substitution = checker->NewSubstitution(); + for (size_t i = 0; i < nPosParams; i++) { + substitution->emplace(functionN->TypeArguments()[i]->AsETSTypeParameter(), + checker->MaybeBoxType(signature->Params()[i]->TsType())); + } auto *elementType = checker->GetElementTypeOfArray(signature->RestVar()->TsType()); - substitution->emplace(functionN->TypeArguments()[0]->AsETSTypeParameter(), checker->MaybeBoxType(elementType)); + substitution->emplace(functionN->TypeArguments()[nPosParams]->AsETSTypeParameter(), + checker->MaybeBoxType(elementType)); + substitution->emplace(functionN->TypeArguments()[nPosParams + 1]->AsETSTypeParameter(), + checker->MaybeBoxType(signature->ReturnType())); return functionN->Substitute(checker->Relation(), substitution, true, isExtensionHack); } diff --git a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp index fee50e2129dad809a90c9fc3d5bd33213280ad90..cf0ba7b9deb41845d6ce26d116f520ab4d038c1d 100644 --- a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp +++ b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp @@ -509,9 +509,13 @@ static ArenaVector CreateRestArgumentsArrayReall auto *checker = ctx->checker->AsETSChecker(); auto *restParameterType = lciInfo->lambdaSignature->RestVar()->TsType(); + auto *restParameterSubstituteType = restParameterType->Substitute(checker->Relation(), lciInfo->substitution); bool isFixedArray = restParameterSubstituteType->IsETSArrayType(); auto *elementType = checker->GetElementTypeOfArray(restParameterSubstituteType); + auto *elementTypeWithDefault = checker->TypeHasDefaultValue(elementType) + ? elementType + : checker->CreateETSUnionType({elementType, checker->GlobalETSUndefinedType()}); std::stringstream statements; auto restParameterIndex = GenName(allocator).View(); auto spreadArrIterator = GenName(allocator).View(); @@ -521,7 +525,7 @@ static ArenaVector CreateRestArgumentsArrayReall statements << "let @@I1: int = 0;"; if (elementType->IsETSReferenceType()) { // NOTE(vpukhov): this is a clear null-safety violation that should be rewitten with a runtime intrinsic - statements << "let @@I2: FixedArray<@@T3 | undefined> = new (@@T4 | undefined)[@@I5.length];"; + statements << "let @@I2: FixedArray<@@T3> = new (@@T4)[@@I5.length];"; } else { statements << "let @@I2: FixedArray<@@T3> = new (@@T4)[@@I5.length];"; } @@ -534,8 +538,8 @@ static ArenaVector CreateRestArgumentsArrayReall << " @@I16 = @@I17 + 1;" << "}"; args = parser->CreateFormattedStatement( - statements.str(), restParameterIndex, tmpArray, elementType, elementType, lciInfo->restParameterIdentifier, - lciInfo->restArgumentIdentifier, tmpArray, elementType, spreadArrIterator, + statements.str(), restParameterIndex, tmpArray, elementTypeWithDefault, elementTypeWithDefault, + lciInfo->restParameterIdentifier, lciInfo->restArgumentIdentifier, tmpArray, elementType, spreadArrIterator, checker->GlobalETSNullishObjectType(), lciInfo->restParameterIdentifier, lciInfo->restArgumentIdentifier, restParameterIndex, spreadArrIterator, elementType, restParameterIndex, restParameterIndex); } else {