diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 359b48f15bbd685db3160927f2c18da742438741..20fc11bf0e7bf1a9bc8d97244486f73c87b59516 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -1082,6 +1082,9 @@ checker::Type *ETSAnalyzer::Check(ir::Identifier *expr) const ETSChecker *checker = GetETSChecker(); auto *identType = checker->ResolveIdentifier(expr); + if (identType->IsETSTypeParameter() && identType->AsETSTypeParameter()->IdenticalToFinalConstraint()) { + identType = identType->AsETSTypeParameter()->GetConstraintType(); + } if (expr->Variable() != nullptr && (expr->Parent() == nullptr || !expr->Parent()->IsAssignmentExpression() || expr != expr->Parent()->AsAssignmentExpression()->Left())) { if (auto *const smartType = checker->Context().GetSmartCast(expr->Variable()); smartType != nullptr) { diff --git a/ets2panda/checker/ets/typeRelationContext.cpp b/ets2panda/checker/ets/typeRelationContext.cpp index 7d03ff0b843229cce2fecc079ffae868b5011391..723dcbb5c85b03be39126ae458d6c4ea1388d111 100644 --- a/ets2panda/checker/ets/typeRelationContext.cpp +++ b/ets2panda/checker/ets/typeRelationContext.cpp @@ -41,6 +41,13 @@ void AssignmentContext::ValidateArrayTypeInitializerByElement(TypeRelation *rela } } +void AssignmentContext::MaybeFinalSubstitute(Type *&type) +{ + if (type->IsETSTypeParameter() && type->AsETSTypeParameter()->IdenticalToFinalConstraint()) { + type = type->AsETSTypeParameter()->GetConstraintType(); + } +} + bool InstantiationContext::ValidateTypeArguments(ETSObjectType *type, ir::TSTypeParameterInstantiation *typeArgs, const lexer::SourcePosition &pos) { diff --git a/ets2panda/checker/ets/typeRelationContext.h b/ets2panda/checker/ets/typeRelationContext.h index 9e5943cc65df40f61f92201c990638713f3619c8..8ec9d097cb8815db3f2dab86889edcfab969c3e4 100644 --- a/ets2panda/checker/ets/typeRelationContext.h +++ b/ets2panda/checker/ets/typeRelationContext.h @@ -41,6 +41,9 @@ public: flags_ |= flags; relation->SetNode(node); + MaybeFinalSubstitute(source); + MaybeFinalSubstitute(target); + // NOTE (oeotvos) The narrowing flag will be applied here. It means, that the result of "let tmp: int = 1.5" // will be 1, which could cause problems. if (source->HasTypeFlag(TypeFlag::CONSTANT)) { @@ -75,6 +78,8 @@ public: void ValidateArrayTypeInitializerByElement(TypeRelation *relation, ir::ArrayExpression *node, ETSArrayType *target); + void MaybeFinalSubstitute(Type *&type); + private: TypeRelationFlag flags_ = TypeRelationFlag::IN_ASSIGNMENT_CONTEXT; bool assignable_ {false}; @@ -94,6 +99,7 @@ public: auto *const etsChecker = relation->GetChecker()->AsETSChecker(); relation->SetNode(node); + relation->SetFlags(flags_ | initialFlags); if (!relation->IsAssignableTo(source, target)) { diff --git a/ets2panda/checker/types/ets/etsTypeParameter.cpp b/ets2panda/checker/types/ets/etsTypeParameter.cpp index 0ae9a6f2b592e935bb31ff2a431cca3c0ac55aa8..3108ffb3f44218e8f70f5d6a66484218c6baa9e5 100644 --- a/ets2panda/checker/types/ets/etsTypeParameter.cpp +++ b/ets2panda/checker/types/ets/etsTypeParameter.cpp @@ -131,4 +131,17 @@ ETSTypeParameter *ETSTypeParameter::GetOriginal() const return GetDeclNode()->Name()->Variable()->TsType()->AsETSTypeParameter(); } -} // namespace ark::es2panda::checker +bool ETSTypeParameter::IdenticalToFinalConstraint() const +{ + if (constraint_ == nullptr) { + return false; + } + + if (constraint_->Variable() != nullptr && constraint_->Variable()->Declaration() != nullptr) { + auto declNode = constraint_->Variable()->Declaration()->Node(); + return declNode != nullptr && declNode->IsFinal(); + } + return false; +} + +} // namespace ark::es2panda::checker \ No newline at end of file diff --git a/ets2panda/checker/types/ets/etsTypeParameter.h b/ets2panda/checker/types/ets/etsTypeParameter.h index ed35e3cf647eb4e61df63aac7bd7a7a946d6c6ac..c8d0d45dcbf9cca2b5685aaf6495b84d59bba829 100644 --- a/ets2panda/checker/types/ets/etsTypeParameter.h +++ b/ets2panda/checker/types/ets/etsTypeParameter.h @@ -71,6 +71,7 @@ public: void IsSubtypeOf(TypeRelation *relation, Type *target) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; Type *Substitute(TypeRelation *relation, const Substitution *substitution) override; + bool IdenticalToFinalConstraint() const; void ToAssemblerType(std::stringstream &ss) const override; void ToDebugInfoType(std::stringstream &ss) const override;