Extend using-for.

This commit is contained in:
hrkrshnn
2022-03-14 12:33:44 +01:00
committed by chriseth
parent db30f4d495
commit 672951ccc7
55 changed files with 992 additions and 150 deletions
+120 -31
View File
@@ -4,17 +4,51 @@
{
"C":
[
5
13
],
"L":
[
1
4
],
"f":
[
10
]
},
"id": 6,
"id": 14,
"nodeType": "SourceUnit",
"nodes":
[
{
"functionList":
[
{
"function":
{
"id": 1,
"name": "f",
"nodeType": "IdentifierPath",
"referencedDeclaration": 10,
"src": "7:1:1"
}
}
],
"id": 3,
"nodeType": "UsingForDirective",
"src": "0:19:1",
"typeName":
{
"id": 2,
"name": "uint",
"nodeType": "ElementaryTypeName",
"src": "14:4:1",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
}
},
{
"abstract": false,
"baseContracts": [],
@@ -22,19 +56,86 @@
"contractDependencies": [],
"contractKind": "library",
"fullyImplemented": true,
"id": 1,
"id": 4,
"linearizedBaseContracts":
[
1
4
],
"name": "L",
"nameLocation": "8:1:1",
"nameLocation": "28:1:1",
"nodeType": "ContractDefinition",
"nodes": [],
"scope": 6,
"src": "0:12:1",
"scope": 14,
"src": "20:12:1",
"usedErrors": []
},
{
"body":
{
"id": 9,
"nodeType": "Block",
"src": "50:2:1",
"statements": []
},
"id": 10,
"implemented": true,
"kind": "freeFunction",
"modifiers": [],
"name": "f",
"nameLocation": "42:1:1",
"nodeType": "FunctionDefinition",
"parameters":
{
"id": 7,
"nodeType": "ParameterList",
"parameters":
[
{
"constant": false,
"id": 6,
"mutability": "mutable",
"name": "",
"nameLocation": "-1:-1:-1",
"nodeType": "VariableDeclaration",
"scope": 10,
"src": "44:4:1",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName":
{
"id": 5,
"name": "uint",
"nodeType": "ElementaryTypeName",
"src": "44:4:1",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"visibility": "internal"
}
],
"src": "43:6:1"
},
"returnParameters":
{
"id": 8,
"nodeType": "ParameterList",
"parameters": [],
"src": "50:0:1"
},
"scope": 14,
"src": "33:19:1",
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "internal"
},
{
"abstract": false,
"baseContracts": [],
@@ -42,46 +143,34 @@
"contractDependencies": [],
"contractKind": "contract",
"fullyImplemented": true,
"id": 5,
"id": 13,
"linearizedBaseContracts":
[
5
13
],
"name": "C",
"nameLocation": "22:1:1",
"nameLocation": "62:1:1",
"nodeType": "ContractDefinition",
"nodes":
[
{
"id": 4,
"id": 12,
"libraryName":
{
"id": 2,
"id": 11,
"name": "L",
"nodeType": "IdentifierPath",
"referencedDeclaration": 1,
"src": "32:1:1"
"referencedDeclaration": 4,
"src": "72:1:1"
},
"nodeType": "UsingForDirective",
"src": "26:17:1",
"typeName":
{
"id": 3,
"name": "uint",
"nodeType": "ElementaryTypeName",
"src": "38:4:1",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
}
"src": "66:14:1"
}
],
"scope": 6,
"src": "13:32:1",
"scope": 14,
"src": "53:29:1",
"usedErrors": []
}
],
"src": "0:46:1"
"src": "0:83:1"
}
@@ -1,3 +1,6 @@
library L {} contract C { using L for uint; }
using {f} for uint;
library L {}
function f(uint) {}
contract C { using L for *; }
// ----
@@ -1,57 +1,131 @@
{
"absolutePath": "a",
"id": 6,
"id": 14,
"nodeType": "SourceUnit",
"nodes":
[
{
"functionList":
[
{
"function":
{
"id": 1,
"name": "f",
"nodeType": "IdentifierPath",
"src": "7:1:1"
}
}
],
"id": 3,
"nodeType": "UsingForDirective",
"src": "0:19:1",
"typeName":
{
"id": 2,
"name": "uint",
"nodeType": "ElementaryTypeName",
"src": "14:4:1",
"typeDescriptions": {}
}
},
{
"abstract": false,
"baseContracts": [],
"contractDependencies": [],
"contractKind": "library",
"id": 1,
"id": 4,
"name": "L",
"nameLocation": "8:1:1",
"nameLocation": "28:1:1",
"nodeType": "ContractDefinition",
"nodes": [],
"src": "0:12:1",
"src": "20:12:1",
"usedErrors": []
},
{
"body":
{
"id": 9,
"nodeType": "Block",
"src": "50:2:1",
"statements": []
},
"id": 10,
"implemented": true,
"kind": "freeFunction",
"modifiers": [],
"name": "f",
"nameLocation": "42:1:1",
"nodeType": "FunctionDefinition",
"parameters":
{
"id": 7,
"nodeType": "ParameterList",
"parameters":
[
{
"constant": false,
"id": 6,
"mutability": "mutable",
"name": "",
"nameLocation": "-1:-1:-1",
"nodeType": "VariableDeclaration",
"src": "44:4:1",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions": {},
"typeName":
{
"id": 5,
"name": "uint",
"nodeType": "ElementaryTypeName",
"src": "44:4:1",
"typeDescriptions": {}
},
"visibility": "internal"
}
],
"src": "43:6:1"
},
"returnParameters":
{
"id": 8,
"nodeType": "ParameterList",
"parameters": [],
"src": "50:0:1"
},
"src": "33:19:1",
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "internal"
},
{
"abstract": false,
"baseContracts": [],
"contractDependencies": [],
"contractKind": "contract",
"id": 5,
"id": 13,
"name": "C",
"nameLocation": "22:1:1",
"nameLocation": "62:1:1",
"nodeType": "ContractDefinition",
"nodes":
[
{
"id": 4,
"id": 12,
"libraryName":
{
"id": 2,
"id": 11,
"name": "L",
"nodeType": "IdentifierPath",
"src": "32:1:1"
"src": "72:1:1"
},
"nodeType": "UsingForDirective",
"src": "26:17:1",
"typeName":
{
"id": 3,
"name": "uint",
"nodeType": "ElementaryTypeName",
"src": "38:4:1",
"typeDescriptions": {}
}
"src": "66:14:1"
}
],
"src": "13:32:1",
"src": "53:29:1",
"usedErrors": []
}
],
"src": "0:46:1"
"src": "0:83:1"
}
@@ -0,0 +1,19 @@
contract C {
function f(uint[] calldata arr) external returns (uint) {
return arr.sum();
}
}
function sum(uint[] memory arr) returns (uint result) {
for(uint i = 0; i < arr.length; i++) {
result += arr[i];
}
}
using {sum} for uint[];
// ====
// compileViaYul: also
// ----
// f(uint256[]): 0x20, 3, 1, 2, 8 -> 11
@@ -0,0 +1,26 @@
function id(uint x) pure returns (uint) {
return x;
}
function zero(uint) pure returns (uint) {
return 0;
}
contract C {
function f(uint z) pure external returns(uint) {
return z.id();
}
function g(uint z) pure external returns (uint) {
return z.zero();
}
using {id, zero} for uint;
}
// ====
// compileViaYul: also
// ----
// f(uint256): 10 -> 10
// g(uint256): 10 -> 0
// f(uint256): 256 -> 0x0100
// g(uint256): 256 -> 0
@@ -0,0 +1,27 @@
contract C {
function f(uint z) pure external returns(uint) {
return z.id();
}
using {id, zero, zero, id} for uint;
function g(uint z) pure external returns (uint) {
return z.zero();
}
}
function id(uint x) pure returns (uint) {
return x;
}
function zero(uint) pure returns (uint) {
return 0;
}
// ====
// compileViaYul: also
// ----
// f(uint256): 10 -> 10
// g(uint256): 10 -> 0
// f(uint256): 256 -> 0x0100
// g(uint256): 256 -> 0
@@ -0,0 +1,30 @@
using {zero} for uint;
contract C {
using {id} for uint;
function f(uint z) pure external returns(uint) {
return z.id();
}
function g(uint z) pure external returns (uint) {
return z.zero();
}
}
function id(uint x) pure returns (uint) {
return x;
}
function zero(uint) pure returns (uint) {
return 0;
}
// ====
// compileViaYul: also
// ----
// f(uint256): 10 -> 10
// g(uint256): 10 -> 0
// f(uint256): 256 -> 0x0100
// g(uint256): 256 -> 0
@@ -0,0 +1,19 @@
==== Source: A ====
function inc(uint x) pure returns (uint) {
return x + 1;
}
==== Source: B ====
contract C {
function f(uint x) public returns (uint) {
return x.f() + x.inc();
}
}
using {A.inc, f} for uint;
import {inc as f} from "A";
import "A" as A;
// ====
// compileViaYul: also
// ----
// f(uint256): 5 -> 12
// f(uint256): 10 -> 0x16
@@ -0,0 +1,34 @@
==== Source: A ====
library L {
function id(uint x) internal pure returns (uint) {
return x;
}
function one_ext(uint) pure external returns(uint) {
return 1;
}
function empty() pure internal {
}
}
==== Source: B ====
contract C {
using M.L for uint;
function f(uint x) public pure returns (uint) {
return x.id();
}
function g(uint x) public pure returns (uint) {
return x.one_ext();
}
}
import "A" as M;
// ====
// compileViaYul: also
// ----
// library: "A":L
// f(uint256): 5 -> 5
// f(uint256): 10 -> 10
// g(uint256): 5 -> 1
// g(uint256): 10 -> 1
@@ -0,0 +1,26 @@
==== Source: A ====
function f(uint x) pure returns (uint) {
return x + 2;
}
function g(uint x) pure returns (uint) {
return x + 8;
}
==== Source: B ====
import {f as g, g as f} from "A";
==== Source: C ====
contract C {
function test(uint x, uint y) public pure returns (uint, uint) {
return (x.f(), y.g());
}
}
using {M.g, M.f} for uint;
import "B" as M;
// ====
// compileViaYul: also
// ----
// test(uint256,uint256): 1, 1 -> 9, 3
@@ -7,4 +7,4 @@ contract C {
using S for S;
}
// ----
// TypeError 4357: (113-114): Library name expected.
// TypeError 4357: (113-114): Library name expected. If you want to attach a function, use '{...}'.
@@ -7,4 +7,4 @@ interface I {
function g() external;
}
// ----
// TypeError 9088: (60-76): The "using for" directive is not allowed inside interfaces.
// SyntaxError 9088: (60-76): The "using for" directive is not allowed inside interfaces.
@@ -3,4 +3,4 @@ contract C {
using D for uint;
}
// ----
// TypeError 4357: (38-39): Library name expected.
// TypeError 4357: (38-39): Library name expected. If you want to attach a function, use '{...}'.
@@ -7,4 +7,4 @@ library L {
}
}
// ----
// TypeError 4357: (120-121): Library name expected.
// TypeError 4357: (120-121): Library name expected. If you want to attach a function, use '{...}'.
@@ -0,0 +1,19 @@
function id(uint x) pure returns (uint) {
return x;
}
function zero(address) pure returns (address) {
return address(0);
}
contract C {
using * for *;
function f(uint x) pure external returns (uint) {
return x.id();
}
function g(address a) pure external returns (address) {
return a.zero();
}
}
// ----
// ParserError 2314: (156-157): Expected identifier but got '*'
@@ -0,0 +1,22 @@
==== Source: A ====
function id(uint x) pure returns (uint) {
return x;
}
// we check that the effect of this directive is
// limited to this file.
using {id} for uint;
function t() pure {
uint y = 2;
y = y.id();
}
==== Source: B ====
import "A";
function f() pure {
uint y = 2;
y = y.id();
}
// ----
// TypeError 9582: (B:57-61): Member "id" not found or not visible after argument-dependent lookup in uint256.
@@ -0,0 +1,6 @@
function id(uint16 x) pure returns(uint16) {
return x;
}
contract C {
using {id} for uint8;
}
@@ -0,0 +1,8 @@
function id(uint16 x) pure returns(uint16) {
return x;
}
contract C {
using {id} for uint256;
}
// ----
// TypeError 3100: (85-87): The function "id" cannot be bound to the type "uint256" because the type cannot be implicitly converted to the first argument of the function ("uint16").
@@ -0,0 +1,12 @@
function id(int8 x) pure returns(int8) {
return x;
}
function id(uint256 x) pure returns(uint256) {
return x;
}
contract C {
using {id} for uint256;
}
// ----
// DeclarationError 7920: (145-147): Identifier not found or not unique.
@@ -0,0 +1,10 @@
function f(uint8 x) pure returns (uint) {
return x;
}
function f(int8 storage x) pure returns (int) {
return x[0];
}
using {f} for uint8;
using {f} for int;
// ----
// DeclarationError 7920: (132-133): Identifier not found or not unique.
@@ -0,0 +1,9 @@
function f(uint x, uint[] y) pure returns (uint) {
return x;
}
function f(uint x, uint y) pure returns (int) {
return x;
}
using {f} for uint;
// ----
// DeclarationError 7920: (138-139): Identifier not found or not unique.
@@ -0,0 +1,11 @@
function f(uint[] memory x) pure returns (uint) {
return x[0];
}
function g(uint[] storage x) view returns (uint) {
return x[0];
}
function h(uint[] calldata x) pure returns (uint) {
return x[0];
}
using {f, g, h} for uint[];
// ----
@@ -0,0 +1,16 @@
==== Source: A ====
library L {
function id(uint x) pure internal returns (uint) {
return x;
}
}
==== Source: B ====
import {L as M} from "A";
contract C {
using M for uint;
function f(uint x) public pure returns (uint) {
return x.id();
}
}
@@ -0,0 +1,14 @@
library L {
function id_ext(uint x) external returns(uint) {
return x;
}
}
contract C {
using L.id_ext for uint;
function f(uint x) external {
x.id_ext();
}
}
// ----
// DeclarationError 7920: (115-123): Identifier not found or not unique.
@@ -0,0 +1,13 @@
library L {
function id(uint x) internal pure returns(uint) {
return x;
}
}
contract C {
using {L.id} for uint;
function f(uint x) external pure {
x.id();
}
}
// ----
@@ -0,0 +1,12 @@
==== Source: A ====
function id(uint x) pure returns (uint) {
return x;
}
==== Source: B ====
import "A" as M;
contract C {
using M for uint;
}
// ----
// TypeError 4357: (B:40-41): Library name expected. If you want to attach a function, use '{...}'.
@@ -0,0 +1,14 @@
==== Source: A ====
function id(uint x) pure returns (uint) {
return x;
}
==== Source: B ====
import {id as Id} from "A";
contract C {
using { Id } for uint;
function f(uint x) public pure returns (uint) {
return x.Id();
}
}
@@ -0,0 +1,14 @@
==== Source: A ====
function id(uint x) pure returns (uint) {
return x;
}
==== Source: B ====
import "A" as M;
contract C {
using {M.id} for uint;
function f(uint x) public pure returns (uint) {
return x.id();
}
}
@@ -0,0 +1,13 @@
==== Source: A ====
function id(uint x) pure returns (uint) {
return x;
}
==== Source: B ====
import "A" as M;
contract C {
using { id } for uint;
}
// ----
// DeclarationError 7920: (B:43-45): Identifier not found or not unique.
@@ -0,0 +1,13 @@
contract C {
function f(uint) external {
}
}
interface I {
function f(uint) external;
}
contract Test {
using C for uint;
}
// ----
// TypeError 4357: (127-128): Library name expected. If you want to attach a function, use '{...}'.
@@ -0,0 +1,5 @@
contract C {
using {} for uint;
}
// ----
// ParserError 2314: (24-25): Expected identifier but got '}'
@@ -0,0 +1,3 @@
using {} for uint;
// ----
// ParserError 2314: (7-8): Expected identifier but got '}'
@@ -0,0 +1,7 @@
function id(uint x) pure returns (uint) {
return x;
}
using {id} for *;
// ----
// SyntaxError 8118: (59-76): The type has to be specified explicitly at file level (cannot use '*').
@@ -0,0 +1,16 @@
function id(uint x) pure returns (uint) {
return x;
}
function zero(uint) pure returns (uint) {
return 0;
}
using {id} for uint;
contract C {
using {zero} for uint;
function g(uint z) pure external {
z.zero();
z.id();
}
}
@@ -0,0 +1,7 @@
function one() pure returns(uint) {
return 1;
}
using {one} for uint;
// ----
// TypeError 4731: (60-63): The function "one" does not have any parameters, and therefore cannot be bound to the type "uint256".
@@ -0,0 +1,7 @@
function f(uint) {}
contract C {
using {f} for *;
}
// ----
// SyntaxError 3349: (38-54): The type has to be specified explicitly when attaching specific functions.
@@ -0,0 +1,3 @@
using * for uint;
// ----
// ParserError 2314: (6-7): Expected identifier but got '*'
@@ -0,0 +1,5 @@
contract C {
using * for uint;
}
// ----
// ParserError 2314: (23-24): Expected identifier but got '*'
@@ -0,0 +1,4 @@
library L { }
using L for *;
// ----
// SyntaxError 8118: (14-28): The type has to be specified explicitly at file level (cannot use '*').
@@ -0,0 +1,3 @@
library L { }
using L for uint;
// ----
@@ -0,0 +1,9 @@
contract C {
using {f, g} for uint;
function f(uint) internal { }
function g(uint) public { }
}
// ----
// TypeError 4167: (24-25): Only file-level functions and library functions can be bound to a type in a "using" statement
// TypeError 4167: (27-28): Only file-level functions and library functions can be bound to a type in a "using" statement
@@ -0,0 +1,6 @@
contract C {
function() internal pure x;
using {x} for uint;
}
// ----
// TypeError 8187: (56-57): Expected function name.