Tests, Docs and Changelog

This commit is contained in:
Harikrishnan Mulackal 2020-06-07 21:30:52 +05:30
parent d41eaeba56
commit eeadb5a6b5
48 changed files with 215 additions and 124 deletions

View File

@ -8,6 +8,8 @@ Breaking changes:
* Parser: NatSpec comments on variables are only allowed for public state variables.
* Type Checker: Disallow shifts by signed types.
* Type Checker: Exponentiation and shifts of literals by non-literals will always use ``uint256`` or ``int256`` as a type.
* Type Checker: Disallow structs and arrays in memory or calldata if they contain nested mappings.
* Type Checker: Disallow assignments to state variables that contain nested mappings.
Language Features:
* Yul: Disallow EVM instruction `pc()`.

View File

@ -26,6 +26,7 @@ are allowed for state variables, as storage reference types
in functions, or as parameters for library functions.
They cannot be used as parameters or return parameters
of contract functions that are publicly visible.
These restrictions are also true for arrays and structs that contain mappings.
You can mark state variables of mapping type as ``public`` and Solidity creates a
:ref:`getter <visibility-and-getters>` for you. The ``_KeyType`` becomes a parameter for the getter.

View File

@ -488,12 +488,11 @@ shown in the following example:
function newCampaign(address payable beneficiary, uint goal) public returns (uint campaignID) {
campaignID = numCampaigns++; // campaignID is return variable
// Creates new struct in memory and copies it to storage.
// We leave out the mapping type, because it is not valid in memory.
// If structs are copied (even from storage to storage),
// types that are not valid outside of storage (ex. mappings and array of mappings)
// are always omitted, because they cannot be enumerated.
campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0);
// We cannot use "campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0)"
// because the RHS creates a memory-struct "Campaign" that contains a mapping.
Campaign storage c = campaigns[campaignID];
c.beneficiary = beneficiary;
c.fundingGoal = goal;
}
function contribute(uint campaignID) public payable {

View File

@ -3465,12 +3465,12 @@ BOOST_AUTO_TEST_CASE(array_copy_calldata_storage)
ABI_CHECK(callContractFunction("retrieve()"), encodeArgs(9, 28, 9, 28, 4, 3, 32));
}
BOOST_AUTO_TEST_CASE(array_copy_including_mapping)
BOOST_AUTO_TEST_CASE(array_copy_including_array)
{
char const* sourceCode = R"(
contract c {
mapping(uint=>uint)[90][] large;
mapping(uint=>uint)[3][] small;
uint[3][90][] large;
uint[3][3][] small;
function test() public returns (uint r) {
for (uint i = 0; i < 7; i++) {
large.push();
@ -3505,9 +3505,8 @@ BOOST_AUTO_TEST_CASE(array_copy_including_mapping)
}
)";
compileAndRun(sourceCode);
ABI_CHECK(callContractFunction("test()"), encodeArgs(0x02000200));
// storage is not empty because we cannot delete the mappings
BOOST_CHECK(!storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("test()"), encodeArgs(0x02000202));
BOOST_CHECK(storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("clear()"), encodeArgs(0, 0));
BOOST_CHECK(storageEmpty(m_contractAddress));
}

View File

@ -1,50 +0,0 @@
contract Test {
struct A {
mapping(uint=>uint) m;
}
struct B {
mapping(uint=>uint) m;
uint x;
}
struct C {
mapping(uint=>uint)[] ma;
}
struct D {
A[] a;
}
A storageA;
B storageB;
C storageC;
D storageD;
constructor() public {
storageA.m[1] = 2;
storageB.m[3] = 4;
storageB.x = 5;
for (uint i = 0; i < 6; i++)
storageC.ma.push();
for (uint i = 0; i < 7; i++)
storageD.a.push();
}
function run() public returns (uint, uint, uint, uint, uint, uint) {
A memory memoryA = A();
B memory memoryB = B(42);
C memory memoryC = C();
D memory memoryD1 = D(new A[](999));
D memory memoryD2 = storageD;
storageA = memoryA;
storageB = memoryB;
storageC = memoryC;
// the following line does not compile because unimplemented
// storageD = memoryD1;
return (
storageA.m[1],
storageB.x,
memoryB.x,
storageC.ma.length,
memoryD1.a.length,
memoryD2.a.length
);
}
}
// ----
// run() -> 2, 42, 42, 6, 999, 7

View File

@ -1,24 +0,0 @@
contract Test {
struct S {
uint8 a;
mapping(uint256 => uint256) b;
uint8 c;
}
S s;
function f() public returns (uint256) {
S memory x;
if (x.a != 0 || x.c != 0) return 1;
x.a = 4;
x.c = 5;
s = x;
if (s.a != 4 || s.c != 5) return 2;
x = S(2, 3);
if (x.a != 2 || x.c != 3) return 3;
x = s;
if (s.a != 4 || s.c != 5) return 4;
}
}
// ----
// f() -> 0

View File

@ -5,7 +5,6 @@ contract c {
}
struct Struct {
uint256 a;
mapping(uint256 => Struct) b;
Nested nested;
uint256 c;
}

View File

@ -0,0 +1,8 @@
pragma experimental ABIEncoderV2;
contract Test {
function f(mapping(uint => uint)[] memory x) public pure {}
}
// ----
// TypeError 4103: (66-98): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (66-98): Type mapping(uint256 => uint256)[] is only valid in storage because it contains a (nested) mapping.

View File

@ -0,0 +1,6 @@
pragma experimental ABIEncoderV2;
library L {
function f(mapping(uint => uint)[2] memory a) external pure returns (mapping(uint => uint)[2] memory) {}
}
// ----
// TypeError 4061: (61-94): Type mapping(uint256 => uint256)[2] is only valid in storage because it contains a (nested) mapping.

View File

@ -5,7 +5,6 @@ contract C {
struct S { uint256 [ ] [ 0.425781 ether ] s1 ;
uint [ 2 ** 0xFF ] [ 2 ** 0x42 ] s2 ;
X s3 ;
mapping ( uint => address payable ) c ;
uint [ 9 hours ** 16 ] d ;
string s ;
}
@ -14,4 +13,4 @@ contract C {
}
}
// ----
// TypeError 1534: (530-540): Type too large for memory.
// TypeError 1534: (474-484): Type too large for memory.

View File

@ -11,3 +11,4 @@ contract Test {
}
// ----
// DeclarationError 2333: (157-198): Identifier already declared.
// TypeError 4061: (268-300): Type struct Test.RecursiveStruct[1] is only valid in storage because it contains a (nested) mapping.

View File

@ -4,4 +4,4 @@ library L {
}
}
// ----
// TypeError 9214: (108-109): Mappings cannot be assigned to.
// TypeError 9214: (108-109): Types in storage containing (nested) mappings cannot be assigned to.

