Skip to content

Polymorphic capture functions can be exploited to hide captures #21347

Closed
@Linyxus

Description

@Linyxus

Compiler version

The main branch

Minimized code

import language.experimental.captureChecking

def runOps[C^](ops: List[() ->{C^} Unit]): Unit =
  ops.foreach: op =>
    op()

def boom(f: () => Unit): () -> Unit =
  () => runOps(f :: Nil)

Output

It type-checks.

Expectation

It should not type-check. Accepting the boom function is clearly unsound: given any impure operations that could perform arbitrary effects, boom could hide its captures and pretend that this operation is pure.

The capture checker rejects the morally equivalent variant that uses only reach capabilities:

def runOpsAlt(ops: List[() => Unit]): Unit =
  ops.foreach: op =>
    op()

The compiler complains:

-- Error: issues/drop-caparg.scala:4:15 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4 |  ops.foreach: op =>
  |               ^
  |               Local reach capability ops* leaks into capture scope of method runOpsAlt
5 |    op()

We should do something similar with capture polymorphism.

/cc @odersky

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions