瀏覽代碼

params operator implicit cast, params generic inference fix

Brian Fiete 10 月之前
父節點
當前提交
64d646e130
共有 3 個文件被更改,包括 81 次插入12 次删除
  1. 62 10
      IDEHelper/Compiler/BfExprEvaluator.cpp
  2. 2 2
      IDEHelper/Compiler/BfModule.cpp
  3. 17 0
      IDEHelper/Tests/src/MethodCalls.bf

+ 62 - 10
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -1980,9 +1980,16 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
 
 					if (methodInstance->GetParamKind(paramIdx) == BfParamKind_Params)
 					{
-						paramsParamIdx = paramIdx;
-						if ((wantType->IsArray()) || (wantType->IsSizedArray()) || (wantType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)))
-							wantType = wantType->GetUnderlyingType();
+						if ((mArguments[argIdx].mArgFlags & BfArgFlag_ParamsExpr) != 0)							
+						{
+							// Match to entire thing
+						}
+						else
+						{
+							paramsParamIdx = paramIdx;
+							if ((wantType->IsArray()) || (wantType->IsSizedArray()) || (wantType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)))
+								wantType = wantType->GetUnderlyingType();
+						}
 					}
 
 					if (!genericInferContext.InferGenericArgument(methodInstance, type, wantType, argTypedValue.mValue))
@@ -22954,15 +22961,60 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
 				}
 				else
 				{
-					auto isValid = false;
-					auto genericTypeInst = mResult.mType->ToGenericTypeInstance();
-					if ((genericTypeInst != NULL) && (genericTypeInst->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)))
-						isValid = true;
-					else if ((mResult.mType->IsArray()) || (mResult.mType->IsSizedArray()))
-						isValid = true;
+					auto origValue = mResult;
+					auto isValid = false;					
+
+					for (int pass = 0; pass < 2; pass++)
+					{
+						auto typeInst = mResult.mType->ToTypeInstance();
+						auto genericTypeInst = mResult.mType->ToGenericTypeInstance();
+						if ((genericTypeInst != NULL) && (genericTypeInst->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)))
+							isValid = true;
+						else if ((mResult.mType->IsArray()) || (mResult.mType->IsSizedArray()))
+							isValid = true;
+						else if ((typeInst != NULL) && (pass == 0))
+						{
+							BfBaseClassWalker baseClassWalker(typeInst, NULL, mModule);
+
+							BfType* bestCastType = NULL;
+							while (true)
+							{
+								auto entry = baseClassWalker.Next();
+								auto checkType = entry.mTypeInstance;
+								if (checkType == NULL)
+									break;
+								for (auto operatorDef : checkType->mTypeDef->mOperators)
+								{
+									if (operatorDef->mOperatorDeclaration->mIsConvOperator)
+									{
+										if (operatorDef->IsExplicit())
+											continue;
+
+										auto methodInstance = mModule->GetRawMethodInstanceAtIdx(typeInst, operatorDef->mIdx);
+
+										auto checkType = methodInstance->mReturnType;
+										if (checkType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef))
+											bestCastType = checkType;
+										else if ((checkType->IsArray()) || (checkType->IsSizedArray()))
+											bestCastType = checkType;
+									}
+								}
+							}
+
+							if (bestCastType == NULL)
+								break;							
+							auto castTypedValue = mModule->Cast(opToken, mResult, bestCastType, BfCastFlags_SilentFail);
+							if (!castTypedValue)
+								break;
+							mResult = castTypedValue;							
+						}
+						else
+							break;
+					}	
+
 					if (!isValid)
 					{
-						mModule->Fail(StrFormat("A 'params' expression cannot be used on type '%s'", mModule->TypeToString(mResult.mType).c_str()), opToken);
+						mModule->Fail(StrFormat("A 'params' expression cannot be used on type '%s'", mModule->TypeToString(origValue.mType).c_str()), opToken);
 					}
 				}
 			}

+ 2 - 2
IDEHelper/Compiler/BfModule.cpp

@@ -2861,8 +2861,8 @@ bool BfModule::CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* me
 		if (curCheckType != NULL)
 		{
 			allowPrivate |= IsInnerType(curCheckType->mTypeDef, memberOwner->mTypeDef);
-			if (memberOwner->mTypeDef->IsGlobalsContainer())			
-				allowPrivate |= curCheckType->mTypeDef->mNamespace.StartsWith(memberOwner->mTypeDef->mNamespace);			
+			if (memberOwner->mTypeDef->IsGlobalsContainer())
+				allowPrivate |= curCheckType->mTypeDef->mNamespace == memberOwner->mTypeDef->mNamespace;
 		}
 		if (allowPrivate)
 			flags = (BfProtectionCheckFlags)(flags | BfProtectionCheckFlag_AllowPrivate | BfProtectionCheckFlag_CheckedPrivate);

+ 17 - 0
IDEHelper/Tests/src/MethodCalls.bf

@@ -1,4 +1,6 @@
 using System;
+using System.Collections;
+
 namespace Tests
 {
 	class MethodCalls
@@ -205,6 +207,16 @@ namespace Tests
 		static int sIdx = 0;
 		static int GetNext() => ++sIdx;
 
+		public static float ParamsTest(params Span<float> span)
+		{
+			return span[0];
+		}
+
+		public static T ParamsTest2<T>(params Span<T> span)
+		{
+			return span[0];
+		}
+
 		[Test]
 		public static void TestBasics()
 		{
@@ -273,6 +285,11 @@ namespace Tests
 			Test.Assert(Named(p3:GetNext(), p2:GetNext(), p1:GetNext()) == 10321);
 			Test.Assert(Named(p2:GetNext(), p1:GetNext(), p0:GetNext()) == 20654);
 			Test.Assert(Named(p1:9) == 30193);
+
+			List<float> fList = scope .();
+			fList.Add(1.2f);
+			Test.Assert(ParamsTest(params fList) == 1.2f);
+			Test.Assert(ParamsTest2(params fList) == 1.2f);
 		}
 	}
 }