ICE: invalid utility Yul generated for calldata→storage copy of struct containing `function() external` member (related to #12057)
- 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
Assessment
This issue has not been assessed yet.