From 3fc0d194a4fcbcb59fe88b68fec3775b2902d352 Mon Sep 17 00:00:00 2001 From: Tatiana Pivovarova Date: Wed, 14 Jun 2023 17:34:12 +0300 Subject: [PATCH] Check if type parameters without wildcards are strictly equal Fixes #11765 internal issue Signed-off-by: Tatiana Pivovarova --- checker/ETSchecker.h | 2 ++ checker/ets/helpers.cpp | 46 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/checker/ETSchecker.h b/checker/ETSchecker.h index cfe168bd1..6166f2a85 100644 --- a/checker/ETSchecker.h +++ b/checker/ETSchecker.h @@ -402,6 +402,8 @@ public: void CheckBoxedSourceTypeAssignable(TypeRelation *relation, Type *source, Type *target); void CheckUnboxedSourceTypeWithWideningAssignable(TypeRelation *relation, Type *source, Type *target); void CheckValidGenericTypeParameter(Type *arg_type, const lexer::SourcePosition &pos); + void CheckValidGenericTypeAssignable(ir::ETSTypeReferencePart *source, ir::ETSTypeReferencePart *target, + const lexer::SourcePosition &pos); void ValidateResolvedProperty(const binder::LocalVariable *property, const ETSObjectType *target, const ir::Identifier *ident, PropertySearchFlags flags); Type *GetReferredTypeFromETSTypeReference(Type *type_ref) const; diff --git a/checker/ets/helpers.cpp b/checker/ets/helpers.cpp index fe56e102c..bac26bc0a 100644 --- a/checker/ets/helpers.cpp +++ b/checker/ets/helpers.cpp @@ -757,6 +757,14 @@ checker::Type *ETSChecker::CheckVariableDeclaration(ir::Identifier *ident, ir::T checker::Type *const init_type = init->Check(this); if (annotation_type != nullptr) { + if (init->TsType()->HasTypeFlag(TypeFlag::GENERIC) && + type_annotation->TsType()->HasTypeFlag(TypeFlag::GENERIC) && init->IsETSNewClassInstanceExpression()) { + auto ref = init->AsETSNewClassInstanceExpression()->GetTypeRef(); + if (ref != nullptr && ref->IsETSTypeReference() && type_annotation->IsETSTypeReference()) { + CheckValidGenericTypeAssignable(ref->AsETSTypeReference()->Part(), + type_annotation->AsETSTypeReference()->Part(), ident->Start()); + } + } AssignmentContext(Relation(), init, init_type, annotation_type, init->Start(), {"Initializers type is not assignable to the target type"}); if (is_const && init_type->HasTypeFlag(TypeFlag::ETS_PRIMITIVE) && @@ -2077,4 +2085,42 @@ void ETSChecker::SubstituteGenericTypeDeclTypeParams(ETSObjectType *const type) type->TypeArguments().push_back(type_param_type); } } + +void ETSChecker::CheckValidGenericTypeAssignable(ir::ETSTypeReferencePart *source, ir::ETSTypeReferencePart *target, + const lexer::SourcePosition &pos) +{ + bool is_valid = true; + is_valid &= target->Name()->Variable() == source->Name()->Variable(); + is_valid &= target->Modifiers() == source->Modifiers(); + + auto const target_type_args = target->TypeParams()->Params(); + auto const source_type_args = source->TypeParams()->Params(); + ASSERT(target_type_args.size() == source_type_args.size()); + + const auto get_original_base_type_or_type = [this](Type *const original_type) { + auto *const base_type = this->GetOriginalBaseType(original_type); + return base_type == nullptr ? original_type : base_type; + }; + + for (size_t idx = 0; idx < source_type_args.size(); idx++) { + if (target_type_args[idx]->IsETSWildcardType() || source_type_args[idx]->IsETSWildcardType()) { + continue; + } + is_valid &= target_type_args[idx]->Variable() == source_type_args[idx]->Variable(); + is_valid &= target_type_args[idx]->Modifiers() == source_type_args[idx]->Modifiers(); + + auto *const target_arg_type = get_original_base_type_or_type(target_type_args[idx]->GetType(this)); + auto *const source_arg_type = get_original_base_type_or_type(source_type_args[idx]->GetType(this)); + + is_valid &= target_arg_type != nullptr && source_arg_type != nullptr; + + if (is_valid) { + target_arg_type->Identical(Relation(), source_arg_type); + is_valid &= Relation()->IsTrue(); + } else { + ThrowTypeError("Cannot convert incompatible types.", pos); + } + } +} + } // namespace panda::es2panda::checker -- Gitee