User-defined operators: Tests

This commit is contained in:
wechman 2022-07-28 08:39:10 +02:00 committed by Kamil Śliwak
parent fd6359000e
commit 1edb74dbc9
85 changed files with 2138 additions and 1 deletions

View File

@ -0,0 +1,663 @@
{
"absolutePath": "a",
"exportedSymbols":
{
"C":
[
49
],
"I8":
[
2
],
"sub":
[
20
],
"unsub":
[
30
]
},
"id": 50,
"nodeType": "SourceUnit",
"nodes":
[
{
"canonicalName": "I8",
"id": 2,
"name": "I8",
"nameLocation": "5:2:1",
"nodeType": "UserDefinedValueTypeDefinition",
"src": "0:16:1",
"underlyingType":
{
"id": 1,
"name": "int8",
"nodeType": "ElementaryTypeName",
"src": "11:4:1",
"typeDescriptions":
{
"typeIdentifier": "t_int8",
"typeString": "int8"
}
}
},
{
"functionList":
[
{
"function":
{
"id": 3,
"name": "sub",
"nameLocations":
[
"24:3:1"
],
"nodeType": "IdentifierPath",
"referencedDeclaration": 20,
"src": "24:3:1"
},
"operator": "-"
},
{
"function":
{
"id": 4,
"name": "unsub",
"nameLocations":
[
"34:5:1"
],
"nodeType": "IdentifierPath",
"referencedDeclaration": 30,
"src": "34:5:1"
},
"operator": "-"
}
],
"global": true,
"id": 7,
"nodeType": "UsingForDirective",
"src": "17:43:1",
"typeName":
{
"id": 6,
"nodeType": "UserDefinedTypeName",
"pathNode":
{
"id": 5,
"name": "I8",
"nameLocations":
[
"50:2:1"
],
"nodeType": "IdentifierPath",
"referencedDeclaration": 2,
"src": "50:2:1"
},
"referencedDeclaration": 2,
"src": "50:2:1",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
}
}
},
{
"body":
{
"id": 19,
"nodeType": "Block",
"src": "100:2:1",
"statements": []
},
"id": 20,
"implemented": true,
"kind": "freeFunction",
"modifiers": [],
"name": "sub",
"nameLocation": "70:3:1",
"nodeType": "FunctionDefinition",
"parameters":
{
"id": 14,
"nodeType": "ParameterList",
"parameters":
[
{
"constant": false,
"id": 10,
"mutability": "mutable",
"name": "",
"nameLocation": "-1:-1:-1",
"nodeType": "VariableDeclaration",
"scope": 20,
"src": "74:2:1",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
},
"typeName":
{
"id": 9,
"nodeType": "UserDefinedTypeName",
"pathNode":
{
"id": 8,
"name": "I8",
"nameLocations":
[
"74:2:1"
],
"nodeType": "IdentifierPath",
"referencedDeclaration": 2,
"src": "74:2:1"
},
"referencedDeclaration": 2,
"src": "74:2:1",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
}
},
"visibility": "internal"
},
{
"constant": false,
"id": 13,
"mutability": "mutable",
"name": "",
"nameLocation": "-1:-1:-1",
"nodeType": "VariableDeclaration",
"scope": 20,
"src": "78:2:1",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
},
"typeName":
{
"id": 12,
"nodeType": "UserDefinedTypeName",
"pathNode":
{
"id": 11,
"name": "I8",
"nameLocations":
[
"78:2:1"
],
"nodeType": "IdentifierPath",
"referencedDeclaration": 2,
"src": "78:2:1"
},
"referencedDeclaration": 2,
"src": "78:2:1",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
}
},
"visibility": "internal"
}
],
"src": "73:8:1"
},
"returnParameters":
{
"id": 18,
"nodeType": "ParameterList",
"parameters":
[
{
"constant": false,
"id": 17,
"mutability": "mutable",
"name": "",
"nameLocation": "-1:-1:-1",
"nodeType": "VariableDeclaration",
"scope": 20,
"src": "96:2:1",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
},
"typeName":
{
"id": 16,
"nodeType": "UserDefinedTypeName",
"pathNode":
{
"id": 15,
"name": "I8",
"nameLocations":
[
"96:2:1"
],
"nodeType": "IdentifierPath",
"referencedDeclaration": 2,
"src": "96:2:1"
},
"referencedDeclaration": 2,
"src": "96:2:1",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
}
},
"visibility": "internal"
}
],
"src": "95:4:1"
},
"scope": 50,
"src": "61:41:1",
"stateMutability": "pure",
"virtual": false,
"visibility": "internal"
},
{
"body":
{
"id": 29,
"nodeType": "Block",
"src": "140:2:1",
"statements": []
},
"id": 30,
"implemented": true,
"kind": "freeFunction",
"modifiers": [],
"name": "unsub",
"nameLocation": "112:5:1",
"nodeType": "FunctionDefinition",
"parameters":
{
"id": 24,
"nodeType": "ParameterList",
"parameters":
[
{
"constant": false,
"id": 23,
"mutability": "mutable",
"name": "",
"nameLocation": "-1:-1:-1",
"nodeType": "VariableDeclaration",
"scope": 30,
"src": "118:2:1",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
},
"typeName":
{
"id": 22,
"nodeType": "UserDefinedTypeName",
"pathNode":
{
"id": 21,
"name": "I8",
"nameLocations":
[
"118:2:1"
],
"nodeType": "IdentifierPath",
"referencedDeclaration": 2,
"src": "118:2:1"
},
"referencedDeclaration": 2,
"src": "118:2:1",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
}
},
"visibility": "internal"
}
],
"src": "117:4:1"
},
"returnParameters":
{
"id": 28,
"nodeType": "ParameterList",
"parameters":
[
{
"constant": false,
"id": 27,
"mutability": "mutable",
"name": "",
"nameLocation": "-1:-1:-1",
"nodeType": "VariableDeclaration",
"scope": 30,
"src": "136:2:1",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
},
"typeName":
{
"id": 26,
"nodeType": "UserDefinedTypeName",
"pathNode":
{
"id": 25,
"name": "I8",
"nameLocations":
[
"136:2:1"
],
"nodeType": "IdentifierPath",
"referencedDeclaration": 2,
"src": "136:2:1"
},
"referencedDeclaration": 2,
"src": "136:2:1",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
}
},
"visibility": "internal"
}
],
"src": "135:4:1"
},
"scope": 50,
"src": "103:39:1",
"stateMutability": "pure",
"virtual": false,
"visibility": "internal"
},
{
"abstract": false,
"baseContracts": [],
"canonicalName": "C",
"contractDependencies": [],
"contractKind": "contract",
"fullyImplemented": true,
"id": 49,
"linearizedBaseContracts":
[
49
],
"name": "C",
"nameLocation": "152:1:1",
"nodeType": "ContractDefinition",
"nodes":
[
{
"body":
{
"id": 47,
"nodeType": "Block",
"src": "208:30:1",
"statements":
[
{
"expression":
{
"commonType":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
},
"function": 20,
"id": 45,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftExpression":
{
"function": 30,
"id": 43,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"nodeType": "UnaryOperation",
"operator": "-",
"prefix": true,
"src": "225:2:1",
"subExpression":
{
"id": 42,
"name": "a",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 33,
"src": "226:1:1",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
}
},
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
}
},
"nodeType": "BinaryOperation",
"operator": "-",
"rightExpression":
{
"id": 44,
"name": "b",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 36,
"src": "230:1:1",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
}
},
"src": "225:6:1",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
}
},
"functionReturnParameters": 41,
"id": 46,
"nodeType": "Return",
"src": "218:13:1"
}
]
},
"functionSelector": "ac9fe858",
"id": 48,
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "f",
"nameLocation": "169:1:1",
"nodeType": "FunctionDefinition",
"parameters":
{
"id": 37,
"nodeType": "ParameterList",
"parameters":
[
{
"constant": false,
"id": 33,
"mutability": "mutable",
"name": "a",
"nameLocation": "174:1:1",
"nodeType": "VariableDeclaration",
"scope": 48,
"src": "171:4:1",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
},
"typeName":
{
"id": 32,
"nodeType": "UserDefinedTypeName",
"pathNode":
{
"id": 31,
"name": "I8",
"nameLocations":
[
"171:2:1"
],
"nodeType": "IdentifierPath",
"referencedDeclaration": 2,
"src": "171:2:1"
},
"referencedDeclaration": 2,
"src": "171:2:1",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
}
},
"visibility": "internal"
},
{
"constant": false,
"id": 36,
"mutability": "mutable",
"name": "b",
"nameLocation": "180:1:1",
"nodeType": "VariableDeclaration",
"scope": 48,
"src": "177:4:1",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
},
"typeName":
{
"id": 35,
"nodeType": "UserDefinedTypeName",
"pathNode":
{
"id": 34,
"name": "I8",
"nameLocations":
[
"177:2:1"
],
"nodeType": "IdentifierPath",
"referencedDeclaration": 2,
"src": "177:2:1"
},
"referencedDeclaration": 2,
"src": "177:2:1",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
}
},
"visibility": "internal"
}
],
"src": "170:12:1"
},
"returnParameters":
{
"id": 41,
"nodeType": "ParameterList",
"parameters":
[
{
"constant": false,
"id": 40,
"mutability": "mutable",
"name": "",
"nameLocation": "-1:-1:-1",
"nodeType": "VariableDeclaration",
"scope": 48,
"src": "204:2:1",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
},
"typeName":
{
"id": 39,
"nodeType": "UserDefinedTypeName",
"pathNode":
{
"id": 38,
"name": "I8",
"nameLocations":
[
"204:2:1"
],
"nodeType": "IdentifierPath",
"referencedDeclaration": 2,
"src": "204:2:1"
},
"referencedDeclaration": 2,
"src": "204:2:1",
"typeDescriptions":
{
"typeIdentifier": "t_userDefinedValueType$_I8_$2",
"typeString": "I8"
}
},
"visibility": "internal"
}
],
"src": "203:4:1"
},
"scope": 49,
"src": "160:78:1",
"stateMutability": "pure",
"virtual": false,
"visibility": "public"
}
],
"scope": 50,
"src": "143:97:1",
"usedErrors": []
}
],
"src": "0:241:1"
}

