From 938cce60191d141f9e84f4d0c74d7db49ace3fed Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Sat, 21 Jun 2025 15:26:09 +0300 Subject: [PATCH] Fix bug in interaction btw instanceof and generics Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICGV43 Signed-off-by: Georgy Bronnikov --- .../bindings/src/generated/Es2pandaEnums.ts | 21 +++++----- ets2panda/checker/checkerContext.h | 25 ++++++------ ets2panda/checker/ets/arithmetic.cpp | 11 ++---- ets2panda/checker/ets/typeRelationContext.cpp | 7 ---- ets2panda/ir/brokenTypeNode.cpp | 3 +- ets2panda/ir/brokenTypeNode.h | 2 +- ets2panda/ir/ets/etsFunctionType.cpp | 2 +- ets2panda/ir/ets/etsFunctionType.h | 2 +- ets2panda/ir/ets/etsKeyofType.cpp | 4 +- ets2panda/ir/ets/etsKeyofType.h | 4 +- ets2panda/ir/ets/etsNeverType.cpp | 3 +- ets2panda/ir/ets/etsNeverType.h | 2 +- ets2panda/ir/ets/etsNonNullishTypeNode.cpp | 3 +- ets2panda/ir/ets/etsNonNullishTypeNode.h | 4 +- ets2panda/ir/ets/etsNullishTypes.cpp | 6 ++- ets2panda/ir/ets/etsNullishTypes.h | 4 +- ets2panda/ir/ets/etsPrimitiveType.cpp | 3 +- ets2panda/ir/ets/etsPrimitiveType.h | 2 +- ets2panda/ir/ets/etsStringLiteralType.cpp | 3 +- ets2panda/ir/ets/etsStringLiteralType.h | 2 +- ets2panda/ir/ets/etsTuple.cpp | 4 +- ets2panda/ir/ets/etsTuple.h | 2 +- ets2panda/ir/ets/etsTypeReference.cpp | 4 +- ets2panda/ir/ets/etsTypeReference.h | 2 +- ets2panda/ir/ets/etsTypeReferencePart.cpp | 10 +++-- ets2panda/ir/ets/etsTypeReferencePart.h | 2 +- ets2panda/ir/ets/etsUnionType.cpp | 4 +- ets2panda/ir/ets/etsUnionType.h | 2 +- ets2panda/ir/ets/etsWildcardType.cpp | 3 +- ets2panda/ir/ets/etsWildcardType.h | 2 +- ets2panda/ir/opaqueTypeNode.cpp | 3 +- ets2panda/ir/opaqueTypeNode.h | 2 +- ets2panda/ir/ts/tsArrayType.cpp | 2 +- ets2panda/ir/ts/tsArrayType.h | 2 +- ets2panda/ir/ts/tsFunctionType.cpp | 3 +- ets2panda/ir/ts/tsFunctionType.h | 2 +- ets2panda/ir/ts/tsIntersectionType.cpp | 3 +- ets2panda/ir/ts/tsIntersectionType.h | 2 +- ets2panda/ir/ts/tsThisType.cpp | 3 +- ets2panda/ir/ts/tsThisType.h | 2 +- ets2panda/ir/typeNode.h | 3 +- ets2panda/test/runtime/ets/27016.ets | 39 +++++++++++++++++++ ets2panda/util/perfMetrics.cpp | 1 + 43 files changed, 130 insertions(+), 85 deletions(-) create mode 100644 ets2panda/test/runtime/ets/27016.ets diff --git a/ets2panda/bindings/src/generated/Es2pandaEnums.ts b/ets2panda/bindings/src/generated/Es2pandaEnums.ts index 5638cddfaf..3ecfd13775 100644 --- a/ets2panda/bindings/src/generated/Es2pandaEnums.ts +++ b/ets2panda/bindings/src/generated/Es2pandaEnums.ts @@ -88,17 +88,16 @@ export enum Es2pandaCheckerStatus { CHECKER_STATUS_IGNORE_VISIBILITY = 16384, CHECKER_STATUS_IN_INSTANCE_EXTENSION_METHOD = 32768, CHECKER_STATUS_IN_LOCAL_CLASS = 65536, - CHECKER_STATUS_IN_INSTANCEOF_CONTEXT = 131072, - CHECKER_STATUS_IN_TEST_EXPRESSION = 262144, - CHECKER_STATUS_IN_LOOP = 524288, - CHECKER_STATUS_MEET_RETURN = 1048576, - CHECKER_STATUS_MEET_BREAK = 2097152, - CHECKER_STATUS_MEET_CONTINUE = 4194304, - CHECKER_STATUS_MEET_THROW = 8388608, - CHECKER_STATUS_IN_EXTERNAL = 16777216, - CHECKER_STATUS_IN_BRIDGE_TEST = 33554432, - CHECKER_STATUS_IN_GETTER = 67108864, - CHECKER_STATUS_IN_SETTER = 134217728 + CHECKER_STATUS_IN_TEST_EXPRESSION = 131072, + CHECKER_STATUS_IN_TEST_LOOP = 262144, + CHECKER_STATUS_MEET_RETURN = 524288, + CHECKER_STATUS_MEET_BREAK = 1048576, + CHECKER_STATUS_MEET_CONTINUE = 2097152, + CHECKER_STATUS_MEET_THROW = 4194304, + CHECKER_STATUS_IN_EXTERNAL = 8388608, + CHECKER_STATUS_IN_BRIDGE_TEST = 16777216, + CHECKER_STATUS_IN_GETTER = 33554432, + CHECKER_STATUS_IN_SETTER = 67108864 } export enum Es2pandaLexicalScopeType { diff --git a/ets2panda/checker/checkerContext.h b/ets2panda/checker/checkerContext.h index aa5e6b26fc..43dc34aed9 100644 --- a/ets2panda/checker/checkerContext.h +++ b/ets2panda/checker/checkerContext.h @@ -64,19 +64,18 @@ enum class CheckerStatus : uint32_t { IGNORE_VISIBILITY = 1U << 14U, IN_EXTENSION_METHOD = 1U << 15U, IN_LOCAL_CLASS = 1U << 16U, - IN_INSTANCEOF_CONTEXT = 1U << 17U, - IN_TEST_EXPRESSION = 1U << 18U, - IN_LOOP = 1U << 19U, - MEET_RETURN = 1U << 20U, - MEET_BREAK = 1U << 21U, - MEET_CONTINUE = 1U << 22U, - MEET_THROW = 1U << 23U, - IN_EXTERNAL = 1U << 24U, - IN_BRIDGE_TEST = 1U << 25U, - IN_GETTER = 1U << 26U, - IN_SETTER = 1U << 27U, - IN_EXTENSION_ACCESSOR_CHECK = 1U << 28U, - IN_TYPE_INFER = 1U << 29U, + IN_TEST_EXPRESSION = 1U << 17U, + IN_LOOP = 1U << 18U, + MEET_RETURN = 1U << 19U, + MEET_BREAK = 1U << 20U, + MEET_CONTINUE = 1U << 21U, + MEET_THROW = 1U << 22U, + IN_EXTERNAL = 1U << 23U, + IN_BRIDGE_TEST = 1U << 24U, + IN_GETTER = 1U << 25U, + IN_SETTER = 1U << 26U, + IN_EXTENSION_ACCESSOR_CHECK = 1U << 27U, + IN_TYPE_INFER = 1U << 28U, }; } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/ets/arithmetic.cpp b/ets2panda/checker/ets/arithmetic.cpp index af98822566..5d930ac848 100644 --- a/ets2panda/checker/ets/arithmetic.cpp +++ b/ets2panda/checker/ets/arithmetic.cpp @@ -824,7 +824,6 @@ std::tuple ETSChecker::CheckBinaryOperatorInstanceOf(lexer::Sour } checker::Type *opType = GlobalETSObjectType(); - RemoveStatus(checker::CheckerStatus::IN_INSTANCEOF_CONTEXT); return {GlobalETSBooleanBuiltinType(), opType}; } @@ -1187,16 +1186,14 @@ std::tuple ETSChecker::CheckBinaryOperator(ir::Expression *left, return {rightType, rightType}; } - if (operationType == lexer::TokenType::KEYW_INSTANCEOF) { - AddStatus(checker::CheckerStatus::IN_INSTANCEOF_CONTEXT); - } - Context().CheckTestSmartCastCondition(operationType); // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - checker::Type *rightType = right->Check(this); + checker::Type *rightType; if (right->IsTypeNode()) { - rightType = right->AsTypeNode()->GetType(this); + rightType = right->AsTypeNode()->GetType(this, false); + } else { + rightType = right->Check(this); } if (rightType == nullptr) { diff --git a/ets2panda/checker/ets/typeRelationContext.cpp b/ets2panda/checker/ets/typeRelationContext.cpp index bfcd8ef61a..e4ed3ddecf 100644 --- a/ets2panda/checker/ets/typeRelationContext.cpp +++ b/ets2panda/checker/ets/typeRelationContext.cpp @@ -45,13 +45,6 @@ bool AssignmentContext::ValidateArrayTypeInitializerByElement(TypeRelation *rela bool InstantiationContext::ValidateTypeArguments(ETSObjectType *type, ir::TSTypeParameterInstantiation *typeArgs, const lexer::SourcePosition &pos) { - if (checker_->HasStatus(CheckerStatus::IN_INSTANCEOF_CONTEXT)) { - if (typeArgs != nullptr) { - checker_->LogDiagnostic(diagnostic::INSTANCEOF_ERASED, {type->Name()}, pos); - } - result_ = type; - return true; - } if (!checker_->CheckNumberOfTypeArguments(type, typeArgs, pos)) { result_ = checker_->GlobalTypeError(); return true; diff --git a/ets2panda/ir/brokenTypeNode.cpp b/ets2panda/ir/brokenTypeNode.cpp index 7194b87d8d..f634184bf6 100644 --- a/ets2panda/ir/brokenTypeNode.cpp +++ b/ets2panda/ir/brokenTypeNode.cpp @@ -59,7 +59,8 @@ checker::Type *BrokenTypeNode::GetType([[maybe_unused]] checker::TSChecker *chec return nullptr; } -checker::Type *BrokenTypeNode::GetType([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *BrokenTypeNode::GetType([[maybe_unused]] checker::ETSChecker *checker, + [[maybe_unused]] bool expectTypeArguments) { return checker->GlobalTypeError(); } diff --git a/ets2panda/ir/brokenTypeNode.h b/ets2panda/ir/brokenTypeNode.h index 81df2eeea8..01fbd54bd5 100644 --- a/ets2panda/ir/brokenTypeNode.h +++ b/ets2panda/ir/brokenTypeNode.h @@ -41,7 +41,7 @@ public: checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::VerifiedType Check([[maybe_unused]] checker::ETSChecker *checker) override; - checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker, bool expectTypeArguments = true) override; void Accept(ASTVisitorT *v) override { diff --git a/ets2panda/ir/ets/etsFunctionType.cpp b/ets2panda/ir/ets/etsFunctionType.cpp index ef128fde8a..ef3e62b914 100644 --- a/ets2panda/ir/ets/etsFunctionType.cpp +++ b/ets2panda/ir/ets/etsFunctionType.cpp @@ -110,7 +110,7 @@ checker::VerifiedType ETSFunctionType::Check(checker::ETSChecker *checker) return {this, checker->GetAnalyzer()->Check(this)}; } -checker::Type *ETSFunctionType::GetType(checker::ETSChecker *checker) +checker::Type *ETSFunctionType::GetType(checker::ETSChecker *checker, [[maybe_unused]] bool expectTypeArguments) { return Check(checker); } diff --git a/ets2panda/ir/ets/etsFunctionType.h b/ets2panda/ir/ets/etsFunctionType.h index 142e16671c..73a88b60a9 100644 --- a/ets2panda/ir/ets/etsFunctionType.h +++ b/ets2panda/ir/ets/etsFunctionType.h @@ -134,7 +134,7 @@ public: checker::Type *Check(checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::VerifiedType Check(checker::ETSChecker *checker) override; - checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *GetType(checker::ETSChecker *checker, bool expectTypeArguments = true) override; void Accept(ASTVisitorT *v) override { diff --git a/ets2panda/ir/ets/etsKeyofType.cpp b/ets2panda/ir/ets/etsKeyofType.cpp index d266214e5b..60173406ea 100644 --- a/ets2panda/ir/ets/etsKeyofType.cpp +++ b/ets2panda/ir/ets/etsKeyofType.cpp @@ -57,7 +57,7 @@ checker::VerifiedType ETSKeyofType::Check([[maybe_unused]] checker::ETSChecker * return {this, checker->GetAnalyzer()->Check(this)}; } -checker::Type *ETSKeyofType::GetType(checker::ETSChecker *checker) +checker::Type *ETSKeyofType::GetType(checker::ETSChecker *checker, [[maybe_unused]] bool expectTypeArguments) { if (TsType() != nullptr) { return TsType(); @@ -89,4 +89,4 @@ ETSKeyofType *ETSKeyofType::Clone(ArenaAllocator *const allocator, AstNode *cons clone->type_->SetParent(clone); return clone; } -} // namespace ark::es2panda::ir \ No newline at end of file +} // namespace ark::es2panda::ir diff --git a/ets2panda/ir/ets/etsKeyofType.h b/ets2panda/ir/ets/etsKeyofType.h index 9e063e798b..28eef9a04d 100644 --- a/ets2panda/ir/ets/etsKeyofType.h +++ b/ets2panda/ir/ets/etsKeyofType.h @@ -38,7 +38,7 @@ public: void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::VerifiedType Check([[maybe_unused]] checker::ETSChecker *checker) override; - checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *GetType(checker::ETSChecker *checker, bool expectTypeArguments = true) override; void Accept(ASTVisitorT *v) override { @@ -52,4 +52,4 @@ private: }; } // namespace ark::es2panda::ir -#endif \ No newline at end of file +#endif diff --git a/ets2panda/ir/ets/etsNeverType.cpp b/ets2panda/ir/ets/etsNeverType.cpp index 3f40e34750..d347821560 100644 --- a/ets2panda/ir/ets/etsNeverType.cpp +++ b/ets2panda/ir/ets/etsNeverType.cpp @@ -59,7 +59,8 @@ checker::VerifiedType ETSNeverType::Check([[maybe_unused]] checker::ETSChecker * return {this, checker->GetAnalyzer()->Check(this)}; } -checker::Type *ETSNeverType::GetType([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ETSNeverType::GetType([[maybe_unused]] checker::ETSChecker *checker, + [[maybe_unused]] bool expectTypeArguments) { SetTsType(checker->GlobalETSNeverType()); return TsType(); diff --git a/ets2panda/ir/ets/etsNeverType.h b/ets2panda/ir/ets/etsNeverType.h index 8f7a231b48..788b22f746 100644 --- a/ets2panda/ir/ets/etsNeverType.h +++ b/ets2panda/ir/ets/etsNeverType.h @@ -30,7 +30,7 @@ public: void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::VerifiedType Check([[maybe_unused]] checker::ETSChecker *checker) override; - checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *GetType(checker::ETSChecker *checker, bool expectTypeArguments = true) override; void Accept(ASTVisitorT *v) override { diff --git a/ets2panda/ir/ets/etsNonNullishTypeNode.cpp b/ets2panda/ir/ets/etsNonNullishTypeNode.cpp index 14226f3c0f..9e46ad5ad5 100644 --- a/ets2panda/ir/ets/etsNonNullishTypeNode.cpp +++ b/ets2panda/ir/ets/etsNonNullishTypeNode.cpp @@ -60,7 +60,8 @@ checker::VerifiedType ETSNonNullishTypeNode::Check([[maybe_unused]] checker::ETS return {this, checker->GetAnalyzer()->Check(this)}; } -checker::Type *ETSNonNullishTypeNode::GetType([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ETSNonNullishTypeNode::GetType([[maybe_unused]] checker::ETSChecker *checker, + [[maybe_unused]] bool expectTypeArguments) { return TsType() != nullptr ? TsType() : Check(checker); } diff --git a/ets2panda/ir/ets/etsNonNullishTypeNode.h b/ets2panda/ir/ets/etsNonNullishTypeNode.h index 2de8462ca0..7fa07fc8e8 100644 --- a/ets2panda/ir/ets/etsNonNullishTypeNode.h +++ b/ets2panda/ir/ets/etsNonNullishTypeNode.h @@ -38,7 +38,7 @@ public: void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::VerifiedType Check([[maybe_unused]] checker::ETSChecker *checker) override; - checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker, bool expectTypeArguments = true) override; void Accept(ASTVisitorT *v) override { @@ -52,4 +52,4 @@ private: }; } // namespace ark::es2panda::ir -#endif \ No newline at end of file +#endif diff --git a/ets2panda/ir/ets/etsNullishTypes.cpp b/ets2panda/ir/ets/etsNullishTypes.cpp index 0957d162a4..2adaccba82 100644 --- a/ets2panda/ir/ets/etsNullishTypes.cpp +++ b/ets2panda/ir/ets/etsNullishTypes.cpp @@ -59,7 +59,8 @@ checker::VerifiedType ETSUndefinedType::Check([[maybe_unused]] checker::ETSCheck return {this, checker->GetAnalyzer()->Check(this)}; } -checker::Type *ETSUndefinedType::GetType([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ETSUndefinedType::GetType([[maybe_unused]] checker::ETSChecker *checker, + [[maybe_unused]] bool expectTypeArguments) { SetTsType(checker->GlobalETSUndefinedType()); return TsType(); @@ -125,7 +126,8 @@ checker::VerifiedType ETSNullType::Check([[maybe_unused]] checker::ETSChecker *c return {this, checker->GetAnalyzer()->Check(this)}; } -checker::Type *ETSNullType::GetType([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ETSNullType::GetType([[maybe_unused]] checker::ETSChecker *checker, + [[maybe_unused]] bool expectTypeArguments) { SetTsType(checker->GlobalETSNullType()); return TsType(); diff --git a/ets2panda/ir/ets/etsNullishTypes.h b/ets2panda/ir/ets/etsNullishTypes.h index 54f40e1c0e..b0ca0bffcf 100644 --- a/ets2panda/ir/ets/etsNullishTypes.h +++ b/ets2panda/ir/ets/etsNullishTypes.h @@ -31,7 +31,7 @@ public: void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::VerifiedType Check([[maybe_unused]] checker::ETSChecker *checker) override; - checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *GetType(checker::ETSChecker *checker, bool expectTypeArguments = true) override; void Accept(ASTVisitorT *v) override { @@ -51,7 +51,7 @@ public: void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::VerifiedType Check([[maybe_unused]] checker::ETSChecker *checker) override; - checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *GetType(checker::ETSChecker *checker, bool expectTypeArguments = true) override; void Accept(ASTVisitorT *v) override { diff --git a/ets2panda/ir/ets/etsPrimitiveType.cpp b/ets2panda/ir/ets/etsPrimitiveType.cpp index 6fc11fec68..b133dd6989 100644 --- a/ets2panda/ir/ets/etsPrimitiveType.cpp +++ b/ets2panda/ir/ets/etsPrimitiveType.cpp @@ -102,7 +102,8 @@ checker::VerifiedType ETSPrimitiveType::Check(checker::ETSChecker *checker) return {this, checker->GetAnalyzer()->Check(this)}; } -checker::Type *ETSPrimitiveType::GetType([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ETSPrimitiveType::GetType([[maybe_unused]] checker::ETSChecker *checker, + [[maybe_unused]] bool expectTypeArguments) { switch (GetPrimitiveType()) { case PrimitiveType::BYTE: { diff --git a/ets2panda/ir/ets/etsPrimitiveType.h b/ets2panda/ir/ets/etsPrimitiveType.h index e26ae82974..9ab15fd9c8 100644 --- a/ets2panda/ir/ets/etsPrimitiveType.h +++ b/ets2panda/ir/ets/etsPrimitiveType.h @@ -44,7 +44,7 @@ public: checker::Type *Check(checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::VerifiedType Check(checker::ETSChecker *checker) override; - checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *GetType(checker::ETSChecker *checker, bool expectTypeArguments = true) override; void Accept(ASTVisitorT *v) override { diff --git a/ets2panda/ir/ets/etsStringLiteralType.cpp b/ets2panda/ir/ets/etsStringLiteralType.cpp index 178160de40..d96eb4ce60 100644 --- a/ets2panda/ir/ets/etsStringLiteralType.cpp +++ b/ets2panda/ir/ets/etsStringLiteralType.cpp @@ -60,7 +60,8 @@ checker::VerifiedType ETSStringLiteralType::Check([[maybe_unused]] checker::ETSC return {this, checker->GetAnalyzer()->Check(this)}; } -checker::Type *ETSStringLiteralType::GetType([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ETSStringLiteralType::GetType([[maybe_unused]] checker::ETSChecker *checker, + [[maybe_unused]] bool expectTypeArguments) { SetTsType(checker->CreateETSStringLiteralType(value_)); return TsType(); diff --git a/ets2panda/ir/ets/etsStringLiteralType.h b/ets2panda/ir/ets/etsStringLiteralType.h index 0144bf17e1..7b1904f0e0 100644 --- a/ets2panda/ir/ets/etsStringLiteralType.h +++ b/ets2panda/ir/ets/etsStringLiteralType.h @@ -34,7 +34,7 @@ public: void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::VerifiedType Check([[maybe_unused]] checker::ETSChecker *checker) override; - checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *GetType(checker::ETSChecker *checker, bool expectTypeArguments = true) override; void Accept(ASTVisitorT *v) override { diff --git a/ets2panda/ir/ets/etsTuple.cpp b/ets2panda/ir/ets/etsTuple.cpp index 3b143a0872..cfdcd0d6d3 100644 --- a/ets2panda/ir/ets/etsTuple.cpp +++ b/ets2panda/ir/ets/etsTuple.cpp @@ -73,7 +73,7 @@ checker::Type *ETSTuple::Check([[maybe_unused]] checker::TSChecker *const checke return nullptr; } -checker::VerifiedType ETSTuple::Check([[maybe_unused]] checker::ETSChecker *const checker) +checker::VerifiedType ETSTuple::Check(checker::ETSChecker *const checker) { return {this, GetType(checker)}; } @@ -96,7 +96,7 @@ checker::Type *ETSTuple::GetHolderTypeForTuple(checker::ETSChecker *const checke return checker->GlobalETSAnyType(); } -checker::Type *ETSTuple::GetType(checker::ETSChecker *const checker) +checker::Type *ETSTuple::GetType(checker::ETSChecker *const checker, [[maybe_unused]] bool expectTypeArguments) { if (TsType() != nullptr) { return TsType(); diff --git a/ets2panda/ir/ets/etsTuple.h b/ets2panda/ir/ets/etsTuple.h index 6039a546e5..6973a984f3 100644 --- a/ets2panda/ir/ets/etsTuple.h +++ b/ets2panda/ir/ets/etsTuple.h @@ -67,7 +67,7 @@ public: void Compile([[maybe_unused]] compiler::ETSGen *etsg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::VerifiedType Check([[maybe_unused]] checker::ETSChecker *checker) override; - [[nodiscard]] checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + [[nodiscard]] checker::Type *GetType(checker::ETSChecker *checker, bool expectTypeArguments = true) override; void Accept(ASTVisitorT *v) override { diff --git a/ets2panda/ir/ets/etsTypeReference.cpp b/ets2panda/ir/ets/etsTypeReference.cpp index 7986198c72..a7e30ea944 100644 --- a/ets2panda/ir/ets/etsTypeReference.cpp +++ b/ets2panda/ir/ets/etsTypeReference.cpp @@ -102,12 +102,12 @@ checker::VerifiedType ETSTypeReference::Check(checker::ETSChecker *checker) { return {this, checker->GetAnalyzer()->Check(this)}; } -checker::Type *ETSTypeReference::GetType(checker::ETSChecker *checker) +checker::Type *ETSTypeReference::GetType(checker::ETSChecker *checker, bool expectTypeArguments) { if (TsType() != nullptr) { return TsType(); } - auto *type = Part()->GetType(checker); + auto *type = Part()->GetType(checker, expectTypeArguments); if (IsReadonlyType()) { type = checker->GetReadonlyType(type); } diff --git a/ets2panda/ir/ets/etsTypeReference.h b/ets2panda/ir/ets/etsTypeReference.h index a69e3679fe..9073e651cc 100644 --- a/ets2panda/ir/ets/etsTypeReference.h +++ b/ets2panda/ir/ets/etsTypeReference.h @@ -58,7 +58,7 @@ public: void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check(checker::TSChecker *checker) override; checker::VerifiedType Check(checker::ETSChecker *checker) override; - checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *GetType(checker::ETSChecker *checker, bool expectTypeArguments = true) override; void Accept(ASTVisitorT *v) override { diff --git a/ets2panda/ir/ets/etsTypeReferencePart.cpp b/ets2panda/ir/ets/etsTypeReferencePart.cpp index 9dbef072a2..5519227a05 100644 --- a/ets2panda/ir/ets/etsTypeReferencePart.cpp +++ b/ets2panda/ir/ets/etsTypeReferencePart.cpp @@ -208,7 +208,7 @@ checker::Type *ETSTypeReferencePart::HandleInternalTypes(checker::ETSChecker *co return nullptr; } -checker::Type *ETSTypeReferencePart::GetType(checker::ETSChecker *checker) +checker::Type *ETSTypeReferencePart::GetType(checker::ETSChecker *checker, bool expectTypeArguments) { if (TypeParams() != nullptr) { for (auto *param : TypeParams()->Params()) { @@ -228,15 +228,19 @@ checker::Type *ETSTypeReferencePart::GetType(checker::ETSChecker *checker) checker::Type *baseType = checker->GetReferencedTypeBase(name); ES2PANDA_ASSERT(baseType != nullptr); - if (baseType->IsETSObjectType()) { + if (baseType->IsETSObjectType() && expectTypeArguments) { checker::InstantiationContext ctx(checker, baseType->AsETSObjectType(), TypeParams(), Start()); SetTsType(ctx.Result()); } else { + if (baseType->IsETSObjectType() && !expectTypeArguments && TypeParams() != nullptr) { + checker->LogDiagnostic(diagnostic::INSTANCEOF_ERASED, {baseType->AsETSObjectType()->Name()}, + Start()); + } SetTsType(baseType); } } } else { - checker::Type *baseType = Previous()->GetType(checker); + checker::Type *baseType = Previous()->GetType(checker, expectTypeArguments); SetTsType(checker->GetReferencedTypeFromBase(baseType, name)); } return TsType(); diff --git a/ets2panda/ir/ets/etsTypeReferencePart.h b/ets2panda/ir/ets/etsTypeReferencePart.h index 9fe657e930..123ad6a780 100644 --- a/ets2panda/ir/ets/etsTypeReferencePart.h +++ b/ets2panda/ir/ets/etsTypeReferencePart.h @@ -95,7 +95,7 @@ public: void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check(checker::TSChecker *checker) override; checker::VerifiedType Check(checker::ETSChecker *checker) override; - checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *GetType(checker::ETSChecker *checker, bool expectTypeArguments = true) override; ir::Identifier *GetIdent(); void Accept(ASTVisitorT *v) override diff --git a/ets2panda/ir/ets/etsUnionType.cpp b/ets2panda/ir/ets/etsUnionType.cpp index de035bcd61..a79a20597c 100644 --- a/ets2panda/ir/ets/etsUnionType.cpp +++ b/ets2panda/ir/ets/etsUnionType.cpp @@ -86,7 +86,7 @@ static bool CheckConstituentTypesValid(ArenaVector const &const return true; } -checker::Type *ETSUnionType::GetType(checker::ETSChecker *checker) +checker::Type *ETSUnionType::GetType(checker::ETSChecker *checker, bool expectTypeArguments) { if (TsType() != nullptr) { return TsType(); @@ -96,7 +96,7 @@ checker::Type *ETSUnionType::GetType(checker::ETSChecker *checker) ArenaVector types(checker->Allocator()->Adapter()); for (auto *it : Types()) { - types.push_back(it->GetType(checker)); + types.push_back(it->GetType(checker, expectTypeArguments)); } checker->Relation()->SetNode(this); diff --git a/ets2panda/ir/ets/etsUnionType.h b/ets2panda/ir/ets/etsUnionType.h index 21a06d8ef1..1d0ac82044 100644 --- a/ets2panda/ir/ets/etsUnionType.h +++ b/ets2panda/ir/ets/etsUnionType.h @@ -44,7 +44,7 @@ public: void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::VerifiedType Check([[maybe_unused]] checker::ETSChecker *checker) override; - checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *GetType(checker::ETSChecker *checker, bool expectTypeArguments = true) override; void Accept(ASTVisitorT *v) override { diff --git a/ets2panda/ir/ets/etsWildcardType.cpp b/ets2panda/ir/ets/etsWildcardType.cpp index ab5ffc9e50..fe59543565 100644 --- a/ets2panda/ir/ets/etsWildcardType.cpp +++ b/ets2panda/ir/ets/etsWildcardType.cpp @@ -85,7 +85,8 @@ checker::VerifiedType ETSWildcardType::Check(checker::ETSChecker *checker) return {this, checker->GetAnalyzer()->Check(this)}; } -checker::Type *ETSWildcardType::GetType([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ETSWildcardType::GetType([[maybe_unused]] checker::ETSChecker *checker, + [[maybe_unused]] bool expectTypeArguments) { return checker->GlobalWildcardType(); } diff --git a/ets2panda/ir/ets/etsWildcardType.h b/ets2panda/ir/ets/etsWildcardType.h index d97e155308..9adb4467c7 100644 --- a/ets2panda/ir/ets/etsWildcardType.h +++ b/ets2panda/ir/ets/etsWildcardType.h @@ -48,7 +48,7 @@ public: checker::Type *Check(checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::VerifiedType Check(checker::ETSChecker *checker) override; - checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *GetType(checker::ETSChecker *checker, bool expectTypeArguments = true) override; void Accept(ASTVisitorT *v) override { diff --git a/ets2panda/ir/opaqueTypeNode.cpp b/ets2panda/ir/opaqueTypeNode.cpp index 4a74b38975..9dd2a1518a 100644 --- a/ets2panda/ir/opaqueTypeNode.cpp +++ b/ets2panda/ir/opaqueTypeNode.cpp @@ -68,7 +68,8 @@ checker::Type *OpaqueTypeNode::GetType([[maybe_unused]] checker::TSChecker *chec return nullptr; } -checker::Type *OpaqueTypeNode::GetType([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *OpaqueTypeNode::GetType([[maybe_unused]] checker::ETSChecker *checker, + [[maybe_unused]] bool expectTypeArguments) { return TsType(); } diff --git a/ets2panda/ir/opaqueTypeNode.h b/ets2panda/ir/opaqueTypeNode.h index f4871890a3..605f4ab90b 100644 --- a/ets2panda/ir/opaqueTypeNode.h +++ b/ets2panda/ir/opaqueTypeNode.h @@ -47,7 +47,7 @@ public: checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::VerifiedType Check([[maybe_unused]] checker::ETSChecker *checker) override; - checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *GetType(checker::ETSChecker *checker, bool expectTypeArguments = true) override; void Accept(ASTVisitorT *v) override { diff --git a/ets2panda/ir/ts/tsArrayType.cpp b/ets2panda/ir/ts/tsArrayType.cpp index fe5c8a3049..bf31575652 100644 --- a/ets2panda/ir/ts/tsArrayType.cpp +++ b/ets2panda/ir/ts/tsArrayType.cpp @@ -87,7 +87,7 @@ checker::VerifiedType TSArrayType::Check(checker::ETSChecker *checker) return {this, checker->GetAnalyzer()->Check(this)}; } -checker::Type *TSArrayType::GetType(checker::ETSChecker *checker) +checker::Type *TSArrayType::GetType(checker::ETSChecker *checker, [[maybe_unused]] bool expectTypeArguments) { checker::Type *type = checker->CreateETSArrayType(elementType_->GetType(checker), IsReadonlyType()); if (IsReadonlyType()) { diff --git a/ets2panda/ir/ts/tsArrayType.h b/ets2panda/ir/ts/tsArrayType.h index 39f5b4872d..fd6ab13ee2 100644 --- a/ets2panda/ir/ts/tsArrayType.h +++ b/ets2panda/ir/ts/tsArrayType.h @@ -49,7 +49,7 @@ public: checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::VerifiedType Check([[maybe_unused]] checker::ETSChecker *checker) override; - checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *GetType(checker::ETSChecker *checker, bool expectTypeArguments = true) override; void Accept(ASTVisitorT *v) override { diff --git a/ets2panda/ir/ts/tsFunctionType.cpp b/ets2panda/ir/ts/tsFunctionType.cpp index 89e4751aeb..556fc447e1 100644 --- a/ets2panda/ir/ts/tsFunctionType.cpp +++ b/ets2panda/ir/ts/tsFunctionType.cpp @@ -80,7 +80,8 @@ checker::VerifiedType TSFunctionType::Check([[maybe_unused]] checker::ETSChecker return {this, checker->GetAnalyzer()->Check(this)}; } -checker::Type *TSFunctionType::GetType([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *TSFunctionType::GetType([[maybe_unused]] checker::ETSChecker *checker, + [[maybe_unused]] bool expectTypeArguments) { return nullptr; } diff --git a/ets2panda/ir/ts/tsFunctionType.h b/ets2panda/ir/ts/tsFunctionType.h index b66474ef0e..c90c71d389 100644 --- a/ets2panda/ir/ts/tsFunctionType.h +++ b/ets2panda/ir/ts/tsFunctionType.h @@ -93,7 +93,7 @@ public: checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::VerifiedType Check([[maybe_unused]] checker::ETSChecker *checker) override; - checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *GetType(checker::ETSChecker *checker, bool expectTypeArguments = true) override; void Accept(ASTVisitorT *v) override { diff --git a/ets2panda/ir/ts/tsIntersectionType.cpp b/ets2panda/ir/ts/tsIntersectionType.cpp index 6dc630a18a..15583a151f 100644 --- a/ets2panda/ir/ts/tsIntersectionType.cpp +++ b/ets2panda/ir/ts/tsIntersectionType.cpp @@ -78,7 +78,8 @@ checker::Type *TSIntersectionType::GetType([[maybe_unused]] checker::TSChecker * return nullptr; } -checker::Type *TSIntersectionType::GetType([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *TSIntersectionType::GetType([[maybe_unused]] checker::ETSChecker *checker, + [[maybe_unused]] bool expectTypeArguments) { // NOTE: validate return checker->GlobalETSObjectType(); diff --git a/ets2panda/ir/ts/tsIntersectionType.h b/ets2panda/ir/ts/tsIntersectionType.h index 11abbca848..3475bdd3b4 100644 --- a/ets2panda/ir/ts/tsIntersectionType.h +++ b/ets2panda/ir/ts/tsIntersectionType.h @@ -39,7 +39,7 @@ public: void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *GetType(checker::ETSChecker *checker, bool expectTypeArguments = true) override; checker::VerifiedType Check([[maybe_unused]] checker::ETSChecker *checker) override; void Accept(ASTVisitorT *v) override diff --git a/ets2panda/ir/ts/tsThisType.cpp b/ets2panda/ir/ts/tsThisType.cpp index 9af97be93c..2ff08edaf9 100644 --- a/ets2panda/ir/ts/tsThisType.cpp +++ b/ets2panda/ir/ts/tsThisType.cpp @@ -68,7 +68,8 @@ checker::VerifiedType TSThisType::Check([[maybe_unused]] checker::ETSChecker *ch return {this, checker->GetAnalyzer()->Check(this)}; } -checker::Type *TSThisType::GetType([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *TSThisType::GetType([[maybe_unused]] checker::ETSChecker *checker, + [[maybe_unused]] bool expectTypeArguments) { return checker->Context().ContainingClass(); } diff --git a/ets2panda/ir/ts/tsThisType.h b/ets2panda/ir/ts/tsThisType.h index e5367ce02f..a43fedd6af 100644 --- a/ets2panda/ir/ts/tsThisType.h +++ b/ets2panda/ir/ts/tsThisType.h @@ -32,7 +32,7 @@ public: checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::VerifiedType Check([[maybe_unused]] checker::ETSChecker *checker) override; - checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *GetType(checker::ETSChecker *checker, bool expectTypeArguments = true) override; TSThisType *Clone(ArenaAllocator *allocator, AstNode *parent) override; void Accept(ASTVisitorT *v) override diff --git a/ets2panda/ir/typeNode.h b/ets2panda/ir/typeNode.h index a3adb7e09c..53850c582f 100644 --- a/ets2panda/ir/typeNode.h +++ b/ets2panda/ir/typeNode.h @@ -43,7 +43,8 @@ public: return nullptr; } - [[nodiscard]] virtual checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) + [[nodiscard]] virtual checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker, + [[maybe_unused]] bool expectTypeArguments = true) { return nullptr; } diff --git a/ets2panda/test/runtime/ets/27016.ets b/ets2panda/test/runtime/ets/27016.ets new file mode 100644 index 0000000000..e551478513 --- /dev/null +++ b/ets2panda/test/runtime/ets/27016.ets @@ -0,0 +1,39 @@ +/* + * 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(a: Object) { + return a instanceof B +} + +interface A { + get(): TA +} +interface B extends A { +} + +class D implements B { + constructor(d: TD) { + this.d = d + } + get(): TD { + return this.d + } + d: TD +} + +function main() { + let a: A = new D(5) + arktest.assertEQ(a.get(), 5) +} diff --git a/ets2panda/util/perfMetrics.cpp b/ets2panda/util/perfMetrics.cpp index 981ec934c4..91cbcbe7a5 100644 --- a/ets2panda/util/perfMetrics.cpp +++ b/ets2panda/util/perfMetrics.cpp @@ -18,6 +18,7 @@ #include "libpandabase/utils/logger.h" #include "libpandabase/utils/type_converter.h" #include "libpandabase/mem/mem.h" +#include #include #include #include -- Gitee