1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 03:52:19 +02:00

Fixed cases of undetected ambiguous calls

This commit is contained in:
Brian Fiete 2020-10-08 12:09:04 -07:00
parent e8b35ce0c4
commit 4cea33d96f
6 changed files with 94 additions and 14 deletions

View file

@ -23,6 +23,11 @@ WaitForResolve()
SleepTicks(20) SleepTicks(20)
AssertFileErrors() AssertFileErrors()
ShowFile("src/Methods.bf")
WaitForResolve()
SleepTicks(20)
AssertFileErrors()
ShowFile("src/Properties.bf") ShowFile("src/Properties.bf")
WaitForResolve() WaitForResolve()
SleepTicks(20) SleepTicks(20)

View file

@ -0,0 +1,47 @@
using System;
namespace IDETest
{
class Methods
{
public class ClassA
{
}
public class ClassB
{
public static implicit operator ClassA(ClassB zongo)
{
return default;
}
}
public static void MethodA(ClassA zong, int arg)
{
}
public static void MethodA(ClassB zong, params Object[] args)
{
}
public static void MethodB(ClassB zong, params Object[] args)
{
}
public static void MethodB(ClassA zong, int arg)
{
}
public static void Test()
{
ClassB cb = scope .();
MethodA(cb, 123); //FAIL
MethodB(cb, 234); //FAIL
}
}
}

View file

@ -718,10 +718,13 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
bool betterByConstExprParam = false; bool betterByConstExprParam = false;
bool worseByConstExprParam = false; bool worseByConstExprParam = false;
bool someArgWasBetter = false;
bool someArgWasWorse = 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;
BfResolvedArg* resolvedArg = NULL; BfResolvedArg* resolvedArg = NULL;
bool wasArgDeferred = false;
if (argIdx == -1) if (argIdx == -1)
{ {
@ -730,6 +733,7 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
else else
{ {
resolvedArg = &mArguments[argIdx]; resolvedArg = &mArguments[argIdx];
wasArgDeferred = resolvedArg->mArgFlags != 0;
arg = resolvedArg->mTypedValue; arg = resolvedArg->mTypedValue;
} }
@ -739,8 +743,8 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
bool wasGenericParam = (newArgIdx >= 0) && newMethodInstance->WasGenericParam(newArgIdx); bool wasGenericParam = (newArgIdx >= 0) && newMethodInstance->WasGenericParam(newArgIdx);
bool prevWasGenericParam = (prevArgIdx >= 0) && prevMethodInstance->WasGenericParam(prevArgIdx); bool prevWasGenericParam = (prevArgIdx >= 0) && prevMethodInstance->WasGenericParam(prevArgIdx);
BfType* paramType = newMethodInstance->GetParamType(newArgIdx); BfType* paramType = newMethodInstance->GetParamType(newArgIdx, true);
BfType* prevParamType = prevMethodInstance->GetParamType(prevArgIdx); BfType* prevParamType = prevMethodInstance->GetParamType(prevArgIdx, true);
numUsedParams++; numUsedParams++;
prevNumUsedParams++; prevNumUsedParams++;
@ -796,9 +800,10 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
{ {
// The resolved argument type may actually match for both considered functions. IE: // The resolved argument type may actually match for both considered functions. IE:
// Method(int8 val) and Method(int16 val) called with Method(0) will create arguments that match their param types // Method(int8 val) and Method(int16 val) called with Method(0) will create arguments that match their param types
if ((!wasGenericParam) && (IsType(arg, paramType)) && ((resolvedArg == NULL) || (prevParamType != resolvedArg->mBestBoundType))) if ((!wasArgDeferred) && (!wasGenericParam) && (IsType(arg, paramType)) && ((resolvedArg == NULL) || (prevParamType != resolvedArg->mBestBoundType)))
isBetter = true; isBetter = true;
else if ((!prevWasGenericParam) && (IsType(arg, prevParamType)) && (!IsType(arg, paramType))) //else if ((!prevWasGenericParam) && (IsType(arg, prevParamType)) && (!IsType(arg, paramType)))
else if ((!wasArgDeferred) && (!prevWasGenericParam) && (IsType(arg, prevParamType)) && ((resolvedArg == NULL) || (paramType != resolvedArg->mBestBoundType)))
isWorse = true; isWorse = true;
else else
{ {
@ -830,6 +835,10 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
isWorse = true; isWorse = true;
} }
} }
else if ((wasArgDeferred) && ((paramType->IsIntegral()) || (prevParamType->IsIntegral())))
{
SET_BETTER_OR_WORSE(paramType->IsIntegral(), prevParamType->IsIntegral());
}
} }
} }
} }
@ -858,7 +867,14 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
if ((usedExtendedForm) || (prevUsedExtendedForm)) if ((usedExtendedForm) || (prevUsedExtendedForm))
break; break;
someArgWasBetter |= isBetter;
someArgWasWorse |= isWorse;
isBetter = false;
isWorse = false;
} }
isBetter |= someArgWasBetter;
isWorse |= someArgWasWorse;
if ((!isBetter) && (!isWorse)) if ((!isBetter) && (!isWorse))
{ {
@ -1870,6 +1886,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
BF_ASSERT(!ambiguousEntry.mBestMethodGenericArguments.empty()); BF_ASSERT(!ambiguousEntry.mBestMethodGenericArguments.empty());
} }
mAmbiguousEntries.push_back(ambiguousEntry); mAmbiguousEntries.push_back(ambiguousEntry);
goto Done;
} }
} }

