mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-10 12:32:20 +02:00
Fixed field var-resolving when calling methods
This commit is contained in:
parent
e12c03d46e
commit
13d7b0c1c5
5 changed files with 72 additions and 13 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue