1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-16 07:14:09 +02:00

Allow for Method<T, T2>(T val) where T : IEnumerable<T2> matching

This commit is contained in:
Brian Fiete 2021-01-13 06:18:40 -08:00
parent df1404e14b
commit 9510faafca
2 changed files with 78 additions and 9 deletions

View file

@ -321,6 +321,7 @@ bool BfGenericInferContext::InferGenericArgument(BfMethodInstance* methodInstanc
if ((*mCheckMethodGenericArguments)[wantGenericParam->mGenericParamIdx] == NULL)
mInferredCount++;
(*mCheckMethodGenericArguments)[wantGenericParam->mGenericParamIdx] = argType;
if (!mPrevArgValues.IsEmpty())
mPrevArgValues[wantGenericParam->mGenericParamIdx] = argValue;
};
@ -356,6 +357,12 @@ bool BfGenericInferContext::InferGenericArgument(BfMethodInstance* methodInstanc
}
}
if (mPrevArgValues.IsEmpty())
{
_SetGeneric();
return true;
}
auto prevGenericMethodArg = (*mCheckMethodGenericArguments)[wantGenericParam->mGenericParamIdx];
auto prevArgValue = mPrevArgValues[wantGenericParam->mGenericParamIdx];
if (prevGenericMethodArg == NULL)
@ -581,6 +588,28 @@ bool BfGenericInferContext::InferGenericArgument(BfMethodInstance* methodInstanc
return true;
}
// void BfGenericInferContext::PropogateInference(BfType* resolvedType, BfType* unresovledType)
// {
// if (!unresovledType->IsUnspecializedTypeVariation())
// return;
//
// auto resolvedTypeInstance = resolvedType->ToTypeInstance();
// auto unresolvedTypeInstance = unresovledType->ToTypeInstance();
//
// if ((resolvedTypeInstance == NULL) || (unresolvedTypeInstance == NULL))
// return;
// if (resolvedTypeInstance->mTypeDef != unresolvedTypeInstance->mTypeDef)
// return;
//
// if (unres)
//
// if (resolvedType->IsGenericTypeInstance())
// {
//
//
// }
// }
int BfMethodMatcher::GetMostSpecificType(BfType* lhs, BfType* rhs)
{
if ((lhs->IsRef()) && (rhs->IsRef()))
@ -1519,10 +1548,6 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
if (checkMethod->mHasAppend)
paramIdx++;
// int outmostGenericCount = 0;
// if (checkMethod->mIsLocalMethod)
// outmostGenericCount = (int)mModule->mCurMethodState->GetRootMethodState()->mMethodInstance->mGenericParams.size();
int uniqueGenericStartIdx = mModule->GetLocalInferrableGenericArgCount(checkMethod);
if ((mHadExplicitGenericArguments) && (checkMethod->mGenericParams.size() != mExplicitMethodGenericArguments.size() + uniqueGenericStartIdx))
@ -1533,7 +1558,6 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
mCheckMethodGenericArguments.resize(checkMethod->mGenericParams.size());
//mPrevArgValues.resize(checkMethod->mGenericParams.size());
for (auto& genericArgRef : mCheckMethodGenericArguments)
genericArgRef = NULL;
@ -14163,6 +14187,38 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc,
}
}
if (genericArg == NULL)
{
// Attempt to infer from other generic args
for (int srcGenericIdx = 0; srcGenericIdx < (int)methodMatcher.mBestMethodGenericArguments.size(); srcGenericIdx++)
{
auto& srcGenericArg = methodMatcher.mBestMethodGenericArguments[srcGenericIdx];
if (srcGenericArg == NULL)
continue;
auto srcGenericParam = unspecializedMethod->mMethodInfoEx->mGenericParams[srcGenericIdx];
BfGenericInferContext genericInferContext;
genericInferContext.mModule = mModule;
genericInferContext.mCheckMethodGenericArguments = &methodMatcher.mBestMethodGenericArguments;
for (auto ifaceConstraint : srcGenericParam->mInterfaceConstraints)
{
if ((ifaceConstraint->IsUnspecializedTypeVariation()) && (ifaceConstraint->IsGenericTypeInstance()))
{
genericInferContext.InferGenericArgument(unspecializedMethod, srcGenericArg, ifaceConstraint, BfIRValue());
auto typeInstance = srcGenericArg->ToTypeInstance();
if (typeInstance != NULL)
{
for (auto ifaceEntry : typeInstance->mInterfaces)
genericInferContext.InferGenericArgument(unspecializedMethod, ifaceEntry.mInterfaceType, ifaceConstraint, BfIRValue());
}
}
}
}
}
if (genericArg == NULL)
{
failed = true;

View file

@ -226,6 +226,16 @@ namespace Tests
}
static int MethodE<T, T2>(T val) where T : IEnumerable<T2>
{
return 0;
}
static int MethodF<T>(IEnumerable<T> val)
{
return 0;
}
[Test]
public static void TestBasics()
{
@ -267,6 +277,9 @@ namespace Tests
Test.Assert(LibA.LibA2.CheckEq(cd, cd2));
Test.Assert(ClassE.Instance.CreateSystem<int>() == 999);
MethodE(list);
MethodF(list);
}
}