View File

@ -9,4 +9,4 @@ contract Test {
}
}
// ----
// TypeError 4994: (208-218): Member "b1" is not available in struct Test.S1 memory outside of storage.
// TypeError 4061: (161-172): Type struct Test.S2 is only valid in storage because it contains a (nested) mapping.

View File

@ -3,8 +3,7 @@ contract Test {
S s;
function f() public {
S memory x;
x.b[1];
}
}
// ----
// TypeError 4994: (118-121): Member "b" is not available in struct Test.S memory outside of storage.
// TypeError 4061: (104-114): Type struct Test.S is only valid in storage because it contains a (nested) mapping.

View File

@ -9,3 +9,4 @@ contract test {
}
}
// ----
// TypeError 9214: (152-156): Types in storage containing (nested) mappings cannot be assigned to.

View File

@ -0,0 +1,9 @@
pragma experimental ABIEncoderV2;
contract C {
struct S { mapping(uint => uint) a; }
function f(S memory) public {}
}
// ----
// TypeError 4103: (105-113): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (105-113): Type struct C.S is only valid in storage because it contains a (nested) mapping.

View File

@ -5,4 +5,5 @@ contract C {
function f(S memory) public {}
}
// ----
// TypeError 4103: (105-113): Only libraries are allowed to use the mapping type in public or external functions.
// TypeError 4103: (105-113): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (105-113): Type struct C.S is only valid in storage because it contains a (nested) mapping.

View File

@ -0,0 +1,10 @@
pragma experimental ABIEncoderV2;
contract C {
struct T { mapping(uint => uint) a; }
struct S { T[][2] b; }
function f(S memory) public {}
}
// ----
// TypeError 4103: (132-140): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (132-140): Type struct C.S is only valid in storage because it contains a (nested) mapping.

View File

@ -6,4 +6,5 @@ contract C {
function f(S memory) public {}
}
// ----
// TypeError 4103: (132-140): Only libraries are allowed to use the mapping type in public or external functions.
// TypeError 4103: (132-140): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (132-140): Type struct C.S is only valid in storage because it contains a (nested) mapping.

View File

@ -4,4 +4,4 @@ contract C {
}
}
// ----
// TypeError 1164: (94-117): Type cannot live outside storage.
// TypeError 1164: (94-117): Array containing a (nested) mapping cannot be constructed in memory.

View File

@ -2,6 +2,6 @@ contract c {
event e(uint indexed a, mapping(uint => uint) indexed b, bool indexed c, uint indexed d, uint indexed e) anonymous;
}
// ----
// TypeError 3448: (41-72): Type is required to live outside storage.
// TypeError 3448: (41-72): Type containing a (nested) mapping is not allowed as event parameter type.
// TypeError 3417: (41-72): Internal or recursive type is not allowed as event parameter type.
// TypeError 8598: (17-132): More than 4 indexed arguments for anonymous event.

