diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index 60c32ea888d672fd753514e638086c66492cc36b..4b1cab77a0251fa5bba5d181f1b4742135dea6fc 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -127,6 +127,7 @@ libes2panda_sources = [ "checker/types/ets/etsObjectType.cpp", "checker/types/ets/etsPartialTypeParameter.cpp", "checker/types/ets/etsReadonlyType.cpp", + "checker/types/ets/etsAwaitedType.cpp", "checker/types/ets/etsResizableArrayType.cpp", "checker/types/ets/etsStringType.cpp", "checker/types/ets/etsTupleType.cpp", diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index 73d465ae3641b94bb806b297268f3b89e79e5884..1a7ee97ef785dd77e91c0cd8cdcb997f7331925f 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -606,6 +606,7 @@ set(ES2PANDA_LIB_SRC checker/types/ets/etsTypeAliasType.cpp checker/types/ets/etsTypeParameter.cpp checker/types/ets/etsPartialTypeParameter.cpp + checker/types/ets/etsAwaitedType.cpp checker/types/ets/etsUnionType.cpp checker/types/ets/etsVoidType.cpp checker/types/ets/wildcardType.cpp diff --git a/ets2panda/ast_verifier/invariants/identifierHasVariable.cpp b/ets2panda/ast_verifier/invariants/identifierHasVariable.cpp index 4eae5c316c003fd8e3545f5390611a2bd0418a13..bdc95f22b1a8476b96dd07bc08d62f0acac1c37c 100644 --- a/ets2panda/ast_verifier/invariants/identifierHasVariable.cpp +++ b/ets2panda/ast_verifier/invariants/identifierHasVariable.cpp @@ -75,7 +75,7 @@ private: // NOTE(mmartin): find a better solution to handle utility type resolution return name.Is(Signatures::PARTIAL_TYPE_NAME) || name.Is(Signatures::REQUIRED_TYPE_NAME) || name.Is(Signatures::READONLY_TYPE_NAME) || name.Is(Signatures::FIXED_ARRAY_TYPE_NAME) || - name.Is(compiler::Signatures::ANY_TYPE_NAME); + name.Is(compiler::Signatures::ANY_TYPE_NAME) || name.Is(compiler::Signatures::AWAITED_TYPE_NAME); } bool IsUnionMemberAccess() diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 3fe590ae199f220822b23cb74cc52f9c48905d17..0dbb7f5ece26423f240738c199ca864f54da3171 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -1285,12 +1285,6 @@ std::tuple ETSAnalyzer::CheckAssignmentExprOperatorTyp return {sourceType, relationNode}; } -static bool IsPromiseType(checker::Type *type, ETSChecker *checker) -{ - return type->IsETSObjectType() && - type->AsETSObjectType()->GetOriginalBaseType() == checker->GlobalBuiltinPromiseType(); -} - checker::Type *ETSAnalyzer::Check(ir::AwaitExpression *expr) const { ETSChecker *checker = GetETSChecker(); @@ -1298,60 +1292,10 @@ checker::Type *ETSAnalyzer::Check(ir::AwaitExpression *expr) const return expr->TsType(); } - checker::Type *argType = checker->GetApparentType(expr->argument_->Check(checker)); - ArenaVector awaitedTypes(checker->ProgramAllocator()->Adapter()); - - if (argType->IsETSUnionType()) { - for (Type *type : argType->AsETSUnionType()->ConstituentTypes()) { - if (!IsPromiseType(type, checker)) { - return checker->TypeError(expr, diagnostic::AWAITED_NOT_PROMISE, expr->Argument()->Start()); - } - - Type *typeArg = type->AsETSObjectType()->TypeArguments().at(0); - awaitedTypes.push_back(UnwrapPromiseType(typeArg)); - } - } else { - if (!IsPromiseType(argType, checker)) { - return checker->TypeError(expr, diagnostic::AWAITED_NOT_PROMISE, expr->Argument()->Start()); - } - - Type *typeArg = argType->AsETSObjectType()->TypeArguments().at(0); - awaitedTypes.push_back(UnwrapPromiseType(typeArg)); - } - - expr->SetTsType(argType->IsETSUnionType() ? checker->CreateETSUnionType(std::move(awaitedTypes)) : awaitedTypes[0]); + expr->SetTsType(checker->HandleAwaitExpression(expr->argument_->Check(checker), expr)); return expr->TsType(); } -checker::Type *ETSAnalyzer::UnwrapPromiseType(checker::Type *type) const -{ - ETSChecker *checker = GetETSChecker(); - checker::Type *promiseType = checker->GlobalBuiltinPromiseType(); - while (type->IsETSObjectType() && type->AsETSObjectType()->GetOriginalBaseType() == promiseType) { - type = type->AsETSObjectType()->TypeArguments().at(0); - } - if (!type->IsETSUnionType()) { - return type; - } - const auto &ctypes = type->AsETSUnionType()->ConstituentTypes(); - auto it = std::find_if(ctypes.begin(), ctypes.end(), [promiseType](checker::Type *t) { - return t == promiseType || (t->IsETSObjectType() && t->AsETSObjectType()->GetBaseType() == promiseType); - }); - if (it == ctypes.end()) { - return type; - } - ArenaVector newCTypes(ctypes); - do { - size_t index = it - ctypes.begin(); - newCTypes[index] = UnwrapPromiseType(ctypes[index]); - ++it; - it = std::find_if(it, ctypes.end(), [promiseType](checker::Type *t) { - return t == promiseType || t->AsETSObjectType()->GetBaseType() == promiseType; - }); - } while (it != ctypes.end()); - return checker->CreateETSUnionType(std::move(newCTypes)); -} - checker::Type *ETSAnalyzer::Check(ir::BinaryExpression *expr) const { if (expr->TsType() != nullptr) { diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index b79f790e698d92f3d4a047b7f61508d47db11507..28c28bcceca707f0574bcccd1a4a94f4f87292a6 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -18,6 +18,7 @@ #include #include +#include #include "checker/checker.h" @@ -301,6 +302,7 @@ public: } [[nodiscard]] Type *GetApparentType(Type *type); [[nodiscard]] Type const *GetApparentType(Type const *type) const; + [[nodiscard]] Type *GetApparentTypeUtilityTypes(Type *type); ETSObjectType *GetClosestCommonAncestor(ETSObjectType *source, ETSObjectType *target); bool HasETSFunctionType(ir::TypeNode *typeAnnotation); @@ -451,6 +453,8 @@ public: Type *argumentType, Substitution *substitution); [[nodiscard]] bool EnhanceSubstitutionForFunction(const ArenaVector &typeParams, ETSFunctionType *paramType, Type *argumentType, Substitution *substitution); + [[nodiscard]] bool EnhanceSubstitutionForAwaited(const ArenaVector &typeParams, ETSAwaitedType *paramType, + Type *argumentType, Substitution *substitution); [[nodiscard]] bool EnhanceSubstitutionForUnion(const ArenaVector &typeParams, ETSUnionType *paramUn, Type *argumentType, Substitution *substitution); [[nodiscard]] bool EnhanceSubstitutionForArray(const ArenaVector &typeParams, ETSArrayType *paramType, @@ -798,6 +802,11 @@ public: // Readonly Type *GetReadonlyType(Type *type); void MakePropertiesReadonly(ETSObjectType *classType); + // Awaited + Type *HandleAwaitedUtilityType(Type *typeToBeAwaited); + Type *HandleAwaitExpression(Type *typeToBeAwaited, ir::AwaitExpression * expr); + Type *UnwrapPromiseType(checker::Type *type); + bool IsPromiseType(Type *type); // Required Type *HandleRequiredType(Type *typeToBeRequired); void MakePropertiesNonNullish(ETSObjectType *classType); diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index 53741e08a368c58d95d14380066221ed3084c3d6..f54ba3e9563039e236ae397cb0d04f5313c8f3e4 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -22,6 +22,7 @@ #include "checker/ets/function_helpers.h" #include "checker/ets/typeRelationContext.h" #include "checker/types/ets/etsAsyncFuncReturnType.h" +#include "checker/types/ets/etsAwaitedType.h" #include "checker/types/ets/etsObjectType.h" #include "checker/types/gradualType.h" #include "compiler/lowering/scopesInit/scopesInitPhase.h" @@ -137,6 +138,9 @@ bool ETSChecker::EnhanceSubstitutionForType(const ArenaVector &typeParam if (paramType->IsETSFunctionType()) { return EnhanceSubstitutionForFunction(typeParams, paramType->AsETSFunctionType(), argumentType, substitution); } + if (paramType->IsETSAwaitedType()) { + return EnhanceSubstitutionForAwaited(typeParams, paramType->AsETSAwaitedType(), argumentType, substitution); + } return true; } @@ -293,6 +297,15 @@ bool ETSChecker::EnhanceSubstitutionForFunction(const ArenaVector &typeP return res; } +bool ETSChecker::EnhanceSubstitutionForAwaited(const ArenaVector &typeParams, ETSAwaitedType *paramType, + Type *argumentType, Substitution *substitution) +{ + auto *argumentAwaitedType = + argumentType->IsETSAwaitedType() ? argumentType->AsETSAwaitedType()->GetUnderlying() : argumentType; + auto *paramAwaitedType = paramType->GetUnderlying(); + return EnhanceSubstitutionForType(typeParams, paramAwaitedType, argumentAwaitedType, substitution); +} + // Try to find the base type somewhere in object subtypes. Incomplete, yet safe static ETSObjectType *FindEnhanceTargetInSupertypes(ETSObjectType *object, ETSObjectType *base) { diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index 82f486c79ec36b88168d8a7e19e117f1e46cefbd..482dcf44901ac9c50cd74b872b7e4b89df9fa8d2 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -19,6 +19,7 @@ #include "checker/types/ets/etsObjectType.h" #include "checker/types/ets/etsTupleType.h" #include "checker/types/ets/etsPartialTypeParameter.h" +#include "checker/types/ets/etsAwaitedType.h" #include "checker/types/gradualType.h" #include "compiler/lowering/phase.h" #include "ir/base/classDefinition.h" @@ -2621,7 +2622,6 @@ Type *ETSChecker::GetApparentType(Type *type) if (type->IsGradualType()) { return cached(type->AsGradualType()->GetBaseType()); } - if (type->IsETSTypeParameter()) { // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) return cached(GetApparentType(type->AsETSTypeParameter()->GetConstraintType())); @@ -2632,12 +2632,6 @@ Type *ETSChecker::GetApparentType(Type *type) // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) GetNonNullishType(GetApparentType(type->AsETSNonNullishType()->GetUnderlying()->GetConstraintType()))); } - if (type->IsETSPartialTypeParameter()) { - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - return cached(CreatePartialType( - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - GetApparentType(type->AsETSPartialTypeParameter()->GetUnderlying()->GetConstraintType()))); - } if (type->IsETSArrayType()) { return cached(type); } @@ -2654,7 +2648,8 @@ Type *ETSChecker::GetApparentType(Type *type) } return cached(differ ? CreateETSUnionType(std::move(newConstituent)) : type); } - return cached(type); + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + return cached(GetApparentTypeUtilityTypes(type)); } Type const *ETSChecker::GetApparentType(Type const *type) const @@ -2663,6 +2658,25 @@ Type const *ETSChecker::GetApparentType(Type const *type) const return const_cast(const_cast(this)->GetApparentType(const_cast(type))); } +Type *ETSChecker::GetApparentTypeUtilityTypes(Type *type) +{ + if (type->IsETSReadonlyType()) { + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + return GetApparentType(type->AsETSReadonlyType()->GetUnderlying()->GetConstraintType()); + } + if (type->IsETSAwaitedType()) { + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + return GetApparentType(type->AsETSAwaitedType()->GetUnderlying()->GetConstraintType()); + } + if (type->IsETSPartialTypeParameter()) { + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + return CreatePartialType( + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + GetApparentType(type->AsETSPartialTypeParameter()->GetUnderlying()->GetConstraintType())); + } + return type; +} + ETSObjectType *ETSChecker::GetClosestCommonAncestor(ETSObjectType *source, ETSObjectType *target) { if (source->AsETSObjectType()->GetDeclNode() == target->AsETSObjectType()->GetDeclNode()) { diff --git a/ets2panda/checker/ets/typeCheckingHelpers.cpp b/ets2panda/checker/ets/typeCheckingHelpers.cpp index 6496cdb8ce75eb3a25d6fc59349a8ce4840f40fc..9b6859dfebbc1a9804af06bb655610f317947c2a 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -368,7 +368,7 @@ bool Type::IsETSMethodType() const TypeFlag::ETS_TYPE_PARAMETER | TypeFlag::WILDCARD | TypeFlag::ETS_NONNULLISH | TypeFlag::ETS_REQUIRED_TYPE_PARAMETER | TypeFlag::ETS_ANY | TypeFlag::ETS_NEVER | TypeFlag::ETS_UNION | TypeFlag::ETS_ARRAY | TypeFlag::FUNCTION | TypeFlag::ETS_PARTIAL_TYPE_PARAMETER | TypeFlag::ETS_TUPLE | - TypeFlag::ETS_ENUM | TypeFlag::ETS_READONLY | TypeFlag::GRADUAL_TYPE; + TypeFlag::ETS_ENUM | TypeFlag::ETS_READONLY | TypeFlag::GRADUAL_TYPE | TypeFlag::ETS_AWAITED; // Issues if (type->IsETSVoidType()) { // NOTE(vpukhov): #19701 void refactoring diff --git a/ets2panda/checker/ets/utilityTypeHandlers.cpp b/ets2panda/checker/ets/utilityTypeHandlers.cpp index 3bc326155822b3d444b65c31076f1d1d42cf44ae..8efcde2d21c50b171a0a5d4e6a5d3f9dfc19b321 100644 --- a/ets2panda/checker/ets/utilityTypeHandlers.cpp +++ b/ets2panda/checker/ets/utilityTypeHandlers.cpp @@ -15,6 +15,7 @@ #include "checker/ETSchecker.h" +#include "generated/diagnostic.h" #include "ir/expressions/identifier.h" #include "ir/ets/etsNullishTypes.h" #include "compiler/lowering/scopesInit/scopesInitPhase.h" @@ -22,8 +23,10 @@ #include "ir/expressions/literals/undefinedLiteral.h" #include "varbinder/ETSBinder.h" #include "checker/types/ets/etsPartialTypeParameter.h" +#include "checker/types/ets/etsAwaitedType.h" #include +#include namespace ark::es2panda::checker { @@ -78,10 +81,99 @@ Type *ETSChecker::HandleUtilityTypeParameterNode(const ir::TSTypeParameterInstan return HandleRequiredType(baseType); } + if (utilityType == compiler::Signatures::AWAITED_TYPE_NAME) { + return HandleAwaitedUtilityType(baseType); + } + LogError(diagnostic::UTILITY_TYPE_UNIMPLEMENTED, {}, typeParams->Start()); return baseType; } +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// Awaited utility type +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +bool ETSChecker::IsPromiseType(Type *type) +{ + if (type->IsETSUnionType()) { + for (Type *type_ : type->AsETSUnionType()->ConstituentTypes()) { + if (!IsPromiseType(type_)) { + return false; + } + } + return true; + } + return type->IsETSObjectType() && type->AsETSObjectType()->GetOriginalBaseType() == GlobalBuiltinPromiseType(); +} + +Type *ETSChecker::UnwrapPromiseType(checker::Type *type) +{ + Type *promiseType = GlobalBuiltinPromiseType(); + while (type->IsETSObjectType() && type->AsETSObjectType()->GetOriginalBaseType() == promiseType) { + type = type->AsETSObjectType()->TypeArguments().at(0); + } + if (!type->IsETSUnionType()) { + return type; + } + const auto &ctypes = type->AsETSUnionType()->ConstituentTypes(); + auto it = std::find_if(ctypes.begin(), ctypes.end(), [promiseType](checker::Type *t) { + return t == promiseType || (t->IsETSObjectType() && t->AsETSObjectType()->GetBaseType() == promiseType); + }); + if (it == ctypes.end()) { + return type; + } + ArenaVector newCTypes(ctypes); + do { + size_t index = it - ctypes.begin(); + newCTypes[index] = UnwrapPromiseType(ctypes[index]); + ++it; + it = std::find_if(it, ctypes.end(), [promiseType](checker::Type *t) { + return t == promiseType || t->AsETSObjectType()->GetBaseType() == promiseType; + }); + } while (it != ctypes.end()); + return CreateETSUnionType(std::move(newCTypes)); +} + +Type *ETSChecker::HandleAwaitedUtilityType(Type *typeToBeAwaited) +{ + if (typeToBeAwaited->IsETSTypeParameter()) { + return ProgramAllocator()->New(typeToBeAwaited->AsETSTypeParameter(), this); + } + + ArenaVector awaitedTypes(ProgramAllocator()->Adapter()); + + if (typeToBeAwaited->IsETSUnionType()) { + for (Type *type : typeToBeAwaited->AsETSUnionType()->ConstituentTypes()) { + if (!IsPromiseType(type)) { + awaitedTypes.push_back(UnwrapPromiseType(type)); + continue; + } + Type *typeArg = type->AsETSObjectType()->TypeArguments().at(0); + if (typeArg->IsETSTypeParameter()) { + return HandleAwaitedUtilityType(typeArg); + } + awaitedTypes.push_back(UnwrapPromiseType(typeArg)); + } + return CreateETSUnionType(std::move(awaitedTypes)); + } else { + if (IsPromiseType(typeToBeAwaited)) { + Type *typeArg = typeToBeAwaited->AsETSObjectType()->TypeArguments().at(0); + auto unwrappedType = UnwrapPromiseType(typeArg); + return unwrappedType->IsETSTypeParameter() ? HandleAwaitedUtilityType(unwrappedType) : unwrappedType; + } + } + + return typeToBeAwaited; +} + +Type *ETSChecker::HandleAwaitExpression(Type *typeToBeAwaited, ir::AwaitExpression * expr) { + if (!IsPromiseType(typeToBeAwaited)) { + LogError(diagnostic::AWAITED_TYPE_NOT_PROMISE, {typeToBeAwaited}, expr->Start()); + return typeToBeAwaited; + } + + return HandleAwaitedUtilityType(typeToBeAwaited); +} + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // Partial utility type // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ diff --git a/ets2panda/checker/types/ets/etsAwaitedType.cpp b/ets2panda/checker/types/ets/etsAwaitedType.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cdc23f329bef913203d5115b5d126abd9250545a --- /dev/null +++ b/ets2panda/checker/types/ets/etsAwaitedType.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "checker/ETSchecker.h" +#include "etsAwaitedType.h" + +namespace ark::es2panda::checker { +ETSAwaitedType::ETSAwaitedType(ETSTypeParameter *const typeParam, ETSChecker *const checker) + : Type(TypeFlag::ETS_AWAITED), checker_(checker), tparam_(typeParam) +{ + ES2PANDA_ASSERT(tparam_ != nullptr && checker_ != nullptr); +} + +void ETSAwaitedType::ToString(std::stringstream &ss, bool precise) const +{ + ss << "Awaited<"; + GetUnderlying()->ToString(ss, precise); + ss << ">"; +} + +void ETSAwaitedType::Identical(TypeRelation *relation, Type *other) +{ + if (other->IsETSAwaitedType()) { + relation->IsIdenticalTo(GetUnderlying(), other->AsETSAwaitedType()->GetUnderlying()); + } +} + +bool ETSAwaitedType::AssignmentSource(TypeRelation *relation, Type *target) +{ + return relation->IsSupertypeOf(target, this); +} + +void ETSAwaitedType::AssignmentTarget(TypeRelation *relation, Type *source) +{ + relation->IsSupertypeOf(this, source); +} + +void ETSAwaitedType::Cast(TypeRelation *relation, Type *target) +{ + if (relation->IsSupertypeOf(target, this)) { + relation->RemoveFlags(TypeRelationFlag::UNCHECKED_CAST); + return; + } + relation->Result(relation->InCastingContext()); +} + +void ETSAwaitedType::CastTarget(TypeRelation *relation, Type *source) +{ + if (relation->IsSupertypeOf(this, source)) { + relation->RemoveFlags(TypeRelationFlag::UNCHECKED_CAST); + return; + } + relation->Result(relation->InCastingContext()); +} + +void ETSAwaitedType::IsSupertypeOf(TypeRelation *relation, [[maybe_unused]] Type *source) +{ + relation->Result(false); +} + +void ETSAwaitedType::IsSubtypeOf(TypeRelation *relation, Type *target) +{ + relation->Result(false); + if (target->IsETSAwaitedType()) { + relation->IsSupertypeOf(target->AsETSAwaitedType()->GetUnderlying(), GetUnderlying()); + } +} +ETSAwaitedType *ETSAwaitedType::Instantiate([[maybe_unused]] ArenaAllocator *allocator, + [[maybe_unused]] TypeRelation *relation, + [[maybe_unused]] GlobalTypesHolder *globalTypes) +{ + return allocator->New( + GetUnderlying()->Instantiate(allocator, relation, globalTypes)->AsETSTypeParameter(), checker_); +} + +Type *ETSAwaitedType::Substitute([[maybe_unused]] TypeRelation *relation, const Substitution *substitution) +{ + auto *substituted = GetUnderlying()->Substitute(relation, substitution); + if (substituted == GetUnderlying()) { + return this; + } + + return checker_->HandleAwaitedUtilityType(substituted); +} + +void ETSAwaitedType::ToAssemblerType(std::stringstream &ss) const +{ + GetUnderlying()->ToAssemblerTypeWithRank(ss); +} + +void ETSAwaitedType::ToDebugInfoType(std::stringstream &ss) const +{ + checker_->HandleAwaitedUtilityType(GetUnderlying()->AsETSTypeParameter()->GetConstraintType())->ToDebugInfoType(ss); +} + +void ETSAwaitedType::CheckVarianceRecursively(TypeRelation *relation, VarianceFlag varianceFlag) +{ + relation->CheckVarianceRecursively(GetUnderlying(), + relation->TransferVariant(varianceFlag, VarianceFlag::COVARIANT)); +} +} // namespace ark::es2panda::checker \ No newline at end of file diff --git a/ets2panda/checker/types/ets/etsAwaitedType.h b/ets2panda/checker/types/ets/etsAwaitedType.h new file mode 100644 index 0000000000000000000000000000000000000000..9ce1ff74279189b2d8b14658a6f97d5c07ba6032 --- /dev/null +++ b/ets2panda/checker/types/ets/etsAwaitedType.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ES2PANDA_COMPILER_CHECKER_TYPES_ETS_AWAITED_TYPE_H +#define ES2PANDA_COMPILER_CHECKER_TYPES_ETS_AWAITED_TYPE_H + +#include "checker/types/ets/etsTypeParameter.h" + +namespace ark::es2panda::checker { +class ETSChecker; +class ETSAwaitedType : public Type { +public: + ETSAwaitedType() = delete; + ~ETSAwaitedType() override = default; + + NO_COPY_SEMANTIC(ETSAwaitedType); + NO_MOVE_SEMANTIC(ETSAwaitedType); + + explicit ETSAwaitedType(ETSTypeParameter *typeParam, ETSChecker *checker); + + ETSTypeParameter *GetUnderlying() const + { + return tparam_; + } + + Type *Substitute(TypeRelation *relation, const Substitution *substitution) override; + + ETSAwaitedType *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, + GlobalTypesHolder *globalTypes) override; + + void Identical(TypeRelation *relation, Type *other) override; + void AssignmentTarget(TypeRelation *relation, Type *source) override; + bool AssignmentSource(TypeRelation *relation, Type *target) override; + void Cast(TypeRelation *relation, Type *target) override; + void CastTarget(TypeRelation *relation, Type *source) override; + void IsSupertypeOf(TypeRelation *relation, Type *source) override; + void IsSubtypeOf(TypeRelation *relation, Type *target) override; + + void CheckVarianceRecursively(TypeRelation *relation, VarianceFlag varianceFlag) override; + + void ToString(std::stringstream &ss, bool precise) const override; + void ToAssemblerType(std::stringstream &ss) const override; + void ToDebugInfoType(std::stringstream &ss) const override; + +private: + ETSChecker *const checker_; + ETSTypeParameter *const tparam_; +}; + +} // namespace ark::es2panda::checker + +#endif diff --git a/ets2panda/checker/types/typeFlag.h b/ets2panda/checker/types/typeFlag.h index 5f01ae82252c6d2fcf311bbdfc2804c5f010a98c..faf965957d956168e610abe1b0d27db3b900f54c 100644 --- a/ets2panda/checker/types/typeFlag.h +++ b/ets2panda/checker/types/typeFlag.h @@ -26,29 +26,30 @@ using ENUMBITOPS_OPERATORS; enum class TypeFlag : uint64_t { NONE = 0, - NUMBER = 1ULL << 0ULL, // x: number - STRING = 1ULL << 1ULL, // x: string - BOOLEAN = 1ULL << 2ULL, // x: boolean - VOID = 1ULL << 3ULL, // x: void - NULL_TYPE = 1ULL << 4ULL, // x: null - UNDEFINED = 1ULL << 5ULL, // x: undefined - UNKNOWN = 1ULL << 6ULL, // x: unknown - NEVER = 1ULL << 7ULL, // x: never - UNION = 1ULL << 8ULL, // x: a | b - OBJECT = 1ULL << 9ULL, // x: object - BIGINT = 1ULL << 10ULL, // x: bigint - BOOLEAN_LITERAL = 1ULL << 11ULL, // x: true - NUMBER_LITERAL = 1ULL << 12ULL, // x: 10 - STRING_LITERAL = 1ULL << 13ULL, // x: "foo" - BIGINT_LITERAL = 1ULL << 14ULL, // x: 10n - ENUM = 1ULL << 15ULL, // enum x - ENUM_LITERAL = 1ULL << 16ULL, // member of enum - SYMBOL = 1ULL << 17ULL, // x: symbol - TYPE_PARAMETER = 1ULL << 18ULL, // function - INTERSECTION = 1ULL << 19ULL, // x: a & b - INDEX = 1ULL << 20ULL, // keyof x - INDEX_ACCESS = 1ULL << 21ULL, // x[a] - TEMPLATE_LITERAL = 1ULL << 23ULL, // x: `hello ${World}` + NUMBER = 1ULL << 0ULL, // x: number + STRING = 1ULL << 1ULL, // x: string + BOOLEAN = 1ULL << 2ULL, // x: boolean + VOID = 1ULL << 3ULL, // x: void + NULL_TYPE = 1ULL << 4ULL, // x: null + UNDEFINED = 1ULL << 5ULL, // x: undefined + UNKNOWN = 1ULL << 6ULL, // x: unknown + NEVER = 1ULL << 7ULL, // x: never + UNION = 1ULL << 8ULL, // x: a | b + OBJECT = 1ULL << 9ULL, // x: object + BIGINT = 1ULL << 10ULL, // x: bigint + BOOLEAN_LITERAL = 1ULL << 11ULL, // x: true + NUMBER_LITERAL = 1ULL << 12ULL, // x: 10 + STRING_LITERAL = 1ULL << 13ULL, // x: "foo" + BIGINT_LITERAL = 1ULL << 14ULL, // x: 10n + ENUM = 1ULL << 15ULL, // enum x + ENUM_LITERAL = 1ULL << 16ULL, // member of enum + SYMBOL = 1ULL << 17ULL, // x: symbol + TYPE_PARAMETER = 1ULL << 18ULL, // function + INTERSECTION = 1ULL << 19ULL, // x: a & b + INDEX = 1ULL << 20ULL, // keyof x + INDEX_ACCESS = 1ULL << 21ULL, // x[a] + // TEMPLATE_LITERAL = 1ULL << 23ULL, // x: `hello ${World}` + ETS_AWAITED = 1ULL << 23ULL, ANY = 1ULL << 24ULL, // x: any ARRAY = 1ULL << 25ULL, // x: number[] FUNCTION = 1ULL << 26ULL, // x: (a) => b diff --git a/ets2panda/checker/types/typeMapping.h b/ets2panda/checker/types/typeMapping.h index 84e3ba9cfef6fdf49983f38bf38c92e203b2e5b3..0ab8b04c640a65123ddad29a541726fe15ad6b5e 100644 --- a/ets2panda/checker/types/typeMapping.h +++ b/ets2panda/checker/types/typeMapping.h @@ -64,6 +64,7 @@ _(TypeFlag::ETS_TYPE_PARAMETER, ETSTypeParameter) \ _(TypeFlag::ETS_NONNULLISH, ETSNonNullishType) \ _(TypeFlag::ETS_READONLY, ETSReadonlyType) \ + _(TypeFlag::ETS_AWAITED, ETSAwaitedType) \ _(TypeFlag::ETS_INT_ENUM, ETSIntEnumType) \ _(TypeFlag::ETS_STRING_ENUM, ETSStringEnumType) \ _(TypeFlag::ETS_ENUM, ETSEnumType) \ diff --git a/ets2panda/compiler/scripts/signatures.yaml b/ets2panda/compiler/scripts/signatures.yaml index 15dfcdbfe96bd5c3900cd74d7e3162fbbc665e31..c4e129d0c64892089442201bed43d1713758a006 100644 --- a/ets2panda/compiler/scripts/signatures.yaml +++ b/ets2panda/compiler/scripts/signatures.yaml @@ -158,6 +158,8 @@ defines: ref: READONLY_TYPE_NAME - name: 'Partial' ref: PARTIAL_TYPE_NAME + - name: 'Awaited' + ref: AWAITED_TYPE_NAME - name: 'FixedArray' ref: FIXED_ARRAY_TYPE_NAME - name: 'Required' diff --git a/ets2panda/ir/ets/etsTypeReferencePart.cpp b/ets2panda/ir/ets/etsTypeReferencePart.cpp index 95812f806b3790fa900e7ebff5b8e207160b5779..35e27d74d3a2db7f2aa15fe3df7b9df42ee73116 100644 --- a/ets2panda/ir/ets/etsTypeReferencePart.cpp +++ b/ets2panda/ir/ets/etsTypeReferencePart.cpp @@ -161,7 +161,8 @@ static checker::Type *CheckPredefinedBuiltinTypes(checker::ETSChecker *const che } if (ident->Name() == compiler::Signatures::READONLY_TYPE_NAME || - ident->Name() == compiler::Signatures::REQUIRED_TYPE_NAME) { + ident->Name() == compiler::Signatures::REQUIRED_TYPE_NAME || + ident->Name() == compiler::Signatures::AWAITED_TYPE_NAME) { return checker->HandleUtilityTypeParameterNode(ref->TypeParams(), ident); } if (ident->Name() == compiler::Signatures::PARTIAL_TYPE_NAME) { diff --git a/ets2panda/test/ast/compiler/ets/awaited_1.ets b/ets2panda/test/ast/compiler/ets/awaited_1.ets new file mode 100644 index 0000000000000000000000000000000000000000..c5cbb5ddb61dde9a9e2b7c38eaf5726fbe47b784 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/awaited_1.ets @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +interface User { + age: Promise +} +class Myuser implements User { + age: Promise = delay(1) +} +const delay = (value: number): Promise => { + return Promise.resolve(value) +} +async function identity(arg: Type): Promise { + return Promise.resolve(arg); +} + +let user = new Myuser() +type user_name = Promise + +async function main() { + let awaited_user = await user.age + let aw = await identity(user.age) +} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/awaited_2.ets b/ets2panda/test/ast/compiler/ets/awaited_2.ets new file mode 100644 index 0000000000000000000000000000000000000000..99fc80034e60d2e5933818bd7f942c757872d8f1 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/awaited_2.ets @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function f(x: Awaited) {} + +async function ff(x: Promise) { + f(await x) +} + +const asyncfunc = async() => { + return Promise.resolve(1.0) +} + +function main() { + let x = ff(asyncfunc()) +} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/awaited_assignability_2_neg.ets b/ets2panda/test/ast/compiler/ets/awaited_assignability_2_neg.ets new file mode 100644 index 0000000000000000000000000000000000000000..eba08ed8791b144bc13f774734dae19ff0345c85 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/awaited_assignability_2_neg.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +async function aw(p: Promise, cb: (v: T) => void) { + let x: T = await p + cb(x) +} + +/* @@? 17:16 Error TypeError: Type 'Awaited' cannot be assigned to type 'T' */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/awaited_assignability_neg.ets b/ets2panda/test/ast/compiler/ets/awaited_assignability_neg.ets new file mode 100644 index 0000000000000000000000000000000000000000..680c93f3280b78250ba89fb295247f77cdca67f9 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/awaited_assignability_neg.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +async function aw(p: Promise, cb: (v: T) => void) { + let x: Awaited = await p + cb(x) +} + +/* @@? 18:5 Error TypeError: No matching call signature for (Awaited) */ +/* @@? 18:8 Error TypeError: Type 'Awaited' is not compatible with type 'T' at index 1 */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/awaited_utility_type.ets b/ets2panda/test/ast/compiler/ets/awaited_utility_type.ets new file mode 100644 index 0000000000000000000000000000000000000000..a5f6182caa655567d923aae90d39c907e08f2d9c --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/awaited_utility_type.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type A = Awaited // string +type B = Awaited>>> // number | boolean +type C = Awaited | boolean> // number | boolean \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/catch_error.ets b/ets2panda/test/ast/compiler/ets/catch_error.ets new file mode 100644 index 0000000000000000000000000000000000000000..069c1025280929585ebe4af8412736ba171cf42e --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/catch_error.ets @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const asyncFunction = async () => { + return new Promise((resolve, reject) => { + setTimeout(() => { + reject(new Error()) + }, 1000) + }) +} + +async function main() { + const result : number = await asyncFunction() + .then((result) => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(result + 1) + }, 500) + }) + }) + .then((result) => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(result + 4) + }, 500) + }) + }).catch((): number => { + console.log("PromiseMultiAsyncOperationTest0300 test error") + return 0 + }) +} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/double_then.ets b/ets2panda/test/ast/compiler/ets/double_then.ets new file mode 100644 index 0000000000000000000000000000000000000000..9f5ee761e87d49676d7d8d757542a533a768493d --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/double_then.ets @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const asyncFunction = async () => { + return Promise.resolve(1.0) +}; + +async function main() { + const result : number = await asyncFunction() + .then((result) => { + return Promise.resolve(result + 2.0) + }) + .then((result) => { + return Promise.resolve(result + 3.0) + }) +} \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/readonly.ets b/ets2panda/test/ast/compiler/ets/readonly.ets new file mode 100644 index 0000000000000000000000000000000000000000..1c547d70ccb907ab28e25bc99ac049ddf47d69af --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/readonly.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function f(x: Readonly) {} + +async function ff(x:T) { + f(a(x)) +} + +function a(x:T) : Readonly { return x } \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/then_ret.ets b/ets2panda/test/ast/compiler/ets/then_ret.ets new file mode 100644 index 0000000000000000000000000000000000000000..ccb920814022254cac89d0ca6eb8f762e322e1e1 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/then_ret.ets @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const asyncFunction = async () => { + return Promise.resolve(1.0) +}; + +let thenRet : Promise = asyncFunction() + .then((result) => { + return Promise.resolve(result + 2.0) + }) \ No newline at end of file diff --git a/ets2panda/test/ast/parser/ets/await_argument_null.ets b/ets2panda/test/ast/parser/ets/await_argument_null.ets index 9b7a14c21a652b69bb7b6964519a143d756cd44d..80bafac1206b5a966adb6866503b595cb26e06ea 100644 --- a/ets2panda/test/ast/parser/ets/await_argument_null.ets +++ b/ets2panda/test/ast/parser/ets/await_argument_null.ets @@ -14,9 +14,10 @@ */ async function foo(): Promise { - let obj: Object = await /* @@ label */null; + let obj: Object = /* @@ label */await null; return /* @@ label1 */null; } -/* @@@ label Error TypeError: 'await' expressions require Promise object as argument. */ +/* @@@ label Error TypeError: Type 'null' can not be awaited, it is not a Promise. */ +/* @@@ label Error TypeError: Type 'null' cannot be assigned to type 'Object' */ /* @@@ label1 Error TypeError: Type 'null' is not compatible with the enclosing method's return type 'Promise | Object' */ diff --git a/ets2panda/test/ast/parser/ets/await_object_bad.ets b/ets2panda/test/ast/parser/ets/await_object_bad.ets index 0b3bf805beece237b9a7d06af2d055d4cec640b1..f7d0995413fe66400d9770a2f20dfaefc65280ee 100644 --- a/ets2panda/test/ast/parser/ets/await_object_bad.ets +++ b/ets2panda/test/ast/parser/ets/await_object_bad.ets @@ -14,9 +14,9 @@ */ async function foo(): Promise { - let obj: Object = await /* @@ label */5; + let obj: Object = /* @@ label */await 5; return /* @@ label1 */null; } -/* @@@ label Error TypeError: 'await' expressions require Promise object as argument. */ +/* @@@ label Error TypeError: Type 'Int' can not be awaited, it is not a Promise. */ /* @@@ label1 Error TypeError: Type 'null' is not compatible with the enclosing method's return type 'Promise | Object' */ diff --git a/ets2panda/test/ast/parser/ets/await_promise_bad.ets b/ets2panda/test/ast/parser/ets/await_promise_bad.ets index d0ee72abbd50899c18e50cd7ebc25219c3dfe023..e1d10cf9598b5c59b6973b46dd952155bdba73f8 100644 --- a/ets2panda/test/ast/parser/ets/await_promise_bad.ets +++ b/ets2panda/test/ast/parser/ets/await_promise_bad.ets @@ -14,9 +14,9 @@ */ async function foo(): Promise { - let obj: Object = await /* @@ label */new Object(); + let obj: Object = /* @@ label */await new Object(); return /* @@ label1 */null; } -/* @@@ label Error TypeError: 'await' expressions require Promise object as argument. */ +/* @@@ label Error TypeError: Type 'Object' can not be awaited, it is not a Promise. */ /* @@@ label1 Error TypeError: Type 'null' is not compatible with the enclosing method's return type 'Promise | Object' */ diff --git a/ets2panda/test/ast/parser/ets/dynmicImportUnimplemented.ets b/ets2panda/test/ast/parser/ets/dynmicImportUnimplemented.ets index 089ace2f225f9df2dbe72da3c65e489a40573c6b..e681815d55230f5a6887312ba1cb5c4b6dabce32 100644 --- a/ets2panda/test/ast/parser/ets/dynmicImportUnimplemented.ets +++ b/ets2panda/test/ast/parser/ets/dynmicImportUnimplemented.ets @@ -28,4 +28,4 @@ function main() { } /* @@? 18:15 Error SyntaxError: Unexpected token 'import'. */ -/* @@? 18:15 Error TypeError: 'await' expressions require Promise object as argument. */ +/* @@? 18:9 Error TypeError: Type '*ERROR_TYPE*' can not be awaited, it is not a Promise. */ diff --git a/ets2panda/test/runtime/ets/awaited_tests/awaited_type.ets b/ets2panda/test/runtime/ets/awaited_tests/awaited_type.ets new file mode 100644 index 0000000000000000000000000000000000000000..99fc80034e60d2e5933818bd7f942c757872d8f1 --- /dev/null +++ b/ets2panda/test/runtime/ets/awaited_tests/awaited_type.ets @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function f(x: Awaited) {} + +async function ff(x: Promise) { + f(await x) +} + +const asyncfunc = async() => { + return Promise.resolve(1.0) +} + +function main() { + let x = ff(asyncfunc()) +} \ No newline at end of file diff --git a/ets2panda/util/diagnostic/semantic.yaml b/ets2panda/util/diagnostic/semantic.yaml index 4912fbec17903d28fc79828c7370fd4ffdfc5cfd..e46ae69d2b6c3c9d878b43499a2e23b554526775 100644 --- a/ets2panda/util/diagnostic/semantic.yaml +++ b/ets2panda/util/diagnostic/semantic.yaml @@ -202,9 +202,9 @@ semantic: id: 1 message: Return type of async function must be 'Promise'. -- name: AWAITED_NOT_PROMISE +- name: AWAITED_TYPE_NOT_PROMISE id: 303 - message: "'await' expressions require Promise object as argument." + message: "Type '{}' can not be awaited, it is not a Promise." - name: BINOP_DYN_UNIMPLEMENTED id: 112 diff --git a/ets2panda/varbinder/ETSBinder.cpp b/ets2panda/varbinder/ETSBinder.cpp index ff783ab4364579225a9b8a5dc79ab89975be4002..ad61eacf370e5d3d4c699724aac9a13f54a77c1c 100644 --- a/ets2panda/varbinder/ETSBinder.cpp +++ b/ets2panda/varbinder/ETSBinder.cpp @@ -59,7 +59,7 @@ static bool IsSpecialName(const util::StringView &name) return name == compiler::Signatures::ANY_TYPE_NAME || name == compiler::Signatures::UNDEFINED || name == compiler::Signatures::NULL_LITERAL || name == compiler::Signatures::READONLY_TYPE_NAME || name == compiler::Signatures::PARTIAL_TYPE_NAME || name == compiler::Signatures::REQUIRED_TYPE_NAME || - name == compiler::Signatures::FIXED_ARRAY_TYPE_NAME; + name == compiler::Signatures::FIXED_ARRAY_TYPE_NAME || name == compiler::Signatures::AWAITED_TYPE_NAME; } bool ETSBinder::LookupInDebugInfoPlugin(ir::Identifier *ident)