1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-16 15:24:10 +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) if ((*mCheckMethodGenericArguments)[wantGenericParam->mGenericParamIdx] == NULL)
mInferredCount++; mInferredCount++;
(*mCheckMethodGenericArguments)[wantGenericParam->mGenericParamIdx] = argType; (*mCheckMethodGenericArguments)[wantGenericParam->mGenericParamIdx] = argType;
if (!mPrevArgValues.IsEmpty())
mPrevArgValues[wantGenericParam->mGenericParamIdx] = argValue; 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 prevGenericMethodArg = (*mCheckMethodGenericArguments)[wantGenericParam->mGenericParamIdx];
auto prevArgValue = mPrevArgValues[wantGenericParam->mGenericParamIdx]; auto prevArgValue = mPrevArgValues[wantGenericParam->mGenericParamIdx];
if (prevGenericMethodArg == NULL) if (prevGenericMethodArg == NULL)
@ -581,6 +588,28 @@ bool BfGenericInferContext::InferGenericArgument(BfMethodInstance* methodInstanc
return true; 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) int BfMethodMatcher::GetMostSpecificType(BfType* lhs, BfType* rhs)
{ {
if ((lhs->IsRef()) && (rhs->IsRef())) if ((lhs->IsRef()) && (rhs->IsRef()))
@ -1519,10 +1548,6 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
if (checkMethod->mHasAppend) if (checkMethod->mHasAppend)
paramIdx++; paramIdx++;
// int outmostGenericCount = 0;
// if (checkMethod->mIsLocalMethod)
// outmostGenericCount = (int)mModule->mCurMethodState->GetRootMethodState()->mMethodInstance->mGenericParams.size();
int uniqueGenericStartIdx = mModule->GetLocalInferrableGenericArgCount(checkMethod); int uniqueGenericStartIdx = mModule->GetLocalInferrableGenericArgCount(checkMethod);
if ((mHadExplicitGenericArguments) && (checkMethod->mGenericParams.size() != mExplicitMethodGenericArguments.size() + uniqueGenericStartIdx)) if ((mHadExplicitGenericArguments) && (checkMethod->mGenericParams.size() != mExplicitMethodGenericArguments.size() + uniqueGenericStartIdx))
@ -1533,7 +1558,6 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
mCheckMethodGenericArguments.resize(checkMethod->mGenericParams.size()); mCheckMethodGenericArguments.resize(checkMethod->mGenericParams.size());
//mPrevArgValues.resize(checkMethod->mGenericParams.size());
for (auto& genericArgRef : mCheckMethodGenericArguments) for (auto& genericArgRef : mCheckMethodGenericArguments)
genericArgRef = NULL; 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) if (genericArg == NULL)
{ {
failed = true; 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] [Test]
public static void TestBasics() public static void TestBasics()
{ {
@ -267,6 +277,9 @@ namespace Tests
Test.Assert(LibA.LibA2.CheckEq(cd, cd2)); Test.Assert(LibA.LibA2.CheckEq(cd, cd2));
Test.Assert(ClassE.Instance.CreateSystem<int>() == 999); Test.Assert(ClassE.Instance.CreateSystem<int>() == 999);
MethodE(list);
MethodF(list);
} }
} }