View File

@ -6,4 +6,4 @@ contract C {
}
}
// ----
// TypeError 9755: (117-126): Wrong argument count for struct constructor: 1 arguments given but expected 2. Members that have to be skipped in memory: c
// TypeError 9515: (117-126): Struct containing a (nested) mapping cannot be constructed.

View File

@ -0,0 +1,15 @@
pragma experimental ABIEncoderV2;
contract test {
struct S {
T t;
}
struct T {
mapping (uint => uint) k;
}
function f(S calldata b) external {
}
}
// ----
// TypeError 4103: (155-167): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (155-167): Type struct test.S is only valid in storage because it contains a (nested) mapping.

View File

@ -1,3 +1,5 @@
pragma experimental ABIEncoderV2;
contract Test {
struct MyStructName {
address addr;
@ -7,4 +9,4 @@ contract Test {
function f(MyStructName memory s) public {}
}
// ----
// TypeError 4103: (112-133): Recursive type not allowed for public or external contract functions.
// TypeError 4103: (147-168): Recursive type not allowed for public or external contract functions.

View File

@ -1,7 +1,9 @@
pragma experimental ABIEncoderV2;
contract C {
struct S { uint a; S[] sub; }
function f() public pure returns (uint, S memory) {
}
}
// ----
// TypeError 4103: (91-99): Recursive type not allowed for public or external contract functions.
// TypeError 4103: (126-134): Recursive type not allowed for public or external contract functions.

View File

@ -1,7 +1,9 @@
pragma experimental ABIEncoderV2;
contract C {
struct S { uint a; S[2][] sub; }
function f() public pure returns (uint, S memory) {
}
}
// ----
// TypeError 4103: (94-102): Recursive type not allowed for public or external contract functions.
// TypeError 4103: (129-137): Recursive type not allowed for public or external contract functions.

View File

@ -1,3 +1,5 @@
pragma experimental ABIEncoderV2;
contract C {
struct S { uint a; S[][][] sub; }
struct T { S s; }
@ -5,4 +7,4 @@ contract C {
}
}
// ----
// TypeError 4103: (119-129): Recursive type not allowed for public or external contract functions.
// TypeError 4103: (154-164): Recursive type not allowed for public or external contract functions.

View File

@ -7,4 +7,4 @@ contract D {
}
}
// ----
// TypeError 9214: (160-161): Mappings cannot be assigned to.
// TypeError 9214: (160-161): Types in storage containing (nested) mappings cannot be assigned to.

View File

@ -20,8 +20,18 @@ contract G {
uint x = 1;
mapping (uint => uint) b = x;
}
contract H {
struct S {mapping (uint => uint) a;}
S x;
S y = x;
S z = z;
}
// ----
// TypeError 6280: (17-67): Mappings cannot be assigned to.
// TypeError 6280: (120-148): Mappings cannot be assigned to.
// TypeError 9214: (263-264): Mappings cannot be assigned to.
// TypeError 6280: (312-340): Mappings cannot be assigned to.
// TypeError 6280: (17-67): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 6280: (120-148): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 9214: (263-264): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 6280: (312-340): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 6280: (407-414): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 6280: (417-424): Types in storage containing (nested) mappings cannot be assigned to.

View File

@ -8,7 +8,7 @@ contract test {
}
}
// ----
// TypeError 9214: (126-129): Mappings cannot be assigned to.
// TypeError 9214: (144-147): Mappings cannot be assigned to.
// TypeError 9214: (163-166): Mappings cannot be assigned to.
// TypeError 9214: (168-171): Mappings cannot be assigned to.
// TypeError 9214: (126-129): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 9214: (144-147): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 9214: (163-166): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 9214: (168-171): Types in storage containing (nested) mappings cannot be assigned to.

View File

@ -11,7 +11,7 @@ contract test {
}
}
// ----
// TypeError 9214: (172-180): Mappings cannot be assigned to.
// TypeError 9214: (195-203): Mappings cannot be assigned to.
// TypeError 9214: (219-227): Mappings cannot be assigned to.
// TypeError 9214: (229-237): Mappings cannot be assigned to.
// TypeError 9214: (172-180): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 9214: (195-203): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 9214: (219-227): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 9214: (229-237): Types in storage containing (nested) mappings cannot be assigned to.

View File

@ -0,0 +1,6 @@
contract test {
function f(mapping(uint => uint)[2] memory b) internal {
}
}
// ----
// TypeError 4061: (31-64): Type mapping(uint256 => uint256)[2] is only valid in storage because it contains a (nested) mapping.

View File

