diff --git a/Changelog.md b/Changelog.md index 46cef7a77..1371af1f8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -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()`. diff --git a/docs/types/mapping-types.rst b/docs/types/mapping-types.rst index 333848619..ed27d0508 100644 --- a/docs/types/mapping-types.rst +++ b/docs/types/mapping-types.rst @@ -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 ` for you. The ``_KeyType`` becomes a parameter for the getter. diff --git a/docs/types/reference-types.rst b/docs/types/reference-types.rst index 49eed437f..e26ee0405 100644 --- a/docs/types/reference-types.rst +++ b/docs/types/reference-types.rst @@ -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 { diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 65becac37..2d3e4f762 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -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)); } diff --git a/test/libsolidity/semanticTests/structs/conversion/assignment_ignore_mapping.sol b/test/libsolidity/semanticTests/structs/conversion/assignment_ignore_mapping.sol deleted file mode 100644 index dd3bceb28..000000000 --- a/test/libsolidity/semanticTests/structs/conversion/assignment_ignore_mapping.sol +++ /dev/null @@ -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 diff --git a/test/libsolidity/semanticTests/structs/memory_structs_with_mappings.sol b/test/libsolidity/semanticTests/structs/memory_structs_with_mappings.sol deleted file mode 100644 index 3aaa354f8..000000000 --- a/test/libsolidity/semanticTests/structs/memory_structs_with_mappings.sol +++ /dev/null @@ -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 diff --git a/test/libsolidity/semanticTests/structs/struct_copy.sol b/test/libsolidity/semanticTests/structs/struct_copy.sol index f6c35f7da..2849c16bc 100644 --- a/test/libsolidity/semanticTests/structs/struct_copy.sol +++ b/test/libsolidity/semanticTests/structs/struct_copy.sol @@ -5,7 +5,6 @@ contract c { } struct Struct { uint256 a; - mapping(uint256 => Struct) b; Nested nested; uint256 c; } diff --git a/test/libsolidity/syntaxTests/array/function_mapping.sol b/test/libsolidity/syntaxTests/array/function_mapping.sol new file mode 100644 index 000000000..934c7ebd8 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/function_mapping.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/array/function_mapping_library.sol b/test/libsolidity/syntaxTests/array/function_mapping_library.sol new file mode 100644 index 000000000..fb709292a --- /dev/null +++ b/test/libsolidity/syntaxTests/array/function_mapping_library.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/iceRegressionTests/large_array_in_memory_struct.sol b/test/libsolidity/syntaxTests/iceRegressionTests/large_array_in_memory_struct.sol index 7cf12b8c4..84be465fa 100644 --- a/test/libsolidity/syntaxTests/iceRegressionTests/large_array_in_memory_struct.sol +++ b/test/libsolidity/syntaxTests/iceRegressionTests/large_array_in_memory_struct.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/iceRegressionTests/recursive_struct_memory.sol b/test/libsolidity/syntaxTests/iceRegressionTests/recursive_struct_memory.sol index aa79246c4..892cfdd8d 100644 --- a/test/libsolidity/syntaxTests/iceRegressionTests/recursive_struct_memory.sol +++ b/test/libsolidity/syntaxTests/iceRegressionTests/recursive_struct_memory.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/lvalues/library_mapping.sol b/test/libsolidity/syntaxTests/lvalues/library_mapping.sol index 2a1fe1fd8..2c774f55c 100644 --- a/test/libsolidity/syntaxTests/lvalues/library_mapping.sol +++ b/test/libsolidity/syntaxTests/lvalues/library_mapping.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/memberLookup/memory_structs_with_mapping_array_struct_array.sol b/test/libsolidity/syntaxTests/memberLookup/memory_structs_with_mapping_array_struct_array.sol index e9e1f7a06..164d32ff0 100644 --- a/test/libsolidity/syntaxTests/memberLookup/memory_structs_with_mapping_array_struct_array.sol +++ b/test/libsolidity/syntaxTests/memberLookup/memory_structs_with_mapping_array_struct_array.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/memberLookup/memory_structs_with_mappings.sol b/test/libsolidity/syntaxTests/memberLookup/memory_structs_with_mappings.sol index 594c881b7..fd510ed17 100644 --- a/test/libsolidity/syntaxTests/memberLookup/memory_structs_with_mappings.sol +++ b/test/libsolidity/syntaxTests/memberLookup/memory_structs_with_mappings.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/017_assignment_to_struct.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/017_assignment_to_struct.sol index 6fbd09aea..a1fed9967 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/017_assignment_to_struct.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/017_assignment_to_struct.sol @@ -9,3 +9,4 @@ contract test { } } // ---- +// TypeError 9214: (152-156): Types in storage containing (nested) mappings cannot be assigned to. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/041_functions_with_stucts_of_non_external_types_in_interface.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/041_functions_with_structs_of_non_external_types_in_interface.sol similarity index 100% rename from test/libsolidity/syntaxTests/nameAndTypeResolution/041_functions_with_stucts_of_non_external_types_in_interface.sol rename to test/libsolidity/syntaxTests/nameAndTypeResolution/041_functions_with_structs_of_non_external_types_in_interface.sol diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/042_functions_with_structs_of_non_external_types_in_interface_2.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/042_functions_with_structs_of_non_external_types_in_interface_2.sol new file mode 100644 index 000000000..541dd0a04 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/042_functions_with_structs_of_non_external_types_in_interface_2.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/042_functions_with_stucts_of_non_external_types_in_interface_2.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/042_functions_with_stucts_of_non_external_types_in_interface_2.sol index 0254a1928..541dd0a04 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/042_functions_with_stucts_of_non_external_types_in_interface_2.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/042_functions_with_stucts_of_non_external_types_in_interface_2.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/043_functions_with_structs_of_non_external_types_in_interface_nested.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/043_functions_with_structs_of_non_external_types_in_interface_nested.sol new file mode 100644 index 000000000..d2c96d4bc --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/043_functions_with_structs_of_non_external_types_in_interface_nested.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/043_functions_with_stucts_of_non_external_types_in_interface_nested.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/043_functions_with_stucts_of_non_external_types_in_interface_nested.sol index c36e4ac0e..d2c96d4bc 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/043_functions_with_stucts_of_non_external_types_in_interface_nested.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/043_functions_with_stucts_of_non_external_types_in_interface_nested.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/264_mapping_in_memory_array.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/264_mapping_in_memory_array.sol index 1102f6ecd..d561bd29e 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/264_mapping_in_memory_array.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/264_mapping_in_memory_array.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/587_event_param_type_outside_storage.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/587_event_param_type_outside_storage.sol index b15dbc8df..483bfab21 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/587_event_param_type_outside_storage.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/587_event_param_type_outside_storage.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/invalidArgs/creating_struct_members_skipped.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/invalidArgs/creating_struct_members_skipped.sol index 08714f500..74764ed30 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/invalidArgs/creating_struct_members_skipped.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/invalidArgs/creating_struct_members_skipped.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/structs/calldata_struct_mapping_function.sol b/test/libsolidity/syntaxTests/structs/calldata_struct_mapping_function.sol new file mode 100644 index 000000000..398c52701 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/calldata_struct_mapping_function.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/structs/recursion/recursive_struct_as_contract_function_parameter.sol b/test/libsolidity/syntaxTests/structs/recursion/recursive_struct_as_contract_function_parameter.sol index 7f4c0e014..f0a3de401 100644 --- a/test/libsolidity/syntaxTests/structs/recursion/recursive_struct_as_contract_function_parameter.sol +++ b/test/libsolidity/syntaxTests/structs/recursion/recursive_struct_as_contract_function_parameter.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs.sol b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs.sol index 680c8b8a9..15fca7d71 100644 --- a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs.sol +++ b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs2.sol b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs2.sol index 085d333d3..a5b1507d3 100644 --- a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs2.sol +++ b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs2.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs3.sol b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs3.sol index 4e32d57ec..fa9eebb9b 100644 --- a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs3.sol +++ b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs3.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/types/mapping/assignment_local_err.sol b/test/libsolidity/syntaxTests/types/mapping/assignment_local_err.sol index b353a521a..1d75c53b9 100644 --- a/test/libsolidity/syntaxTests/types/mapping/assignment_local_err.sol +++ b/test/libsolidity/syntaxTests/types/mapping/assignment_local_err.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/types/mapping/assignment_map.sol b/test/libsolidity/syntaxTests/types/mapping/assignment_map.sol index 3c756e945..fda9abf3d 100644 --- a/test/libsolidity/syntaxTests/types/mapping/assignment_map.sol +++ b/test/libsolidity/syntaxTests/types/mapping/assignment_map.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/types/mapping/assignment_state_variable.sol b/test/libsolidity/syntaxTests/types/mapping/assignment_state_variable.sol index d78f319dd..bcf0c7e7b 100644 --- a/test/libsolidity/syntaxTests/types/mapping/assignment_state_variable.sol +++ b/test/libsolidity/syntaxTests/types/mapping/assignment_state_variable.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/types/mapping/assignment_struct.sol b/test/libsolidity/syntaxTests/types/mapping/assignment_struct.sol index b1ef76ee0..c1051f25a 100644 --- a/test/libsolidity/syntaxTests/types/mapping/assignment_struct.sol +++ b/test/libsolidity/syntaxTests/types/mapping/assignment_struct.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/types/mapping/function_type_argument_array.sol b/test/libsolidity/syntaxTests/types/mapping/function_type_argument_array.sol new file mode 100644 index 000000000..e7587ad0c --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/function_type_argument_array.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_argument_storage.sol b/test/libsolidity/syntaxTests/types/mapping/library_argument_storage.sol new file mode 100644 index 000000000..edf86e397 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_argument_storage.sol @@ -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; + } +} diff --git a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_external.sol index 1826ea2b9..ca875546e 100644 --- a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_external.sol +++ b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_external.sol @@ -3,4 +3,3 @@ library L { } } // ---- -// TypeError 3312: (27-58): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_public.sol b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_public.sol index 644bc5129..03ca40145 100644 --- a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_public.sol +++ b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_public.sol @@ -3,4 +3,3 @@ library L { } } // ---- -// TypeError 3312: (27-58): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_nested_mapping.sol b/test/libsolidity/syntaxTests/types/mapping/library_nested_mapping.sol new file mode 100644 index 000000000..31bf3cb1f --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_nested_mapping.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_nested_storage.sol b/test/libsolidity/syntaxTests/types/mapping/library_nested_storage.sol new file mode 100644 index 000000000..11b09ce25 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_nested_storage.sol @@ -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 {} +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_array_data_location_function_param_external.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_array_data_location_function_param_external.sol index 07b7553ca..72c2a12a8 100644 --- a/test/libsolidity/syntaxTests/types/mapping/mapping_array_data_location_function_param_external.sol +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_array_data_location_function_param_external.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_external.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_external.sol index db2b3235b..3bc5d7a29 100644 --- a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_external.sol +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_external.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_internal.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_internal.sol index 92f2e0ed4..95ca53279 100644 --- a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_internal.sol +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_internal.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_public.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_public.sol index 5547e071d..f8a666675 100644 --- a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_public.sol +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_public.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_function_calldata.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_function_calldata.sol new file mode 100644 index 000000000..f2360b2d1 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_function_calldata.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_return_public_memory.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_return_public_memory.sol index e3e4d2cc3..4d06bad5a 100644 --- a/test/libsolidity/syntaxTests/types/mapping/mapping_return_public_memory.sol +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_return_public_memory.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_struct_data_location_memory.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_struct_data_location_memory.sol new file mode 100644 index 000000000..648e2f74e --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_struct_data_location_memory.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_struct_recusrive_data_location_memory.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_struct_recusrive_data_location_memory.sol new file mode 100644 index 000000000..350129dff --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_struct_recusrive_data_location_memory.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/types/mapping/memory_struct_recursive.sol b/test/libsolidity/syntaxTests/types/mapping/memory_struct_recursive.sol new file mode 100644 index 000000000..c6f8f48f3 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/memory_struct_recursive.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/types/mapping/memory_structs_with_mappings.sol b/test/libsolidity/syntaxTests/types/mapping/memory_structs_with_mappings.sol new file mode 100644 index 000000000..f583b4314 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/memory_structs_with_mappings.sol @@ -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.