Skip to content

Compiler crash by assertion on mixed memory-calldata tuple conditional assignment #16066

Open
@Czar102

Description

@Czar102

Description

The compiler crashes when a conditional value is assigned to a tuple which contains both memory and calldata variables. (I may be wrong about the exact reasons – this is only from repetitive testing and derivation of a minimal reproducible scenario)

The error:

Error: Internal compiler error:
/solidity/libsolidity/codegen/YulUtilFunctions.cpp(3849): Throw in function std::string solidity::frontend::YulUtilFunctions::arrayConversionFunction(const solidity::frontend::ArrayType&, const solidity::frontend::ArrayType&)
Dynamic exception type: boost::wrapexcept<solidity::langutil::InternalCompilerError>
std::exception::what: Solidity assertion failed
[solidity::util::tag_comment*] = Solidity assertion failed

Note: I discovered this bug when trying to return some data from memory and some data from calldata, but it seems it's also triggered when assigning to a tuple. The latter is more minimal, so it's the one being shared. But the original use case of return data is not so easily worked around. In particular, changing the declared returned variable to be located to memory has very severe consequences for returning arrays of structs (my use case), since conversion to memory turns them into arrays of pointers, only to be brought back to the original form for abi encoding, which is very inefficient. So, there is currently no workaround for this issue without using Yul for abi encoding.

Environment

  • Compiler version: 0.8.30
  • Compilation pipeline (legacy, IR, EOF): default (IR)
  • Target EVM version (as per compiler settings): cancun
  • Framework/IDE (e.g. Foundry, Hardhat, Remix): Foundry
  • EVM execution environment / backend / blockchain client: ---
  • Operating system: Arch Linux

Steps to Reproduce

// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.30;

contract Crash {
	function crashCompiler(bool conditional, uint[] calldata arr) external pure {
		uint[] memory ops1; // we take two arrays so the compiler won't short-circuit the conditional
		uint[] memory ops2;

		(uint[] memory a, uint[] calldata b) = conditional ? (ops1, arr) : (ops2, arr);
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions