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:
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->mVTableOrigLength = typeInstance->mVirtualMethodTableSize;
|
||||||
hotTypeData->mOrigInterfaceMethodsLength = typeInstance->GetIFaceVMethodSize();
|
hotTypeData->mOrigInterfaceMethodsLength = typeInstance->GetIFaceVMethodSize();
|
||||||
}
|
}
|
||||||
|
BfLogSysM("PopulateHotTypeDataVTable set %p HotDataType->mVTableOrigLength To %d\n", typeInstance, hotTypeData->mVTableOrigLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
int vTableStart = -1;
|
int vTableStart = -1;
|
||||||
|
|
|
@ -109,6 +109,14 @@ public:
|
||||||
|
|
||||||
class BfTypeState
|
class BfTypeState
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
enum ResolveKind
|
||||||
|
{
|
||||||
|
ResolveKind_None,
|
||||||
|
ResolveKind_BuildingGenericParams,
|
||||||
|
ResolveKind_ResolvingVarType
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BfTypeState* mPrevState;
|
BfTypeState* mPrevState;
|
||||||
|
|
||||||
|
@ -121,7 +129,7 @@ public:
|
||||||
BfTypeReference* mCurAttributeTypeRef;
|
BfTypeReference* mCurAttributeTypeRef;
|
||||||
BfFieldDef* mCurFieldDef;
|
BfFieldDef* mCurFieldDef;
|
||||||
BfTypeDef* mCurTypeDef;
|
BfTypeDef* mCurTypeDef;
|
||||||
bool mBuildingGenericParams;
|
ResolveKind mResolveKind;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BfTypeState()
|
BfTypeState()
|
||||||
|
@ -135,7 +143,7 @@ public:
|
||||||
mCurFieldDef = NULL;
|
mCurFieldDef = NULL;
|
||||||
mCurAttributeTypeRef = NULL;
|
mCurAttributeTypeRef = NULL;
|
||||||
mCurTypeDef = NULL;
|
mCurTypeDef = NULL;
|
||||||
mBuildingGenericParams = false;
|
mResolveKind = ResolveKind_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
BfTypeState(BfTypeInstance* typeInstance, BfTypeState* prevState = NULL)
|
BfTypeState(BfTypeInstance* typeInstance, BfTypeState* prevState = NULL)
|
||||||
|
@ -149,7 +157,7 @@ public:
|
||||||
mCurFieldDef = NULL;
|
mCurFieldDef = NULL;
|
||||||
mCurAttributeTypeRef = NULL;
|
mCurAttributeTypeRef = NULL;
|
||||||
mCurTypeDef = NULL;
|
mCurTypeDef = NULL;
|
||||||
mBuildingGenericParams = false;
|
mResolveKind = ResolveKind_None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1745,6 +1745,29 @@ bool BfMethodMatcher::CheckType(BfTypeInstance* typeInstance, BfTypedValue targe
|
||||||
auto checkMethod = nextMethodDef;
|
auto checkMethod = nextMethodDef;
|
||||||
nextMethodDef = nextMethodDef->mNextWithSameName;
|
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))
|
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
|
// Accept either a method in the same project but that's the root definition, OR a method that's in a dependent project
|
||||||
|
@ -5084,7 +5107,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
||||||
moduleMethodInstance.mFunc = mModule->mBfIRBuilder->CreateIntToPtr(target.mValue, funcPtrType);
|
moduleMethodInstance.mFunc = mModule->mBfIRBuilder->CreateIntToPtr(target.mValue, funcPtrType);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mModule->CheckStaticAccess(methodInstance->mMethodInstanceGroup->mOwner);
|
mModule->CheckStaticAccess(methodInstance->mMethodInstanceGroup->mOwner);
|
||||||
|
|
||||||
if (target)
|
if (target)
|
||||||
|
|
|
@ -3410,8 +3410,15 @@ BfType* BfModule::ResolveVarFieldType(BfTypeInstance* typeInstance, BfFieldInsta
|
||||||
|
|
||||||
BfType* resolvedType = NULL;
|
BfType* resolvedType = NULL;
|
||||||
if (!hadInferenceCycle)
|
if (!hadInferenceCycle)
|
||||||
{
|
{
|
||||||
SetAndRestoreValue<bool> prevIgnoreWrite(mBfIRBuilder->mIgnoreWrites, true);
|
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*/);
|
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL/*ctorMethod.mMethodInstance*/);
|
||||||
|
|
||||||
auto prevInsertBlock = mBfIRBuilder->GetInsertBlock();
|
auto prevInsertBlock = mBfIRBuilder->GetInsertBlock();
|
||||||
|
@ -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)
|
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);
|
PopulateType(typeInstance, BfPopulateType_DataAndMethods);
|
||||||
|
|
||||||
//TODO: Create a hashset of these, we don't need to repeatedly call static ctors for a given type
|
//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);
|
BF_ASSERT(mCurMethodInstance->mIsReified);
|
||||||
|
|
||||||
if (mCurTypeInstance->mHotTypeData == NULL)
|
if (mCurTypeInstance->mHotTypeData == NULL)
|
||||||
|
{
|
||||||
mCurTypeInstance->mHotTypeData = new BfHotTypeData();
|
mCurTypeInstance->mHotTypeData = new BfHotTypeData();
|
||||||
|
BfLogSysM("Created HotTypeData %p created for type %p in AddHotDataReferences\n", mCurTypeInstance->mHotTypeData, mCurTypeInstance);
|
||||||
|
}
|
||||||
|
|
||||||
auto hotMethod = mCurMethodInstance->mHotMethod;
|
auto hotMethod = mCurMethodInstance->mHotMethod;
|
||||||
for (auto depData : hotMethod->mReferences)
|
for (auto depData : hotMethod->mReferences)
|
||||||
|
@ -18653,7 +18667,8 @@ void BfModule::SetupIRFunction(BfMethodInstance* methodInstance, StringImpl& man
|
||||||
|
|
||||||
if (isTemporaryFunc)
|
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";
|
mangledName = "autocomplete_tmp";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18870,6 +18885,9 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
||||||
{
|
{
|
||||||
BP_ZONE("BfModule::BfMethodDeclaration");
|
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
|
// We could trigger a DoMethodDeclaration from a const resolver or other location, so we reset it here
|
||||||
// to effectively make mIgnoreWrites method-scoped
|
// to effectively make mIgnoreWrites method-scoped
|
||||||
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mWantsIRIgnoreWrites || mCurMethodInstance->mIsUnspecialized);
|
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mWantsIRIgnoreWrites || mCurMethodInstance->mIsUnspecialized);
|
||||||
|
@ -18882,6 +18900,12 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
||||||
mCurMethodInstance->mMethodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingReference;
|
mCurMethodInstance->mMethodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingReference;
|
||||||
|
|
||||||
bool ignoreWrites = mBfIRBuilder->mIgnoreWrites;
|
bool ignoreWrites = mBfIRBuilder->mIgnoreWrites;
|
||||||
|
|
||||||
|
if ((!isTemporaryFunc) && (mCurTypeInstance->mDefineState < BfTypeDefineState_Defined))
|
||||||
|
{
|
||||||
|
BF_ASSERT(mContext->mResolvingVarField);
|
||||||
|
isTemporaryFunc = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (mAwaitingInitFinish)
|
if (mAwaitingInitFinish)
|
||||||
FinishInit();
|
FinishInit();
|
||||||
|
@ -19731,9 +19755,9 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
||||||
if (isTemporaryFunc)
|
if (isTemporaryFunc)
|
||||||
{
|
{
|
||||||
// This handles temporary methods for autocomplete types
|
// This handles temporary methods for autocomplete types
|
||||||
BF_ASSERT(mIsScratchModule);
|
//BF_ASSERT(mIsScratchModule);
|
||||||
BF_ASSERT(mCompiler->IsAutocomplete());
|
//BF_ASSERT(mCompiler->IsAutocomplete());
|
||||||
BfLogSysM("DoMethodDeclaration autocomplete bailout\n");
|
BfLogSysM("DoMethodDeclaration isTemporaryFunc bailout\n");
|
||||||
return; // Bail out early for autocomplete pass
|
return; // Bail out early for autocomplete pass
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ bool BfModule::BuildGenericParams(BfType* resolvedTypeRef)
|
||||||
{
|
{
|
||||||
BfTypeState typeState;
|
BfTypeState typeState;
|
||||||
typeState.mPrevState = mContext->mCurTypeState;
|
typeState.mPrevState = mContext->mCurTypeState;
|
||||||
typeState.mBuildingGenericParams = true;
|
typeState.mResolveKind = BfTypeState::ResolveKind_BuildingGenericParams;
|
||||||
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
||||||
|
|
||||||
BF_ASSERT(mCurMethodInstance == NULL);
|
BF_ASSERT(mCurMethodInstance == NULL);
|
||||||
|
@ -2886,7 +2886,10 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
if ((mCompiler->mOptions.mAllowHotSwapping) && (typeInstance->mDefineState < BfTypeDefineState_Defined))
|
if ((mCompiler->mOptions.mAllowHotSwapping) && (typeInstance->mDefineState < BfTypeDefineState_Defined))
|
||||||
{
|
{
|
||||||
if (typeInstance->mHotTypeData == NULL)
|
if (typeInstance->mHotTypeData == NULL)
|
||||||
|
{
|
||||||
typeInstance->mHotTypeData = new BfHotTypeData();
|
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)
|
// Clear any unused versions (if we have errors, etc)
|
||||||
if (mCompiler->mHotState != NULL)
|
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',
|
// 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
|
// because this check will see the lib using 'C', which it won't consider visible
|
||||||
if ((checkActiveTypeDef != NULL) &&
|
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)) ||
|
if ((!srcType->IsTypeMemberAccessible(ifaceInst.mDeclaringType, checkActiveTypeDef)) ||
|
||||||
(!srcType->IsTypeMemberIncluded(ifaceInst.mDeclaringType, checkActiveTypeDef, this)))
|
(!srcType->IsTypeMemberIncluded(ifaceInst.mDeclaringType, checkActiveTypeDef, this)))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue