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

Fixed base type with 'static using' typeref lookup

This commit is contained in:
Brian Fiete 2021-10-23 08:46:17 -07:00
parent b316b1412c
commit 5618718e8d
2 changed files with 98 additions and 92 deletions

View file

@ -2679,154 +2679,9 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if (!typeInstance->mTypeFailed)
CheckCircularDataError();
bool underlyingTypeDeferred = false;
BfType* underlyingType = NULL;
if (typeInstance->mBaseType != NULL)
if (typeInstance->mDefineState < BfTypeDefineState_Declaring)
{
if (typeInstance->IsTypedPrimitive())
underlyingType = typeInstance->GetUnderlyingType();
if ((typeInstance->mRebuildFlags & BfTypeRebuildFlag_UnderlyingTypeDeferred) != 0)
underlyingTypeDeferred = true;
}
else if (typeInstance->IsEnum())
{
bool hasPayloads = false;
for (auto fieldDef : typeDef->mFields)
{
if ((fieldDef->IsEnumCaseEntry()) && (fieldDef->mTypeRef != NULL))
{
hasPayloads = true;
break;
}
}
if (!hasPayloads)
{
bool hadType = false;
for (auto baseTypeRef : typeDef->mBaseTypes)
{
SetAndRestoreValue<BfTypeReference*> prevTypeRef(mContext->mCurTypeState->mCurBaseTypeRef, baseTypeRef);
SetAndRestoreValue<BfTypeDefineState> prevDefineState(typeInstance->mDefineState, BfTypeDefineState_ResolvingBaseType);
SetAndRestoreValue<bool> prevIgnoreError(mIgnoreErrors, true);
SetAndRestoreValue<bool> prevSkipTypeProtectionChecks(typeInstance->mSkipTypeProtectionChecks, true);
auto baseType = ResolveTypeRef(baseTypeRef, BfPopulateType_Declaration);
if (baseType != NULL)
{
if (baseType->IsIntegral())
{
if (!hadType)
{
hadType = true;
underlyingType = baseType;
}
else
{
Fail("Underlying enum type already specified", baseTypeRef);
}
}
else
{
Fail("Invalid underlying enum type", baseTypeRef);
}
}
else
{
AssertErrorState();
typeInstance->mTypeFailed = true;
}
}
if (underlyingType == NULL)
{
underlyingType = GetPrimitiveType(BfTypeCode_Int64);
underlyingTypeDeferred = true;
}
}
}
// else if (typeInstance->IsFunction())
// {
// underlyingType = GetPrimitiveType(BfTypeCode_NullPtr);
// }
else if (((typeInstance->IsStruct()) || (typeInstance->IsTypedPrimitive())) &&
(!typeInstance->mTypeFailed))
{
for (auto baseTypeRef : typeDef->mBaseTypes)
{
auto declTypeDef = typeDef;
if (typeDef->mIsCombinedPartial)
declTypeDef = typeDef->mPartials.front();
SetAndRestoreValue<BfTypeDef*> prevTypeDef(mContext->mCurTypeState->mCurTypeDef, declTypeDef);
SetAndRestoreValue<BfTypeDefineState> prevDefineState(typeInstance->mDefineState, BfTypeDefineState_ResolvingBaseType);
SetAndRestoreValue<BfTypeReference*> prevTypeRef(mContext->mCurTypeState->mCurBaseTypeRef, baseTypeRef);
// We ignore errors here to avoid double-errors for type lookups, but this is where data cycles are detected
// but that type of error supersedes the mIgnoreErrors setting
SetAndRestoreValue<bool> prevIgnoreError(mIgnoreErrors, true);
// Temporarily allow us to derive from private classes, to avoid infinite loop from TypeIsSubTypeOf
SetAndRestoreValue<bool> prevSkipTypeProtectionChecks(typeInstance->mSkipTypeProtectionChecks, true);
auto baseType = ResolveTypeRef(baseTypeRef, BfPopulateType_Declaration);
if (baseType != NULL)
{
if (baseType->IsPrimitiveType())
{
underlyingType = baseType;
}
else if (baseType->IsTypedPrimitive())
{
//PopulateType(baseType, true);
underlyingType = baseType->GetUnderlyingType();
BF_ASSERT(underlyingType != NULL);
}
}
else
{
AssertErrorState();
typeInstance->mTypeFailed = true;
}
if (_CheckTypeDone())
{
prevDefineState.CancelRestore();
return;
}
}
// Incase we had re-entry, work this through ourselves again here
typeInstance->mIsTypedPrimitive = false;
}
if (underlyingTypeDeferred)
typeInstance->mRebuildFlags = (BfTypeRebuildFlags)(typeInstance->mRebuildFlags | BfTypeRebuildFlag_UnderlyingTypeDeferred);
typeInstance->mIsTypedPrimitive = underlyingType != NULL;
int wantFieldCount = (int)typeDef->mFields.size() + (((underlyingType != NULL) || (typeInstance->IsPayloadEnum())) ? 1 : 0);
if ((int)typeInstance->mFieldInstances.size() < wantFieldCount)
{
// Closures don't include the enclosed fields on their first pass through PopulateType, and they have no typeDef of their own
// so we need to take care not to truncate their fieldInstance vector here (thus the 'wantFieldCount' check above)
typeInstance->mFieldInstances.Resize(wantFieldCount);
}
if (underlyingType != NULL)
{
auto fieldInstance = &typeInstance->mFieldInstances.back();
fieldInstance->mDataOffset = 0;
fieldInstance->mDataSize = underlyingType->mSize;
fieldInstance->mOwner = typeInstance;
fieldInstance->mResolvedType = underlyingType;
typeInstance->mSize = underlyingType->mSize;
typeInstance->mAlign = underlyingType->mAlign;
typeInstance->mInstSize = underlyingType->mSize;
typeInstance->mInstAlign = underlyingType->mAlign;
typeInstance->mHasPackingHoles = underlyingType->HasPackingHoles();
}
// Partial population break out point
if (typeInstance->mDefineState < BfTypeDefineState_Declared)
{
typeInstance->mDefineState = BfTypeDefineState_Declared;
typeInstance->mDefineState = BfTypeDefineState_Declaring;
if (typeInstance->IsGenericTypeInstance())
{
@ -2915,6 +2770,156 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
else
_AddStaticSearch(typeDef);
}
bool underlyingTypeDeferred = false;
BfType* underlyingType = NULL;
if (typeInstance->mBaseType != NULL)
{
if (typeInstance->IsTypedPrimitive())
underlyingType = typeInstance->GetUnderlyingType();
if ((typeInstance->mRebuildFlags & BfTypeRebuildFlag_UnderlyingTypeDeferred) != 0)
underlyingTypeDeferred = true;
}
else if (typeInstance->IsEnum())
{
bool hasPayloads = false;
for (auto fieldDef : typeDef->mFields)
{
if ((fieldDef->IsEnumCaseEntry()) && (fieldDef->mTypeRef != NULL))
{
hasPayloads = true;
break;
}
}
if (!hasPayloads)
{
bool hadType = false;
for (auto baseTypeRef : typeDef->mBaseTypes)
{
SetAndRestoreValue<BfTypeReference*> prevTypeRef(mContext->mCurTypeState->mCurBaseTypeRef, baseTypeRef);
SetAndRestoreValue<BfTypeDefineState> prevDefineState(typeInstance->mDefineState, BfTypeDefineState_ResolvingBaseType);
SetAndRestoreValue<bool> prevIgnoreError(mIgnoreErrors, true);
SetAndRestoreValue<bool> prevSkipTypeProtectionChecks(typeInstance->mSkipTypeProtectionChecks, true);
auto baseType = ResolveTypeRef(baseTypeRef, BfPopulateType_Declaration);
if (baseType != NULL)
{
if (baseType->IsIntegral())
{
if (!hadType)
{
hadType = true;
underlyingType = baseType;
}
else
{
Fail("Underlying enum type already specified", baseTypeRef);
}
}
else
{
Fail("Invalid underlying enum type", baseTypeRef);
}
}
else
{
AssertErrorState();
TypeFailed(typeInstance);
}
}
if (underlyingType == NULL)
{
underlyingType = GetPrimitiveType(BfTypeCode_Int64);
underlyingTypeDeferred = true;
}
}
}
// else if (typeInstance->IsFunction())
// {
// underlyingType = GetPrimitiveType(BfTypeCode_NullPtr);
// }
else if (((typeInstance->IsStruct()) || (typeInstance->IsTypedPrimitive())) &&
(!typeInstance->mTypeFailed))
{
for (auto baseTypeRef : typeDef->mBaseTypes)
{
auto declTypeDef = typeDef;
if (typeDef->mIsCombinedPartial)
declTypeDef = typeDef->mPartials.front();
SetAndRestoreValue<BfTypeDef*> prevTypeDef(mContext->mCurTypeState->mCurTypeDef, declTypeDef);
SetAndRestoreValue<BfTypeDefineState> prevDefineState(typeInstance->mDefineState, BfTypeDefineState_ResolvingBaseType);
SetAndRestoreValue<BfTypeReference*> prevTypeRef(mContext->mCurTypeState->mCurBaseTypeRef, baseTypeRef);
// We ignore errors here to avoid double-errors for type lookups, but this is where data cycles are detected
// but that type of error supersedes the mIgnoreErrors setting
SetAndRestoreValue<bool> prevIgnoreError(mIgnoreErrors, true);
// Temporarily allow us to derive from private classes, to avoid infinite loop from TypeIsSubTypeOf
SetAndRestoreValue<bool> prevSkipTypeProtectionChecks(typeInstance->mSkipTypeProtectionChecks, true);
auto baseType = ResolveTypeRef(baseTypeRef, BfPopulateType_Declaration);
if (baseType != NULL)
{
if (baseType->IsPrimitiveType())
{
underlyingType = baseType;
}
else if (baseType->IsTypedPrimitive())
{
//PopulateType(baseType, true);
underlyingType = baseType->GetUnderlyingType();
BF_ASSERT(underlyingType != NULL);
}
}
else
{
AssertErrorState();
TypeFailed(typeInstance);
}
if (_CheckTypeDone())
{
prevDefineState.CancelRestore();
return;
}
}
// Incase we had re-entry, work this through ourselves again here
typeInstance->mIsTypedPrimitive = false;
}
if (underlyingTypeDeferred)
typeInstance->mRebuildFlags = (BfTypeRebuildFlags)(typeInstance->mRebuildFlags | BfTypeRebuildFlag_UnderlyingTypeDeferred);
typeInstance->mIsTypedPrimitive = underlyingType != NULL;
int wantFieldCount = (int)typeDef->mFields.size() + (((underlyingType != NULL) || (typeInstance->IsPayloadEnum())) ? 1 : 0);
if ((int)typeInstance->mFieldInstances.size() < wantFieldCount)
{
// Closures don't include the enclosed fields on their first pass through PopulateType, and they have no typeDef of their own
// so we need to take care not to truncate their fieldInstance vector here (thus the 'wantFieldCount' check above)
typeInstance->mFieldInstances.Resize(wantFieldCount);
}
if (underlyingType != NULL)
{
auto fieldInstance = &typeInstance->mFieldInstances.back();
fieldInstance->mDataOffset = 0;
fieldInstance->mDataSize = underlyingType->mSize;
fieldInstance->mOwner = typeInstance;
fieldInstance->mResolvedType = underlyingType;
typeInstance->mSize = underlyingType->mSize;
typeInstance->mAlign = underlyingType->mAlign;
typeInstance->mInstSize = underlyingType->mSize;
typeInstance->mInstAlign = underlyingType->mAlign;
typeInstance->mHasPackingHoles = underlyingType->HasPackingHoles();
}
// Partial population break out point
if (typeInstance->mDefineState < BfTypeDefineState_Declared)
typeInstance->mDefineState = BfTypeDefineState_Declared;
if (populateType == BfPopulateType_Declaration)
{
return;

View file

@ -430,6 +430,7 @@ class BfTypeDIReplaceCallback;
enum BfTypeDefineState : uint8
{
BfTypeDefineState_Undefined,
BfTypeDefineState_Declaring,
BfTypeDefineState_Declared,
BfTypeDefineState_ResolvingBaseType,
BfTypeDefineState_HasInterfaces,