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

Fixed operator constraint checking with generic operators

This commit is contained in:
Brian Fiete 2021-01-20 11:23:28 -08:00
parent 48f2ec42f5
commit d0cfb37309
2 changed files with 56 additions and 13 deletions

View file

@ -20846,17 +20846,33 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
if ((flags & BfBinOpFlag_IsConstraintCheck) != 0) if ((flags & BfBinOpFlag_IsConstraintCheck) != 0)
{ {
// We can't do CheckMethod because circular referencing means we may have to evaluate this before our type is complete, if (operatorDef->mGenericParams.IsEmpty())
// which means before method processing has occurred {
// Fast check
auto returnType = mModule->CheckOperator(checkType, operatorDef, args[0].mTypedValue, args[1].mTypedValue); auto returnType = mModule->CheckOperator(checkType, operatorDef, args[0].mTypedValue, args[1].mTypedValue);
if (returnType != NULL) if (returnType != NULL)
{ {
operatorConstraintReturnType = returnType; operatorConstraintReturnType = returnType;
methodMatcher.mBestMethodDef = operatorDef; methodMatcher.mBestMethodDef = operatorDef;
methodMatcher.mBestMethodTypeInstance = checkType;
foundExactMatch = true; foundExactMatch = true;
} }
} }
else else
{
if (methodMatcher.CheckMethod(NULL, checkType, operatorDef, false))
{
auto rawMethodInstance = mModule->GetRawMethodInstance(checkType, operatorDef);
auto returnType = mModule->ResolveGenericType(rawMethodInstance->mReturnType, NULL, &methodMatcher.mBestMethodGenericArguments);
if (returnType != NULL)
{
operatorConstraintReturnType = returnType;
foundExactMatch = true;
}
}
}
}
else
{ {
if (methodMatcher.CheckMethod(NULL, checkType, operatorDef, false)) if (methodMatcher.CheckMethod(NULL, checkType, operatorDef, false))
{ {
@ -20877,16 +20893,35 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
{ {
if ((flags & BfBinOpFlag_IsConstraintCheck) != 0) if ((flags & BfBinOpFlag_IsConstraintCheck) != 0)
{ {
if (oppositeOperatorDef->mGenericParams.IsEmpty())
{
// Fast check
auto returnType = mModule->CheckOperator(checkType, oppositeOperatorDef, args[0].mTypedValue, args[1].mTypedValue); auto returnType = mModule->CheckOperator(checkType, oppositeOperatorDef, args[0].mTypedValue, args[1].mTypedValue);
if (returnType != NULL) if (returnType != NULL)
{ {
operatorConstraintReturnType = returnType; operatorConstraintReturnType = returnType;
methodMatcher.mBestMethodDef = oppositeOperatorDef; methodMatcher.mBestMethodDef = oppositeOperatorDef;
methodMatcher.mBestMethodTypeInstance = checkType;
methodMatcher.mSelfType = entry.mSrcType; methodMatcher.mSelfType = entry.mSrcType;
wasTransformedUsage = true; wasTransformedUsage = true;
} }
} }
else else
{
if (methodMatcher.CheckMethod(NULL, checkType, oppositeOperatorDef, false))
{
auto rawMethodInstance = mModule->GetRawMethodInstance(checkType, oppositeOperatorDef);
auto returnType = mModule->ResolveGenericType(rawMethodInstance->mReturnType, NULL, &methodMatcher.mBestMethodGenericArguments);
if (returnType != NULL)
{
operatorConstraintReturnType = returnType;
methodMatcher.mSelfType = entry.mSrcType;
wasTransformedUsage = true;
}
}
}
}
else
{ {
if (methodMatcher.CheckMethod(NULL, checkType, oppositeOperatorDef, false)) if (methodMatcher.CheckMethod(NULL, checkType, oppositeOperatorDef, false))
{ {

View file

@ -59,6 +59,11 @@ namespace Tests
Test.Assert(i == 100); Test.Assert(i == 100);
} }
public static T DoAdd<T>(T lhs, T rhs) where T : operator T + T
{
return lhs + rhs;
}
[Test] [Test]
public static void TestOperators() public static void TestOperators()
{ {
@ -84,6 +89,9 @@ namespace Tests
Test.Assert(iNull == 100); Test.Assert(iNull == 100);
Test.Assert(iNull != 99); Test.Assert(iNull != 99);
Test.Assert(!(iNull != 100)); Test.Assert(!(iNull != 100));
Test.Assert(DoAdd(iNull, iNull) == 200);
Test.Assert(DoAdd(iNull, null) == null);
} }
} }
} }