1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-16 15:24:10 +02:00

Fixed const expr preference in method selection

This commit is contained in:
Brian Fiete 2020-08-01 12:16:17 -07:00
parent fb960747ec
commit 91dea6cd3b
2 changed files with 69 additions and 13 deletions

View file

@ -678,6 +678,9 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
bool betterByGenericParam = false; bool betterByGenericParam = false;
bool worseByGenericParam = false; bool worseByGenericParam = false;
bool betterByConstExprParam = false;
bool worseByConstExprParam = false;
for (argIdx = anyIsExtension ? -1 : 0; argIdx < (int)mArguments.size(); argIdx++) for (argIdx = anyIsExtension ? -1 : 0; argIdx < (int)mArguments.size(); argIdx++)
{ {
BfTypedValue arg; BfTypedValue arg;
@ -708,12 +711,20 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
BfType* origParamType = paramType; BfType* origParamType = paramType;
BfType* origPrevParamType = prevParamType; BfType* origPrevParamType = prevParamType;
bool paramWasConstExpr = false;
bool prevParamWasConstExpr = false;
bool paramWasUnspecialized = paramType->IsUnspecializedType(); bool paramWasUnspecialized = paramType->IsUnspecializedType();
if ((genericArgumentsSubstitute != NULL) && (paramWasUnspecialized)) if ((genericArgumentsSubstitute != NULL) && (paramWasUnspecialized))
{ {
paramType = mModule->ResolveGenericType(paramType, NULL, genericArgumentsSubstitute, allowSpecializeFail); paramType = mModule->ResolveGenericType(paramType, NULL, genericArgumentsSubstitute, allowSpecializeFail);
paramType = mModule->FixIntUnknown(paramType); paramType = mModule->FixIntUnknown(paramType);
} }
if (paramType->IsConstExprValue())
{
prevParamWasConstExpr = true;
paramType = ((BfConstExprValueType*)paramType)->mType;
}
bool prevParamWasUnspecialized = prevParamType->IsUnspecializedType(); bool prevParamWasUnspecialized = prevParamType->IsUnspecializedType();
if ((prevGenericArgumentsSubstitute != NULL) && (prevParamWasUnspecialized)) if ((prevGenericArgumentsSubstitute != NULL) && (prevParamWasUnspecialized))
@ -721,6 +732,11 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
prevParamType = mModule->ResolveGenericType(prevParamType, NULL, prevGenericArgumentsSubstitute, allowSpecializeFail); prevParamType = mModule->ResolveGenericType(prevParamType, NULL, prevGenericArgumentsSubstitute, allowSpecializeFail);
prevParamType = mModule->FixIntUnknown(prevParamType); prevParamType = mModule->FixIntUnknown(prevParamType);
} }
if (prevParamType->IsConstExprValue())
{
prevParamWasConstExpr = true;
prevParamType = ((BfConstExprValueType*)prevParamType)->mType;
}
bool paramsEquivalent = paramType == prevParamType; bool paramsEquivalent = paramType == prevParamType;
@ -735,9 +751,6 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
SET_BETTER_OR_WORSE((!isUnspecializedParam) && (!paramType->IsVar()), SET_BETTER_OR_WORSE((!isUnspecializedParam) && (!paramType->IsVar()),
(!isPrevUnspecializedParam) && (!prevParamType->IsVar())); (!isPrevUnspecializedParam) && (!prevParamType->IsVar()));
if ((!isBetter) && (!isWorse))
SET_BETTER_OR_WORSE(paramType->IsConstExprValue(), prevParamType->IsConstExprValue());
if ((!isBetter) && (!isWorse) && (!isUnspecializedParam) && (!isPrevUnspecializedParam)) if ((!isBetter) && (!isWorse) && (!isUnspecializedParam) && (!isPrevUnspecializedParam))
{ {
SET_BETTER_OR_WORSE((paramType != NULL) && (!paramType->IsUnspecializedType()), SET_BETTER_OR_WORSE((paramType != NULL) && (!paramType->IsUnspecializedType()),
@ -785,14 +798,20 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
} }
} }
if (((!isBetter) && (!isWorse)) && (paramsEquivalent) && if ((!isBetter) & (!isWorse) && (paramsEquivalent))
((paramWasUnspecialized) || (prevParamWasUnspecialized)))
{ {
int origTypeMoreSpecific = GetMostSpecificType(origParamType, origPrevParamType); if ((origParamType != origPrevParamType) && (paramWasConstExpr) && (!prevParamWasConstExpr))
if (origTypeMoreSpecific == 0) betterByConstExprParam = true;
betterByGenericParam = true; else if ((origParamType != origPrevParamType) && (!paramWasConstExpr) && (prevParamWasConstExpr))
else if (origTypeMoreSpecific == 1) worseByConstExprParam = true;
worseByGenericParam = true; else if (((paramWasUnspecialized) || (prevParamWasUnspecialized)))
{
int origTypeMoreSpecific = GetMostSpecificType(origParamType, origPrevParamType);
if (origTypeMoreSpecific == 0)
betterByGenericParam = true;
else if (origTypeMoreSpecific == 1)
worseByGenericParam = true;
}
} }
if ((newArgIdx >= 0) && (newMethodInstance->GetParamKind(newArgIdx) == BfParamKind_Params)) if ((newArgIdx >= 0) && (newMethodInstance->GetParamKind(newArgIdx) == BfParamKind_Params))
@ -815,6 +834,17 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
} }
} }
if ((!isBetter) && (!isWorse))
{
// Don't allow ambiguity
if ((betterByConstExprParam && !worseByConstExprParam) ||
(!betterByConstExprParam && worseByConstExprParam))
{
isBetter = betterByConstExprParam;
isWorse = worseByConstExprParam;
}
}
if ((isBetter) || (isWorse)) if ((isBetter) || (isWorse))
{ {
RETURN_RESULTS; RETURN_RESULTS;

View file

@ -81,6 +81,26 @@ namespace Tests
return 2; return 2;
} }
public static int MethodE<T>(T val, int val2)
{
return 1;
}
public static int MethodE<T, TVal>(T val, TVal val2) where TVal : const int
{
return 2;
}
public static int MethodE<T>(List<T> val, int val2)
{
return 3;
}
public static int MethodE<T, TVal>(List<T> val, TVal val2) where TVal : const int
{
return 4;
}
[Test] [Test]
public static void TestBasics() public static void TestBasics()
{ {
@ -115,8 +135,14 @@ namespace Tests
Test.Assert(MethodB(("A", "B")) == 3); Test.Assert(MethodB(("A", "B")) == 3);
Test.Assert(MethodC(("A", "B")) == 3); Test.Assert(MethodC(("A", "B")) == 3);
int[][] arrArr = new int[1][]; int[][] arrArr = scope int[1][];
Test.Assert(MethodD(ref arrArr) == 2); Test.Assert(MethodD(ref arrArr) == 2);
int a = 100;
Test.Assert(MethodE(sa, a) == 1);
Test.Assert(MethodE(sa, 100) == 2);
Test.Assert(MethodE(sal, a) == 3);
Test.Assert(MethodE(sal, 200) == 4);
} }
} }
} }