1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 12:32:20 +02:00

Fixed some comptime dependency rebuilding issues with aliases/extensions

This commit is contained in:
Brian Fiete 2022-02-16 18:28:23 -05:00
parent 1cd198cea9
commit 434a7406de
22 changed files with 394 additions and 86 deletions

View file

@ -4,28 +4,43 @@
NS_BF_BEGIN; NS_BF_BEGIN;
#define BF_BITSET_ELEM_SIZE (sizeof(uintptr)*8) #define BF_BITSET_ELEM_BITCOUNT (sizeof(uintptr)*8)
class BitSet class BitSet
{ {
public: public:
uintptr* mBits; uintptr* mBits;
int mNumInts; int mNumBits;
public: public:
BitSet() BitSet()
{ {
mNumInts = 0; mNumBits = 0;
mBits = NULL; mBits = NULL;
} }
BitSet(int numBits) BitSet(int numBits)
{ {
mNumInts = 0; mNumBits = 0;
mBits = NULL; mBits = NULL;
this->Resize(numBits); this->Resize(numBits);
} }
BitSet(BitSet&& other)
{
mNumBits = other.mNumBits;
mBits = other.mBits;
other.mNumBits = 0;
other.mBits = NULL;
}
BitSet(const BitSet& other)
{
mNumBits = 0;
mBits = NULL;
*this = other;
}
~BitSet() ~BitSet()
{ {
delete this->mBits; delete this->mBits;
@ -33,28 +48,68 @@ public:
void Resize(int numBits) void Resize(int numBits)
{ {
int numInts = (numBits + BF_BITSET_ELEM_SIZE - 1) / BF_BITSET_ELEM_SIZE; int numInts = (numBits + BF_BITSET_ELEM_BITCOUNT - 1) / BF_BITSET_ELEM_BITCOUNT;
if (numInts == mNumInts) int curNumInts = (mNumBits + BF_BITSET_ELEM_BITCOUNT - 1) / BF_BITSET_ELEM_BITCOUNT;
return; mNumBits = numBits;
this->mNumInts = numInts; if (numInts == curNumInts)
return;
this->mNumBits = numBits;
delete this->mBits; delete this->mBits;
this->mBits = new uintptr[numInts]; this->mBits = new uintptr[numInts];
memset(this->mBits, 0, numInts * sizeof(uintptr)); memset(this->mBits, 0, numInts * sizeof(uintptr));
} }
bool IsSet(int idx) void Clear()
{ {
return (this->mBits[idx / BF_BITSET_ELEM_SIZE] & ((uintptr)1 << (idx % BF_BITSET_ELEM_SIZE))) != 0; int curNumInts = (mNumBits + BF_BITSET_ELEM_BITCOUNT - 1) / BF_BITSET_ELEM_BITCOUNT;
memset(mBits, 0, curNumInts * sizeof(uintptr));
}
bool IsSet(int idx) const
{
BF_ASSERT((uintptr)idx < (uintptr)mNumBits);
return (this->mBits[idx / BF_BITSET_ELEM_BITCOUNT] & ((uintptr)1 << (idx % BF_BITSET_ELEM_BITCOUNT))) != 0;
} }
void Set(int idx) void Set(int idx)
{ {
this->mBits[idx / BF_BITSET_ELEM_SIZE] |= ((uintptr)1 << (idx % BF_BITSET_ELEM_SIZE)); BF_ASSERT((uintptr)idx < (uintptr)mNumBits);
this->mBits[idx / BF_BITSET_ELEM_BITCOUNT] |= ((uintptr)1 << (idx % BF_BITSET_ELEM_BITCOUNT));
} }
void Clear(int idx) void Clear(int idx)
{ {
this->mBits[idx / BF_BITSET_ELEM_SIZE] &= ~((uintptr)1 << (idx % BF_BITSET_ELEM_SIZE)); BF_ASSERT((uintptr)idx < (uintptr)mNumBits);
this->mBits[idx / BF_BITSET_ELEM_BITCOUNT] &= ~((uintptr)1 << (idx % BF_BITSET_ELEM_BITCOUNT));
}
bool IsEmpty()
{
return mNumBits == 0;
}
bool operator==(const BitSet& other) const
{
int curNumInts = (mNumBits + BF_BITSET_ELEM_BITCOUNT - 1) / BF_BITSET_ELEM_BITCOUNT;
if (mNumBits != other.mNumBits)
return false;
for (int i = 0; i < curNumInts; i++)
if (mBits[i] != other.mBits[i])
return false;
return true;
}
bool operator!=(const BitSet& other) const
{
return !(*this == other);
}
BitSet& operator=(const BitSet& other)
{
Resize(other.mNumBits);
int curNumInts = (mNumBits + BF_BITSET_ELEM_BITCOUNT - 1) / BF_BITSET_ELEM_BITCOUNT;
memcpy(mBits, other.mBits, curNumInts * sizeof(uintptr));
return *this;
} }
}; };

View file

@ -0,0 +1,5 @@
FileVersion = 1
[Project]
Name = "Bug"
StartupObject = "Bug.Program"

View file

@ -0,0 +1,6 @@
FileVersion = 1
Projects = {Bug = {Path = "."}}
[Workspace]
StartupProject = "Bug"

View file

@ -0,0 +1,15 @@
# This tests that comptime changes to generic passed extension constraints rebuilds dependencies
ShowFile("src/Program.bf")
GotoText("//End")
ToggleBreakpoint()
RunWithCompiling()
AssertEvalEquals("val", "1")
StopRunning()
ShowFile("src/Gen.bf")
ToggleCommentAt("Void")
ToggleCommentAt("String")
RunWithCompiling()
AssertEvalEquals("val", "2")
StopRunning()

View file

@ -0,0 +1,18 @@
using System;
namespace Bug
{
class Gen
{
public static Type Get()
{
//*Void
return typeof(void);
/*@*/
/*String
return typeof(String);
*/
}
}
}

View file

@ -0,0 +1,34 @@
#pragma warning disable 168
using System;
using System.Collections;
namespace Bug
{
class Zonk<T>
{
public int Call(float val)
{
return 1;
}
}
extension Zonk<T> where comptype(Gen.Get()) : String
{
public int Call(int val)
{
return 2;
}
}
class Program
{
public static int Main(String[] args)
{
Zonk<int> zk = scope .();
int val = zk.Call(1);
//End
return 0;
}
}
}

View file

@ -0,0 +1,5 @@
FileVersion = 1
[Project]
Name = "Bug"
StartupObject = "Bug.Program"

View file

@ -0,0 +1,6 @@
FileVersion = 1
Projects = {Bug = {Path = "."}}
[Workspace]
StartupProject = "Bug"

View file

@ -0,0 +1,15 @@
# This tests that comptime alias changes rebuild dependent types
ShowFile("src/Program.bf")
GotoText("//End")
ToggleBreakpoint()
RunWithCompiling()
AssertEvalEquals("val", "1")
StopRunning()
ShowFile("src/Gen.bf")
ToggleCommentAt("ClassA")
ToggleCommentAt("ClassB")
RunWithCompiling()
AssertEvalEquals("val", "2")
StopRunning()

View file

@ -0,0 +1,18 @@
using System;
namespace Bug
{
class Gen
{
public static Type Get()
{
//*ClassA
return typeof(ClassA);
/*@*/
/*ClassB
return typeof(ClassB);
*/
}
}
}

View file

@ -0,0 +1,42 @@
#pragma warning disable 168
using System;
using System.Collections;
namespace Bug
{
class ClassA
{
public int Call()
{
return 1;
}
}
class ClassB
{
public int Call()
{
return 2;
}
}
typealias Alias1 = comptype(Gen.Get());
typealias Alias2 = Alias1;
class Zonk<T> : Alias2
{
}
class Program
{
public static int Main(String[] args)
{
Zonk<int> zk = scope .();
int val = zk.Call();
//End
return 0;
}
}
}

View file

@ -7012,47 +7012,58 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mStats.mTypesQueued += (int)mContext->mPopulateTypeWorkList.size(); mStats.mTypesQueued += (int)mContext->mPopulateTypeWorkList.size();
mStats.mMethodsQueued += (int)mContext->mMethodWorkList.size(); mStats.mMethodsQueued += (int)mContext->mMethodWorkList.size();
// while (true)
{
if (mBfObjectTypeDef != NULL)
mContext->mScratchModule->ResolveTypeDef(mBfObjectTypeDef, BfPopulateType_Full);
mContext->RemapObject();
mSystem->CheckLockYield();
mWantsDeferMethodDecls = mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude;
CompileReified();
mWantsDeferMethodDecls = false;
}
BpLeave();
BpEnter("Compile_End");
{ {
BP_ZONE("ProcessingLiveness"); //
for (auto type : mContext->mResolvedTypes)
{
auto depType = type->ToDependedType();
if (depType != NULL)
depType->mRebuildFlags = (BfTypeRebuildFlags)(depType->mRebuildFlags | BfTypeRebuildFlag_AwaitingReference);
}
bool didWork = false;
UpdateDependencyMap(mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_ResolveUnused, didWork);
if (mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude)
{ {
// If UpdateDependencyMap caused methods to be reified, then we need to run PopulateReified again- if (mBfObjectTypeDef != NULL)
// because those methods may be virtual and we need to reify overrides (for example). mContext->mScratchModule->ResolveTypeDef(mBfObjectTypeDef, BfPopulateType_Full);
// We use the DoWorkLoop result to determine if there were actually any changes from UpdateDependencyMap
if (didWork) mContext->RemapObject();
mSystem->CheckLockYield();
mWantsDeferMethodDecls = mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude;
CompileReified();
mWantsDeferMethodDecls = false;
}
BpLeave();
BpEnter("Compile_End");
mContext->mHasReifiedQueuedRebuildTypes = false;
//
{
BP_ZONE("ProcessingLiveness");
for (auto type : mContext->mResolvedTypes)
{ {
PopulateReified(); auto depType = type->ToDependedType();
if (depType != NULL)
depType->mRebuildFlags = (BfTypeRebuildFlags)(depType->mRebuildFlags | BfTypeRebuildFlag_AwaitingReference);
} }
}
bool didWork = false;
UpdateDependencyMap(mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_ResolveUnused, didWork);
if (mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude)
{
// If UpdateDependencyMap caused methods to be reified, then we need to run PopulateReified again-
// because those methods may be virtual and we need to reify overrides (for example).
// We use the DoWorkLoop result to determine if there were actually any changes from UpdateDependencyMap
if (didWork)
{
PopulateReified();
}
}
}
if (!mContext->mHasReifiedQueuedRebuildTypes)
break;
BfLogSysM("DoCompile looping over CompileReified due to mHasReifiedQueuedRebuildTypes\n");
} }
ProcessPurgatory(true); ProcessPurgatory(true);

View file

@ -77,7 +77,8 @@ BfContext::BfContext(BfCompiler* compiler) :
mValueTypeDeinitSentinel = (BfMethodInstance*)1; mValueTypeDeinitSentinel = (BfMethodInstance*)1;
mCurStringObjectPoolId = 0; mCurStringObjectPoolId = 0;
mHasReifiedQueuedRebuildTypes = false;
} }
void BfReportMemory(); void BfReportMemory();
@ -945,6 +946,9 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
return; return;
} }
if (typeInst->mIsReified)
mHasReifiedQueuedRebuildTypes = true;
typeInst->mRebuildFlags = (BfTypeRebuildFlags)(typeInst->mRebuildFlags & ~BfTypeRebuildFlag_AddedToWorkList); typeInst->mRebuildFlags = (BfTypeRebuildFlags)(typeInst->mRebuildFlags & ~BfTypeRebuildFlag_AddedToWorkList);
bool addToWorkList = true; bool addToWorkList = true;
@ -1131,8 +1135,8 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
genericTypeInstance->mGenericTypeInfo->mGenericParams.Clear(); genericTypeInstance->mGenericTypeInfo->mGenericParams.Clear();
genericTypeInstance->mGenericTypeInfo->mValidatedGenericConstraints = false; genericTypeInstance->mGenericTypeInfo->mValidatedGenericConstraints = false;
genericTypeInstance->mGenericTypeInfo->mHadValidateErrors = false; genericTypeInstance->mGenericTypeInfo->mHadValidateErrors = false;
delete genericTypeInstance->mGenericTypeInfo->mGenericExtensionInfo; if (genericTypeInstance->mGenericTypeInfo->mGenericExtensionInfo != NULL)
genericTypeInstance->mGenericTypeInfo->mGenericExtensionInfo = NULL; genericTypeInstance->mGenericTypeInfo->mGenericExtensionInfo->Clear();
genericTypeInstance->mGenericTypeInfo->mProjectsReferenced.Clear(); genericTypeInstance->mGenericTypeInfo->mProjectsReferenced.Clear();
} }
@ -1182,6 +1186,22 @@ void BfContext::RebuildDependentTypes(BfDependedType* dType)
TypeMethodSignaturesChanged(typeInst); TypeMethodSignaturesChanged(typeInst);
} }
void BfContext::RebuildDependentTypes_MidCompile(BfDependedType* dType, const String& reason)
{
dType->mRebuildFlags = (BfTypeRebuildFlags)(dType->mRebuildFlags | BfTypeRebuildFlag_ChangedMidCompile);
int prevDeletedTypes = mCompiler->mStats.mTypesDeleted;
if (mCompiler->mIsResolveOnly)
mCompiler->mNeedsFullRefresh = true;
BfLogSysM("Rebuilding dependent types MidCompile Type:%p Reason:%s\n", dType, reason.c_str());
RebuildDependentTypes(dType);
if (mCompiler->mStats.mTypesDeleted != prevDeletedTypes)
{
BfLogSysM("Rebuilding dependent types MidCompile Type:%p Reason:%s - updating after deleting types\n", dType, reason.c_str());
UpdateAfterDeletingTypes();
}
}
// Dependencies cascade as such: // Dependencies cascade as such:
// DerivedFrom / StructMemberData: these change the layout of memory for the dependent classes, // DerivedFrom / StructMemberData: these change the layout of memory for the dependent classes,
// so not only do the dependent classes need to be rebuild, but any other classes relying on those derived classes // so not only do the dependent classes need to be rebuild, but any other classes relying on those derived classes
@ -1254,7 +1274,7 @@ void BfContext::TypeDataChanged(BfDependedType* dType, bool isNonStaticDataChang
} }
if (dependentType->mRevision != mCompiler->mRevision) if (dependentType->mRevision != mCompiler->mRevision)
{ {
// We need to include DependencyFlag_ParamOrReturnValue because it could be a struct that changes its splatting ability // We need to include DependencyFlag_ParamOrReturnValue because it could be a struct that changes its splatting ability
// We can't ONLY check against structs, though, because a type could change from a class to a struct // We can't ONLY check against structs, though, because a type could change from a class to a struct
if (dependencyFlags & if (dependencyFlags &
@ -1264,6 +1284,12 @@ void BfContext::TypeDataChanged(BfDependedType* dType, bool isNonStaticDataChang
{ {
RebuildType(dependentType); RebuildType(dependentType);
} }
else if (((dependencyFlags & BfDependencyMap::DependencyFlag_NameReference) != 0) &&
((dType->mRebuildFlags & BfTypeRebuildFlag_ChangedMidCompile) != 0) &&
(dType->IsTypeAlias()))
{
RebuildType(dependentType);
}
} }
} }
else else
@ -1276,7 +1302,7 @@ void BfContext::TypeDataChanged(BfDependedType* dType, bool isNonStaticDataChang
} }
} }
if (dType->mRevision != mCompiler->mRevision) if (dType->mRevision != mCompiler->mRevision)
RebuildType(dType); RebuildType(dType);
} }

