mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
Fixed some comptime dependency rebuilding issues with aliases/extensions
This commit is contained in:
parent
1cd198cea9
commit
434a7406de
22 changed files with 394 additions and 86 deletions
|
@ -4,28 +4,43 @@
|
|||
|
||||
NS_BF_BEGIN;
|
||||
|
||||
#define BF_BITSET_ELEM_SIZE (sizeof(uintptr)*8)
|
||||
#define BF_BITSET_ELEM_BITCOUNT (sizeof(uintptr)*8)
|
||||
|
||||
class BitSet
|
||||
{
|
||||
public:
|
||||
uintptr* mBits;
|
||||
int mNumInts;
|
||||
int mNumBits;
|
||||
|
||||
public:
|
||||
BitSet()
|
||||
{
|
||||
mNumInts = 0;
|
||||
mNumBits = 0;
|
||||
mBits = NULL;
|
||||
}
|
||||
|
||||
BitSet(int numBits)
|
||||
{
|
||||
mNumInts = 0;
|
||||
mNumBits = 0;
|
||||
mBits = NULL;
|
||||
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()
|
||||
{
|
||||
delete this->mBits;
|
||||
|
@ -33,28 +48,68 @@ public:
|
|||
|
||||
void Resize(int numBits)
|
||||
{
|
||||
int numInts = (numBits + BF_BITSET_ELEM_SIZE - 1) / BF_BITSET_ELEM_SIZE;
|
||||
if (numInts == mNumInts)
|
||||
return;
|
||||
this->mNumInts = numInts;
|
||||
int numInts = (numBits + BF_BITSET_ELEM_BITCOUNT - 1) / BF_BITSET_ELEM_BITCOUNT;
|
||||
int curNumInts = (mNumBits + BF_BITSET_ELEM_BITCOUNT - 1) / BF_BITSET_ELEM_BITCOUNT;
|
||||
mNumBits = numBits;
|
||||
if (numInts == curNumInts)
|
||||
return;
|
||||
this->mNumBits = numBits;
|
||||
delete this->mBits;
|
||||
this->mBits = new uintptr[numInts];
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
5
IDE/Tests/BugW008/BeefProj.toml
Normal file
5
IDE/Tests/BugW008/BeefProj.toml
Normal file
|
@ -0,0 +1,5 @@
|
|||
FileVersion = 1
|
||||
|
||||
[Project]
|
||||
Name = "Bug"
|
||||
StartupObject = "Bug.Program"
|
6
IDE/Tests/BugW008/BeefSpace.toml
Normal file
6
IDE/Tests/BugW008/BeefSpace.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
FileVersion = 1
|
||||
Projects = {Bug = {Path = "."}}
|
||||
|
||||
[Workspace]
|
||||
StartupProject = "Bug"
|
||||
|
15
IDE/Tests/BugW008/scripts/Test.txt
Normal file
15
IDE/Tests/BugW008/scripts/Test.txt
Normal 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()
|
18
IDE/Tests/BugW008/src/Gen.bf
Normal file
18
IDE/Tests/BugW008/src/Gen.bf
Normal file
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
|
||||
namespace Bug
|
||||
{
|
||||
class Gen
|
||||
{
|
||||
public static Type Get()
|
||||
{
|
||||
//*Void
|
||||
return typeof(void);
|
||||
/*@*/
|
||||
|
||||
/*String
|
||||
return typeof(String);
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
34
IDE/Tests/BugW008/src/Program.bf
Normal file
34
IDE/Tests/BugW008/src/Program.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
5
IDE/Tests/BugW009/BeefProj.toml
Normal file
5
IDE/Tests/BugW009/BeefProj.toml
Normal file
|
@ -0,0 +1,5 @@
|
|||
FileVersion = 1
|
||||
|
||||
[Project]
|
||||
Name = "Bug"
|
||||
StartupObject = "Bug.Program"
|
6
IDE/Tests/BugW009/BeefSpace.toml
Normal file
6
IDE/Tests/BugW009/BeefSpace.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
FileVersion = 1
|
||||
Projects = {Bug = {Path = "."}}
|
||||
|
||||
[Workspace]
|
||||
StartupProject = "Bug"
|
||||
|
15
IDE/Tests/BugW009/scripts/Test.txt
Normal file
15
IDE/Tests/BugW009/scripts/Test.txt
Normal 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()
|
18
IDE/Tests/BugW009/src/Gen.bf
Normal file
18
IDE/Tests/BugW009/src/Gen.bf
Normal file
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
|
||||
namespace Bug
|
||||
{
|
||||
class Gen
|
||||
{
|
||||
public static Type Get()
|
||||
{
|
||||
//*ClassA
|
||||
return typeof(ClassA);
|
||||
/*@*/
|
||||
|
||||
/*ClassB
|
||||
return typeof(ClassB);
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
42
IDE/Tests/BugW009/src/Program.bf
Normal file
42
IDE/Tests/BugW009/src/Program.bf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7012,47 +7012,58 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
|
|||
mStats.mTypesQueued += (int)mContext->mPopulateTypeWorkList.size();
|
||||
mStats.mMethodsQueued += (int)mContext->mMethodWorkList.size();
|
||||
|
||||
//
|
||||
{
|
||||
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");
|
||||
|
||||
while (true)
|
||||
{
|
||||
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-
|
||||
// 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)
|
||||
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");
|
||||
|
||||
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);
|
||||
|
|
|
@ -77,7 +77,8 @@ BfContext::BfContext(BfCompiler* compiler) :
|
|||
|
||||
mValueTypeDeinitSentinel = (BfMethodInstance*)1;
|
||||
|
||||
mCurStringObjectPoolId = 0;
|
||||
mCurStringObjectPoolId = 0;
|
||||
mHasReifiedQueuedRebuildTypes = false;
|
||||
}
|
||||
|
||||
void BfReportMemory();
|
||||
|
@ -945,6 +946,9 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
|
|||
return;
|
||||
}
|
||||
|
||||
if (typeInst->mIsReified)
|
||||
mHasReifiedQueuedRebuildTypes = true;
|
||||
|
||||
typeInst->mRebuildFlags = (BfTypeRebuildFlags)(typeInst->mRebuildFlags & ~BfTypeRebuildFlag_AddedToWorkList);
|
||||
|
||||
bool addToWorkList = true;
|
||||
|
@ -1131,8 +1135,8 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
|
|||
genericTypeInstance->mGenericTypeInfo->mGenericParams.Clear();
|
||||
genericTypeInstance->mGenericTypeInfo->mValidatedGenericConstraints = false;
|
||||
genericTypeInstance->mGenericTypeInfo->mHadValidateErrors = false;
|
||||
delete genericTypeInstance->mGenericTypeInfo->mGenericExtensionInfo;
|
||||
genericTypeInstance->mGenericTypeInfo->mGenericExtensionInfo = NULL;
|
||||
if (genericTypeInstance->mGenericTypeInfo->mGenericExtensionInfo != NULL)
|
||||
genericTypeInstance->mGenericTypeInfo->mGenericExtensionInfo->Clear();
|
||||
genericTypeInstance->mGenericTypeInfo->mProjectsReferenced.Clear();
|
||||
}
|
||||
|
||||
|
@ -1182,6 +1186,22 @@ void BfContext::RebuildDependentTypes(BfDependedType* dType)
|
|||
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:
|
||||
// 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
|
||||
|
@ -1254,7 +1274,7 @@ void BfContext::TypeDataChanged(BfDependedType* dType, bool isNonStaticDataChang
|
|||
}
|
||||
|
||||
if (dependentType->mRevision != mCompiler->mRevision)
|
||||
{
|
||||
{
|
||||
// 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
|
||||
if (dependencyFlags &
|
||||
|
@ -1264,6 +1284,12 @@ void BfContext::TypeDataChanged(BfDependedType* dType, bool isNonStaticDataChang
|
|||
{
|
||||
RebuildType(dependentType);
|
||||
}
|
||||
else if (((dependencyFlags & BfDependencyMap::DependencyFlag_NameReference) != 0) &&
|
||||
((dType->mRebuildFlags & BfTypeRebuildFlag_ChangedMidCompile) != 0) &&
|
||||
(dType->IsTypeAlias()))
|
||||
{
|
||||
RebuildType(dependentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1276,7 +1302,7 @@ void BfContext::TypeDataChanged(BfDependedType* dType, bool isNonStaticDataChang
|
|||
}
|
||||
}
|
||||
|
||||
if (dType->mRevision != mCompiler->mRevision)
|
||||
if (dType->mRevision != mCompiler->mRevision)
|
||||
RebuildType(dType);
|
||||
}
|
||||
|
||||
|
|
|
@ -351,7 +351,7 @@ class BfContext
|
|||
{
|
||||
public:
|
||||
CritSect mCritSect;
|
||||
bool mDeleting;
|
||||
bool mDeleting;
|
||||
|
||||
BfTypeState* mCurTypeState;
|
||||
BfSizedArray<BfNamespaceDeclaration*>* mCurNamespaceNodes;
|
||||
|
@ -397,6 +397,7 @@ public:
|
|||
WorkQueue<BfTypeRefVerifyRequest> mTypeRefVerifyWorkList;
|
||||
PtrWorkQueue<BfModule*> mFinishedSlotAwaitModuleWorkList;
|
||||
PtrWorkQueue<BfModule*> mFinishedModuleWorkList;
|
||||
bool mHasReifiedQueuedRebuildTypes;
|
||||
|
||||
Array<BfGenericParamType*> mGenericParamTypes[3];
|
||||
|
||||
|
@ -475,6 +476,7 @@ public:
|
|||
void ValidateDependencies();
|
||||
void RebuildType(BfType* type, bool deleteOnDemandTypes = true, bool rebuildModule = true, bool placeSpecializiedInPurgatory = true);
|
||||
void RebuildDependentTypes(BfDependedType* dType);
|
||||
void RebuildDependentTypes_MidCompile(BfDependedType* dType, const String& reason);
|
||||
void TypeDataChanged(BfDependedType* dType, bool isNonStaticDataChange);
|
||||
void TypeMethodSignaturesChanged(BfTypeInstance* typeInst);
|
||||
void TypeInlineMethodInternalsChanged(BfTypeInstance* typeInst);
|
||||
|
|
|
@ -1746,7 +1746,11 @@ String BfIRBuilder::ToString(BfIRValue irValue)
|
|||
auto typeofConst = (BfTypeOf_WithData_Const*)constant;
|
||||
return "typeof_withData " + mModule->TypeToString(typeofConst->mType);
|
||||
}
|
||||
|
||||
else if (constant->mConstType == BfConstType_Undef)
|
||||
{
|
||||
auto constUndef = (BfConstantUndef*)constant;
|
||||
return "undef " + ToString(constUndef->mType);
|
||||
}
|
||||
else
|
||||
{
|
||||
BF_FATAL("Unhandled");
|
||||
|
|
|
@ -1258,7 +1258,7 @@ void BfModule::StartNewRevision(RebuildKind rebuildKind, bool force)
|
|||
mHadBuildError = false;
|
||||
mHadBuildWarning = false;
|
||||
mExtensionCount = 0;
|
||||
mRevision = mCompiler->mRevision;
|
||||
mRevision = mCompiler->mRevision;
|
||||
mRebuildIdx++;
|
||||
ClearModuleData(!force);
|
||||
|
||||
|
|
|
@ -1775,7 +1775,7 @@ public:
|
|||
void ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind, bool underlyingTypeDeferred);
|
||||
void DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers, bool underlyingTypeDeferred);
|
||||
void DoCEEmit(BfMethodInstance* methodInstance);
|
||||
void DoPopulateType_TypeAlias(BfTypeInstance* typeAlias);
|
||||
void DoPopulateType_TypeAlias(BfTypeAliasType* typeAlias);
|
||||
void DoPopulateType_InitSearches(BfTypeInstance* typeInstance);
|
||||
void DoPopulateType_SetGenericDependencies(BfTypeInstance* genericTypeInstance);
|
||||
void DoPopulateType_FinishEnum(BfTypeInstance* typeInstance, bool underlyingTypeDeferred, HashContext* dataMemberHashCtx, BfType* unionInnerType);
|
||||
|
|
|
@ -184,6 +184,21 @@ bool BfModule::FinishGenericParams(BfType* resolvedTypeRef)
|
|||
|
||||
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)
|
||||
{
|
||||
if (!partialTypeDef->IsExtension())
|
||||
|
@ -222,6 +237,13 @@ bool BfModule::FinishGenericParams(BfType* resolvedTypeRef)
|
|||
auto genericExEntry = BuildGenericExtensionInfo(genericTypeInst, partialTypeDef);
|
||||
if (genericExEntry == NULL)
|
||||
continue;
|
||||
|
||||
auto genericExtensionInfo = genericTypeInst->mGenericTypeInfo->mGenericExtensionInfo;
|
||||
if (extensionCount == 0)
|
||||
genericExtensionInfo->mConstraintsPassedSet.Resize(typeDef->mPartials.mSize);
|
||||
|
||||
extensionCount++;
|
||||
|
||||
if (!genericTypeInst->IsUnspecializedType())
|
||||
{
|
||||
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
|
||||
|
@ -1224,7 +1257,8 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
|
|||
if (resolvedTypeRef->IsTypeAlias())
|
||||
{
|
||||
// Always populate these all the way
|
||||
populateType = BfPopulateType_Data;
|
||||
if (populateType != BfPopulateType_IdentityNoRemapAlias)
|
||||
populateType = BfPopulateType_Data;
|
||||
}
|
||||
|
||||
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<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL);
|
||||
|
@ -2766,6 +2800,8 @@ void BfModule::DoPopulateType_TypeAlias(BfTypeInstance* typeAlias)
|
|||
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->IsConstExprValue())
|
||||
|
@ -2776,16 +2812,19 @@ void BfModule::DoPopulateType_TypeAlias(BfTypeInstance* typeAlias)
|
|||
}
|
||||
|
||||
if (aliasToType != NULL)
|
||||
{
|
||||
{
|
||||
AddDependency(aliasToType, typeAlias, BfDependencyMap::DependencyFlag_DerivedFrom);
|
||||
}
|
||||
else
|
||||
mContext->mFailTypes.Add(typeAlias);
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -3188,9 +3227,10 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
if (resolvedTypeRef->IsTypeAlias())
|
||||
{
|
||||
prevTypeState.Restore();
|
||||
DoPopulateType_TypeAlias(typeInstance);
|
||||
DoPopulateType_TypeAlias((BfTypeAliasType*)typeInstance);
|
||||
|
||||
typeInstance->mTypeIncomplete = false;
|
||||
resolvedTypeRef->mRebuildFlags = BfTypeRebuildFlag_None;
|
||||
resolvedTypeRef->mDefineState = BfTypeDefineState_DefinedAndMethodsSlotted;
|
||||
return;
|
||||
}
|
||||
|
@ -4453,19 +4493,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
if (!typeInstance->mCeTypeInfo->mNext->mFailed)
|
||||
{
|
||||
if ((typeInstance->mCeTypeInfo->mHash != typeInstance->mCeTypeInfo->mNext->mHash) && (!typeInstance->mCeTypeInfo->mHash.IsZero()))
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
mContext->RebuildDependentTypes_MidCompile(typeInstance, "comptime hash changed");
|
||||
typeInstance->mCeTypeInfo->mOnCompileMap = typeInstance->mCeTypeInfo->mNext->mOnCompileMap;
|
||||
typeInstance->mCeTypeInfo->mTypeIFaceMap = typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap;
|
||||
typeInstance->mCeTypeInfo->mHash = typeInstance->mCeTypeInfo->mNext->mHash;
|
||||
|
@ -8922,9 +8950,11 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
|
|||
{
|
||||
if (mCurTypeInstance != NULL)
|
||||
AddDependency(resolvedTypeRef, mCurTypeInstance, BfDependencyMap::DependencyFlag_NameReference);
|
||||
if (resolvedTypeRef->mDefineState == BfTypeDefineState_Undefined)
|
||||
PopulateType(resolvedTypeRef);
|
||||
if ((typeInstance->mCustomAttributes != NULL) && (!typeRef->IsTemporary()))
|
||||
CheckErrorAttributes(typeInstance, NULL, typeInstance->mCustomAttributes, typeRef);
|
||||
resolvedTypeRef = resolvedTypeRef->GetUnderlyingType();
|
||||
CheckErrorAttributes(typeInstance, NULL, typeInstance->mCustomAttributes, typeRef);
|
||||
resolvedTypeRef = resolvedTypeRef->GetUnderlyingType();
|
||||
if (resolvedTypeRef != NULL)
|
||||
typeInstance = resolvedTypeRef->ToTypeInstance();
|
||||
else
|
||||
|
@ -11088,7 +11118,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
#ifdef _DEBUG
|
||||
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);
|
||||
BF_ASSERT(refHash == typeHash);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "BfSource.h"
|
||||
#include "BfIRBuilder.h"
|
||||
#include "BeefySysLib/util/MultiHashSet.h"
|
||||
#include "BeefySysLib/util/BitSet.h"
|
||||
|
||||
NS_BF_BEGIN
|
||||
|
||||
|
@ -428,7 +429,8 @@ enum BfTypeRebuildFlags
|
|||
BfTypeRebuildFlag_ResolvingBase = 0x8000,
|
||||
BfTypeRebuildFlag_InFailTypes = 0x10000,
|
||||
BfTypeRebuildFlag_RebuildQueued = 0x20000,
|
||||
BfTypeRebuildFlag_ConstEvalCancelled = 0x40000
|
||||
BfTypeRebuildFlag_ConstEvalCancelled = 0x40000,
|
||||
BfTypeRebuildFlag_ChangedMidCompile = 0x80000,
|
||||
};
|
||||
|
||||
class BfTypeDIReplaceCallback;
|
||||
|
@ -489,7 +491,7 @@ public:
|
|||
|
||||
BfContext* mContext;
|
||||
int mTypeId;
|
||||
int mRevision;
|
||||
int mRevision;
|
||||
|
||||
// For Objects, align and size is ref-sized (object*).
|
||||
// Use mInstSize/mInstAlign for actual data size/align
|
||||
|
@ -1842,6 +1844,12 @@ class BfGenericExtensionInfo
|
|||
{
|
||||
public:
|
||||
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
|
||||
|
|
|
@ -6122,7 +6122,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
|
|||
}
|
||||
|
||||
if (varType == NULL)
|
||||
varType = mContext->mBfObjectType;
|
||||
varType = GetPrimitiveType(BfTypeCode_Var);
|
||||
bool isArray = target.mType->IsArray();
|
||||
bool isSizedArray = target.mType->IsSizedArray();
|
||||
bool isVarEnumerator = target.mType->IsVar();
|
||||
|
@ -6437,7 +6437,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
|
|||
}
|
||||
}
|
||||
if (nextEmbeddedType == NULL)
|
||||
nextEmbeddedType = mContext->mBfObjectType;
|
||||
nextEmbeddedType = GetPrimitiveType(BfTypeCode_Var);
|
||||
|
||||
BfLocalVariable* itrLocalDef = NULL;
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Tests
|
|||
|
||||
public struct Inner
|
||||
{
|
||||
public const EnumA cVal = EnumA.C("InnerTest");
|
||||
public const EnumA cVal = .C("InnerTest");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,14 @@ PUSHD %~dp0..\
|
|||
@CALL :TEST
|
||||
@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
|
||||
@CALL :TEST
|
||||
@IF !ERRORLEVEL! NEQ 0 GOTO HADERROR
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue