Browse Source

Valueless equality check fix, respecting equality operator overloads

Brian Fiete 3 years ago
parent
commit
fd08367e2b
1 changed files with 41 additions and 13 deletions
  1. 41 13
      IDEHelper/Compiler/BfExprEvaluator.cpp

+ 41 - 13
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -21478,19 +21478,6 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
 				return;
 			}
 		}
-
-		// Valueless types always compare as 'equal'
-		if (leftValue.mType == rightValue.mType)
-		{
-			mModule->PopulateType(leftValue.mType);
-			if (leftValue.mType->IsValuelessType())
-			{
-				auto boolType = mModule->GetPrimitiveType(BfTypeCode_Boolean);
-					bool isEqual = (binaryOp == BfBinaryOp_Equality) || (binaryOp == BfBinaryOp_StrictEquality);
-					mResult = BfTypedValue(mModule->GetConstValue(isEqual ? 1 : 0, boolType), boolType);
-					return;
-			}
-		}
 	}
 
 	if ((leftValue.mType->IsTypeInstance()) || (leftValue.mType->IsGenericParam()) || 
@@ -22206,6 +22193,47 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
 					return;
 				}
 
+				// Valueless types always compare as 'equal' if we can ensure no members could have an equality operator overload
+				if (leftValue.mType->IsComposite())
+				{
+					mModule->PopulateType(leftValue.mType);					
+					if (leftValue.mType->IsValuelessType())
+					{
+						bool mayHaveEqualOverload = false;
+						auto leftTypeInst = leftValue.mType->ToTypeInstance();
+						if (leftTypeInst != NULL)
+						{
+							std::function<bool(BfType*)> _HasTypeInstance = [&](BfType* type)
+							{
+								if (type == NULL)
+									return false;
+
+								if (type->IsTypeInstance())
+									return true;
+
+								if (type->IsSizedArray())
+									return _HasTypeInstance(((BfSizedArrayType*)type)->mElementType);
+
+								return false;
+							};
+
+							for (auto& fieldInstance : leftTypeInst->mFieldInstances)
+							{
+								if (_HasTypeInstance(fieldInstance.mResolvedType))
+									mayHaveEqualOverload = true;
+							}
+						}
+
+						if (!mayHaveEqualOverload)
+						{
+							auto boolType = mModule->GetPrimitiveType(BfTypeCode_Boolean);
+							bool isEqual = (binaryOp == BfBinaryOp_Equality) || (binaryOp == BfBinaryOp_StrictEquality);
+							mResult = BfTypedValue(mModule->GetConstValue(isEqual ? 1 : 0, boolType), boolType);
+							return;
+						}
+					}
+				}
+
 				if (_CallValueTypeEquals())
 					return;
 			}