View File

@ -0,0 +1,11 @@
type I8 is int8;
using {sub as -, unsub as -} for I8 global;
function sub(I8, I8) pure returns (I8) {}
function unsub(I8) pure returns (I8) {}
contract C {
function f(I8 a, I8 b) public pure returns (I8) {
return -a - b;
}
}
// ----

View File

@ -1702,6 +1702,72 @@ BOOST_AUTO_TEST_CASE(using_for)
checkCallGraphExpectations(get<1>(graphs), expectedDeployedEdges);
}
BOOST_AUTO_TEST_CASE(user_defined_binary_operator)
{
unique_ptr<CompilerStack> compilerStack = parseAndAnalyzeContracts(R"(
type Int is int128;
using {add as +} for Int;
function add(Int, Int) pure returns (Int) {
return Int.wrap(0);
}
contract C {
function pub() public {
Int.wrap(0) + Int.wrap(1);
}
}
)"s);
tuple<CallGraphMap, CallGraphMap> graphs = collectGraphs(*compilerStack);
map<string, EdgeNames> expectedCreationEdges = {
{"C", {}},
};
map<string, EdgeNames> expectedDeployedEdges = {
{"C", {
{"Entry", "function C.pub()"},
{"function C.pub()", "function add(Int,Int)"},
}},
};
checkCallGraphExpectations(get<0>(graphs), expectedCreationEdges);
checkCallGraphExpectations(get<1>(graphs), expectedDeployedEdges);
}
BOOST_AUTO_TEST_CASE(user_defined_unary_operator)
{
unique_ptr<CompilerStack> compilerStack = parseAndAnalyzeContracts(R"(
type Int is int128;
using {sub as -} for Int;
function sub(Int) pure returns (Int) {
return Int.wrap(0);
}
contract C {
function pub() public {
-Int.wrap(1);
}
}
)"s);
tuple<CallGraphMap, CallGraphMap> graphs = collectGraphs(*compilerStack);
map<string, EdgeNames> expectedCreationEdges = {
{"C", {}},
};
map<string, EdgeNames> expectedDeployedEdges = {
{"C", {
{"Entry", "function C.pub()"},
{"function C.pub()", "function sub(Int)"},
}},
};
checkCallGraphExpectations(get<0>(graphs), expectedCreationEdges);
checkCallGraphExpectations(get<1>(graphs), expectedDeployedEdges);
}
BOOST_AUTO_TEST_CASE(getters)
{
unique_ptr<CompilerStack> compilerStack = parseAndAnalyzeContracts(R"(

View File

@ -0,0 +1,20 @@
type Int is int16;
using {add as +, add} for Int;
function add(Int _a, Int _b) pure returns (Int) {
return Int.wrap(Int.unwrap(_a) + Int.unwrap(_b));
}
contract C {
function f() pure public returns (Int) {
return Int.wrap(5) + Int.wrap(5);
}
function g() pure public returns (Int) {
return Int.wrap(7).add(Int.wrap(6));
}
}
// ----
// f() -> 10
// g() -> 13

View File

@ -0,0 +1,125 @@
type Int is int128;
using {
bitor as |, bitand as &, bitxor as ^, bitnot as ~,
add as +, sub as -, unsub as -, mul as *, div as /, mod as %,
eq as ==, noteq as !=, lt as <, gt as >, leq as <=, geq as >=,
shl as <<, sar as >>, exp as **, not as !
} for Int;
function uw(Int x) pure returns (int128) {
return Int.unwrap(x);
}
function w(int128 x) pure returns (Int) {
return Int.wrap(x);
}
function bitor(Int, Int) pure returns (Int) {
return w(10);
}
function bitand(Int, Int) pure returns (Int) {
return w(11);
}
function bitxor(Int, Int) pure returns (Int) {
return w(12);
}
function bitnot(Int) pure returns (Int) {
return w(13);
}
function add(Int x, Int) pure returns (Int) {
return w(uw(x) + 10);
}
function sub(Int, Int) pure returns (Int) {
return w(15);
}
function unsub(Int) pure returns (Int) {
return w(16);
}
function mul(Int, Int) pure returns (Int) {
return w(17);
}
function div(Int, Int) pure returns (Int) {
return w(18);
}
function mod(Int, Int) pure returns (Int) {
return w(19);
}
function eq(Int x, Int) pure returns (bool) {
return uw(x) == 1;
}
function noteq(Int x, Int) pure returns (bool) {
return uw(x) == 2;
}
function lt(Int x, Int) pure returns (bool) {
return uw(x) < 10;
}
function gt(Int x, Int) pure returns (bool) {
return uw(x) > 10;
}
function leq(Int x, Int) pure returns (bool) {
return uw(x) <= 10;
}
function geq(Int x, Int) pure returns (bool) {
return uw(x) >= 10;
}
function shl(Int, Int) pure returns (Int) {
return w(20);
}
function sar(Int, Int) pure returns (Int) {
return w(21);
}
function exp(Int, Int) pure returns (Int) {
return w(22);
}
function not(Int) pure returns (Int) {
return w(23);
}
contract C {
function test_bitor() public pure returns (Int) { return w(1) | w(2); }
function test_bitand() public pure returns (Int) { return w(1) & w(2); }
function test_bitxor() public pure returns (Int) { return w(1) ^ w(2); }
function test_bitnot() public pure returns (Int) { return ~w(1); }
function test_add(int128 x) public pure returns (Int) { return w(x) + w(2); }
function test_sub() public pure returns (Int) { return w(1) - w(2); }
function test_unsub() public pure returns (Int) { return -w(1); }
function test_mul() public pure returns (Int) { return w(1) * w(2); }
function test_div() public pure returns (Int) { return w(1) / w(2); }
function test_mod() public pure returns (Int) { return w(1) % w(2); }
function test_eq(int128 x) public pure returns (bool) { return w(x) == w(2); }
function test_neq(int128 x) public pure returns (bool) { return w(x) != w(2); }
function test_lt(int128 x) public pure returns (bool) { return w(x) < w(2); }
function test_gt(int128 x) public pure returns (bool) { return w(x) > w(2); }
function test_leq(int128 x) public pure returns (bool) { return w(x) <= w(2); }
function test_geq(int128 x) public pure returns (bool) { return w(x) >= w(2); }
function test_shl() public pure returns (Int) { return w(1) << w(2); }
function test_sar() public pure returns (Int) { return w(1) >> w(2); }
function test_exp() public pure returns (Int) { return w(1) ** w(2); }
function test_not() public pure returns (Int) { return !w(1); }
}
// ----
// test_bitor() -> 10
// test_bitand() -> 11
// test_bitxor() -> 12
// test_bitnot() -> 13
// test_add(int128): 4 -> 14
// test_add(int128): 104 -> 114
// test_sub() -> 15
// test_unsub() -> 16
// test_mul() -> 17
// test_div() -> 18
// test_mod() -> 19
// test_eq(int128): 1 -> true
// test_eq(int128): 2 -> false
// test_neq(int128): 2 -> true
// test_neq(int128): 1 -> false
// test_lt(int128): 9 -> true
// test_lt(int128): 10 -> false
// test_gt(int128): 11 -> true
// test_gt(int128): 10 -> false
// test_leq(int128): 10 -> true
// test_leq(int128): 11 -> false
// test_geq(int128): 10 -> true
// test_geq(int128): 9 -> false
// test_shl() -> 20
// test_sar() -> 21
// test_exp() -> 22
// test_not() -> 23

View File

@ -0,0 +1,93 @@
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 !
} for Int;
function uw(Int x) pure returns (int64) { return Int.unwrap(x); }
function w(int64 x) pure returns (Int) { return Int.wrap(x); }
function bitor(Int x, Int y) pure returns (Int) { return w(uw(x) | uw(y)); }
function bitand(Int x, Int y) pure returns (Int) { return w(uw(x) & uw(y)); }
function bitxor(Int x, Int y) pure returns (Int) { return w(uw(x) ^ uw(y)); }
function bitnot(Int x) pure returns (Int) { return w(~uw(x)); }
function shl(Int x, Int y) pure returns (Int) { return w(uw(x) << uint64(uw(y))); }
function sar(Int x, Int y) pure returns (Int) { return w(uw(x) >> uint64(uw(y))); }
function add(Int x, Int y) pure returns (Int) { return w(uw(x) + uw(y)); }
function sub(Int x, Int y) pure returns (Int) { return w(uw(x) - uw(y)); }
function unsub(Int x) pure returns (Int) { return w(-uw(x)); }
function mul(Int x, Int y) pure returns (Int) { return w(uw(x) * uw(y)); }
function div(Int x, Int y) pure returns (Int) { return w(uw(x) / uw(y)); }
function mod(Int x, Int y) pure returns (Int) { return w(uw(x) % uw(y)); }
function exp(Int x, Int y) pure returns (Int) { return w(uw(x) ** uint64(uw(y))); }
function eq(Int x, Int y) pure returns (bool) { return uw(x) == uw(y); }
function noteq(Int x, Int y) pure returns (bool) { return uw(x) != uw(y); }
function not(Int x) pure returns (Int) { return w((uw(x) == 0 ? int64(1) : int64(0))); }
contract C {
Int constant I0 = Int.wrap(0);
Int constant I1 = Int.wrap(1);
Int constant I2 = Int.wrap(2);
Int constant I3 = Int.wrap(3);
Int constant I4 = Int.wrap(4);
Int constant I5 = Int.wrap(5);
Int constant I6 = Int.wrap(6);
Int constant I7 = Int.wrap(7);
Int constant I10 = Int.wrap(10);
Int constant I13 = Int.wrap(13);
Int constant I15 = Int.wrap(15);
Int constant I20 = Int.wrap(20);
Int constant I128 = Int.wrap(128);
function test_bitwise() public pure {
assert(Int.unwrap(I0 & I0 | I1) == (0 & 0 | 1));
assert(Int.unwrap(I0 & I0 | I1) == ((0 & 0) | 1));
}
function test_bitwise_arithmetic() public pure {
assert(Int.unwrap(I1 << I1 + I1 & ~I1 | I1 << I2 * I3 - I1 & ~I3) == (1 << 1 + 1 & ~1 | 1 << 2 * 3 - 1 & ~3));
assert(Int.unwrap(I1 << I1 + I1 & ~I1 | I1 << I2 * I3 - I1 & ~I3) == (((1 << (1 + 1)) & (~1)) | ((1 << ((2 * 3) - 1)) & (~3))));
}
function test_arithmetic() public pure {
assert(Int.unwrap(I1 + I2 ** I3 / I4 - I5 % I6 * I7) == (1 + 2 ** 3 / 4 - 5 % 6 * 7));
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) ==
(128 + 1 - 10 + 4 & ~1 ^ ~1 >> 1 + 1 << 3 ** 2 | -15 % -10 * 20 / 2 + 13 & ~3)
);
assert(
Int.unwrap(I128 + I1 - I10 + I4 & ~I1 ^ ~I1 >> I1 + I1 << I3 ** I2 | -I15 % -I10 * I20 / I2 + I13 & ~I3) ==
(
(
((((128 + 1) - 10) + 4) & (~1)) ^
(((~1) >> (1 + 1)) << (3 ** 2))
) |
((((((-15) % (-10)) * 20) / 2) + 13) & (~3))
)
);
}
}
// ----
// test_bitwise() ->
// test_bitwise_arithmetic() ->
// test_arithmetic() ->
// test_not() ->
// test_all() ->

