From 95a27d5e9333ec17e193b42f09c62c221cb2b7a9 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Tue, 18 Jan 2022 10:34:33 -0500 Subject: [PATCH] Fixes to new conversion overload invoker --- BeefLibs/corlib/src/Nullable.bf | 9 ++++++ IDEHelper/Compiler/BfExprEvaluator.cpp | 9 ++++-- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 38 ++++++++++++++++++++++-- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/BeefLibs/corlib/src/Nullable.bf b/BeefLibs/corlib/src/Nullable.bf index b32165d2..1e195af7 100644 --- a/BeefLibs/corlib/src/Nullable.bf +++ b/BeefLibs/corlib/src/Nullable.bf @@ -84,6 +84,15 @@ namespace System return result; } + [Inline] + public static Nullable operator implicit (TOther value) where T : operator implicit TOther + { + Nullable result; + result.mHasValue = true; + result.mValue = value; + return result; + } + [Inline] public static explicit operator T(Nullable value) { diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 26214a28..650d0e2c 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -2076,7 +2076,11 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst if ((wantType->IsRef()) && (!argTypedValue.mType->IsRef()) && ((mAllowImplicitRef) || (wantType->IsIn()))) 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)) { @@ -2128,8 +2132,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst { auto wantType = mCheckReturnType; if ((genericArgumentsSubstitute != NULL) && (wantType->IsUnspecializedType())) - { - wantType = typeUnspecMethodInstance->GetParamType(paramIdx); + { auto resolvedType = mModule->ResolveGenericType(wantType, typeGenericArguments, genericArgumentsSubstitute, false); if (resolvedType == NULL) goto NoMatch; diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 67f1c1d1..c021654e 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -12644,6 +12644,20 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp 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) { // Check method generic constraints @@ -12694,7 +12708,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp } } } - } + } else if (isConstraintCheck) { auto result = BfTypedValue(mBfIRBuilder->GetFakeVal(), operatorConstraintReturnType); @@ -12709,6 +12723,24 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp BfExprEvaluator exprEvaluator(this); exprEvaluator.mBfEvalExprFlags = BfEvalExprFlags_FromConversionOp; + auto methodDeclaration = BfNodeDynCast(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); if (moduleMethodInstance.mMethodInstance != NULL) { @@ -12727,7 +12759,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp } 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()) { typedVal = MakeAddressable(typedVal); @@ -12749,7 +12781,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp result = LoadValue(result); if (result.mType != toType) - return CastToValue(srcNode, result, toType, BfCastFlags_Explicit, resultFlags); + return CastToValue(srcNode, result, toType, (BfCastFlags)(castFlags | BfCastFlags_Explicit), resultFlags); if (result) return result.mValue;