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

Improved recursive checks in InferGenericArgument

This commit is contained in:
Brian Fiete 2022-05-25 14:41:17 -07:00
parent f1257fb7fc
commit 0c34e62df2
2 changed files with 25 additions and 24 deletions

View file

@ -255,22 +255,25 @@ bool BfMethodMatcher::IsMemberAccessible(BfTypeInstance* typeInst, BfTypeDef* de
return true;
}
bool BfGenericInferContext::InferGenericArgument(BfMethodInstance* methodInstance, BfType* argType, BfType* wantType, BfIRValue argValue)
bool BfGenericInferContext::AddToCheckedSet(BfType* argType, BfType* wantType)
{
int64 idPair = ((int64)argType->mTypeId << 32) | (wantType->mTypeId);
return mCheckedTypeSet.Add(idPair);
}
bool BfGenericInferContext::InferGenericArgument(BfMethodInstance* methodInstance, BfType* argType, BfType* wantType, BfIRValue argValue, bool checkCheckedSet)
{
if (argType == NULL)
return false;
if (!wantType->IsUnspecializedType())
return true;
bool alreadyChecked = false;
auto _AddToCheckedSet = [](BfType* type, HashSet<BfType*>& checkedTypeSet, bool& alreadyChecked)
if (checkCheckedSet)
{
if (alreadyChecked)
if (!AddToCheckedSet(argType, wantType))
return true;
alreadyChecked = true;
return checkedTypeSet.Add(type);
};
}
if (wantType->IsGenericParam())
{
@ -305,7 +308,7 @@ bool BfGenericInferContext::InferGenericArgument(BfMethodInstance* methodInstanc
if (argGenericType->mTypeDef->GetLatest() == wantGenericType->mTypeDef->GetLatest())
{
for (int genericArgIdx = 0; genericArgIdx < (int)argGenericType->mGenericTypeInfo->mTypeGenericArguments.size(); genericArgIdx++)
InferGenericArgument(methodInstance, argGenericType->mGenericTypeInfo->mTypeGenericArguments[genericArgIdx], wantGenericType->mGenericTypeInfo->mTypeGenericArguments[genericArgIdx], BfIRValue());
InferGenericArgument(methodInstance, argGenericType->mGenericTypeInfo->mTypeGenericArguments[genericArgIdx], wantGenericType->mGenericTypeInfo->mTypeGenericArguments[genericArgIdx], BfIRValue(), true);
}
}
else if (checkArgType->IsSizedArray())
@ -316,7 +319,7 @@ bool BfGenericInferContext::InferGenericArgument(BfMethodInstance* methodInstanc
InferGenericArgument(methodInstance, sizedArrayType->mElementType, wantGenericType->mGenericTypeInfo->mTypeGenericArguments[0], BfIRValue());
auto intType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
BfTypedValue arraySize = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, (uint64)sizedArrayType->mElementCount), intType);
InferGenericArgument(methodInstance, mModule->CreateConstExprValueType(arraySize), wantGenericType->mGenericTypeInfo->mTypeGenericArguments[1], BfIRValue());
InferGenericArgument(methodInstance, mModule->CreateConstExprValueType(arraySize), wantGenericType->mGenericTypeInfo->mTypeGenericArguments[1], BfIRValue(), true);
}
}
else if (checkArgType->IsPointer())
@ -324,7 +327,7 @@ bool BfGenericInferContext::InferGenericArgument(BfMethodInstance* methodInstanc
auto pointerType = (BfPointerType*)checkArgType;
if (wantGenericType->IsInstanceOf(mModule->mCompiler->mPointerTTypeDef))
{
InferGenericArgument(methodInstance, pointerType->mElementType, wantGenericType->mGenericTypeInfo->mTypeGenericArguments[0], BfIRValue());
InferGenericArgument(methodInstance, pointerType->mElementType, wantGenericType->mGenericTypeInfo->mTypeGenericArguments[0], BfIRValue(), true);
}
}
@ -502,10 +505,8 @@ bool BfGenericInferContext::InferGenericArgument(BfMethodInstance* methodInstanc
{
BfType* wantGenericArgument = wantGenericType->mGenericTypeInfo->mTypeGenericArguments[genericArgIdx];
if (!wantGenericArgument->IsUnspecializedType())
continue;
if (!_AddToCheckedSet(argType, mCheckedTypeSet, alreadyChecked))
return true;
InferGenericArgument(methodInstance, argGenericType->mGenericTypeInfo->mTypeGenericArguments[genericArgIdx], wantGenericArgument, BfIRValue());
continue;
InferGenericArgument(methodInstance, argGenericType->mGenericTypeInfo->mTypeGenericArguments[genericArgIdx], wantGenericArgument, BfIRValue(), true);
}
return true;
}
@ -567,7 +568,7 @@ bool BfGenericInferContext::InferGenericArgument(BfMethodInstance* methodInstanc
if (((argType->IsDelegate()) || (argType->IsFunction())) &&
(wantType->IsDelegate() == argType->IsDelegate()))
{
if (!_AddToCheckedSet(argType, mCheckedTypeSet, alreadyChecked))
if (!AddToCheckedSet(argType, wantType))
return true;
auto argInvokeMethod = mModule->GetRawMethodByName(argType->ToTypeInstance(), "Invoke");
@ -583,7 +584,7 @@ bool BfGenericInferContext::InferGenericArgument(BfMethodInstance* methodInstanc
else if (argType->IsMethodRef())
{
auto methodTypeRef = (BfMethodRefType*)argType;
if (!_AddToCheckedSet(argType, mCheckedTypeSet, alreadyChecked))
if (!AddToCheckedSet(argType, wantType))
return true;
auto argInvokeMethod = methodTypeRef->mMethodRef;
@ -1687,7 +1688,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
BfGenericInferContext genericInferContext;
genericInferContext.mModule = mModule;
genericInferContext.mCheckMethodGenericArguments = &mCheckMethodGenericArguments;
genericInferContext.mCheckMethodGenericArguments = &mCheckMethodGenericArguments;
HashSet<int> allowEmptyGenericSet;
BfAutoComplete* autoComplete = NULL;
@ -1900,8 +1901,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
if ((wantType->IsArray()) || (wantType->IsSizedArray()) || (wantType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)))
wantType = wantType->GetUnderlyingType();
}
genericInferContext.mCheckedTypeSet.Clear();
if (!genericInferContext.InferGenericArgument(methodInstance, type, wantType, argTypedValue.mValue))
return ResultKind_Failed;
}
@ -1994,8 +1994,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
}
if ((mCheckReturnType != NULL) && (methodInstance->mReturnType->IsUnspecializedType()))
{
genericInferContext.mCheckedTypeSet.Clear();
{
if (!genericInferContext.InferGenericArgument(methodInstance, mCheckReturnType, methodInstance->mReturnType, BfIRValue()))
return ResultKind_Failed;
}

View file

@ -136,7 +136,7 @@ public:
class BfGenericInferContext
{
public:
HashSet<BfType*> mCheckedTypeSet;
HashSet<int64> mCheckedTypeSet;
BfModule* mModule;
BfTypeVector* mCheckMethodGenericArguments;
SizedArray<BfIRValue, 4> mPrevArgValues;
@ -148,7 +148,9 @@ public:
mModule = NULL;
mInferredCount = 0;
}
bool InferGenericArgument(BfMethodInstance* methodInstance, BfType* argType, BfType* wantType, BfIRValue argValue);
bool AddToCheckedSet(BfType* argType, BfType* wantType);
bool InferGenericArgument(BfMethodInstance* methodInstance, BfType* argType, BfType* wantType, BfIRValue argValue, bool checkCheckedSet = false);
int GetUnresolvedCount()
{
return (int)mCheckMethodGenericArguments->size() - mInferredCount;