View File

@ -0,0 +1,18 @@
type A is address;
using {add as +} for A;
function add(A a, A b) pure returns (A) {
return A.wrap(address(uint160(A.unwrap(a)) + uint160(A.unwrap(b))));
}
contract C {
function g() public pure returns (A) {
A a = A.wrap(0x3333333333333333333333333333333333333333);
A b = A.wrap(0x1111111111111111111111111111111111111111);
A c = A.wrap(0x5555555555555555555555555555555555555555);
return a + b + c;
}
}
// ----
// g() -> 0x9999999999999999999999999999999999999999

View File

@ -0,0 +1,26 @@
type Int is int16;
using {add as +} for Int;
function add(Int, Int) returns (Int) {
B b = new B();
return b.f();
}
contract B {
Int s;
function f() external returns (Int) {
s = Int.wrap(3);
return s;
}
}
contract C {
function test() public returns (Int) {
return Int.wrap(0) + Int.wrap(0);
}
}
// ----
// test() -> 3
// gas legacy: 119695

View File

@ -0,0 +1,28 @@
==== Source: s1.sol ====
type Int is int;
using {add1 as +} for Int global;
function add1(Int, Int) pure returns (Int) {
return Int.wrap(3);
}
==== Source: s2.sol ====
import {Int} from "s1.sol";
using {add2 as +} for Int;
function add2(Int, Int) pure returns (Int) {
return Int.wrap(7);
}
==== Source: s3.sol ====
import {Int} from "s2.sol";
contract C {
function f() pure public returns (Int) {
return Int.wrap(0) + Int.wrap(0);
}
}
// ----
// f() -> 3

