فهرست منبع

Fixes to new conversion overload invoker

Brian Fiete 3 سال پیش
والد
کامیت
95a27d5e93
3فایلهای تغییر یافته به همراه50 افزوده شده و 6 حذف شده
  1. 9 0
      BeefLibs/corlib/src/Nullable.bf
  2. 6 3
      IDEHelper/Compiler/BfExprEvaluator.cpp
  3. 35 3
      IDEHelper/Compiler/BfModuleTypeUtils.cpp

+ 9 - 0
BeefLibs/corlib/src/Nullable.bf

@@ -84,6 +84,15 @@ namespace System
 			return result;
 			return result;
         }
         }
 
 
+		[Inline]
+		public static Nullable<T> operator implicit <TOther>(TOther value) where T : operator implicit TOther
+		{
+			Nullable<T> result;
+			result.mHasValue = true;
+			result.mValue = value;
+			return result;
+		}
+
         [Inline]
         [Inline]
         public static explicit operator T(Nullable<T> value)
         public static explicit operator T(Nullable<T> value)
         {
         {

+ 6 - 3
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -2076,7 +2076,11 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
 				if ((wantType->IsRef()) && (!argTypedValue.mType->IsRef()) &&
 				if ((wantType->IsRef()) && (!argTypedValue.mType->IsRef()) &&
 					((mAllowImplicitRef) || (wantType->IsIn())))
 					((mAllowImplicitRef) || (wantType->IsIn())))
 					wantType = wantType->GetUnderlyingType();
 					wantType = wantType->GetUnderlyingType();
-				if (!mModule->CanCast(argTypedValue, wantType, ((mBfEvalExprFlags & BfEvalExprFlags_FromConversionOp) != 0) ? BfCastFlags_NoConversionOperator : BfCastFlags_None))
+
+				BfCastFlags castFlags = ((mBfEvalExprFlags & BfEvalExprFlags_FromConversionOp) != 0) ? BfCastFlags_NoConversionOperator : BfCastFlags_None;
+				if ((mBfEvalExprFlags & BfEvalExprFlags_FromConversionOp_Explicit) != 0)
+					castFlags = (BfCastFlags)(castFlags | BfCastFlags_Explicit);
+				if (!mModule->CanCast(argTypedValue, wantType, castFlags))
 				{
 				{
 					if ((mAllowImplicitWrap) && (argTypedValue.mType->IsWrappableType()) && (mModule->GetWrappedStructType(argTypedValue.mType) == wantType))
 					if ((mAllowImplicitWrap) && (argTypedValue.mType->IsWrappableType()) && (mModule->GetWrappedStructType(argTypedValue.mType) == wantType))
 					{
 					{
@@ -2128,8 +2132,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
 	{
 	{
 		auto wantType = mCheckReturnType;
 		auto wantType = mCheckReturnType;
 		if ((genericArgumentsSubstitute != NULL) && (wantType->IsUnspecializedType()))
 		if ((genericArgumentsSubstitute != NULL) && (wantType->IsUnspecializedType()))
-		{
-			wantType = typeUnspecMethodInstance->GetParamType(paramIdx);
+		{			
 			auto resolvedType = mModule->ResolveGenericType(wantType, typeGenericArguments, genericArgumentsSubstitute, false);
 			auto resolvedType = mModule->ResolveGenericType(wantType, typeGenericArguments, genericArgumentsSubstitute, false);
 			if (resolvedType == NULL)
 			if (resolvedType == NULL)
 				goto NoMatch;
 				goto NoMatch;

+ 35 - 3
IDEHelper/Compiler/BfModuleTypeUtils.cpp

@@ -12644,6 +12644,20 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 
 
 		methodMatcher.FlushAmbiguityError();
 		methodMatcher.FlushAmbiguityError();
 
 
+		if (methodMatcher.mBestMethodDef != NULL)
+		{
+			if (mayBeBox)
+			{
+				if (!ignoreErrors)
+				{
+					if (Fail("Ambiguous cast, may be conversion operator or may be boxing request", srcNode) != NULL)
+						mCompiler->mPassInstance->MoreInfo("See conversion operator", methodMatcher.mBestMethodDef->GetRefNode());
+				}
+				else if (!silentFail)
+					SetFail();
+			}
+		}
+
 		if (methodMatcher.mBestMethodDef == NULL)
 		if (methodMatcher.mBestMethodDef == NULL)
 		{
 		{
 			// Check method generic constraints
 			// Check method generic constraints
@@ -12694,7 +12708,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 					}
 					}
 				}
 				}
 			}
 			}
-		}		
+		}
 		else if (isConstraintCheck)
 		else if (isConstraintCheck)
 		{
 		{
 			auto result = BfTypedValue(mBfIRBuilder->GetFakeVal(), operatorConstraintReturnType);
 			auto result = BfTypedValue(mBfIRBuilder->GetFakeVal(), operatorConstraintReturnType);
@@ -12709,6 +12723,24 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 			BfExprEvaluator exprEvaluator(this);
 			BfExprEvaluator exprEvaluator(this);
 			exprEvaluator.mBfEvalExprFlags = BfEvalExprFlags_FromConversionOp;			
 			exprEvaluator.mBfEvalExprFlags = BfEvalExprFlags_FromConversionOp;			
 
 
+			auto methodDeclaration = BfNodeDynCast<BfMethodDeclaration>(methodMatcher.mBestMethodDef->mMethodDeclaration);
+			if ((methodDeclaration != NULL) && (methodDeclaration->mBody == NULL))
+			{
+				auto fromType = typedVal.mType;
+
+				// Handle the typedPrim<->underlying part implicitly
+				if (fromType->IsTypedPrimitive())
+				{
+					auto convTypedValue = BfTypedValue(typedVal.mValue, fromType->GetUnderlyingType());
+					return CastToValue(srcNode, convTypedValue, toType, (BfCastFlags)(castFlags & ~BfCastFlags_Explicit), NULL);
+				}
+				else if (toType->IsTypedPrimitive())
+				{
+					auto castedVal = CastToValue(srcNode, typedVal, toType->GetUnderlyingType(), (BfCastFlags)(castFlags & ~BfCastFlags_Explicit), NULL);
+					return castedVal;
+				}
+			}
+
 			auto moduleMethodInstance = exprEvaluator.GetSelectedMethod(methodMatcher);
 			auto moduleMethodInstance = exprEvaluator.GetSelectedMethod(methodMatcher);
 			if (moduleMethodInstance.mMethodInstance != NULL)
 			if (moduleMethodInstance.mMethodInstance != NULL)
 			{
 			{
@@ -12727,7 +12759,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 					}
 					}
 					else
 					else
 					{
 					{
-						methodMatcher.mArguments[0].mTypedValue = Cast(srcNode, typedVal, wantType, BfCastFlags_Explicit);
+						methodMatcher.mArguments[0].mTypedValue = Cast(srcNode, typedVal, wantType, (BfCastFlags)(castFlags | BfCastFlags_Explicit));
 						if (paramType->IsRef())
 						if (paramType->IsRef())
 						{
 						{
 							typedVal = MakeAddressable(typedVal);
 							typedVal = MakeAddressable(typedVal);
@@ -12749,7 +12781,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 				result = LoadValue(result);
 				result = LoadValue(result);
 
 
 			if (result.mType != toType)
 			if (result.mType != toType)
-				return CastToValue(srcNode, result, toType, BfCastFlags_Explicit, resultFlags);
+				return CastToValue(srcNode, result, toType, (BfCastFlags)(castFlags | BfCastFlags_Explicit), resultFlags);
 
 
 			if (result)
 			if (result)
 				return result.mValue;
 				return result.mValue;