View file

@ -351,7 +351,7 @@ class BfContext
{ {
public: public:
CritSect mCritSect; CritSect mCritSect;
bool mDeleting; bool mDeleting;
BfTypeState* mCurTypeState; BfTypeState* mCurTypeState;
BfSizedArray<BfNamespaceDeclaration*>* mCurNamespaceNodes; BfSizedArray<BfNamespaceDeclaration*>* mCurNamespaceNodes;
@ -397,6 +397,7 @@ public:
WorkQueue<BfTypeRefVerifyRequest> mTypeRefVerifyWorkList; WorkQueue<BfTypeRefVerifyRequest> mTypeRefVerifyWorkList;
PtrWorkQueue<BfModule*> mFinishedSlotAwaitModuleWorkList; PtrWorkQueue<BfModule*> mFinishedSlotAwaitModuleWorkList;
PtrWorkQueue<BfModule*> mFinishedModuleWorkList; PtrWorkQueue<BfModule*> mFinishedModuleWorkList;
bool mHasReifiedQueuedRebuildTypes;
Array<BfGenericParamType*> mGenericParamTypes[3]; Array<BfGenericParamType*> mGenericParamTypes[3];
@ -475,6 +476,7 @@ public:
void ValidateDependencies(); void ValidateDependencies();
void RebuildType(BfType* type, bool deleteOnDemandTypes = true, bool rebuildModule = true, bool placeSpecializiedInPurgatory = true); void RebuildType(BfType* type, bool deleteOnDemandTypes = true, bool rebuildModule = true, bool placeSpecializiedInPurgatory = true);
void RebuildDependentTypes(BfDependedType* dType); void RebuildDependentTypes(BfDependedType* dType);
void RebuildDependentTypes_MidCompile(BfDependedType* dType, const String& reason);
void TypeDataChanged(BfDependedType* dType, bool isNonStaticDataChange); void TypeDataChanged(BfDependedType* dType, bool isNonStaticDataChange);
void TypeMethodSignaturesChanged(BfTypeInstance* typeInst); void TypeMethodSignaturesChanged(BfTypeInstance* typeInst);
void TypeInlineMethodInternalsChanged(BfTypeInstance* typeInst); void TypeInlineMethodInternalsChanged(BfTypeInstance* typeInst);

View file

@ -1746,7 +1746,11 @@ String BfIRBuilder::ToString(BfIRValue irValue)
auto typeofConst = (BfTypeOf_WithData_Const*)constant; auto typeofConst = (BfTypeOf_WithData_Const*)constant;
return "typeof_withData " + mModule->TypeToString(typeofConst->mType); return "typeof_withData " + mModule->TypeToString(typeofConst->mType);
} }
else if (constant->mConstType == BfConstType_Undef)
{
auto constUndef = (BfConstantUndef*)constant;
return "undef " + ToString(constUndef->mType);
}
else else
{ {
BF_FATAL("Unhandled"); BF_FATAL("Unhandled");

View file

@ -1258,7 +1258,7 @@ void BfModule::StartNewRevision(RebuildKind rebuildKind, bool force)
mHadBuildError = false; mHadBuildError = false;
mHadBuildWarning = false; mHadBuildWarning = false;
mExtensionCount = 0; mExtensionCount = 0;
mRevision = mCompiler->mRevision; mRevision = mCompiler->mRevision;
mRebuildIdx++; mRebuildIdx++;
ClearModuleData(!force); ClearModuleData(!force);

View file

@ -1775,7 +1775,7 @@ public:
void ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind, bool underlyingTypeDeferred); void ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind, bool underlyingTypeDeferred);
void DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers, bool underlyingTypeDeferred); void DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers, bool underlyingTypeDeferred);
void DoCEEmit(BfMethodInstance* methodInstance); void DoCEEmit(BfMethodInstance* methodInstance);
void DoPopulateType_TypeAlias(BfTypeInstance* typeAlias); void DoPopulateType_TypeAlias(BfTypeAliasType* typeAlias);
void DoPopulateType_InitSearches(BfTypeInstance* typeInstance); void DoPopulateType_InitSearches(BfTypeInstance* typeInstance);
void DoPopulateType_SetGenericDependencies(BfTypeInstance* genericTypeInstance); void DoPopulateType_SetGenericDependencies(BfTypeInstance* genericTypeInstance);
void DoPopulateType_FinishEnum(BfTypeInstance* typeInstance, bool underlyingTypeDeferred, HashContext* dataMemberHashCtx, BfType* unionInnerType); void DoPopulateType_FinishEnum(BfTypeInstance* typeInstance, bool underlyingTypeDeferred, HashContext* dataMemberHashCtx, BfType* unionInnerType);

