From d46c60d956ccdb0fafc781ed9cb87bd9969615c7 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Sat, 17 Oct 2020 16:31:46 -0700 Subject: [PATCH] Fixed tuple duplicate name check circular dependency issue --- IDEHelper/Compiler/BfExprEvaluator.cpp | 10 +++++++++- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 11 +++++++---- IDEHelper/Tests/src/Structs.bf | 6 ++++++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 051b4449..689b129d 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -17203,6 +17203,7 @@ void BfExprEvaluator::Visit(BfTupleExpression* tupleExpr) { BfTypeVector fieldTypes; Array fieldNames; + HashSet fieldNameSet; for (auto typedVal : typedValues) { auto type = typedVal.mType; @@ -17216,7 +17217,14 @@ void BfExprEvaluator::Visit(BfTupleExpression* tupleExpr) if (requestedName == NULL) fieldNames.push_back(""); else - fieldNames.push_back(requestedName->mNameNode->ToString()); + { + auto fieldName = requestedName->mNameNode->ToString(); + if (!fieldNameSet.TryAdd(fieldName, NULL)) + { + mModule->Fail(StrFormat("A field named '%s' has already been declared", fieldName.c_str()), requestedName->mNameNode); + } + fieldNames.push_back(fieldName); + } } tupleType = mModule->CreateTupleType(fieldTypes, fieldNames); } diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 266ff0c1..6175045b 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -2361,8 +2361,10 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy SetAndRestoreValue prevTypeRef(mContext->mCurTypeState->mCurBaseTypeRef, checkTypeRef); SetAndRestoreValue prevDefineState(typeInstance->mDefineState, BfTypeDefineState_ResolvingBaseType); - bool populateBase = !typeInstance->mTypeFailed; - auto checkType = ResolveTypeRef(checkTypeRef, populateBase ? BfPopulateType_Data : BfPopulateType_Declaration); + bool populateBase = !typeInstance->mTypeFailed; + auto checkType = ResolveTypeRef(checkTypeRef, BfPopulateType_Declaration); + if ((checkType != NULL) && (!checkType->IsInterface()) && (populateBase)) + PopulateType(checkType, BfPopulateType_Data); if (typeInstance->mDefineState >= BfTypeDefineState_Defined) { @@ -7206,8 +7208,9 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy if (typeInstance->IsTuple()) { - if (typeInstance->mDefineState < BfTypeDefineState_Defined) - PopulateType(typeInstance); + //TODO: This can cause circular reference issues. Is there a case this is needed? + //if (typeInstance->mDefineState < BfTypeDefineState_Defined) + // PopulateType(typeInstance); if (typeInstance->mHasDeclError) { if (auto tupleTypeRef = BfNodeDynCast(typeRef)) diff --git a/IDEHelper/Tests/src/Structs.bf b/IDEHelper/Tests/src/Structs.bf index b7c48136..4f5dd1da 100644 --- a/IDEHelper/Tests/src/Structs.bf +++ b/IDEHelper/Tests/src/Structs.bf @@ -1,6 +1,7 @@ #pragma warning disable 168 using System; +using System.Collections; namespace Tests { @@ -118,6 +119,11 @@ namespace Tests int32 mB; } + struct StructK + { + Dictionary dict; + } + [Test] static void TestBasics() {