From 69028249d74f60691914bc308ba49303a51ef1e6 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Sat, 19 Mar 2022 10:09:14 -0700 Subject: [PATCH] Improved handling of recursive type aliases --- IDEHelper/Compiler/BfModule.cpp | 7 +++ IDEHelper/Compiler/BfModule.h | 1 + IDEHelper/Compiler/BfModuleTypeUtils.cpp | 78 +++++++++++++++--------- 3 files changed, 56 insertions(+), 30 deletions(-) diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 43aabfc8..c5cb0e3f 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -3650,6 +3650,13 @@ void BfModule::AddDependency(BfType* usedType, BfType* userType, BfDependencyMap } } + if (usedType->IsTypeAlias()) + { + usedType = SafeResolveAliasType((BfTypeAliasType*)usedType); + if (usedType == NULL) + return; + } + if (!usedType->IsGenericTypeInstance()) { auto underlyingType = usedType->GetUnderlyingType(); diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index bb4294dc..01f9d852 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1873,6 +1873,7 @@ public: BfTypeInstance* GetBaseType(BfTypeInstance* typeInst); void HandleTypeGenericParamRef(BfAstNode* refNode, BfTypeDef* typeDef, int typeGenericParamIdx); void HandleMethodGenericParamRef(BfAstNode* refNode, BfTypeDef* typeDef, BfMethodDef* methodDef, int typeGenericParamIdx); + BfType* SafeResolveAliasType(BfTypeAliasType* aliasType); bool ResolveTypeResult_Validate(BfAstNode* typeRef, BfType* resolvedTypeRef); BfType* ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTypeRef, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags); void ShowAmbiguousTypeError(BfAstNode* refNode, BfTypeDef* typeDef, BfTypeDef* otherTypeDef); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 0b827985..9c9155ac 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -2899,22 +2899,6 @@ void BfModule::DoPopulateType_TypeAlias(BfTypeAliasType* typeAlias) typeAlias->mAliasToType = aliasToType; if (aliasToType != NULL) - { - typeAlias->mSize = aliasToType->mSize; - typeAlias->mAlign = aliasToType->mAlign; - - if (auto aliasToTypeInst = aliasToType->ToTypeInstance()) - { - typeAlias->mInstSize = aliasToTypeInst->mInstSize; - typeAlias->mInstAlign = aliasToTypeInst->mInstAlign; - } - else - { - typeAlias->mInstSize = aliasToType->mSize; - typeAlias->mInstAlign = aliasToType->mAlign; - } - } - else { typeAlias->mSize = 0; typeAlias->mAlign = 1; @@ -8741,6 +8725,28 @@ bool BfModule::ResolveTypeResult_Validate(BfAstNode* typeRef, BfType* resolvedTy return true; } +BfType* BfModule::SafeResolveAliasType(BfTypeAliasType* aliasType) +{ + int aliasDepth = 0; + HashSet seenAliases; + + BfType* type = aliasType; + while (type->IsTypeAlias()) + { + aliasDepth++; + if (aliasDepth > 8) + { + if (!seenAliases.Add(type)) + return NULL; + } + + type = type->GetUnderlyingType(); + if (type == NULL) + return NULL; + } + return type; +} + BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTypeRef, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags) { if ((mCompiler->mIsResolveOnly) && (!IsInSpecializedSection())) @@ -8808,26 +8814,24 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy BfSourceElementType elemType = BfSourceElementType_Type; { - auto typeRef = resolvedTypeRef; - while (typeRef->IsTypeAlias()) + auto type = resolvedTypeRef; + + if (type->IsTypeAlias()) { - typeRef = typeRef->GetUnderlyingType(); - if (typeRef == NULL) - { - typeRef = resolvedTypeRef; - break; - } + type = SafeResolveAliasType((BfTypeAliasType*)type); + if (type == NULL) + type = resolvedTypeRef; } - if (typeRef->IsInterface()) + if (type->IsInterface()) elemType = BfSourceElementType_Interface; - else if (typeRef->IsObject()) + else if (type->IsObject()) elemType = BfSourceElementType_RefType; - else if (typeRef->IsGenericParam()) + else if (type->IsGenericParam()) elemType = BfSourceElementType_GenericParam; - else if (typeRef->IsPrimitiveType()) + else if (type->IsPrimitiveType()) elemType = BfSourceElementType_PrimitiveType; - else if (typeRef->IsStruct() || (typeRef->IsTypedPrimitive() && !typeRef->IsEnum())) + else if (type->IsStruct() || (type->IsTypedPrimitive() && !type->IsEnum())) elemType = BfSourceElementType_Struct; } @@ -9029,8 +9033,22 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy if ((populateType != BfPopulateType_TypeDef) && (populateType != BfPopulateType_IdentityNoRemapAlias)) { + int aliasDepth = 0; + HashSet seenAliases; + while ((resolvedTypeRef != NULL) && (resolvedTypeRef->IsTypeAlias())) { + aliasDepth++; + if (aliasDepth > 8) + { + if (!seenAliases.Add(resolvedTypeRef)) + { + if ((typeRef != NULL) && (!typeRef->IsTemporary())) + Fail(StrFormat("Type alias '%s' has a recursive definition", TypeToString(resolvedTypeRef).c_str()), typeRef); + break; + } + } + if (mCurTypeInstance != NULL) AddDependency(resolvedTypeRef, mCurTypeInstance, BfDependencyMap::DependencyFlag_NameReference); if (resolvedTypeRef->mDefineState == BfTypeDefineState_Undefined) @@ -9041,7 +9059,7 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy if (resolvedTypeRef != NULL) typeInstance = resolvedTypeRef->ToTypeInstance(); else - typeInstance = NULL; + typeInstance = NULL; } }