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

Fixed field var-resolving when calling methods

This commit is contained in:
Brian Fiete 2020-04-07 08:31:17 -07:00
parent e12c03d46e
commit 13d7b0c1c5
5 changed files with 72 additions and 13 deletions

View file

@ -1226,6 +1226,7 @@ void BfContext::PopulateHotTypeDataVTable(BfTypeInstance* typeInstance)
hotTypeData->mVTableOrigLength = typeInstance->mVirtualMethodTableSize;
hotTypeData->mOrigInterfaceMethodsLength = typeInstance->GetIFaceVMethodSize();
}
BfLogSysM("PopulateHotTypeDataVTable set %p HotDataType->mVTableOrigLength To %d\n", typeInstance, hotTypeData->mVTableOrigLength);
}
int vTableStart = -1;

View file

@ -109,6 +109,14 @@ public:
class BfTypeState
{
public:
enum ResolveKind
{
ResolveKind_None,
ResolveKind_BuildingGenericParams,
ResolveKind_ResolvingVarType
};
public:
BfTypeState* mPrevState;
@ -121,7 +129,7 @@ public:
BfTypeReference* mCurAttributeTypeRef;
BfFieldDef* mCurFieldDef;
BfTypeDef* mCurTypeDef;
bool mBuildingGenericParams;
ResolveKind mResolveKind;
public:
BfTypeState()
@ -135,7 +143,7 @@ public:
mCurFieldDef = NULL;
mCurAttributeTypeRef = NULL;
mCurTypeDef = NULL;
mBuildingGenericParams = false;
mResolveKind = ResolveKind_None;
}
BfTypeState(BfTypeInstance* typeInstance, BfTypeState* prevState = NULL)
@ -149,7 +157,7 @@ public:
mCurFieldDef = NULL;
mCurAttributeTypeRef = NULL;
mCurTypeDef = NULL;
mBuildingGenericParams = false;
mResolveKind = ResolveKind_None;
}
};

View file