View File

@ -0,0 +1,40 @@
type Int is int;
function add1(Int, Int) pure returns (Int) {
return Int.wrap(1);
}
function add2(Int, Int) pure returns (Int) {
return Int.wrap(2);
}
contract C1 {
using {add1 as +} for Int;
function f() public returns (Int) {
return Int.wrap(0) + Int.wrap(0);
}
}
contract C2 {
using {add2 as +} for Int;
function f() public returns (Int) {
return Int.wrap(0) + Int.wrap(0);
}
}
contract C {
function test1() public returns (Int) {
C1 c = new C1();
return c.f();
}
function test2() public returns (Int) {
C2 c = new C2();
return c.f();
}
}
// ----
// test1() -> 1
// test2() -> 2

View File

@ -0,0 +1,41 @@
type Int is int128;
function addA(Int, Int) pure returns (Int) {
return Int.wrap(1);
}
function addB(Int, Int) pure returns (Int) {
return Int.wrap(3);
}
function addC(Int, Int) pure returns (Int) {
return Int.wrap(7);
}
contract A {
using {addA as +} for Int;
function testA() pure public returns (Int) {
return Int.wrap(0) + Int.wrap(0);
}
}
contract B is A {
using {addB as +} for Int;
function testB() pure public returns (Int) {
return Int.wrap(0) + Int.wrap(0);
}
}
contract C is A, B {
using {addC as +} for Int;
function testC() pure public returns (Int) {
return Int.wrap(0) + Int.wrap(0);
}
}
// ----
// testA() -> 1
// testB() -> 3
// testC() -> 7

