Ver Fonte

Fixed cases of undetected ambiguous calls

Brian Fiete há 5 anos atrás
pai
commit
4cea33d96f

+ 5 - 0
IDE/Tests/CompileFail001/scripts/CompileFail.txt

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

+ 47 - 0
IDE/Tests/CompileFail001/src/Methods.bf

@@ -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
+		}
+	}
+}

+ 24 - 7
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -718,18 +718,22 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
 		bool betterByConstExprParam = false;
 		bool worseByConstExprParam = false;
 
+		bool someArgWasBetter = false;
+		bool someArgWasWorse = false;
 		for (argIdx = anyIsExtension ? -1 : 0; argIdx < (int)mArguments.size(); argIdx++)
 		{
 			BfTypedValue arg;
-			BfResolvedArg* resolvedArg = NULL;
+			BfResolvedArg* resolvedArg = NULL;		
+			bool wasArgDeferred = false;
 			
 			if (argIdx == -1)
 			{
 				arg = mTarget;
 			}
 			else
-			{
+			{								
 				resolvedArg = &mArguments[argIdx];
+				wasArgDeferred = resolvedArg->mArgFlags != 0;
 				arg = resolvedArg->mTypedValue;
 			}
 			
@@ -739,8 +743,8 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
  			bool wasGenericParam = (newArgIdx >= 0) && newMethodInstance->WasGenericParam(newArgIdx);
  			bool prevWasGenericParam = (prevArgIdx >= 0) && prevMethodInstance->WasGenericParam(prevArgIdx);
 
-			BfType* paramType = newMethodInstance->GetParamType(newArgIdx);
-			BfType* prevParamType = prevMethodInstance->GetParamType(prevArgIdx);
+			BfType* paramType = newMethodInstance->GetParamType(newArgIdx, true);
+			BfType* prevParamType = prevMethodInstance->GetParamType(prevArgIdx, true);
 
 			numUsedParams++;
 			prevNumUsedParams++;
@@ -796,9 +800,10 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
 					{
 						// 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
-						if ((!wasGenericParam) && (IsType(arg, paramType)) && ((resolvedArg == NULL) || (prevParamType != resolvedArg->mBestBoundType)))
+						if ((!wasArgDeferred) && (!wasGenericParam) && (IsType(arg, paramType)) && ((resolvedArg == NULL) || (prevParamType != resolvedArg->mBestBoundType)))
 							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;
 						else
 						{
@@ -830,6 +835,10 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
 										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))
 				break;
+
+			someArgWasBetter |= isBetter;
+			someArgWasWorse |= isWorse;
+			isBetter = false;
+			isWorse = false;			
 		}
+		isBetter |= someArgWasBetter;
+		isWorse |= someArgWasWorse;
 
 		if ((!isBetter) && (!isWorse))
 		{
@@ -1869,7 +1885,8 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
 				{
 					BF_ASSERT(!ambiguousEntry.mBestMethodGenericArguments.empty());
 				}
-				mAmbiguousEntries.push_back(ambiguousEntry);				
+				mAmbiguousEntries.push_back(ambiguousEntry);
+				goto Done;
 			}
 		}
 		

+ 3 - 5
IDEHelper/Compiler/BfModule.cpp

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

+ 14 - 1
IDEHelper/Compiler/BfResolvedTypeUtils.cpp

@@ -868,7 +868,7 @@ String BfMethodInstance::GetParamName(int paramIdx)
 	return paramName;
 }
 
-BfType* BfMethodInstance::GetParamType(int paramIdx, bool useResolvedType)
+BfType* BfMethodInstance::GetParamType(int paramIdx, bool returnUnderlyingParamsType)
 {	
 	if (paramIdx == -1)
 	{
@@ -892,6 +892,19 @@ BfType* BfMethodInstance::GetParamType(int paramIdx, bool useResolvedType)
 		BfMethodInstance* invokeMethodInstance = methodParam->GetDelegateParamInvoke();
 		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;
 }
 

+ 1 - 1
IDEHelper/Compiler/BfResolvedTypeUtils.h

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