View file

@ -16339,14 +16339,12 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp
bool isParamSkipped = methodInstance->IsParamSkipped(paramIdx); bool isParamSkipped = methodInstance->IsParamSkipped(paramIdx);
BfType* unresolvedType = methodInstance->GetParamType(paramIdx, false); auto resolvedType = methodInstance->GetParamType(paramIdx);
if (unresolvedType == NULL) if (resolvedType == NULL)
{ {
AssertErrorState(); AssertErrorState();
unresolvedType = mContext->mBfObjectType;
paramVar->mParamFailed = true; paramVar->mParamFailed = true;
} }
auto resolvedType = methodInstance->GetParamType(paramIdx, true);
prevIgnoreErrors.Restore(); prevIgnoreErrors.Restore();
PopulateType(resolvedType, BfPopulateType_Declaration); PopulateType(resolvedType, BfPopulateType_Declaration);
paramVar->mResolvedType = resolvedType; paramVar->mResolvedType = resolvedType;

View file

@ -868,7 +868,7 @@ String BfMethodInstance::GetParamName(int paramIdx)
return paramName; return paramName;
} }
BfType* BfMethodInstance::GetParamType(int paramIdx, bool useResolvedType) BfType* BfMethodInstance::GetParamType(int paramIdx, bool returnUnderlyingParamsType)
{ {
if (paramIdx == -1) if (paramIdx == -1)
{ {
@ -892,6 +892,19 @@ BfType* BfMethodInstance::GetParamType(int paramIdx, bool useResolvedType)
BfMethodInstance* invokeMethodInstance = methodParam->GetDelegateParamInvoke(); BfMethodInstance* invokeMethodInstance = methodParam->GetDelegateParamInvoke();
return invokeMethodInstance->GetParamType(methodParam->mDelegateParamIdx, true); return invokeMethodInstance->GetParamType(methodParam->mDelegateParamIdx, true);
} }
if (returnUnderlyingParamsType)
{
BfParameterDef* paramDef = mMethodDef->mParams[methodParam->mParamDefIdx];
if (paramDef->mParamKind == BfParamKind_Params)
{
auto underlyingType = methodParam->mResolvedType->GetUnderlyingType();
if (underlyingType != NULL)
return underlyingType;
return methodParam->mResolvedType;
}
}
return methodParam->mResolvedType; return methodParam->mResolvedType;
} }

View file

@ -902,7 +902,7 @@ public:
int GetImplicitParamCount(); int GetImplicitParamCount();
void GetParamName(int paramIdx, StringImpl& name); void GetParamName(int paramIdx, StringImpl& name);
String GetParamName(int paramIdx); String GetParamName(int paramIdx);
BfType* GetParamType(int paramIdx, bool useResolvedType = true); BfType* GetParamType(int paramIdx, bool returnUnderlyingParamsType = false);
bool GetParamIsSplat(int paramIdx); bool GetParamIsSplat(int paramIdx);
BfParamKind GetParamKind(int paramIdx); BfParamKind GetParamKind(int paramIdx);
bool WasGenericParam(int paramIdx); bool WasGenericParam(int paramIdx);