Capture checking and SAM

I’m struggling to get the following code to work, both using 3.8.0-RC1 and 3.8.1-RC1-bin-20251231-32e416e-NIGHTLY:

//> using scala 3.nightly
//> using option -language:experimental.captureChecking

import caps.*

trait Rand extends SharedCapability

trait Plan:
  def execute(test: Rand ?=> Unit): Boolean

object Plan:
  def execute(test: Rand ?=> Unit): Boolean =
    true

  val standard: Plan =
    test =>
      execute(test)

It fails with the following error:

[error] Capability cap outlives its scope: it leaks into outer capture set 's1 of parameter test.
[error] The leakage occurred when trying to match the following types:
[error] 
[error] Found:    (contextual$1: rep$_.this.Rand^'s2) ?->{test} Unit
[error] Required: (rep$_.this.Rand^) ?=> Unit
[error] 
[error] where:    ?=> refers to a fresh root capability created in anonymous function of type (test²: (rep$_.this.Rand) ?=> Unit): Boolean when checking argument to parameter test of method execute
[error]           ^   refers to the universal root capability
[error]           cap is a fresh root capability classified as SharedCapability created in anonymous function of type (using contextual$1: rep$_.this.Rand^'s2): Unit of parameter parameter contextual$1² of method $anonfun
[error]       execute(test)

Note that it works perfectly if I rewrite standard as follows, with an explicit type ascription:

val standard: Plan =
  (test: Rand ?=> Unit) =>
    execute(test)

I’m not entirely sure why that type ascription is necessary, although my intuition would be that conversion to context function is applied before SAM desugaring, and adds undesired elements to the capture set. Something like that?

As requested in another topic, here’s the corresponding bug report.

1 Like