View file

@ -184,6 +184,21 @@ bool BfModule::FinishGenericParams(BfType* resolvedTypeRef)
if (!typeDef->mPartials.empty()) if (!typeDef->mPartials.empty())
{ {
BitSet prevConstraintsPassedSet;
if (!genericTypeInst->IsUnspecializedType())
{
if (genericTypeInst->mGenericTypeInfo->mGenericExtensionInfo != NULL)
{
auto genericExtensionInfo = genericTypeInst->mGenericTypeInfo->mGenericExtensionInfo;
prevConstraintsPassedSet = genericExtensionInfo->mConstraintsPassedSet;
genericExtensionInfo->mConstraintsPassedSet.Clear();
}
}
int extensionCount = 0;
BfLogSysM("BfModule::FinishGenericParams %p\n", resolvedTypeRef);
for (auto partialTypeDef : typeDef->mPartials) for (auto partialTypeDef : typeDef->mPartials)
{ {
if (!partialTypeDef->IsExtension()) if (!partialTypeDef->IsExtension())
@ -222,6 +237,13 @@ bool BfModule::FinishGenericParams(BfType* resolvedTypeRef)
auto genericExEntry = BuildGenericExtensionInfo(genericTypeInst, partialTypeDef); auto genericExEntry = BuildGenericExtensionInfo(genericTypeInst, partialTypeDef);
if (genericExEntry == NULL) if (genericExEntry == NULL)
continue; continue;
auto genericExtensionInfo = genericTypeInst->mGenericTypeInfo->mGenericExtensionInfo;
if (extensionCount == 0)
genericExtensionInfo->mConstraintsPassedSet.Resize(typeDef->mPartials.mSize);
extensionCount++;
if (!genericTypeInst->IsUnspecializedType()) if (!genericTypeInst->IsUnspecializedType())
{ {
SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true); SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true);
@ -249,7 +271,18 @@ bool BfModule::FinishGenericParams(BfType* resolvedTypeRef)
} }
} }
} }
}
if (genericExEntry->mConstraintsPassed)
genericExtensionInfo->mConstraintsPassedSet.Set(partialTypeDef->mPartialIdx);
BfLogSysM("BfModule::FinishGenericParams %p partialTypeDef:%p passed:%d\n", resolvedTypeRef, partialTypeDef, genericExEntry->mConstraintsPassed);
}
}
auto genericExtensionInfo = genericTypeInst->mGenericTypeInfo->mGenericExtensionInfo;
if ((extensionCount > 0) && (!prevConstraintsPassedSet.IsEmpty()) && (genericExtensionInfo->mConstraintsPassedSet != prevConstraintsPassedSet))
{
mContext->RebuildDependentTypes_MidCompile(genericTypeInst, "mConstraintsPassedSet changed");
} }
} }
else else
@ -1224,7 +1257,8 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
if (resolvedTypeRef->IsTypeAlias()) if (resolvedTypeRef->IsTypeAlias())
{ {
// Always populate these all the way // Always populate these all the way
populateType = BfPopulateType_Data; if (populateType != BfPopulateType_IdentityNoRemapAlias)
populateType = BfPopulateType_Data;
} }
if (resolvedTypeRef->IsSizedArray()) if (resolvedTypeRef->IsSizedArray())
@ -2730,7 +2764,7 @@ void BfModule::DoPopulateType_SetGenericDependencies(BfTypeInstance* genericType
} }
} }
void BfModule::DoPopulateType_TypeAlias(BfTypeInstance* typeAlias) void BfModule::DoPopulateType_TypeAlias(BfTypeAliasType* typeAlias)
{ {
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, typeAlias); SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, typeAlias);
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL); SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL);
@ -2766,6 +2800,8 @@ void BfModule::DoPopulateType_TypeAlias(BfTypeInstance* typeAlias)
aliasToType = ResolveTypeRef(typeAliasDecl->mAliasToType, BfPopulateType_IdentityNoRemapAlias); aliasToType = ResolveTypeRef(typeAliasDecl->mAliasToType, BfPopulateType_IdentityNoRemapAlias);
} }
BfLogSysM("DoPopulateType_TypeAlias %p %s = %p %s\n", typeAlias, TypeToString(typeAlias).c_str(), aliasToType, (aliasToType != NULL) ? TypeToString(aliasToType).c_str() : NULL);
if (aliasToType != NULL) if (aliasToType != NULL)
{ {
if (aliasToType->IsConstExprValue()) if (aliasToType->IsConstExprValue())
@ -2776,16 +2812,19 @@ void BfModule::DoPopulateType_TypeAlias(BfTypeInstance* typeAlias)
} }
if (aliasToType != NULL) if (aliasToType != NULL)
{ {
AddDependency(aliasToType, typeAlias, BfDependencyMap::DependencyFlag_DerivedFrom); AddDependency(aliasToType, typeAlias, BfDependencyMap::DependencyFlag_DerivedFrom);
} }
else else
mContext->mFailTypes.Add(typeAlias); mContext->mFailTypes.Add(typeAlias);
if (typeAlias->mTypeFailed) if (typeAlias->mTypeFailed)
aliasToType = NULL; aliasToType = NULL;
((BfTypeAliasType*)typeAlias)->mAliasToType = aliasToType; if ((typeAlias->mAliasToType != NULL) && (typeAlias->mAliasToType != aliasToType) && (!typeAlias->mDependencyMap.IsEmpty()))
mContext->RebuildDependentTypes_MidCompile(typeAlias, "type alias remapped");
typeAlias->mAliasToType = aliasToType;
if (aliasToType != NULL) if (aliasToType != NULL)
{ {
@ -3188,9 +3227,10 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if (resolvedTypeRef->IsTypeAlias()) if (resolvedTypeRef->IsTypeAlias())
{ {
prevTypeState.Restore(); prevTypeState.Restore();
DoPopulateType_TypeAlias(typeInstance); DoPopulateType_TypeAlias((BfTypeAliasType*)typeInstance);
typeInstance->mTypeIncomplete = false; typeInstance->mTypeIncomplete = false;
resolvedTypeRef->mRebuildFlags = BfTypeRebuildFlag_None;
resolvedTypeRef->mDefineState = BfTypeDefineState_DefinedAndMethodsSlotted; resolvedTypeRef->mDefineState = BfTypeDefineState_DefinedAndMethodsSlotted;
return; return;
} }
@ -4453,19 +4493,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if (!typeInstance->mCeTypeInfo->mNext->mFailed) if (!typeInstance->mCeTypeInfo->mNext->mFailed)
{ {
if ((typeInstance->mCeTypeInfo->mHash != typeInstance->mCeTypeInfo->mNext->mHash) && (!typeInstance->mCeTypeInfo->mHash.IsZero())) if ((typeInstance->mCeTypeInfo->mHash != typeInstance->mCeTypeInfo->mNext->mHash) && (!typeInstance->mCeTypeInfo->mHash.IsZero()))
{ mContext->RebuildDependentTypes_MidCompile(typeInstance, "comptime hash changed");
int prevDeletedTypes = mCompiler->mStats.mTypesDeleted;
if (mCompiler->mIsResolveOnly)
mCompiler->mNeedsFullRefresh = true;
BfLogSysM("Type %p hash changed, rebuilding dependent types\n", typeInstance);
mContext->RebuildDependentTypes(typeInstance);
if (mCompiler->mStats.mTypesDeleted != prevDeletedTypes)
{
BfLogSysM("Type %p hash changed, rebuilding dependent types - updating after deleting types\n", typeInstance);
mContext->UpdateAfterDeletingTypes();
}
}
typeInstance->mCeTypeInfo->mOnCompileMap = typeInstance->mCeTypeInfo->mNext->mOnCompileMap; typeInstance->mCeTypeInfo->mOnCompileMap = typeInstance->mCeTypeInfo->mNext->mOnCompileMap;
typeInstance->mCeTypeInfo->mTypeIFaceMap = typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap; typeInstance->mCeTypeInfo->mTypeIFaceMap = typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap;
typeInstance->mCeTypeInfo->mHash = typeInstance->mCeTypeInfo->mNext->mHash; typeInstance->mCeTypeInfo->mHash = typeInstance->mCeTypeInfo->mNext->mHash;
@ -8922,9 +8950,11 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
{ {
if (mCurTypeInstance != NULL) if (mCurTypeInstance != NULL)
AddDependency(resolvedTypeRef, mCurTypeInstance, BfDependencyMap::DependencyFlag_NameReference); AddDependency(resolvedTypeRef, mCurTypeInstance, BfDependencyMap::DependencyFlag_NameReference);
if (resolvedTypeRef->mDefineState == BfTypeDefineState_Undefined)
PopulateType(resolvedTypeRef);
if ((typeInstance->mCustomAttributes != NULL) && (!typeRef->IsTemporary())) if ((typeInstance->mCustomAttributes != NULL) && (!typeRef->IsTemporary()))
CheckErrorAttributes(typeInstance, NULL, typeInstance->mCustomAttributes, typeRef); CheckErrorAttributes(typeInstance, NULL, typeInstance->mCustomAttributes, typeRef);
resolvedTypeRef = resolvedTypeRef->GetUnderlyingType(); resolvedTypeRef = resolvedTypeRef->GetUnderlyingType();
if (resolvedTypeRef != NULL) if (resolvedTypeRef != NULL)
typeInstance = resolvedTypeRef->ToTypeInstance(); typeInstance = resolvedTypeRef->ToTypeInstance();
else else
@ -11088,7 +11118,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
#ifdef _DEBUG #ifdef _DEBUG
if (BfResolvedTypeSet::Hash(refType, &lookupCtx) != resolvedEntry->mHash) if (BfResolvedTypeSet::Hash(refType, &lookupCtx) != resolvedEntry->mHash)
{ {
int refHash = BfResolvedTypeSet::Hash(typeRef, &lookupCtx); int refHash = BfResolvedTypeSet::Hash(typeRef, &lookupCtx, BfResolvedTypeSet::BfHashFlag_AllowRef);
int typeHash = BfResolvedTypeSet::Hash(refType, &lookupCtx); int typeHash = BfResolvedTypeSet::Hash(refType, &lookupCtx);
BF_ASSERT(refHash == typeHash); BF_ASSERT(refHash == typeHash);
} }

View file

@ -7,6 +7,7 @@
#include "BfSource.h" #include "BfSource.h"
#include "BfIRBuilder.h" #include "BfIRBuilder.h"
#include "BeefySysLib/util/MultiHashSet.h" #include "BeefySysLib/util/MultiHashSet.h"
#include "BeefySysLib/util/BitSet.h"
NS_BF_BEGIN NS_BF_BEGIN
@ -428,7 +429,8 @@ enum BfTypeRebuildFlags
BfTypeRebuildFlag_ResolvingBase = 0x8000, BfTypeRebuildFlag_ResolvingBase = 0x8000,
BfTypeRebuildFlag_InFailTypes = 0x10000, BfTypeRebuildFlag_InFailTypes = 0x10000,
BfTypeRebuildFlag_RebuildQueued = 0x20000, BfTypeRebuildFlag_RebuildQueued = 0x20000,
BfTypeRebuildFlag_ConstEvalCancelled = 0x40000 BfTypeRebuildFlag_ConstEvalCancelled = 0x40000,
BfTypeRebuildFlag_ChangedMidCompile = 0x80000,
}; };
class BfTypeDIReplaceCallback; class BfTypeDIReplaceCallback;
@ -489,7 +491,7 @@ public:
BfContext* mContext; BfContext* mContext;
int mTypeId; int mTypeId;
int mRevision; int mRevision;
// For Objects, align and size is ref-sized (object*). // For Objects, align and size is ref-sized (object*).
// Use mInstSize/mInstAlign for actual data size/align // Use mInstSize/mInstAlign for actual data size/align
@ -1842,6 +1844,12 @@ class BfGenericExtensionInfo
{ {
public: public:
Dictionary<BfTypeDef*, BfGenericExtensionEntry> mExtensionMap; Dictionary<BfTypeDef*, BfGenericExtensionEntry> mExtensionMap;
BitSet mConstraintsPassedSet;
void Clear()
{
mExtensionMap.Clear();
}
}; };
// Note on nested generic types- mGenericParams is the accumulation of all generic params from outer to inner, so // Note on nested generic types- mGenericParams is the accumulation of all generic params from outer to inner, so

View file

@ -6122,7 +6122,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
} }
if (varType == NULL) if (varType == NULL)
varType = mContext->mBfObjectType; varType = GetPrimitiveType(BfTypeCode_Var);
bool isArray = target.mType->IsArray(); bool isArray = target.mType->IsArray();
bool isSizedArray = target.mType->IsSizedArray(); bool isSizedArray = target.mType->IsSizedArray();
bool isVarEnumerator = target.mType->IsVar(); bool isVarEnumerator = target.mType->IsVar();
@ -6437,7 +6437,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
} }
} }
if (nextEmbeddedType == NULL) if (nextEmbeddedType == NULL)
nextEmbeddedType = mContext->mBfObjectType; nextEmbeddedType = GetPrimitiveType(BfTypeCode_Var);
BfLocalVariable* itrLocalDef = NULL; BfLocalVariable* itrLocalDef = NULL;

View file

@ -14,7 +14,7 @@ namespace Tests
public struct Inner public struct Inner
{ {
public const EnumA cVal = EnumA.C("InnerTest"); public const EnumA cVal = .C("InnerTest");
} }
} }

View file

@ -67,6 +67,14 @@ PUSHD %~dp0..\
@CALL :TEST @CALL :TEST
@IF !ERRORLEVEL! NEQ 0 GOTO HADERROR @IF !ERRORLEVEL! NEQ 0 GOTO HADERROR
@SET TESTPATH=IDE\Tests\BugW008
@CALL :TEST
@IF !ERRORLEVEL! NEQ 0 GOTO HADERROR
@SET TESTPATH=IDE\Tests\BugW009
@CALL :TEST
@IF !ERRORLEVEL! NEQ 0 GOTO HADERROR
@SET TESTPATH=IDE\Tests\IndentTest @SET TESTPATH=IDE\Tests\IndentTest
@CALL :TEST @CALL :TEST
@IF !ERRORLEVEL! NEQ 0 GOTO HADERROR @IF !ERRORLEVEL! NEQ 0 GOTO HADERROR