diff --git a/ets2panda/checker/ets/arithmetic.cpp b/ets2panda/checker/ets/arithmetic.cpp index b0b3e32efd5af3ce71e4525bf4e8fca6e88a970f..d1a9a2b91c00d42b3fc4eb5ef7d84a90e260c7f7 100644 --- a/ets2panda/checker/ets/arithmetic.cpp +++ b/ets2panda/checker/ets/arithmetic.cpp @@ -657,7 +657,8 @@ static Type *CheckOperatorEqualDynamic(ETSChecker *checker, BinaryArithmOperands return checker->GlobalETSNullishObjectType(); } -static Type *HandelReferenceBinaryEquality(ETSChecker *checker, BinaryArithmOperands const &ops) +static Type *HandelReferenceBinaryEquality(ETSChecker *checker, BinaryArithmOperands const &ops, + lexer::SourcePosition pos) { [[maybe_unused]] auto const [expr, typeL, typeR, reducedL, reducedR] = ops; if ((typeR->IsETSNullType() && typeL->IsETSPrimitiveType()) || @@ -681,6 +682,22 @@ static Type *HandelReferenceBinaryEquality(ETSChecker *checker, BinaryArithmOper return checker->CreateETSUnionType({typeL, typeR}); } + Type *const unboxedL = TryConvertToPrimitiveType(checker, typeL); + Type *const unboxedR = TryConvertToPrimitiveType(checker, typeR); + bool hasPrimitiveConvertible = + !typeL->IsETSUnionType() && !typeR->IsETSUnionType() && + ((unboxedL == nullptr && unboxedR != nullptr) || (unboxedL != nullptr && unboxedR == nullptr)); + if (hasPrimitiveConvertible) { + checker->Relation()->SetNode(expr->Left()); + bool incompatible = + !checker->Relation()->IsCastableTo(typeL, typeR) && !checker->Relation()->IsCastableTo(typeR, typeL) && + !checker->Relation()->IsSupertypeOf(typeL, typeR) && !checker->Relation()->IsSupertypeOf(typeR, typeL); + if (incompatible) { + checker->LogError(diagnostic::BINOP_INCOMPARABLE, {}, pos); + return nullptr; + } + } + if ((reducedL->IsETSReferenceType() || reducedR->IsETSReferenceType()) && !(typeL->IsETSNullType() || typeL->IsETSUndefinedType()) && !(typeR->IsETSNullType() || typeR->IsETSUndefinedType())) { @@ -693,7 +710,7 @@ static Type *HandelReferenceBinaryEquality(ETSChecker *checker, BinaryArithmOper return nullptr; } -static Type *CheckBinaryOperatorEqual(ETSChecker *checker, BinaryArithmOperands const &ops) +static Type *CheckBinaryOperatorEqual(ETSChecker *checker, BinaryArithmOperands const &ops, lexer::SourcePosition pos) { [[maybe_unused]] auto const [expr, typeL, typeR, reducedL, reducedR] = ops; @@ -717,7 +734,7 @@ static Type *CheckBinaryOperatorEqual(ETSChecker *checker, BinaryArithmOperands return checker->GlobalETSBooleanType(); } - return HandelReferenceBinaryEquality(checker, ops); + return HandelReferenceBinaryEquality(checker, ops, pos); } // Satisfying the Chinese checker @@ -927,7 +944,7 @@ static std::tuple CheckBinaryOperatorHelper(ETSChecker *checker, case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: case lexer::TokenType::PUNCTUATOR_EQUAL: case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: { - if (Type *res = CheckBinaryOperatorEqual(checker, opsRepaired); res != nullptr) { + if (Type *res = CheckBinaryOperatorEqual(checker, opsRepaired, pos); res != nullptr) { return {checker->GlobalETSBooleanType(), res}; } [[fallthrough]];