@ -0,0 +1,13 @@
library Set {
struct Data { mapping(uint => bool) flags; }
function insert(Data storage self, uint value)
public
returns (bool)
{
if (self.flags[value])
return false; // already there
self.flags[value] = true;
return true;
}
}

View File

@ -3,4 +3,3 @@ library L {
}
}
// ----
// TypeError 3312: (27-58): Type is required to live outside storage.

View File

@ -3,4 +3,3 @@ library L {
}
}
// ----
// TypeError 3312: (27-58): Type is required to live outside storage.

View File

@ -0,0 +1,7 @@
pragma experimental ABIEncoderV2;
library L {
struct S { mapping(uint => uint) m; }
function f(S memory a) external pure returns (S memory) {}
}
// ----
// TypeError 4061: (103-113): Type struct L.S is only valid in storage because it contains a (nested) mapping.

View File

@ -0,0 +1,6 @@
library Test {
struct Nested { mapping(uint => uint)[2][] a; uint y; }
struct X { Nested n; }
function f(X storage x) external {}
}
// ----

View File

@ -2,5 +2,5 @@ contract c {
function f1(mapping(uint => uint)[] calldata) pure external {}
}
// ----
// TypeError 3312: (29-61): Type is required to live outside storage.
// TypeError 4103: (29-61): Only libraries are allowed to use the mapping type in public or external functions.
// TypeError 4103: (29-61): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (29-61): Type mapping(uint256 => uint256)[] is only valid in storage because it contains a (nested) mapping.

View File

@ -2,5 +2,5 @@ contract c {
function f1(mapping(uint => uint) calldata) pure external returns (mapping(uint => uint) memory) {}
}
// ----
// TypeError 3442: (29-59): Mapping types can only have a data location of "storage" and thus only be parameters or return variables for internal or library functions.
// TypeError 3442: (84-112): Mapping types can only have a data location of "storage" and thus only be parameters or return variables for internal or library functions.
// TypeError 4103: (29-59): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (29-59): Type mapping(uint256 => uint256) is only valid in storage because it contains a (nested) mapping.

View File

@ -3,4 +3,4 @@ contract c {
function f5(mapping(uint => uint) memory) pure internal {}
}
// ----
// TypeError 5380: (93-121): Mapping types can only have a data location of "storage".
// TypeError 4061: (93-121): Type mapping(uint256 => uint256) is only valid in storage because it contains a (nested) mapping.

View File

@ -2,4 +2,5 @@ contract c {
function f3(mapping(uint => uint) memory) view public {}
}
// ----
// TypeError 3442: (29-57): Mapping types can only have a data location of "storage" and thus only be parameters or return variables for internal or library functions.
// TypeError 4103: (29-57): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (29-57): Type mapping(uint256 => uint256) is only valid in storage because it contains a (nested) mapping.

View File

@ -0,0 +1,12 @@
pragma experimental ABIEncoderV2;
contract test {
struct S {
mapping (uint => uint) s;
}
function f(S calldata b) external {
}
}
// ----
// TypeError 4103: (121-133): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (121-133): Type struct test.S is only valid in storage because it contains a (nested) mapping.

View File

@ -3,4 +3,5 @@ contract C {
}
}
// ----
// TypeError 3442: (51-79): Mapping types can only have a data location of "storage" and thus only be parameters or return variables for internal or library functions.
// TypeError 4103: (51-79): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (51-79): Type mapping(uint256 => uint256) is only valid in storage because it contains a (nested) mapping.

View File

@ -0,0 +1,8 @@
pragma experimental ABIEncoderV2;
contract C {
struct S { mapping(uint => uint) a; }
function f(S memory) public {}
}
// ----
// TypeError 4103: (104-112): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (104-112): Type struct C.S is only valid in storage because it contains a (nested) mapping.

View File

@ -0,0 +1,10 @@
pragma experimental ABIEncoderV2;
contract C {
struct S { mapping(uint => uint) a; }
struct T { S s; }
struct U { T t; }
function f(U memory) public {}
}
// ----
// TypeError 4103: (148-156): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (148-156): Type struct C.U is only valid in storage because it contains a (nested) mapping.

View File

@ -0,0 +1,20 @@
contract Test {
struct S {
T[] t;
}
struct T {
U[] u;
}
struct U {
S[] s;
mapping (uint => S) map;
}
function f() public {
S memory s;
}
}
// ----
// TypeError 4061: (143-153): Type struct Test.S is only valid in storage because it contains a (nested) mapping.

View File

@ -0,0 +1,15 @@
contract Test {
struct S {
uint8 a;
mapping(uint256 => uint256) b;
uint8 c;
}
S s;
function f() public returns (uint256) {
S memory x;
}
}
// ----
// TypeError 4061: (172-182): Type struct Test.S is only valid in storage because it contains a (nested) mapping.