已合并
Defined a CTE for invalid recursive type alias constructions #10173
Defined a CTE for invalid recursive type alias constructions #10173
已合并
fanglou创建于 3月17日
共 3 个文件变更+66-22
@@ -959,6 +959,10 @@ private:
959 // Check type alias for recursive cases959 // Check type alias for recursive cases
960 bool IsAllowedTypeAliasRecursion(const ir::TSTypeAliasDeclaration *typeAliasNode,960 bool IsAllowedTypeAliasRecursion(const ir::TSTypeAliasDeclaration *typeAliasNode,
961 std::unordered_set<const ir::TSTypeAliasDeclaration *> &typeAliases);961 std::unordered_set<const ir::TSTypeAliasDeclaration *> &typeAliases);
962+ bool CheckTypeReferencePartRecursion(ir::ETSTypeReferencePart *part,
963+ std::unordered_set<const ir::TSTypeAliasDeclaration *> &typeAliases);
964+ bool CheckTypeParamsRecursion(ir::TSTypeParameterInstantiation *typeParams,
965+ std::unordered_set<const ir::TSTypeAliasDeclaration *> &typeAliases);
962 966 
963 bool IsExceptionOrErrorType(checker::Type *type);967 bool IsExceptionOrErrorType(checker::Type *type);
964 968 
@@ -781,6 +781,43 @@ Type *ETSChecker::GuaranteedTypeForUnionFieldAccess(ir::MemberExpression *member
781 return CreateETSUnionType(std::move(apparentTypes));781 return CreateETSUnionType(std::move(apparentTypes));
782}782}
783 783 
784+bool ETSChecker::CheckTypeParamsRecursion(ir::TSTypeParameterInstantiation *typeParams,
785+ std::unordered_set<const ir::TSTypeAliasDeclaration *> &typeAliases)
786+{
787+ bool allowed = true;
788+ for (auto *typeParam : typeParams->Params()) {
789+ if (typeParam->IsETSTypeReference()) {
790+ allowed &= CheckTypeReferencePartRecursion(typeParam->AsETSTypeReference()->Part(), typeAliases);
791+ }
792+ }
793+ return allowed;
794+}
795+ 
796+bool ETSChecker::CheckTypeReferencePartRecursion(ir::ETSTypeReferencePart *part,
797+ std::unordered_set<const ir::TSTypeAliasDeclaration *> &typeAliases)
798+{
799+ if (!part->Name()->IsIdentifier() && !part->Name()->IsTSQualifiedName()) {
800+ return false;
801+ }
802+ auto *var = part->Name()->IsIdentifier() ? part->Name()->Variable()
803+ : part->Name()->AsTSQualifiedName()->Right()->Variable();
804+ if (part->Name()->Variable() == nullptr) {
805+ return true;
806+ }
807+ 
808+ auto const *const decl = var->Declaration();
809+ if (auto const *const node = decl->Node(); node != nullptr && node->IsTSTypeAliasDeclaration()) {
810+ bool allowed = IsAllowedTypeAliasRecursion(node->AsTSTypeAliasDeclaration(), typeAliases);
811+ if (allowed && part->TypeParams() != nullptr) {
812+ allowed &= CheckTypeParamsRecursion(part->TypeParams(), typeAliases);
813+ }
814+ 
815+ return allowed;
816+ }
817+ 
818+ return true;
819+}
820+ 
784bool ETSChecker::IsAllowedTypeAliasRecursion(const ir::TSTypeAliasDeclaration *typeAliasNode,821bool ETSChecker::IsAllowedTypeAliasRecursion(const ir::TSTypeAliasDeclaration *typeAliasNode,
785 std::unordered_set<const ir::TSTypeAliasDeclaration *> &typeAliases)822 std::unordered_set<const ir::TSTypeAliasDeclaration *> &typeAliases)
786{823{
@@ -792,39 +829,23 @@ bool ETSChecker::IsAllowedTypeAliasRecursion(const ir::TSTypeAliasDeclaration *t
792 return false;829 return false;
793 }830 }
794 831 
795- auto typeAliasDeclarationCheck = [this, &typeAliases](ir::ETSTypeReferencePart *part) {
796- if (!part->Name()->IsIdentifier() && !part->Name()->IsTSQualifiedName()) {
797- return false;
798- }
799- auto *var = part->Name()->IsIdentifier() ? part->Name()->Variable()
800- : part->Name()->AsTSQualifiedName()->Right()->Variable();
801- if (part->Name()->Variable() == nullptr) {
802- return true;
803- }
804- 
805- auto const *const decl = var->Declaration();
806- if (auto const *const node = decl->Node(); node != nullptr && node->IsTSTypeAliasDeclaration()) {
807- return IsAllowedTypeAliasRecursion(node->AsTSTypeAliasDeclaration(), typeAliases);
808- }
809- 
810- return true;
811- };
812- 
813 if (typeAliasNode->TypeAnnotation()->IsETSFunctionType() &&832 if (typeAliasNode->TypeAnnotation()->IsETSFunctionType() &&
814 typeAliasNode->TypeAnnotation()->AsETSFunctionType()->ReturnType()->IsETSTypeReference()) {833 typeAliasNode->TypeAnnotation()->AsETSFunctionType()->ReturnType()->IsETSTypeReference()) {
815- isAllowedRerursiveType &= typeAliasDeclarationCheck(834+ isAllowedRerursiveType &= CheckTypeReferencePartRecursion(
816- typeAliasNode->TypeAnnotation()->AsETSFunctionType()->ReturnType()->AsETSTypeReference()->Part());835+ typeAliasNode->TypeAnnotation()->AsETSFunctionType()->ReturnType()->AsETSTypeReference()->Part(),
836+ typeAliases);
817 }837 }
818 838 
819 if (typeAliasNode->TypeAnnotation()->IsETSTypeReference()) {839 if (typeAliasNode->TypeAnnotation()->IsETSTypeReference()) {
820 isAllowedRerursiveType &=840 isAllowedRerursiveType &=
821- typeAliasDeclarationCheck(typeAliasNode->TypeAnnotation()->AsETSTypeReference()->Part());841+ CheckTypeReferencePartRecursion(typeAliasNode->TypeAnnotation()->AsETSTypeReference()->Part(), typeAliases);
822 }842 }
823 843 
824 if (isAllowedRerursiveType && typeAliasNode->TypeAnnotation()->IsETSUnionType()) {844 if (isAllowedRerursiveType && typeAliasNode->TypeAnnotation()->IsETSUnionType()) {
825 for (auto &type : typeAliasNode->TypeAnnotation()->AsETSUnionType()->Types()) {845 for (auto &type : typeAliasNode->TypeAnnotation()->AsETSUnionType()->Types()) {
826 if (type->IsETSTypeReference()) {846 if (type->IsETSTypeReference()) {
827- isAllowedRerursiveType &= typeAliasDeclarationCheck(type->AsETSTypeReference()->Part());847+ isAllowedRerursiveType &=
848+ CheckTypeReferencePartRecursion(type->AsETSTypeReference()->Part(), typeAliases);
828 }849 }
829 }850 }
830 }851 }
@@ -0,0 +1,19 @@
1+/*
2+ * Copyright (c) 2026 Huawei Device Co., Ltd.
3+ * Licensed under the Apache License, Version 2.0 (the "License");
4+ * you may not use this file except in compliance with the License.
5+ * You may obtain a copy of the License at
6+ *
7+ * http://www.apache.org/licenses/LICENSE-2.0
8+ *
9+ * Unless required by applicable law or agreed to in writing, software
10+ * distributed under the License is distributed on an "AS IS" BASIS,
11+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+ * See the License for the specific language governing permissions and
13+ * limitations under the License.
14+ */
15+ 
16+type C<T> = T
17+type A = C<A>
18+ 
19+/* @@? 17:1 Error Semantic error ESE0311: Circular type alias reference */