User-defined operators: Tests

This commit is contained in:
wechman
2023-01-25 00:29:10 +01:00
committed by Kamil Śliwak
parent fd6359000e
commit 1edb74dbc9
85 changed files with 2138 additions and 1 deletions
@@ -0,0 +1,11 @@
type Int is int256;
function f() pure {
Int a = Int.wrap(0);
a + a;
a >>> a;
}
// ----
// TypeError 2271: (70-75): Built-in binary operator + cannot be applied to types Int and Int. No matching user-defined operator found.
// TypeError 2271: (81-88): Built-in binary operator >>> cannot be applied to types Int and Int.
@@ -0,0 +1,11 @@
type Int is int256;
function f() pure {
Int a = Int.wrap(0);
-a;
a++;
}
// ----
// TypeError 4907: (70-72): Built-in unary operator - cannot be applied to type Int. No matching user-defined operator found.
// TypeError 9767: (78-81): Built-in unary operator ++ cannot be applied to type Int.
@@ -0,0 +1,12 @@
type Int is int16;
using {add as +} for Int;
function add(Int, Int) pure returns (Int) {}
function f() {
Int a;
a.add(a);
}
// ----
// TypeError 9582: (123-128): Member "add" not found or not visible after argument-dependent lookup in Int.
@@ -0,0 +1,12 @@
type Int is int16;
using {add as +} for Int;
function add(Int, Int) pure returns (Int) {}
function f() {
Int a;
a.+(a);
}
// ----
// ParserError 2314: (125-126): Expected identifier but got '+'
@@ -0,0 +1,18 @@
==== Source: s1.sol ====
type Int is int;
using {add as +} for Int global;
using {sub as -} for Int;
function add(Int, Int) pure returns (Int) {}
function sub(Int, Int) pure returns (Int) {}
==== Source: s2.sol ====
import "s1.sol";
contract C {
function f() pure public {
Int.wrap(0) + Int.wrap(0);
Int.wrap(0) - Int.wrap(0);
}
}
// ----
// TypeError 2271: (s2.sol:104-129): Built-in binary operator - cannot be applied to types Int and Int. No matching user-defined operator found.
@@ -0,0 +1,25 @@
==== Source: s0.sol ====
type Int is int;
==== Source: s1.sol ====
import "s0.sol";
using {add1 as +} for Int;
function add1(Int, Int) pure returns (Int) {}
==== Source: s2.sol ====
import "s0.sol";
using {add2 as +} for Int;
function add2(Int, Int) pure returns (Int) {}
==== Source: s3.sol ====
import "s1.sol";
import "s2.sol";
contract C {
function f() public {
Int.wrap(0) + Int.wrap(0);
}
}
// ----
// TypeError 2271: (s3.sol:81-106): Built-in binary operator + cannot be applied to types Int and Int. No matching user-defined operator found.
@@ -0,0 +1,32 @@
using {add as +, unsub as -} for U;
type U is uint;
function add(U, U) pure returns (U) {}
function unsub(U) pure returns (U) {}
contract C {
function fromBool() public {
U u;
u + true;
true + u;
-true;
}
function fromUint() public {
U u;
uint32 u32;
u + u32;
u32 + u;
-u32;
}
}
// ----
// TypeError 5653: (200-208): The type of the second operand of this user-defined binary operator + does not match the type of the first operand, which is U.
// TypeError 2271: (218-226): Built-in binary operator + cannot be applied to types bool and U.
// TypeError 4907: (236-241): Built-in unary operator - cannot be applied to type bool.
// TypeError 5653: (325-332): The type of the second operand of this user-defined binary operator + does not match the type of the first operand, which is U.
// TypeError 2271: (342-349): Built-in binary operator + cannot be applied to types uint32 and U.
// TypeError 4907: (359-363): Built-in unary operator - cannot be applied to type uint32. Unary negation is only allowed for signed integers.
@@ -0,0 +1,13 @@
using {f as +} for uint;
using {f as +} for uint[2];
using {f as +} for mapping(uint => uint);
using {f as +} for function (uint) pure returns (uint);
using {f as +} for string;
function f(uint, uint) pure returns (uint) {}
// ----
// TypeError 5332: (7-8): Operators can only be implemented for user-defined value types.
// TypeError 5332: (32-33): Operators can only be implemented for user-defined value types.
// TypeError 5332: (60-61): Operators can only be implemented for user-defined value types.
// TypeError 5332: (102-103): Operators can only be implemented for user-defined value types.
// TypeError 5332: (158-159): Operators can only be implemented for user-defined value types.
@@ -0,0 +1,11 @@
using {fc as +} for C;
using {fa as +} for A;
function fc(C, C) returns (C) {}
function fa(A, A) returns (A) {}
contract C {}
abstract contract A {}
// ----
// TypeError 5332: (7-9): Operators can only be implemented for user-defined value types.
// TypeError 5332: (30-32): Operators can only be implemented for user-defined value types.
@@ -0,0 +1,10 @@
using {add as +} for E;
enum E {
E1,
E2
}
function add(E, E) pure returns (E) {}
// ----
// TypeError 5332: (7-10): Operators can only be implemented for user-defined value types.
@@ -0,0 +1,10 @@
using {add as +} for E;
error E();
function add(E, E) pure returns (E) {
return E.E1;
}
// ----
// TypeError 5172: (21-22): Name has to refer to a user-defined type.
@@ -0,0 +1,10 @@
using {add as +} for C.Event;
contract C {
event Event();
}
function add(C.Event, C.Event) pure returns (C.Event) {}
// ----
// TypeError 5172: (21-28): Name has to refer to a user-defined type.
@@ -0,0 +1,7 @@
using {f as +} for I;
function f(I, I) returns (I) {}
interface I {}
// ----
// TypeError 5332: (7-8): Operators can only be implemented for user-defined value types.
@@ -0,0 +1,6 @@
using {f as +} for L;
function f() {}
library L {}
// ----
// TypeError 1130: (19-20): Invalid use of a library name.
@@ -0,0 +1,9 @@
using {add as +} for S;
struct S {
uint x;
}
function add(S memory, S memory) pure returns (S memory) {}
// ----
// TypeError 5332: (7-10): Operators can only be implemented for user-defined value types.
@@ -0,0 +1,9 @@
type Int is int;
function add(Int, Int) returns (Int) {}
contract C {
using {add as +} for *;
}
// ----
// SyntaxError 3349: (76-99): The type has to be specified explicitly when attaching specific functions.
@@ -0,0 +1,5 @@
using {add as +} for *;
function add(int, int) returns (int) {}
// ----
// SyntaxError 8118: (0-23): The type has to be specified explicitly at file level (cannot use '*').
@@ -0,0 +1,9 @@
type Int is uint;
using {f} for Int;
Int constant v;
using {v.f as +} for Int;
function f(Int) pure returns (Int) {}
// ----
// DeclarationError 7920: (61-64): Identifier not found or not unique.
@@ -0,0 +1,8 @@
type Int is int16;
using {abi.encode as +} for Int;
function f(Int, Int) pure returns (Int) {}
// ----
// DeclarationError 7920: (27-37): Identifier not found or not unique.
@@ -0,0 +1,5 @@
type Int is int16;
using {keccak256 as +} for Int;
// ----
// TypeError 8187: (27-36): Expected function name.
@@ -0,0 +1,5 @@
type Int is int16;
using {revert as +} for Int;
// ----
// DeclarationError 7920: (27-33): Identifier not found or not unique.
@@ -0,0 +1,9 @@
type Int is int;
contract C {
using {add as +} for Int;
function add(Int, Int) public returns (Int) {}
}
// ----
// TypeError 4167: (42-45): Only file-level functions and library functions can be attached to a type in a "using" statement
@@ -0,0 +1,11 @@
type Int is int;
using {C.add as +} for Int;
contract C {
function add(Int, Int) public returns (Int) {
return 0;
}
}
// ----
// TypeError 4167: (25-30): Only file-level functions and library functions can be attached to a type in a "using" statement
@@ -0,0 +1,7 @@
type Int is int16;
using {IntError as +} for Int;
error IntError(Int a, Int b);
// ----
// TypeError 8187: (27-35): Expected function name.
@@ -0,0 +1,9 @@
type Int is int16;
using {C.IntEvent as +} for Int;
contract C {
event IntEvent(Int a, Int b);
}
// ----
// TypeError 8187: (27-37): Expected function name.
@@ -0,0 +1,8 @@
type Int is int8;
contract C {
function(Int, Int) external returns (Int) ptr;
using {ptr as +} for Int;
}
// ----
// TypeError 8187: (94-97): Expected function name.
@@ -0,0 +1,9 @@
type Int is int16;
using {keccak256 as +} for Int;
function keccak256(Int, Int) pure returns (Int) {
return Int.wrap(0);
}
// ----
// Warning 2319: (53-128): This declaration shadows a builtin symbol.
@@ -0,0 +1,11 @@
type Int is int128;
library L {
function externalOperator(Int, Int) external returns (Int) {}
}
// FIXME: Not being able to use external library functions in 'using for' is a bug.
// https://github.com/ethereum/solidity/issues/13765
using {L.externalOperator as +} for Int;
// ----
// DeclarationError 7920: (246-264): Identifier not found or not unique.
@@ -0,0 +1,6 @@
type Int is int128;
library L {
using {L.privateOperator as +} for Int;
function privateOperator(Int, Int) private pure returns (Int) {}
}
@@ -0,0 +1,13 @@
type Int is int128;
library L {
function publicOperator(Int, Int) public pure returns (Int) {}
function internalOperator(Int, Int) internal pure returns (Int) {}
function privateOperator(Int, Int) private pure returns (Int) {}
}
using {L.publicOperator as +} for Int;
using {L.internalOperator as +} for Int;
// FIXME: Being able to use private library functions in a file-level 'using for' is a bug.
// See: https://github.com/ethereum/solidity/issues/13764
using {L.privateOperator as +} for Int;
@@ -0,0 +1,10 @@
using {add as +} for A;
using {add as +} for AP;
function add(A, A) pure returns (A) {}
function add(AP, AP) pure returns (AP) {}
type A is address;
type AP is address payable;
// ----
// DeclarationError 7920: (7-10): Identifier not found or not unique.
@@ -0,0 +1,13 @@
type Int is int;
using {add as +} for Int global;
using {another_add as +} for Int;
function add(Int, Int) pure returns (Int) {}
function another_add(Int, Int) pure returns (Int) {}
function test() pure returns (Int) {
return Int.wrap(1) + Int.wrap(2);
}
// ----
// TypeError 5583: (233-258): User-defined binary operator + has more than one definition matching the operand types visible in the current scope.
@@ -0,0 +1,19 @@
==== Source: Int.sol ====
type Int is int;
using {add as +} for Int global;
function add(Int, Int) pure returns (Int) {}
==== Source: test.sol ====
import "Int.sol";
using {another_add as +} for Int;
function another_add(Int, Int) pure returns (Int) {}
function test() pure returns (Int) {
return Int.wrap(0) + Int.wrap(0);
}
// ----
// TypeError 5583: (test.sol:156-181): User-defined binary operator + has more than one definition matching the operand types visible in the current scope.
@@ -0,0 +1,13 @@
type Int is int;
using {unsub as -} for Int global;
using {another_unsub as -} for Int;
function unsub(Int) pure returns (Int) {}
function another_unsub(Int) pure returns (Int) {}
function test() pure returns (Int) {
return -Int.wrap(2);
}
// ----
// TypeError 4705: (231-243): User-defined unary operator - has more than one definition matching the operand type visible in the current scope.
@@ -0,0 +1,12 @@
type Int is uint128;
using {add as +, sub as +} for Int;
function add(Int, Int) pure returns (Int) {}
function sub(Int, Int) pure returns (Int) {}
function test() {
Int.wrap(0) + Int.wrap(1);
}
// ----
// TypeError 5583: (172-197): User-defined binary operator + has more than one definition matching the operand types visible in the current scope.
@@ -0,0 +1,10 @@
type Int is uint128;
// No error if the operator is not actually used
using {add1 as +, add2 as +} for Int;
using {unsub1 as -, unsub2 as -} for Int;
function add1(Int, Int) pure returns (Int) {}
function add2(Int, Int) pure returns (Int) {}
function unsub1(Int) pure returns (Int) {}
function unsub2(Int) pure returns (Int) {}
@@ -0,0 +1,22 @@
type Int is int;
using {add as +} for Int;
function add(Int, Int) pure returns (Int) {}
function another_add(Int, Int) pure returns (Int) {}
contract B {
using {another_add as +} for Int;
function f() public {
Int.wrap(0) + Int.wrap(0);
}
}
contract C is B {
function g() public {
Int.wrap(0) + Int.wrap(0);
}
}
// ----
// TypeError 5583: (230-255): User-defined binary operator + has more than one definition matching the operand types visible in the current scope.
@@ -0,0 +1,9 @@
type Int is int32;
using {add as +, add as +} for Int;
function add(Int, Int) pure returns(Int) {}
function f(int32 a, int32 b) pure {
Int.wrap(a) + Int.wrap(b);
}
@@ -0,0 +1,10 @@
type Int is int32;
using {add as +} for Int;
using {add as +} for Int;
function add(Int, Int) pure returns(Int) {}
function f(int32 a, int32 b) pure {
Int.wrap(a) + Int.wrap(b);
}
@@ -0,0 +1,13 @@
type Int is uint128;
using {add as +, add128 as +} for Int;
function add(Int, Int) pure returns (Int) {}
function add128(Int, int128) pure returns (Int) {}
function test() {
Int.wrap(0) + Int.wrap(1);
}
// ----
// TypeError 1884: (122-135): Wrong parameters in operator definition. The function "add128" needs to have two parameters of type Int and the same data location to be used for the operator +.
// TypeError 5583: (181-206): User-defined binary operator + has more than one definition matching the operand types visible in the current scope.
@@ -0,0 +1,3 @@
using {as -} for uint;
// ----
// ParserError 2314: (7-9): Expected identifier but got 'as'
@@ -0,0 +1,3 @@
using f as - for uint;
// ----
// ParserError 2314: (8-10): Expected 'for' but got 'as'
@@ -0,0 +1,16 @@
using {
f as ++,
f as --,
f as x,
f as delete,
f as new,
f as ()
} for int256;
// ----
// ParserError 4403: (17-19): Not a user-definable operator: ++. Only the following operators can be user-defined: |, &, ^, ~, <<, >>, +, -, *, /, %, **, ==, !=, <, >, <=, >=, !
// ParserError 4403: (30-32): Not a user-definable operator: --. Only the following operators can be user-defined: |, &, ^, ~, <<, >>, +, -, *, /, %, **, ==, !=, <, >, <=, >=, !
// ParserError 4403: (43-44): Not a user-definable operator: x. Only the following operators can be user-defined: |, &, ^, ~, <<, >>, +, -, *, /, %, **, ==, !=, <, >, <=, >=, !
// ParserError 4403: (55-61): Not a user-definable operator: delete. Only the following operators can be user-defined: |, &, ^, ~, <<, >>, +, -, *, /, %, **, ==, !=, <, >, <=, >=, !
// ParserError 4403: (72-75): Not a user-definable operator: new. Only the following operators can be user-defined: |, &, ^, ~, <<, >>, +, -, *, /, %, **, ==, !=, <, >, <=, >=, !
// ParserError 4403: (86-87): Not a user-definable operator: (. Only the following operators can be user-defined: |, &, ^, ~, <<, >>, +, -, *, /, %, **, ==, !=, <, >, <=, >=, !
// ParserError 2314: (87-88): Expected '}' but got ')'
@@ -0,0 +1,4 @@
using {f as} for uint;
// ----
// ParserError 4403: (11-12): Not a user-definable operator: }. Only the following operators can be user-defined: |, &, ^, ~, <<, >>, +, -, *, /, %, **, ==, !=, <, >, <=, >=, !
// ParserError 2314: (13-16): Expected '}' but got 'for'
@@ -0,0 +1,3 @@
using {f as as} for uint;
// ----
// ParserError 4403: (12-14): Not a user-definable operator: as. Only the following operators can be user-defined: |, &, ^, ~, <<, >>, +, -, *, /, %, **, ==, !=, <, >, <=, >=, !
@@ -0,0 +1,33 @@
type Int is int256;
using {
add as +,
div as /,
unsub as -,
bitnot as ~,
gt as >,
lt as <
} for Int;
function add(Int x, Int y) pure returns (int256) {}
function div(Int x, Int y) pure {}
function unsub(Int) pure returns (Int, Int) {}
function bitnot(Int) pure returns (int256) {}
function gt(Int, Int) pure returns (Int) {}
function lt(Int, Int) pure returns (bool, Int) {}
function f() pure {
Int.wrap(0) + Int.wrap(1);
Int.wrap(0) / Int.wrap(0);
-Int.wrap(0);
~Int.wrap(0);
Int.wrap(0) < Int.wrap(0);
Int.wrap(0) > Int.wrap(0);
}
// ----
// TypeError 7743: (167-175): Wrong return parameters in operator definition. The function "add" needs to return exactly one value of type Int to be used for the operator +.
// TypeError 7743: (211-211): Wrong return parameters in operator definition. The function "div" needs to return exactly one value of type Int to be used for the operator /.
// TypeError 7743: (247-257): Wrong return parameters in operator definition. The function "unsub" needs to return exactly one value of type Int to be used for the operator -.
// TypeError 7743: (295-303): Wrong return parameters in operator definition. The function "bitnot" needs to return exactly one value of type Int to be used for the operator ~.
// TypeError 7743: (342-347): Wrong return parameters in operator definition. The function "gt" needs to return exactly one value of type bool to be used for the operator >.
// TypeError 7743: (386-397): Wrong return parameters in operator definition. The function "lt" needs to return exactly one value of type bool to be used for the operator <.
@@ -0,0 +1,26 @@
type Int is int256;
using {
add as +,
sub as -,
div as /
} for Int;
function add(Int) pure returns (Int) {}
function sub(Int, Int, Int) pure returns (Int) {}
function div(int256, int256) pure returns (Int) {}
function f() pure {
Int.wrap(0) + Int.wrap(1);
Int.wrap(0) - Int.wrap(0);
Int.wrap(0) / Int.wrap(0);
}
// ----
// TypeError 1884: (94-99): Wrong parameters in operator definition. The function "add" needs to have two parameters of type Int and the same data location to be used for the operator +.
// TypeError 1884: (134-149): Wrong parameters in operator definition. The function "sub" needs to have one or two parameters of type Int and the same data location to be used for the operator -.
// TypeError 1884: (184-200): Wrong parameters in operator definition. The function "div" needs to have one or two parameters of type Int and the same data location to be used for the operator /.
// TypeError 7743: (214-219): Wrong return parameters in operator definition. The function "div" needs to return a value of the same type and data location as its parameters to be used for the operator /.
// TypeError 2271: (248-273): Built-in binary operator + cannot be applied to types Int and Int. No matching user-defined operator found.
// TypeError 2271: (279-304): Built-in binary operator - cannot be applied to types Int and Int. No matching user-defined operator found.
// TypeError 2271: (310-335): Built-in binary operator / cannot be applied to types Int and Int. No matching user-defined operator found.
@@ -0,0 +1,11 @@
type Int is int;
using {
f as +
} for Int;
function f() returns (Int) {
return Int.wrap(0);
}
// ----
// TypeError 4731: (30-31): The function "f" does not have any parameters, and therefore cannot be attached to the type "Int".
@@ -0,0 +1,11 @@
type Int is int;
using {
f as ~
} for Int;
function f() returns (Int) {
return Int.wrap(0);
}
// ----
// TypeError 4731: (30-31): The function "f" does not have any parameters, and therefore cannot be attached to the type "Int".
@@ -0,0 +1,20 @@
type Int is int128;
using {
add as +,
sub as -,
mul as *,
div as /
} for Int;
function add(Int, int128) pure returns (Int) {}
function sub(int128, Int) pure returns (int128) {}
function mul(int128, int256) pure returns (Int) {}
function div(Int, Int) pure returns (int256) {}
// ----
// TypeError 1884: (108-121): Wrong parameters in operator definition. The function "add" needs to have two parameters of type Int and the same data location to be used for the operator +.
// TypeError 1884: (156-169): Wrong parameters in operator definition. The function "sub" needs to have one or two parameters of type Int and the same data location to be used for the operator -.
// TypeError 7743: (183-191): Wrong return parameters in operator definition. The function "sub" needs to return exactly one value of type Int to be used for the operator -.
// TypeError 1884: (207-223): Wrong parameters in operator definition. The function "mul" needs to have two parameters of type Int and the same data location to be used for the operator *.
// TypeError 7743: (237-242): Wrong return parameters in operator definition. The function "mul" needs to return a value of the same type and data location as its parameters to be used for the operator *.
// TypeError 7743: (282-290): Wrong return parameters in operator definition. The function "div" needs to return exactly one value of type Int to be used for the operator /.
@@ -0,0 +1,14 @@
type Int is int128;
using {bitnot as ~} for Int;
function bitnot(Int, Int) pure returns (Int) {}
contract C {
function test() public pure {
~Int.wrap(1);
}
}
// ----
// TypeError 1884: (66-76): Wrong parameters in operator definition. The function "bitnot" needs to have exactly one parameter of type Int to be used for the operator ~.
// TypeError 4907: (155-167): Built-in unary operator ~ cannot be applied to type Int. No matching user-defined operator found.
@@ -0,0 +1,13 @@
type Int is int16;
function add(Int, Int) pure returns (Int) {}
contract C {
using {add as +} for Int global;
function test() pure public {
Int.wrap(0) + Int.wrap(0);
}
}
// ----
// SyntaxError 3367: (83-115): "global" can only be used at file level.
@@ -0,0 +1,13 @@
==== Source: s1.sol ====
type Bool is bool;
==== Source: s2.sol ====
import "s1.sol";
function not(Bool) pure returns (Bool) {}
contract C {
using {not as !} for Bool global;
}
// ----
// SyntaxError 3367: (s2.sol:78-111): "global" can only be used at file level.
@@ -0,0 +1,28 @@
type Int is int128;
function add(Int, Int) pure returns (Int) {}
function another_add(Int, Int) pure returns (Int) {}
contract B {
using {add as +} for Int;
function f() pure public returns (Int) {
return Int.wrap(0) + Int.wrap(0);
}
}
contract C is B {
using {another_add as +} for Int;
function g() pure public returns (Int) {
return Int.wrap(0) + Int.wrap(0);
}
}
contract D is B {
function h() pure public returns (Int) {
return Int.wrap(0) + Int.wrap(0);
}
}
// ----
// TypeError 2271: (491-516): Built-in binary operator + cannot be applied to types Int and Int. No matching user-defined operator found.
@@ -0,0 +1,9 @@
type Int is int;
function add(Int, Int) pure returns (Int) {}
interface I {
using {add as +} for Int;
}
// ----
// SyntaxError 9088: (82-107): The "using for" directive is not allowed inside interfaces.
@@ -0,0 +1,8 @@
type Int is int;
library L {
using {add as +} for Int;
function add(Int, Int) internal pure returns (Int) {}
function unsub(Int) internal pure returns (Int) {}
}
@@ -0,0 +1,11 @@
==== Source: s1.sol ====
type Bool is bool;
==== Source: s2.sol ====
import "s1.sol";
function not(Bool) pure returns (Bool) {}
using {not as !} for Bool global;
// ----
// TypeError 4117: (s2.sol:61-94): Can only use "global" with types defined in the same source unit at file level.