@ -1745,6 +1745,29 @@ bool BfMethodMatcher::CheckType(BfTypeInstance* typeInstance, BfTypedValue targe
auto checkMethod = nextMethodDef;
nextMethodDef = nextMethodDef->mNextWithSameName;
if (mModule->mContext->mResolvingVarField)
{
bool isResolvingVarField = false;
auto checkTypeState = mModule->mContext->mCurTypeState;
while (checkTypeState != NULL)
{
if ((checkTypeState->mResolveKind == BfTypeState::ResolveKind_ResolvingVarType) &&
(checkTypeState->mTypeInstance == typeInstance))
isResolvingVarField = true;
checkTypeState = checkTypeState->mPrevState;
}
if (isResolvingVarField)
{
// Don't even consider - we can't do method calls on ourselves when we are resolving var fields, because
// we are not allowed to generate methods when our field types are unknown. We may fix this in the future,
// but currently it breaks out expected order of operations. One issue is that our call signatures change
// depending on whether we are valueless or splattable, which depend on underlying type information
break;
}
}
if ((checkExtensionBase) && (curTypeInst == mModule->mCurTypeInstance))
{
// Accept either a method in the same project but that's the root definition, OR a method that's in a dependent project

View file

@ -3411,6 +3411,13 @@ BfType* BfModule::ResolveVarFieldType(BfTypeInstance* typeInstance, BfFieldInsta
BfType* resolvedType = NULL;
if (!hadInferenceCycle)
{
BfTypeState typeState;
typeState.mPrevState = mContext->mCurTypeState;
typeState.mTypeInstance = typeInstance;
typeState.mCurFieldDef = field;
typeState.mResolveKind = BfTypeState::ResolveKind_ResolvingVarType;
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
SetAndRestoreValue<bool> prevIgnoreWrite(mBfIRBuilder->mIgnoreWrites, true);
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL/*ctorMethod.mMethodInstance*/);
@ -3450,7 +3457,7 @@ BfType* BfModule::ResolveVarFieldType(BfTypeInstance* typeInstance, BfFieldInsta
{
}
else if (fieldInstance->mDataIdx <= 0)
else if (fieldInstance->mDataIdx >= 0)
{
}
@ -6030,6 +6037,10 @@ BfIRValue BfModule::FixClassVData(BfIRValue value)
void BfModule::CheckStaticAccess(BfTypeInstance* typeInstance)
{
// Note: this is not just for perf, it fixes a field var-type resolution issue
if (!mBfIRBuilder->mIgnoreWrites)
return;
PopulateType(typeInstance, BfPopulateType_DataAndMethods);
//TODO: Create a hashset of these, we don't need to repeatedly call static ctors for a given type
@ -15034,7 +15045,10 @@ void BfModule::AddHotDataReferences(BfHotDataReferenceBuilder* builder)
BF_ASSERT(mCurMethodInstance->mIsReified);
if (mCurTypeInstance->mHotTypeData == NULL)
{
mCurTypeInstance->mHotTypeData = new BfHotTypeData();
BfLogSysM("Created HotTypeData %p created for type %p in AddHotDataReferences\n", mCurTypeInstance->mHotTypeData, mCurTypeInstance);
}
auto hotMethod = mCurMethodInstance->mHotMethod;
for (auto depData : hotMethod->mReferences)
@ -18653,7 +18667,8 @@ void BfModule::SetupIRFunction(BfMethodInstance* methodInstance, StringImpl& man
if (isTemporaryFunc)
{
BF_ASSERT((mCompiler->mIsResolveOnly) && (mCompiler->mResolvePassData->mAutoComplete != NULL));
BF_ASSERT(((mCompiler->mIsResolveOnly) && (mCompiler->mResolvePassData->mAutoComplete != NULL)) ||
(methodInstance->GetOwner()->mDefineState < BfTypeDefineState_Defined));
mangledName = "autocomplete_tmp";
}
@ -18870,6 +18885,9 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
{
BP_ZONE("BfModule::BfMethodDeclaration");
// If we are doing this then we may end up creating methods when var types are unknown still, failing on splat/zero-sized info
BF_ASSERT((!mContext->mResolvingVarField) || (mBfIRBuilder->mIgnoreWrites));
// We could trigger a DoMethodDeclaration from a const resolver or other location, so we reset it here
// to effectively make mIgnoreWrites method-scoped
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mWantsIRIgnoreWrites || mCurMethodInstance->mIsUnspecialized);
@ -18883,6 +18901,12 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
bool ignoreWrites = mBfIRBuilder->mIgnoreWrites;
if ((!isTemporaryFunc) && (mCurTypeInstance->mDefineState < BfTypeDefineState_Defined))
{
BF_ASSERT(mContext->mResolvingVarField);
isTemporaryFunc = true;
}
if (mAwaitingInitFinish)
FinishInit();
@ -19731,9 +19755,9 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
if (isTemporaryFunc)
{
// This handles temporary methods for autocomplete types
BF_ASSERT(mIsScratchModule);
BF_ASSERT(mCompiler->IsAutocomplete());
BfLogSysM("DoMethodDeclaration autocomplete bailout\n");
//BF_ASSERT(mIsScratchModule);
//BF_ASSERT(mCompiler->IsAutocomplete());
BfLogSysM("DoMethodDeclaration isTemporaryFunc bailout\n");
return; // Bail out early for autocomplete pass
}

View file

@ -103,7 +103,7 @@ bool BfModule::BuildGenericParams(BfType* resolvedTypeRef)
{
BfTypeState typeState;
typeState.mPrevState = mContext->mCurTypeState;
typeState.mBuildingGenericParams = true;
typeState.mResolveKind = BfTypeState::ResolveKind_BuildingGenericParams;
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
BF_ASSERT(mCurMethodInstance == NULL);
@ -2886,7 +2886,10 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if ((mCompiler->mOptions.mAllowHotSwapping) && (typeInstance->mDefineState < BfTypeDefineState_Defined))
{
if (typeInstance->mHotTypeData == NULL)
{
typeInstance->mHotTypeData = new BfHotTypeData();
BfLogSysM("Created HotTypeData %p created for type %p in DoPopulateType\n", typeInstance->mHotTypeData, typeInstance);
}
// Clear any unused versions (if we have errors, etc)
if (mCompiler->mHotState != NULL)
@ -9817,7 +9820,7 @@ bool BfModule::TypeIsSubTypeOf(BfTypeInstance* srcType, BfTypeInstance* wantType
// Otherwise "T<A> where T : IB" declared in a lib won't be able to match a type B in a using project 'C',
// because this check will see the lib using 'C', which it won't consider visible
if ((checkActiveTypeDef != NULL) &&
((mCurMethodInstance != NULL) && (mContext->mCurTypeState != NULL) && (!mContext->mCurTypeState->mBuildingGenericParams)))
((mCurMethodInstance != NULL) && (mContext->mCurTypeState != NULL) && (mContext->mCurTypeState->mResolveKind != BfTypeState::ResolveKind_BuildingGenericParams)))
{
if ((!srcType->IsTypeMemberAccessible(ifaceInst.mDeclaringType, checkActiveTypeDef)) ||
(!srcType->IsTypeMemberIncluded(ifaceInst.mDeclaringType, checkActiveTypeDef, this)))