solang icon indicating copy to clipboard operation
solang copied to clipboard

Cannot push to array in a struct

Open LucasSte opened this issue 2 years ago • 4 comments

This contract:

contract Foo {
	struct My {
		bytes bb;
	}
	function bar() public pure returns (uint32) {
		My s;
		s.bb.push(2);
		return s.bb.length;
	}
}

causes this error:

thread 'main' panicked at 'not an array', src/sema/types.rs:1415:18

LucasSte avatar Aug 16 '23 20:08 LucasSte

bb declared with bytes is a dynamic byte array and it doesn't have a push method like arrays in some other programming languages. To do that, you gotta manage the length of the array manually and use memory allocation functions.

  1. Declare s as a memory variable. This would allow you to modify data(array in this case) inside of the bar function as it is declared as pure. It aligns with the function's read-only nature and preventing errors related to modifying storage in a read-only context.
  2. Initialize the bytes array s.bb using new bytes(0).
pragma solidity ^0.8.0;

contract Foo {
    struct My {
        bytes bb;
    }

    function bar() public pure returns (uint256) {
        My memory s; //declare s as a memory variable
        s.bb = new bytes(0); // Initialize the bytes array
        s.bb.push(0x02);

        return s.bb.length;
    }
}

Shiva953 avatar Sep 12 '23 09:09 Shiva953

Thanks @Shiva953, you are right. solc does not allow us to push to a bytes array that is not in memory. The bug, however, still exists. The compiler must not panic because we are trying to build incorrect code. It should raise an error.

LucasSte avatar Sep 12 '23 12:09 LucasSte

yeah sire, that's a solidity compiler limitation and I honestly don't have the slightest of the clues about anything related to compilers

Shiva953 avatar Sep 12 '23 12:09 Shiva953

Solang does support push/pop on memory arrays, even if solc does not. However, it should not panic.

seanyoung avatar Sep 12 '23 14:09 seanyoung