Ensure that closures inside recursive closures capture correctly

With a code like

```
thenDo = \x, callback ->
    callback x

f = \{} ->
    code = 10u16

    bf = \{} ->
        thenDo code \_ -> bf {}

    bf {}
```

The lambda `\_ -> bf {}` must capture `bf`. Previously, this would not
happen correctly, because we assumed that mutually recursive functions
(including singleton recursive functions, like `bf` here) cannot capture
themselves.

Of course, that premise does not hold in general. Instead, we should have
mutually recursive functions capture the closure (haha, get it) of
values captured by all functions constituting the mutual recursion.
Then, any nested closures can capture outer recursive closures' values
appropriately.
This commit is contained in:
Ayaz Hafiz 2023-03-20 17:40:13 -04:00
parent ceacc1792d
commit e8a29d2df4
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
3 changed files with 69 additions and 18 deletions

View file

@ -8778,4 +8778,32 @@ mod solve_expr {
@"main : List w_a"
);
}
#[test]
fn recursive_closure_with_transiently_used_capture() {
infer_queries!(
indoc!(
r#"
app "test" provides [f] to "./platform"
thenDo = \x, callback ->
callback x
f = \{} ->
code = 10u16
bf = \{} ->
#^^{-1}
thenDo code \_ -> bf {}
# ^^^^^^^^^^^
bf {}
"#
),
@r###"
bf : {} -[[bf(5) U16]]-> *
\_ -> bf {} : U16 -[[6 U16]]-> *
"###
);
}
}