View File

@ -0,0 +1,22 @@
type Fixed is int128;
using {add as +, mul as *} for Fixed;
int constant MULTIPLIER = 10**18;
function add(Fixed a, Fixed b) pure returns (Fixed) {
return Fixed.wrap(Fixed.unwrap(a) + Fixed.unwrap(b));
}
function mul(Fixed a, Fixed b) pure returns (Fixed) {
int intermediate = (int(Fixed.unwrap(a)) * int(Fixed.unwrap(b))) / MULTIPLIER;
if (int128(intermediate) != intermediate) { revert("Overflow"); }
return Fixed.wrap(int128(intermediate));
}
contract C {
function applyInterest(Fixed value, Fixed percentage) public pure returns (Fixed result) {
return value + value * percentage;
}
}
// ----
// applyInterest(int128,int128): 500000000000000000000, 100000000000000000 -> 550000000000000000000

View File

@ -0,0 +1,29 @@
==== Source: s1.sol ====
type Int is int;
using {add as +} for Int global;
using {add as +} for Int;
function add(Int a, Int b) pure returns (Int) {
return Int.wrap(Int.unwrap(a) + Int.unwrap(b));
}
function test_add() pure returns (Int) {
return Int.wrap(1) + Int.wrap(2);
}
==== Source: s2.sol ====
import "s1.sol";
contract C2 {
function test1() pure public returns (Int) {
return test_add();
}
function test2() pure public returns (Int) {
return Int.wrap(3) + Int.wrap(4);
}
}
// ----
// test1() -> 3
// test2() -> 7

