Merge pull request #12288 from ethereum/exportUsing

Using global
This commit is contained in:
chriseth
2022-03-14 18:57:26 +01:00
committed by GitHub
26 changed files with 307 additions and 6 deletions
@@ -33,6 +33,7 @@
}
}
],
"global": false,
"id": 3,
"nodeType": "UsingForDirective",
"src": "0:19:1",
@@ -154,6 +155,7 @@
"nodes":
[
{
"global": false,
"id": 12,
"libraryName":
{
@@ -17,6 +17,7 @@
}
}
],
"global": false,
"id": 3,
"nodeType": "UsingForDirective",
"src": "0:19:1",
@@ -111,6 +112,7 @@
"nodes":
[
{
"global": false,
"id": 12,
"libraryName":
{
@@ -0,0 +1,25 @@
==== Source: A ====
import {T as U} from "A";
import "A" as X;
type T is uint;
function f(T x) pure returns (T) { return T.wrap(T.unwrap(x) + 1); }
function g(T x) pure returns (uint) { return T.unwrap(x) + 10; }
using { f } for X.X.U global;
using { g } for T global;
function cr() pure returns (T) {}
==== Source: B ====
import { cr } from "A";
contract C {
function f() public returns (uint) {
return cr().f().g();
}
}
// ====
// compileViaYul: also
// ----
// f() -> 11
@@ -0,0 +1,20 @@
==== Source: A ====
type global is uint;
using { f } for global global;
function f(global x) pure returns (global) { return global.wrap(global.unwrap(x) + 1); }
==== Source: B ====
import { global } from "A";
function g(global x) pure returns (global) { return global.wrap(global.unwrap(x) + 10); }
contract C {
using { g } for global;
function f(global r) public pure returns (global) {
return r.f().g();
}
}
// ====
// compileViaYul: also
// ----
// f(uint256): 100 -> 111
@@ -0,0 +1,45 @@
==== Source: A ====
type T is uint;
using L for T global;
library L {
function inc(T x) internal pure returns (T) {
return T.wrap(T.unwrap(x) + 1);
}
function dec(T x) external pure returns (T) {
return T.wrap(T.unwrap(x) - 1);
}
}
using {unwrap} for T global;
function unwrap(T x) pure returns (uint) {
return T.unwrap(x);
}
==== Source: B ====
contract C {
function f() public pure returns (T r1) {
r1 = r1.inc().inc();
}
}
import {T} from "A";
==== Source: C ====
import {C} from "B";
contract D {
function test() public returns (uint) {
C c = new C();
// This tests that bound functions are available
// even if the type is not available by name.
// This is a regular function call, a
// public and an internal library call
// and a free function call.
return c.f().inc().inc().dec().unwrap();
}
}
// ====
// compileViaYul: also
// ----
// library: "A":L
// test() -> 3
// gas legacy: 130369
@@ -0,0 +1,27 @@
==== Source: A ====
type T is uint;
using L for T global;
library L {
function inc(T x) internal pure returns (T) {
return T.wrap(T.unwrap(x) + 1);
}
function dec(T x) external pure returns (T) {
return T.wrap(T.unwrap(x) - 1);
}
}
==== Source: B ====
contract C {
function f() public pure returns (T r1, T r2) {
r1 = r1.inc().inc();
r2 = r1.dec();
}
}
import {T} from "A";
// ====
// compileViaYul: also
// ----
// library: "A":L
// f() -> 2, 1
@@ -0,0 +1,21 @@
==== Source: A ====
using {f} for S global;
struct S { uint x; }
function gen() pure returns (S memory) {}
function f(S memory _x) pure returns (uint) { return _x.x; }
==== Source: B ====
contract C {
using {fun} for S;
// Adds the same function again with the same name,
// so it's fine.
using {A.f} for S;
function test() pure public
{
uint p = g().f();
p = g().fun();
}
}
import {gen as g, f as fun, S} from "A";
import "A" as A;
// ----
@@ -0,0 +1,5 @@
using {f} for * global;
function f(uint) pure{}
// ----
// SyntaxError 8118: (0-23): The type has to be specified explicitly at file level (cannot use '*').
// SyntaxError 2854: (0-23): Can only globally bind functions to specific types.
@@ -0,0 +1,4 @@
using {f} for uint global;
function f(uint) pure{}
// ----
// TypeError 8841: (0-26): Can only use "global" with user-defined types.
@@ -0,0 +1,7 @@
using {f} for L.S global;
function f(L.S memory) pure{}
library L {
struct S { uint x; }
}
// ----
// TypeError 4117: (0-25): Can only use "global" with types defined in the same source unit at file level.
@@ -0,0 +1,14 @@
==== Source: A ====
struct S { uint x; }
==== Source: B ====
using {f} for S global;
using {f} for A.S global;
function f(S memory) pure{}
import {S} from "A";
import "A" as A;
// ----
// TypeError 4117: (B:1-24): Can only use "global" with types defined in the same source unit at file level.
// TypeError 4117: (B:25-50): Can only use "global" with types defined in the same source unit at file level.
@@ -0,0 +1,7 @@
contract C {
using {f} for uint global;
}
function f(uint) pure{}
// ----
// SyntaxError 3367: (17-43): "global" can only be used at file level.
// TypeError 8841: (17-43): Can only use "global" with user-defined types.
@@ -0,0 +1,21 @@
==== Source: A ====
using {f} for S global;
struct S { uint x; }
function gen() pure returns (S memory) {}
function f(S memory _x) pure returns (uint) { return _x.x; }
function f1(S memory _x) pure returns (uint) { return _x.x + 1; }
==== Source: B ====
contract C {
// Here, f points to f1, so we end up with two different functions
// bound as S.f
using {f} for S;
function test() pure public
{
uint p = g().f();
}
}
import {gen as g, f1 as f, S} from "A";
import "A" as A;
// ----
// TypeError 6675: (B:181-186): Member "f" not unique after argument-dependent lookup in struct S memory.
@@ -0,0 +1,17 @@
==== Source: A ====
using {f} for S global;
using {g} for S;
struct S { uint x; }
function gen() pure returns (S memory) {}
function f(S memory _x) pure { _x.g(); }
function g(S memory _x) pure { }
==== Source: B ====
import "A";
function test() pure
{
gen().f();
gen().g();
}
// ----
// TypeError 9582: (B:54-61): Member "g" not found or not visible after argument-dependent lookup in struct S memory.
@@ -0,0 +1,15 @@
==== Source: A ====
using {f} for S global;
// this should not conflict
using {f} for S;
struct S { uint x; }
function gen() pure returns (S memory) {}
function f(S memory _x) pure returns (uint) { return _x.x; }
==== Source: B ====
function test() pure
{
uint p = g().f();
p++;
}
import {gen as g} from "A";
// ----