Skip to content

Capture checking doesn't work on generic type parameters #24664

@adamw

Description

@adamw

I'm testing capture checking to ensure that resources don't leak outside of a use function. Things work fine when specific classes are used. When a generic type parameter is used instead, the compiler reports an error.

Compiler version

3.8.0-RC3

Minimized code

//> using scala 3.8.0-RC3

import language.experimental.captureChecking
import java.io.FileOutputStream
import java.io.Closeable
import java.io.OutputStream

def use1[R <: Closeable, T](r: R)(f: R^ => T): T =
 try f(r)
 finally r.close()

def use2[T](r: OutputStream)(f: OutputStream^ => T): T =
 try f(r)
 finally r.close()

@main def main4 =
 use1(new FileOutputStream("data.txt"))(out => ())

The example compiles fine with use2 (which is specialised to OutputStreams), but fails with the generic use1:

% scala-cli main4.scala
Compiling project (Scala 3.8.0-RC3, JVM (25))
[error] ./main4.scala:17:42
[error] Found:    (out: java.io.FileOutputStream^'s1) => Unit
[error] Required: (java.io.FileOutputStream^'s2)^ =>² Unit
[error] 
[error] Note that capability cap is not included in capture set {cap²}
[error] because cap is not visible from cap² in method main4.
[error] 
[error] where:    => and ^ and cap refer to the universal root capability
[error]           =>² and cap²     refer to a fresh root capability created in method main4 when checking argument to parameter f of method use1
[error]   use1(new FileOutputStream("data.txt"))(out => ())
[error]                                          ^^^^^^^^^
[error] ./main4.scala:16:1
[error] reference cap is not included in the allowed capture set {}
[error] of the enclosing class main4
[error] @main def main4 =
[error] ^

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions