diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index ad38b55d..26214a28 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -21479,17 +21479,19 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod { bool handled = false; + BfType* expectingType = mExpectingType; + if (leftValue.mType == rightValue.mType) { // All good handled = true; } - else if ((mExpectingType != NULL) && - (mModule->CanCast(leftValue, mExpectingType, BfCastFlags_NoBox)) && - (mModule->CanCast(rightValue, mExpectingType, BfCastFlags_NoBox)) && + else if ((expectingType != NULL) && + (mModule->CanCast(leftValue, expectingType, BfCastFlags_NoBox)) && + (mModule->CanCast(rightValue, expectingType, BfCastFlags_NoBox)) && (!leftValue.mType->IsVar()) && (!rightValue.mType->IsVar())) { - resultType = mExpectingType; + resultType = expectingType; handled = true; } else diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 7dfa4f56..715c273e 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -10600,18 +10600,23 @@ BfType* BfModule::CheckOperator(BfTypeInstance* typeInstance, BfOperatorDef* ope return NULL; if (operatorInfo->mReturnType == NULL) return NULL; + + auto castFlags = BfCastFlags_IsConstraintCheck; + if (operatorDef->mOperatorDeclaration->mIsConvOperator) + castFlags = (BfCastFlags)(castFlags | BfCastFlags_NoConversionOperator); + if (lhs) { if (operatorInfo->mLHSType == NULL) - return NULL; - if (!CanCast(lhs, operatorInfo->mLHSType, BfCastFlags_IsConstraintCheck)) + return NULL; + if (!CanCast(lhs, operatorInfo->mLHSType, castFlags)) return NULL; } if (rhs) { if (operatorInfo->mRHSType == NULL) return NULL; - if (!CanCast(rhs, operatorInfo->mRHSType, BfCastFlags_IsConstraintCheck)) + if (!CanCast(rhs, operatorInfo->mRHSType, castFlags)) return NULL; } return operatorInfo->mReturnType; diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 52a88dbf..67f1c1d1 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -12521,7 +12521,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp if (explicitCast) { - if (((fromPrimType->IsIntegral()) || (fromPrimType->IsFloat()) || (fromPrimType->IsBoolean())) && + if (((fromPrimType->IsIntegral()) || (fromPrimType->IsFloat())) && ((toType->IsIntegral()) || (toType->IsFloat()))) allowCast = true; } @@ -12595,7 +12595,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp methodMatcher.mAllowImplicitWrap = true; BfBaseClassWalker baseClassWalker(walkFromType, walkToType, this); - bool isConstraintCheck = false;// ((opFlags& BfUnaryOpFlag_IsConstraintCheck) != 0); + bool isConstraintCheck = ((castFlags & BfCastFlags_IsConstraintCheck) != 0); BfType* operatorConstraintReturnType = NULL; BfType* bestSelfType = NULL; @@ -12622,8 +12622,20 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp args.mSize = 0; } - if (methodMatcher.CheckMethod(NULL, checkType, operatorDef, false)) - methodMatcher.mSelfType = entry.mSrcType; + if (isConstraintCheck) + { + auto returnType = CheckOperator(checkType, operatorDef, typedVal, BfTypedValue()); + if (returnType != NULL) + { + operatorConstraintReturnType = returnType; + methodMatcher.mBestMethodDef = operatorDef; + } + } + else + { + if (methodMatcher.CheckMethod(NULL, checkType, operatorDef, false)) + methodMatcher.mSelfType = entry.mSrcType; + } args.mSize = prevArgSize; } @@ -12682,6 +12694,14 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp } } } + } + else if (isConstraintCheck) + { + auto result = BfTypedValue(mBfIRBuilder->GetFakeVal(), operatorConstraintReturnType); + if (result.mType != toType) + return CastToValue(srcNode, result, toType, BfCastFlags_Explicit, resultFlags); + if (result) + return result.mValue; } else {