Require the result of user-defined negation operator to be bool

This commit is contained in:
Kamil Śliwak 2023-01-20 10:59:22 +01:00
parent e0722732f6
commit a1438239c3
6 changed files with 9 additions and 26 deletions

View File

@ -46,7 +46,7 @@ Note that private library functions can only be specified when ``using for`` is
If you define an operator (e.g. ``using {f as +} for T``), then the type (``T``) must be a
:ref:`user-defined value type <user-defined-value-types>`.
The definition of an operator must be a ``pure`` function with the types of all parameters and
the return value matching ``T``, except for comparison operators, where the return value must
the return value matching ``T``, except for comparison and boolean operators, where the return value must
be of type ``bool``.
The following operators can be defined this way:

View File

@ -4047,7 +4047,7 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
size_t const returnParameterCount = returnParameterTypes.size();
optional<string> wrongReturnParametersMessage;
if (!TokenTraits::isCompareOp(*operator_))
if (!TokenTraits::isCompareOp(*operator_) && *operator_ != Token::Not)
{
if (returnParameterCount != 1 || *usingForType != *returnParameterTypes.front())
wrongReturnParametersMessage = "exactly one value of type " + usingForType->canonicalName();

View File

@ -28,7 +28,7 @@ function gt(Int x, Int y) pure returns (bool) { return Int.unwrap(x) > Int.unwra
function leq(Int x, Int y) pure returns (bool) { return Int.unwrap(x) <= Int.unwrap(y); }
function geq(Int x, Int y) pure returns (bool) { return Int.unwrap(x) >= Int.unwrap(y); }
function not(Int x) pure returns (Int) { return Int.unwrap(x) == 0 ? Int.wrap(1) : Int.wrap(0); }
function not(Int x) pure returns (bool) { return Int.unwrap(x) == 0; }
contract C {
Int constant ZERO = Int.wrap(0);
@ -103,9 +103,9 @@ contract C {
}
function test_boolean() public pure {
assert(Int.unwrap(!ZERO) == 1);
assert(Int.unwrap(!ONE) == 0);
assert(Int.unwrap(!TWO) == 0);
assert(!ZERO == true);
assert(!ONE == false);
assert(!TWO == false);
}
}
// ----

View File

@ -1,9 +1,7 @@
type Int is int64;
using {
bitor as |, bitand as &, bitxor as ^, bitnot as ~, shl as <<, sar as >>,
add as +, sub as -, unsub as -, mul as *, div as /, mod as %, exp as **,
eq as ==, noteq as !=,
not as !
add as +, sub as -, unsub as -, mul as *, div as /, mod as %, exp as **
} for Int;
function bitor(Int x, Int y) pure returns (Int) { return Int.wrap(Int.unwrap(x) | Int.unwrap(y)); }
@ -21,11 +19,6 @@ function div(Int x, Int y) pure returns (Int) { return Int.wrap(Int.unwrap(x) /
function mod(Int x, Int y) pure returns (Int) { return Int.wrap(Int.unwrap(x) % Int.unwrap(y)); }
function exp(Int x, Int y) pure returns (Int) { return Int.wrap(Int.unwrap(x) ** uint64(Int.unwrap(y))); }
function eq(Int x, Int y) pure returns (bool) { return Int.unwrap(x) == Int.unwrap(y); }
function noteq(Int x, Int y) pure returns (bool) { return Int.unwrap(x) != Int.unwrap(y); }
function not(Int x) pure returns (Int) { return Int.unwrap(x) == 0 ? Int.wrap(1) : Int.wrap(0); }
contract C {
Int constant I0 = Int.wrap(0);
Int constant I1 = Int.wrap(1);
@ -56,15 +49,6 @@ contract C {
assert(Int.unwrap(I1 + I2 ** I3 / I4 - I5 % I6 * I7) == ((1 + ((2 ** 3) / 4)) - ((5 % 6) * 7)));
}
function test_not() public pure {
assert((!I0 + I1) == I2);
assert((!I0 * I1) != I2);
assert((!I0 << I2) == I4);
assert((!I0 | I3) == I3);
assert((!~-I1 + I1) == I2);
}
function test_all() public pure {
assert(
Int.unwrap(I128 + I1 - I10 + I4 & ~I1 ^ ~I1 >> I1 + I1 << I3 ** I2 | -I15 % -I10 * I20 / I2 + I13 & ~I3) ==
@ -86,5 +70,4 @@ contract C {
// test_bitwise() ->
// test_bitwise_arithmetic() ->
// test_arithmetic() ->
// test_not() ->
// test_all() ->

View File

@ -4,7 +4,7 @@ type Bool is bool;
==== Source: s2.sol ====
import "s1.sol";
function not(Bool) pure returns (Bool) {}
function not(Bool) pure returns (bool) {}
contract C {
using {not as !} for Bool global;

View File

@ -4,7 +4,7 @@ type Bool is bool;
==== Source: s2.sol ====
import "s1.sol";
function not(Bool) pure returns (Bool) {}
function not(Bool) pure returns (bool) {}
using {not as !} for Bool global;
// ----