argotorg / argotorg/solidity

ICE: invalid utility Yul generated for calldata→storage copy of struct containing `function() external` member (related to #12057)

Open
#16,751 1 comment 1 reaction 1 assignee Claimed by @cameel View on GitHub
Dominant language
C++
Stars
25.7k
Forks
6.2k
Avg merge
1d 11h
Merged PRs (30d)
21

Description

## Description

Pushing a calldata struct into a storage array — where the struct has a `function() external` member — produces invalid utility Yul that fails the inline-assembly parse and surfaces as an Internal Compiler Error. The Yul errors are the same shape as #12057 (2-slot stack vs 1-slot storage mismatch for external function pointers feeding a 1-value RHS into a 2-variable declaration), but the codegen path is different: this is a calldata→storage struct copy via `.push()`, and it triggers on **both legacy and `--via-ir`**, so the fix that closed #12057 doesn't cover this shape.

## Minimal reproducer

Gist: https://gist.github.com/msooseth/108f50796d4c3656b4e0770f35348e73

```solidity
contract c {
struct S { uint16 a; uint16 b; function() external payable d; }
S[] data;
function test(S calldata c) public { data.push(c); }
}
```

```
$ solc --bin repro.sol # legacy
$ solc --via-ir --bin repro.sol # via-IR
```

Both fail. The relevant errors in the generated Yul are identical in both pipelines:

```
Error (3812): Variable count mismatch for declaration of "memberValue_0, memberValue_1": 2 variables and 1 values.
Error (7000): Function "read_from_calldatat_function_external_payable$__$returns$__$" expects 1 arguments but got 2.
```

- Legacy throws at `libsolidity/codegen/CompilerContext.cpp:464` (`appendInlineAssembly`).
- via-IR throws at `libsolidity/interface/CompilerStack.cpp:866` (`loadGeneratedIR`).

## Diagnostic size can explode

Gist: https://gist.github.com/msooseth/75e4cb4ca4b9d68286aab897c52840f3

The error message embeds the full encoded type in generated Yul function names, and the entire generated prelude is dumped verbatim in the ICE output. With a pathologically deep array type elsewhere in the same struct, a 13-line contract produces a multi-hundred-megabyte error message:

```solidity
contract c {
struct S {
uint16 a;
uint16 b;
uint[][][][][][][][][]…[][] // ~370 nesting levels
[…][3] c;
function() external payable d;
}
S[] data;
function test(S calldata c) public returns (uint16) { data.push(c); }
}
```

Output of `solc --bin` on this: **~101 MB / ~84,800 lines** (vs ~18 KB on the minimal reproducer above — same bug, ~5,600× more text). Each `[]` level extends the encoded type into the names of utility functions like `update_storage_value_offset_0_t_array$_..._dyn_storage(...)`, and those names are repeated throughout the dumped prelude.

## Environment

- Compiler version: `0.8.36-develop.2026.5.18+commit.090bc8ff` (top of `develop`)
- Related: #12057 (same root cause class; closed but its fix does not cover this shape)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.