Просмотр исходного кода

Improved method selection for extension methods with generic 'this'

Brian Fiete 1 месяц назад
Родитель
Сommit
e64e421feb
2 измененных файлов с 30 добавлено и 3 удалено
  1. 10 3
      IDEHelper/Compiler/BfExprEvaluator.cpp
  2. 20 0
      IDEHelper/Tests/src/Extensions.bf

+ 10 - 3
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -889,7 +889,7 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
 
 
 			bool paramWasConstExpr = false;
 			bool paramWasConstExpr = false;
 			bool prevParamWasConstExpr = false;
 			bool prevParamWasConstExpr = false;
-
+						
 			bool paramWasUnspecialized = paramType->IsUnspecializedType();
 			bool paramWasUnspecialized = paramType->IsUnspecializedType();
 			if ((genericArgumentsSubstitute != NULL) && (paramWasUnspecialized))
 			if ((genericArgumentsSubstitute != NULL) && (paramWasUnspecialized))
 			{
 			{
@@ -952,9 +952,16 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
 						else if ((wasArgDeferred) && (paramType != prevParamType) && (paramType == arg.mType) && (paramType == resolvedArg->mBestBoundType))
 						else if ((wasArgDeferred) && (paramType != prevParamType) && (paramType == arg.mType) && (paramType == resolvedArg->mBestBoundType))
 							isBetter = true;
 							isBetter = true;
 						else if ((wasArgDeferred) && (paramType != prevParamType) && (prevParamType == arg.mType) && (prevParamType == resolvedArg->mBestBoundType))
 						else if ((wasArgDeferred) && (paramType != prevParamType) && (prevParamType == arg.mType) && (prevParamType == resolvedArg->mBestBoundType))
-							isWorse = true;
+							isWorse = true;						
+						else if ((argIdx == -1) && (anyIsExtension))
+						{							
+							if ((newMethodInstance->mMethodDef->mMethodType == BfMethodType_Extension) && (wasGenericParam) && (!prevWasGenericParam))
+								isWorse = true;
+							else if ((prevMethodInstance->mMethodDef->mMethodType == BfMethodType_Extension) && (prevWasGenericParam) && (!wasGenericParam))
+								isBetter = true;
+						}
 						else
 						else
-						{
+						{							
 							bool canCastFromCurToPrev = mModule->CanCast(mModule->GetFakeTypedValue(paramType), prevParamType, implicitCastFlags);
 							bool canCastFromCurToPrev = mModule->CanCast(mModule->GetFakeTypedValue(paramType), prevParamType, implicitCastFlags);
 							bool canCastFromPrevToCur = mModule->CanCast(mModule->GetFakeTypedValue(prevParamType), paramType, implicitCastFlags);
 							bool canCastFromPrevToCur = mModule->CanCast(mModule->GetFakeTypedValue(prevParamType), paramType, implicitCastFlags);
 
 

+ 20 - 0
IDEHelper/Tests/src/Extensions.bf

@@ -319,6 +319,17 @@ namespace Tests
 			Test.Assert((ms.mVal == 1) && (ms.mVal2 == 111) && (ms.mVal3 == 222));
 			Test.Assert((ms.mVal == 1) && (ms.mVal2 == 111) && (ms.mVal3 == 222));
 			ms = .(1, 2);
 			ms = .(1, 2);
 			Test.Assert((ms.mVal == 1) && (ms.mVal2 == 2) && (ms.mVal3 == 222));
 			Test.Assert((ms.mVal == 1) && (ms.mVal2 == 2) && (ms.mVal3 == 222));
+
+			List<int32> intList = scope .();
+			for (int32 i < 100)
+				intList.Add(i);
+			Span<int32> intSpan = intList;
+
+			var span = intSpan.ToRawData();
+			Test.Assert(span.Length == 400);
+
+			span = ((int32)123).ToRawData();
+			Test.Assert(span.Length == 4);
 		}
 		}
 
 
 		[Test]
 		[Test]
@@ -430,3 +441,12 @@ namespace Tests
 		}
 		}
 	}
 	}
 }
 }
+
+static
+{
+    public static Span<uint8> ToRawData<T>(this T self) where T : struct
+    {
+        #unwarn
+        return .((uint8*)&self, sizeof(T));
+    }
+}