You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix capture checking of dependent functions (#16264)
Fixes#15921.
Capture checking can be unsound for dependent functions. Minimized
example:
```scala
trait Cap { def use(): Unit }
def main() = {
val f: (io: {*} Cap) -> {} () -> Unit =
io => () => io.use() // should be an error
val g: ({*} Cap) -> {} () -> Unit =
io => () => io.use() // error, as expected
}
```
In the above example, we issue an error for `g`, but not for `f`, which
is unsound.
The root cause of this issue is that in the `Typer` phase, we only
create `InferredTypeTree` for the result type of function values when
the expected type of the function literal is non-dependent; and later
during `Setup` of the capture checking phase, we only create capture set
variables and update the information of function symbols when its result
type tree is an `InferredTypeTree`.
To be more specific, the function literal `io => () => io.use()` in both
`f` and `g` would be expaneded into the following tree in `Typer`:
```scala
def $anonfun(io: {*} Cap): {} () -> Unit =
{
{
def $anonfun(): Unit =
{
io.use()
}
closure($anonfun)
}
}
closure($anonfun)
```
For `g`, where the expected type of the function literal is
non-dependent, we would create capture set variables in `Setup` for the
return type `{} () -> Unit` and update the symbol info of the outer
`$anonfun`. For `f`, we would not do these things because `{} () ->
Unit` is not an `InferredTypeTree`.
This PR fixes this issue by typing the `DependentTypeTree` as an
`InferredTypeTree` in the typer.
~Currently, although this PR fixes the soundness problem, it brings
completeness issues, where sometimes we propagate the universal
capability to some capture sets incorrectly, which prevents some
positive test cases from being accepted. I am still investigating this
issue and thus mark this PR as a draft for now.~
The completeness problem is fixed by two additional refinements:
- preciser propagation of captured references through mapped instance
(see
[dd88672](dd88672)),
- healing ill-formed type parameter capture sets (see
[0e7d33a](0e7d33a)).
0 commit comments