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

View file

@ -136,7 +136,7 @@ public:
class BfGenericInferContext class BfGenericInferContext
{ {
public: public:
HashSet<BfType*> mCheckedTypeSet; HashSet<int64> mCheckedTypeSet;
BfModule* mModule; BfModule* mModule;
BfTypeVector* mCheckMethodGenericArguments; BfTypeVector* mCheckMethodGenericArguments;
SizedArray<BfIRValue, 4> mPrevArgValues; SizedArray<BfIRValue, 4> mPrevArgValues;
@ -148,7 +148,9 @@ public:
mModule = NULL; mModule = NULL;
mInferredCount = 0; 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() int GetUnresolvedCount()
{ {
return (int)mCheckMethodGenericArguments->size() - mInferredCount; return (int)mCheckMethodGenericArguments->size() - mInferredCount;