mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Allow assignments to local variables of mapping types.
This commit is contained in:
		
							parent
							
								
									c0a169ca90
								
							
						
					
					
						commit
						1e4b5886d6
					
				| @ -80,6 +80,7 @@ Bugfixes: | ||||
|  * References Resolver: Enforce ``storage`` as data location for mappings. | ||||
|  * References Resolver: Report error instead of assertion fail when FunctionType has an undeclared type as parameter. | ||||
|  * Type Checker: Disallow assignments to mappings within tuple assignments as well. | ||||
|  * Type Checker: Allow assignments to local variables of mapping types. | ||||
|  * Type Checker: Consider fixed size arrays when checking for recursive structs. | ||||
|  * Type System: Allow arbitrary exponents for literals with a mantissa of zero. | ||||
| 
 | ||||
|  | ||||
| @ -1332,7 +1332,15 @@ void TypeChecker::checkExpressionAssignment(Type const& _type, Expression const& | ||||
| 			checkExpressionAssignment(_type, *tupleExpression->components().front()); | ||||
| 	} | ||||
| 	else if (_type.category() == Type::Category::Mapping) | ||||
| 		m_errorReporter.typeError(_expression.location(), "Mappings cannot be assigned to."); | ||||
| 	{ | ||||
| 		bool isLocalOrReturn = false; | ||||
| 		if (auto const* identifier = dynamic_cast<Identifier const*>(&_expression)) | ||||
| 			if (auto const *variableDeclaration = dynamic_cast<VariableDeclaration const*>(identifier->annotation().referencedDeclaration)) | ||||
| 				if (variableDeclaration->isLocalOrReturn()) | ||||
| 					isLocalOrReturn = true; | ||||
| 		if (!isLocalOrReturn) | ||||
| 			m_errorReporter.typeError(_expression.location(), "Mappings cannot be assigned to."); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool TypeChecker::visit(Assignment const& _assignment) | ||||
|  | ||||
| @ -1478,6 +1478,28 @@ BOOST_AUTO_TEST_CASE(multi_level_mapping) | ||||
| 	testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0)); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(mapping_local_assignment) | ||||
| { | ||||
| 	char const* sourceCode = R"( | ||||
| 		contract test { | ||||
| 			mapping(uint8 => uint8) m1; | ||||
| 			mapping(uint8 => uint8) m2; | ||||
| 			function f() public returns (uint8, uint8, uint8, uint8) { | ||||
| 				mapping(uint8 => uint8) storage m = m1; | ||||
| 				m[1] = 42; | ||||
| 
 | ||||
| 				m = m2; | ||||
| 				m[2] = 21; | ||||
| 
 | ||||
| 				return (m1[1], m1[2], m2[1], m2[2]); | ||||
| 			} | ||||
| 		} | ||||
| 	)"; | ||||
| 	compileAndRun(sourceCode); | ||||
| 
 | ||||
| 	ABI_CHECK(callContractFunction("f()"), encodeArgs(byte(42), byte(0), byte(0), byte(21))); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(structs) | ||||
| { | ||||
| 	char const* sourceCode = R"( | ||||
|  | ||||
| @ -9,7 +9,3 @@ contract test { | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (176-177): Mappings cannot be assigned to. | ||||
| // TypeError: (192-193): Mappings cannot be assigned to. | ||||
| // TypeError: (209-210): Mappings cannot be assigned to. | ||||
| // TypeError: (212-213): Mappings cannot be assigned to. | ||||
|  | ||||
| @ -0,0 +1,7 @@ | ||||
| contract C { | ||||
|     function f() external pure returns (mapping(uint=>uint) storage m) { | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (53-82): Type is required to live outside storage. | ||||
| // TypeError: (53-82): Internal or recursive type is not allowed for public or external functions. | ||||
| @ -0,0 +1,21 @@ | ||||
| // This should be allowed in a future release. | ||||
| contract C { | ||||
|     mapping(uint=>uint) m; | ||||
|     function f() internal view returns (mapping(uint=>uint) storage) { | ||||
|         return m; | ||||
|     } | ||||
|     function g() private view returns (mapping(uint=>uint) storage) { | ||||
|         return m; | ||||
|     } | ||||
|     function h() internal view returns (mapping(uint=>uint) storage r) { | ||||
|         r = m; | ||||
|     } | ||||
|     function i() private view returns (mapping(uint=>uint) storage r) { | ||||
|         (r,r) = (m,m); | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (127-146): Type is required to live outside storage. | ||||
| // TypeError: (221-240): Type is required to live outside storage. | ||||
| // TypeError: (316-345): Type is required to live outside storage. | ||||
| // TypeError: (409-438): Type is required to live outside storage. | ||||
| @ -0,0 +1,7 @@ | ||||
| contract C { | ||||
|     function f() public pure returns (mapping(uint=>uint) storage m) { | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (51-80): Type is required to live outside storage. | ||||
| // TypeError: (51-80): Internal or recursive type is not allowed for public or external functions. | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user