View File

@ -0,0 +1,25 @@
type Int is int16;
using {unsub as -} for Int global;
using {sub as -} for Int;
function sub(Int a, Int b) pure returns (Int) {
return Int.wrap(Int.unwrap(a) - Int.unwrap(b));
}
function unsub(Int a) pure returns (Int) {
return Int.wrap(-Int.unwrap(a));
}
contract C {
function test_sub() public returns (Int) {
return Int.wrap(7) - Int.wrap(2);
}
function test_unsub() public returns (Int) {
return -Int.wrap(4);
}
}
// ----
// test_sub() -> 5
// test_unsub() -> -4

View File

@ -0,0 +1,15 @@
type Int is int16;
using {keccak256 as +} for Int;
function keccak256(Int a, Int b) pure returns (Int) {
return Int.wrap(Int.unwrap(a) + Int.unwrap(b));
}
contract C {
function test() public returns (Int) {
return Int.wrap(3) + Int.wrap(4);
}
}
// ----
// test() -> 7

View File

@ -0,0 +1,30 @@
==== Source: a.sol ====
library L {
type Int is int128;
function add(Int, Int) pure public returns (Int) {
return Int.wrap(7);
}
function sub(Int) pure public returns (Int) {
return Int.wrap(5);
}
}
==== Source: b.sol ====
import "a.sol" as a;
contract C {
using {a.L.add as +} for a.L.Int;
using {a.L.sub as -} for a.L.Int;
function f() pure public returns (a.L.Int) {
return a.L.Int.wrap(0) + a.L.Int.wrap(0);
}
function g() pure public returns (a.L.Int) {
return - a.L.Int.wrap(0);
}
}
// ----
// f() -> 7
// g() -> 5

