mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-14 14:24:10 +02:00
Fixed method selection by extern constraint specificity
This commit is contained in:
parent
d0d89a552e
commit
56bcb6ecd1
2 changed files with 93 additions and 3 deletions
|
@ -993,13 +993,53 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
|
||||||
{
|
{
|
||||||
SET_BETTER_OR_WORSE(newMethodInstance->HasExternConstraints(), prevMethodInstance->HasExternConstraints());
|
SET_BETTER_OR_WORSE(newMethodInstance->HasExternConstraints(), prevMethodInstance->HasExternConstraints());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((isBetter) || (isWorse))
|
if ((isBetter) || (isWorse))
|
||||||
{
|
{
|
||||||
RETURN_RESULTS;
|
RETURN_RESULTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((newMethodInstance->mMethodDef->mExternalConstraints.size() != 0) || (prevMethodInstance->mMethodDef->mExternalConstraints.size() != 0))
|
||||||
|
{
|
||||||
|
struct GenericParamPair
|
||||||
|
{
|
||||||
|
BfGenericMethodParamInstance* mParams[2];
|
||||||
|
GenericParamPair()
|
||||||
|
{
|
||||||
|
mParams[0] = NULL;
|
||||||
|
mParams[1] = NULL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Dictionary<BfType*, GenericParamPair> externConstraints;
|
||||||
|
|
||||||
|
auto _GetParams = [&](int idx, BfMethodInstance* methodInstance)
|
||||||
|
{
|
||||||
|
for (int externConstraintIdx = 0; externConstraintIdx < (int)methodInstance->mMethodDef->mExternalConstraints.size(); externConstraintIdx++)
|
||||||
|
{
|
||||||
|
auto genericParam = methodInstance->mMethodInfoEx->mGenericParams[methodInstance->mMethodDef->mGenericParams.size() + externConstraintIdx];
|
||||||
|
BF_ASSERT(genericParam->mExternType != NULL);
|
||||||
|
GenericParamPair* pairPtr = NULL;
|
||||||
|
externConstraints.TryAdd(genericParam->mExternType, NULL, &pairPtr);
|
||||||
|
pairPtr->mParams[idx] = genericParam;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_GetParams(0, newMethodInstance);
|
||||||
|
_GetParams(0, prevMethodInstance);
|
||||||
|
|
||||||
|
for (auto kv : externConstraints)
|
||||||
|
{
|
||||||
|
SET_BETTER_OR_WORSE(mModule->AreConstraintsSubset(kv.mValue.mParams[1], kv.mValue.mParams[0]), mModule->AreConstraintsSubset(kv.mValue.mParams[0], kv.mValue.mParams[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((isBetter) || (isWorse))
|
||||||
|
{
|
||||||
|
RETURN_RESULTS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Does one have a body and one doesn't? Obvious!
|
// Does one have a body and one doesn't? Obvious!
|
||||||
isBetter = prevMethodDef->IsEmptyPartial();
|
isBetter = prevMethodDef->IsEmptyPartial();
|
||||||
isWorse = newMethodDef->IsEmptyPartial();
|
isWorse = newMethodDef->IsEmptyPartial();
|
||||||
|
@ -1389,7 +1429,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
|
||||||
|
|
||||||
mMethodCheckCount++;
|
mMethodCheckCount++;
|
||||||
|
|
||||||
BfMethodInstance* methodInstance = mModule->GetRawMethodInstance(typeInstance, checkMethod);
|
BfMethodInstance* methodInstance = mModule->GetRawMethodInstance(typeInstance, checkMethod);
|
||||||
if (methodInstance == NULL)
|
if (methodInstance == NULL)
|
||||||
{
|
{
|
||||||
BFMODULE_FATAL(mModule, "Failed to get raw method in BfMethodMatcher::CheckMethod");
|
BFMODULE_FATAL(mModule, "Failed to get raw method in BfMethodMatcher::CheckMethod");
|
||||||
|
|
50
IDEHelper/Tests/src/Generics2.bf
Normal file
50
IDEHelper/Tests/src/Generics2.bf
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Tests
|
||||||
|
{
|
||||||
|
class Generics2
|
||||||
|
{
|
||||||
|
struct TestFunc<T, Del>
|
||||||
|
{
|
||||||
|
private int mId;
|
||||||
|
private Del mComparer;
|
||||||
|
|
||||||
|
public static TestFunc<T, Del> Create(int id, Del comparer)
|
||||||
|
{
|
||||||
|
return .()
|
||||||
|
{
|
||||||
|
mId = id,
|
||||||
|
mComparer = comparer
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckDlg(T item)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckDlg(T item) where Del : delegate bool(T)
|
||||||
|
{
|
||||||
|
return mComparer(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckDlg(T item) where Del : delegate bool(int, T)
|
||||||
|
{
|
||||||
|
return mComparer(mId, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CallCheck(T val)
|
||||||
|
{
|
||||||
|
return CheckDlg(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public static void TestBasics()
|
||||||
|
{
|
||||||
|
let testF = TestFunc<String, delegate bool(String)>.Create(10, scope (s) => s == "Str");
|
||||||
|
Test.Assert(testF.CallCheck("Str"));
|
||||||
|
Test.Assert(!testF.CallCheck("Str2"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue