diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 7de58a472eae05ef500ffe336b287abbca60f4b6..9a2de056eb3e55857c4640f16633c18c483587db 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -363,6 +363,7 @@ public: checker::Type *CheckBinaryBitwiseOperatorForIntEnums(const checker::Type *const leftType, const checker::Type *const rightType); + bool CheckIsComparableClasses(const checker::Type *const leftType, const checker::Type *const rightType); checker::Type *CheckBinaryOperatorPlus( std::tuple op, bool isEqualOp, std::tuple types); diff --git a/ets2panda/checker/ets/arithmetic.cpp b/ets2panda/checker/ets/arithmetic.cpp index 8eebfe0d383c0a0d6035d122636cf7e3a74522d1..cb8de11f4967b3fca4d20dd008a4f5d01b74fe0d 100644 --- a/ets2panda/checker/ets/arithmetic.cpp +++ b/ets2panda/checker/ets/arithmetic.cpp @@ -355,6 +355,13 @@ static checker::Type *CheckBinaryOperatorPlusForEnums(ETSChecker *checker, check return nullptr; } +bool ETSChecker::CheckIsComparableClasses(const checker::Type *const leftType, const checker::Type *const rightType) +{ + return (leftType->IsETSReferenceType() && !leftType->IsETSUnboxableObject()) && + (rightType->IsETSReferenceType() && !rightType->IsETSUnboxableObject()) && + !(leftType->IsETSTypeParameter() && rightType->IsETSTypeParameter()); +} + checker::Type *ETSChecker::CheckBinaryOperatorPlus( std::tuple op, bool isEqualOp, std::tuple types) @@ -603,6 +610,10 @@ bool ETSChecker::CheckValidEqualReferenceType(checker::Type *const leftType, che // NOTE (mxlgv): Skip for generic. Required implementation of the specification section: // 7.25.6 Reference Equality Based on Actual Type (Type Parameter Equality Operators) if (leftType->HasTypeFlag(TypeFlag::GENERIC) || rightType->HasTypeFlag(TypeFlag::GENERIC)) { + if (CheckIsComparableClasses(leftType, rightType) && + (leftType->HasTypeFlag(TypeFlag::ETS_OBJECT) || rightType->HasTypeFlag(TypeFlag::ETS_OBJECT))) { + return Relation()->IsComparableTo(rightType, leftType) || Relation()->IsCastableTo(rightType, leftType); + } return true; } @@ -615,6 +626,8 @@ bool ETSChecker::CheckValidEqualReferenceType(checker::Type *const leftType, che !Relation()->IsIdenticalTo(nonConstRhs, nonConstLhs)) { return false; } + } else if (CheckIsComparableClasses(leftType, rightType)) { + return Relation()->IsComparableTo(rightType, leftType) || Relation()->IsComparableTo(leftType, rightType); } if (FindOpArgsType(this, leftType, rightType, GetGlobalTypesHolder()->GlobalNumericBuiltinType()) && diff --git a/ets2panda/test/ast/compiler/ets/referenceEqualityNotCastable_n.ets b/ets2panda/test/ast/compiler/ets/referenceEqualityNotCastable_n.ets index 51f4fc103e2a54f85a4f7cc30ba05034a6ebeabe..c101c77314c23a210bd62cbe9bc6d36b8dca83ef 100644 --- a/ets2panda/test/ast/compiler/ets/referenceEqualityNotCastable_n.ets +++ b/ets2panda/test/ast/compiler/ets/referenceEqualityNotCastable_n.ets @@ -22,4 +22,5 @@ function main(): void { let c = /* @@ label */a === b; } +/* @@? 22:25 Error TypeError: Operator '===' cannot be applied to types 'A' and 'B'. */ /* @@@ label Node { "type": "BinaryExpression", "operator": "===" } */ diff --git a/ets2panda/test/ast/parser/ets/enum7.ets b/ets2panda/test/ast/parser/ets/enum7.ets index 0027570f04fc1d34fd7bf082bfd5f2b8533f74ef..45c1e01d54c99cd3303a69934d27c36e000b0a48 100644 --- a/ets2panda/test/ast/parser/ets/enum7.ets +++ b/ets2panda/test/ast/parser/ets/enum7.ets @@ -22,3 +22,4 @@ function main(): void { } /* @@@ label Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ +/* @@@ label Error TypeError: Operator '!=' cannot be applied to types 'Color' and 'Color2'. */ diff --git a/ets2panda/test/ast/parser/ets/rest_parameter_13.ets b/ets2panda/test/ast/parser/ets/rest_parameter_13.ets index 46f794926f745d3fcf69c72449cc26f3095e3e87..3a54a9dbf05dc1b520a0eb27e284a2b8d1c656e0 100644 --- a/ets2panda/test/ast/parser/ets/rest_parameter_13.ets +++ b/ets2panda/test/ast/parser/ets/rest_parameter_13.ets @@ -45,3 +45,5 @@ function main() { /* @@@ label3 Error TypeError: Expected 2 arguments, got 3. */ /* @@@ label3 Error TypeError: No matching construct signature for rest_parameter_13.C(A, B, B) */ /* @@? 34:37 Error TypeError: Type 'A' is not compatible with type 'Int' at index 1 */ +/* @@? 23:18 Error TypeError: Operator '==' cannot be applied to types 'A' and 'B'. */ +/* @@? 27:18 Error TypeError: Operator '==' cannot be applied to types 'A' and 'B'. */ diff --git a/ets2panda/test/runtime/ets/RestTuple5.ets b/ets2panda/test/runtime/ets/RestTuple5.ets index 888b16c712a7e5371b7d77865371df7b8fe205dd..74048bae7a78f94353a4e27947e64ce1f9b0b69e 100644 --- a/ets2panda/test/runtime/ets/RestTuple5.ets +++ b/ets2panda/test/runtime/ets/RestTuple5.ets @@ -17,11 +17,11 @@ class A {} class B {} function foo(...p: [A, B]): boolean { - return p[0] == p[1] + return p[0] as Object == p[1] as Object } function moo(a:int, ...p: [A, B]): boolean { - return p[0] == p[1] + return p[0] as Object == p[1] as Object } function main() { diff --git a/ets2panda/test/runtime/ets/RestTuple6.ets b/ets2panda/test/runtime/ets/RestTuple6.ets index 5fc918e8e69eb192ae5eff4c126f84a934b47aad..6e7a3a745057c5f44846fd785dc5bd0a8f1398ca 100644 --- a/ets2panda/test/runtime/ets/RestTuple6.ets +++ b/ets2panda/test/runtime/ets/RestTuple6.ets @@ -18,11 +18,11 @@ class B {} class C { foo(...p: [A, B]): boolean { - return p[0] == p[1] + return p[0] as Object == p[1] as Object } moo(a:int, ...p: [A, B]): boolean { - return p[0] == p[1] + return p[0] as Object == p[1] as Object } } diff --git a/ets2panda/test/runtime/ets/RestTuple7.ets b/ets2panda/test/runtime/ets/RestTuple7.ets index 4368052ce63d5789ba9cb8f6b79b936a9f23f793..528200c6982f541c98dcd2dfbdf4c3112b88e7fc 100644 --- a/ets2panda/test/runtime/ets/RestTuple7.ets +++ b/ets2panda/test/runtime/ets/RestTuple7.ets @@ -18,11 +18,11 @@ class B {} class C { static foo(...p: [A, B]): boolean { - return p[0] == p[1] + return p[0] as Object == p[1] as Object } static moo(a:int, ...p: [A, B]): boolean { - return p[0] == p[1] + return p[0] as Object == p[1] as Object } } diff --git a/ets2panda/test/runtime/ets/RestTuple8.ets b/ets2panda/test/runtime/ets/RestTuple8.ets index 3a802df4085bb9eef700c01bb7a3c53b35be6039..cf62866d90d555cd4313b18120b27233bc592486 100644 --- a/ets2panda/test/runtime/ets/RestTuple8.ets +++ b/ets2panda/test/runtime/ets/RestTuple8.ets @@ -20,11 +20,11 @@ class C { public field : boolean constructor(...p: [A, B]) { - this.field = p[0] == p[1] + this.field = p[0] as Object == p[1] as Object } constructor(a: int, ...p: [A, B]) { - this.field = p[0] == p[1] + this.field = p[0] as Object == p[1] as Object } }