-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Leaking capability in Scott-encoded wrapper #15923
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Note: the following code using a case class fails the compilation, as expected: trait Cap { def use(): Int }
case class Id[X](x: X) {
def apply[T](op: X => T): T = op(x)
}
def mkId[X](x: X): Id[X] = Id(x)
def bar() = {
def withCap[X](op: ({*} Cap) => X): X = {
val cap: {*} Cap = new Cap { def use() = { println("cap is used"); 0 } }
val result = op(cap)
result
}
val leak = withCap(cap => mkId(cap))
leak { c => c.use() }
} |
Until recently, this used to give an error at the expected line With #23171 that error is gone. I tried to make a class based version that re-introduces boxing and that would hopefully give an error again: trait Cap { def use(): Int }
class Id[X](val value: [T] -> (op: X => T) -> T)
def mkId[X](x: X): Id[X] = Id([T] => (op: X => T) => op(x))
def bar() = {
def withCap[X](op: (lcap: caps.Capability) ?-> Cap^{lcap} => X): X = {
val cap: Cap = new Cap { def use() = { println("cap is used"); 0 } }
val result = op(using caps.cap)(cap)
result
}
val leak = withCap(cap => mkId(cap))
} That gives a crash due to a stack-overflow. The stacktrace seems to indicate a cycle in capture set propagation. That crash is present already in main. The original and class based versions are in #23171 as tests/pending/neg-custom-args/captures/i15938.scala and i15938a.scala. |
This fixes problems encountered in scala#15923 where we got infinite recursions caused by infinite streams of new ResultCap instances that were added to capture sets. The analysis of the problem showed that there is a cycle of dependencies involving both forwards and backwards propagations of ResultCap instances between BiMapped capture sets linked by SubstBindingMaps. Each propagation would create a new derived ResultCap instance. We could try to solve the problem by having SubstBindingMaps remember their mappings and have their inverses work backwards. But that could still produce an infinite stream if there was a cycle of SubstBindingMaps of length > 2. So we fix the problem at the root by allowing only one derived ResultCap instance per original ResultCap / binder pair. Fixes scala#15923
This fixes problems encountered in scala#15923 where we got infinite recursions caused by infinite streams of new ResultCap instances that were added to capture sets. The analysis of the problem showed that there is a cycle of dependencies involving both forwards and backwards propagations of ResultCap instances between BiMapped capture sets linked by SubstBindingMaps. Each propagation would create a new derived ResultCap instance. We could try to solve the problem by having SubstBindingMaps remember their mappings and have their inverses work backwards. But that could still produce an infinite stream if there was a cycle of SubstBindingMaps of length > 2. So we fix the problem at the root by allowing only one derived ResultCap instance per original ResultCap / binder pair. Fixes scala#15923
This fixes problems encountered for #15923 where we got infinite recursions caused by infinite streams of new ResultCap instances that were added to capture sets. The analysis of the problem showed that there is a cycle of dependencies involving both forwards and backwards propagations of ResultCap instances between BiMapped capture sets linked by SubstBindingMaps. Each propagation would create a new derived ResultCap instance. We could try to solve the problem by having SubstBindingMaps remember their mappings and have their inverses work backwards. But that could still produce an infinite stream if there was a cycle of SubstBindingMaps of length > 2. So we fix the problem at the root by allowing only one derived ResultCap instance per original ResultCap / binder pair. Fixes #15923 Based on #23184. Only last commit is new.
This fixes problems encountered in scala#15923 where we got infinite recursions caused by infinite streams of new ResultCap instances that were added to capture sets. The analysis of the problem showed that there is a cycle of dependencies involving both forwards and backwards propagations of ResultCap instances between BiMapped capture sets linked by SubstBindingMaps. Each propagation would create a new derived ResultCap instance. We could try to solve the problem by having SubstBindingMaps remember their mappings and have their inverses work backwards. But that could still produce an infinite stream if there was a cycle of SubstBindingMaps of length > 2. So we fix the problem at the root by allowing only one derived ResultCap instance per original ResultCap / binder pair. Fixes scala#15923
Uh oh!
There was an error while loading. Please reload this page.
Compiler version
cc-experiment
branchMinimized code
Output
It compiles.
Expectation
It should not compile. We expect the type of
val leak
to beId[□ {*} Cap]
, so it will expect a function of(□ {*} Cap) => Unit
inleak(...)
. It will not be possible to adaptcap => cap.use() : ({*} Cap) -> Unit
to the type(□ {*} Cap) => Unit
since the adaptioncap => (unbox cap).use()
tries to unbox a reference capturing universal capability.We should issue an error on
leak(...)
.The text was updated successfully, but these errors were encountered: