Skip to content

Conversation

@ryanwilsond
Copy link
Owner

@ryanwilsond ryanwilsond commented Jun 23, 2025

Description

Previously, closure analysis was done purely to rewrite local functions into methods. This approach worked because the Evaluator keeps a stack of locals so even though the locals weren't explicitly passed to the rewritten local, it could still access them.

Now closure analysis actually creates a closure, allowing local functions to emit correctly to IL.

Source:

public static class Program {
    public static void Main() {
        var a = 3;

        Console.PrintLine(F(5));

        int F(int b) {
            return a + b;
        }
    }
}

Old (incorrect):

public static Nullable<int> Program.<Main>ss__F|0_0(Nullable<int> b) {
    return ((a.get_HasValue() && b.get_HasValue()) ? new Nullable<int>((a.get_Value() + b.get_Value())) : null)
}

public static void Program.Main() {
    Nullable<int> a = new Nullable<int>(3)
    Nullable<int> temp0 = Program!.<Main>ss__F|0_0(5)
    global::Console.PrintLine((temp0.get_HasValue() ? (string!)temp0.get_Value() : null))
    nop
    return
}

New (correct):

public Nullable<int> Program.<>Closure__0.<Main>g__F|1_1(Nullable<int> b) {
    return ((this.a.get_HasValue() && b.get_HasValue()) ? new Nullable<int>((this.a.get_Value() + b.get_Value())) : null)
}

public void Program.<>Closure__0..ctor() {
    this..ctor()
    return
}

public static void Program.Main() {
    private sealed Program.<>Closure__0 <>Closure__0_l0 = new Program.<>Closure__0()
    <>Closure__0_l0.a = new Nullable<int>(3)
    Nullable<int> temp0 = <>Closure__0_l0.<Main>g__F|1_1(5)
    global::Console.PrintLine((temp0.get_HasValue() ? (string!)temp0.get_Value() : null))
    nop
    return
}

@ryanwilsond ryanwilsond self-assigned this Jun 23, 2025
@ryanwilsond ryanwilsond merged commit f18c0ca into rw/evalopt Jun 23, 2025
1 check passed
@ryanwilsond ryanwilsond deleted the rw/closures branch June 23, 2025 06:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants