Solc 0.7.0报错:含(嵌套)映射的结构体无法构造,旧版本可编译
Hey there! Let's break down why you're hitting this error and how to fix it properly.
The Root Cause
Starting in Solidity 0.7.0, the compiler enforces stricter rules around structs that contain mappings. Mappings are storage-only reference types—they can't exist in memory because they rely on the contract's storage space to store key-value pairs. Your old code worked in earlier versions because the compiler was more lenient, but that approach was actually unsafe (since memory mappings can't function correctly under the hood).
The Fix
Instead of trying to create the struct in memory, we'll work directly with storage where mappings belong. Here are two clean ways to adjust your code:
Option 1: Direct Storage Initialization (Recommended)
We'll add an empty struct to our storage array first, then modify its fields using a storage reference:
// SPDX-License-Identifier: MIT pragma solidity 0.7.0; contract Test { struct Request { uint256 value; mapping(address => bool) approvals; } Request[] public requests; function createRequest(uint256 value) public { // Push an empty Request into the storage array requests.push(); // Get a storage reference to the new request Request storage newRequest = requests[requests.length - 1]; // Assign the value (mapping auto-initializes to empty) newRequest.value = value; } // Helper function to test approval functionality function approveRequest(uint256 requestIndex) public { requests[requestIndex].approvals[msg.sender] = true; } // Helper function to check approval status function isApproved(uint256 requestIndex, address addr) public view returns (bool) { return requests[requestIndex].approvals[addr]; } }
Option 2: Condensed Storage Pointer Approach
If you prefer a more concise style, you can combine the push and reference into one line:
function createRequest(uint256 value) public { Request storage newRequest = requests.push(); newRequest.value = value; }
Why This Works
- When you call
requests.push(), Solidity creates a newRequestinstance directly in the contract's storage. - The
storagereference lets us modify the struct's fields without copying data around (which is efficient and avoids the memory mapping issue). - Mappings in storage automatically initialize to an empty state—you don't need to "create" them; just start assigning values to keys (like in the
approveRequestfunction).
Key Takeaway for Solidity >=0.7.0
Any struct containing a mapping (or nested struct with a mapping) must be handled in storage. Avoid trying to instantiate these structs in memory—the compiler blocks this to prevent subtle bugs and ensure type safety.
内容的提问来源于stack exchange,提问作者coding