View File

@ -0,0 +1,26 @@
library L {
type Int is int128;
error DivisionByZero();
modifier nonZero(Int a) {
if (Int.unwrap(a) == 0)
revert("Division by zero");
_;
}
function div(Int a, Int b) pure public nonZero(b) returns (Int) {
return Int.wrap(Int.unwrap(a) / Int.unwrap(b));
}
}
contract C {
using {L.div as /} for L.Int;
function testDiv(L.Int a, L.Int b) pure public returns (L.Int) {
return a / b;
}
}
// ----
// testDiv(int128,int128): 10, 2 -> 5
// testDiv(int128,int128): 10, 0 -> FAILURE, hex"08c379a0", 0x20, 0x10, "Division by zero"

View File

@ -0,0 +1,22 @@
==== Source: a.sol ====
library L {
type Int is int128;
function add(Int, Int) pure public returns (Int) {
return Int.wrap(7);
}
}
==== Source: b.sol ====
import "a.sol" as a;
==== Source: c.sol ====
import "b.sol" as b;
contract C {
using {b.a.L.add as +} for b.a.L.Int;
function f() pure public returns (b.a.L.Int) {
return b.a.L.Int.wrap(0) + b.a.L.Int.wrap(0);
}
}
// ----
// f() -> 7

View File

@ -0,0 +1,26 @@
type SmallInt is int;
type BigInt is int;
using {addSmall as +} for SmallInt;
using {addBig as +} for BigInt;
function addSmall(SmallInt a, SmallInt b) pure returns (SmallInt) {
return SmallInt.wrap(SmallInt.unwrap(a) + SmallInt.unwrap(b));
}
function addBig(BigInt a, BigInt b) pure returns (BigInt) {
return BigInt.wrap(10 * (BigInt.unwrap(a) + BigInt.unwrap(b)));
}
contract C {
function small() public pure returns (SmallInt) {
return SmallInt.wrap(1) + SmallInt.wrap(2);
}
function big() public pure returns (BigInt) {
return BigInt.wrap(3) + BigInt.wrap(4);
}
}
// ----
// small() -> 3
// big() -> 70

View File

@ -0,0 +1,20 @@
type Int is int32;
using {foo as +, foo as -} for Int;
function foo(Int a, Int b) pure returns(Int) {
return Int.wrap(Int.unwrap(a) + Int.unwrap(b));
}
contract C {
function f() pure public returns (Int) {
return Int.wrap(2) + Int.wrap(3);
}
function g() pure public returns (Int) {
return Int.wrap(6) - Int.wrap(1);
}
}
// ----
// f() -> 5
// g() -> 7

View File

@ -0,0 +1,10 @@
type Type is uint;
using {f as +} for Type;
function f(Type, Type) pure returns (Type) {}
Type constant t = Type.wrap(1);
Type constant u = v + t;
Type constant v = u + t;
// ----
// TypeError 8349: (141-146): Initial value for constant variable has to be compile-time constant.
// TypeError 8349: (166-171): Initial value for constant variable has to be compile-time constant.

