Captured-variable assignment produces invalid Hull when not constant-folded

Open
#626 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
57/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
haskell
Domain
compilers

Research direction

Start with the linked Hull emission code in src/Solcore/Backend/EmitHull.hs, especially how captured-variable reads and assignment targets are emitted. Reproduce the failure with the provided CaptureAssignment example, then compare normal partial evaluation with --pe-fuel 0. Done when the compiler emits valid bindings for supported captured-variable assignments or rejects unsupported ones at the source level.

Written by the indexing model from the issue text.

Description

Assigning to a captured variable can produce an invalid Hull when the closure call is not folded to a constant during partial evaluation.

Source:

import * from std;

contract CaptureAssignment {
    function main() returns (word) {
        let x: word;
        assembly { x := calldataload(0) }

        let f = lam () -> word {
            x = 42;
            return x;
        };

        let result: word = f();
        return result + x;
    }
}

Result:

sol-core succeeds, but yule fails:

Type error:
Undefined variable: x

The lifted function contains the following, with generated names shortened:

function lambda_impl(env: Closure{word}) -> word {
    x := 42
    return 42
}

x is captured in env, but the assignment still targets an undeclared x. [Hull emission substitutes captured-variable reads, but emits assignment targets using their original names.](https://github.com/argotorg/solcore/blob/5992f406d77f1a1eef011481bfb6d77bc3b65c6f/src/Solcore/Backend/EmitHull.hs#L350-L386)

Replacing the runtime initializer with let x: word = 41; makes the example compile normally: partial evaluation folds the result to 83, and the lifted function is removed. Adding --pe-fuel 0 exposes the same error again.

The compiler should generate valid bindings for supported assignments, or reject unsupported assignments at the source level. Correctness should not depend on constant folding removing the closure.

Related fixes:

  • [#625](https://github.com/argotorg/solcore/pull/625) addresses a different cause: variables referenced only inside assembly are omitted from capture analysis. Here, x is already captured, and its assignment and read inside the closure are ordinary source statements. The assembly block only supplies runtime input.
Dominant language
Haskell
Stars
115
Forks
11
Avg merge
20h 29m
Merged PRs (30d)
2

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from argotorg/solcore

All issues in argotorg/solcore

Similar issues

More Haskell issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.