Fixup transient closure captures during canonicalization

Closure captures can be transient, but previously, we did not handle
that correctly. For example, in

```
x = ""
inner = \{} -> x
outer = \{} -> inner {}
```

`outer` captures `inner`, but `inner` captures `x`, and in the body of
`outer`, we would not construct the closure data for `inner` correctly
before calling it.

There are a couple ways around this.

1. Update mono to do something when we are passed the captured
   environment of a closure, rather than attempting to construct a
   call-by-name's captured environment before callign it.
2. Fix-up closures during canonicalization to remove captured closures
   that themselves capture, and replace them with their captures.

This patch does (2), since (1) is much more involved and is not likely
to bring a lot of wins. In general I think it's reasonable to expect
captured environments, even if transient, to be fairly shallow, so I
don't think this will produce very large closure environments.

Closes #2894
This commit is contained in:
Ayaz Hafiz 2022-08-10 14:31:11 -07:00
parent 565ffacb9a
commit e97ce32b88
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
2 changed files with 235 additions and 36 deletions

View file

@ -7691,4 +7691,42 @@ mod solve_expr {
"###
);
}
#[test]
fn transient_captures() {
infer_queries!(
indoc!(
r#"
x = "abc"
getX = \{} -> x
h = \{} -> (getX {})
#^{-1}
h {}
"#
),
@"h : {}* -[[h(3) Str]]-> Str"
);
}
#[test]
fn transient_captures_after_def_ordering() {
infer_queries!(
indoc!(
r#"
h = \{} -> (getX {})
#^{-1}
getX = \{} -> x
x = "abc"
h {}
"#
),
@"h : {}* -[[h(1) Str]]-> Str"
);
}
}