View File

@ -0,0 +1,17 @@
type X is uint24;
type Y is uint16;
using {addX as +} for X;
using {addY as +} for Y;
function addX(X, X) pure returns (X) {}
function addY(Y, Y) pure returns (Y) { revert(); }
contract C {
function f() public pure {
X.wrap(1) + X.wrap(Y.unwrap(Y.wrap(2) + Y.wrap(3)));
X.wrap(4) + X.wrap(5); // Unreachable
}
}
// ----
// Warning 5740: (293-314): Unreachable code.

View File

@ -0,0 +1,17 @@
type X is uint24;
type Y is uint16;
using {unsubX as -} for X;
using {unsubY as -} for Y;
function unsubX(X) pure returns (X) {}
function unsubY(Y) pure returns (Y) { revert(); }
contract C {
function f() public pure {
-X.wrap(Y.unwrap(-Y.wrap(1)));
-X.wrap(Y.unwrap(Y.wrap(2))); // Unreachable
}
}
// ----
// Warning 5740: (273-301): Unreachable code.

View File

@ -7,4 +7,4 @@ contract test {
}
}
// ----
// TypeError 2271: (79-85): Built-in binary operator == cannot be applied to types struct test.s storage ref and struct test.s storage ref.
// TypeError 2271: (79-85): Built-in binary operator == cannot be applied to types struct test.s storage ref and struct test.s storage ref. No matching user-defined operator found.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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 '+'

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -0,0 +1,6 @@
using {f as +} for L;
function f() {}
library L {}
// ----
// TypeError 1130: (19-20): Invalid use of a library name.

View File

@ -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.

View File

@ -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.

View File

@ -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 '*').

View File

@ -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.

View File

@ -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.

View File

@ -0,0 +1,5 @@
type Int is int16;
using {keccak256 as +} for Int;
// ----
// TypeError 8187: (27-36): Expected function name.

View File

@ -0,0 +1,5 @@
type Int is int16;
using {revert as +} for Int;
// ----
// DeclarationError 7920: (27-33): Identifier not found or not unique.

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -0,0 +1,6 @@
type Int is int128;
library L {
using {L.privateOperator as +} for Int;
function privateOperator(Int, Int) private pure returns (Int) {}
}

View File

@ -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;

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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) {}

View File

@ -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.

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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.

View File

@ -0,0 +1,3 @@
using {as -} for uint;
// ----
// ParserError 2314: (7-9): Expected identifier but got 'as'

View File

@ -0,0 +1,3 @@
using f as - for uint;
// ----
// ParserError 2314: (8-10): Expected 'for' but got 'as'

View File

@ -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 ')'

View File

@ -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'

View File

@ -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: |, &, ^, ~, <<, >>, +, -, *, /, %, **, ==, !=, <, >, <=, >=, !

View File

@ -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 <.

View File

@ -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.

View File

@ -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".

View File

@ -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".

View File

@ -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 /.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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) {}
}

View File

@ -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.

View File

@ -0,0 +1,5 @@
enum E {A, B, C}
function f(E) {}
using {f} for E;

View File

@ -0,0 +1,19 @@
type Int is uint8;
using {
add as +
} for Int;
function add(Int, Int) pure returns (Int) {
return Int.wrap(0);
}
function f() pure {
Int.wrap(0) + Int.wrap(1);
}
function g() {
Int.wrap(0) + Int.wrap(1);
}
// ----
// Warning 2018: (178-225): Function state mutability can be restricted to pure

View File

@ -0,0 +1,17 @@
type Int is uint8;
using {
add as +
} for Int;
function f_view() view {}
function add(Int, Int) view returns (Int) {
f_view();
return Int.wrap(0);
}
function f() view {
Int.wrap(0) + Int.wrap(0);
}

View File

@ -0,0 +1,28 @@
type Int is uint8;
using {
add as +
} for Int;
function f_view() view {}
function add(Int, Int) view returns (Int) {
f_view();
return Int.wrap(0);
}
function f() view {
Int.wrap(0) + Int.wrap(0);
}
function g() {
Int.wrap(0) + Int.wrap(0);
}
function h() pure {
Int.wrap(0) + Int.wrap(0);
}
// ----
// Warning 2018: (220-267): Function state mutability can be restricted to view
// TypeError 2527: (293-318): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".