val later = usingLogFile { f => () => f.write(0) }
and got the following runtime error:
../scala-cli -S 3.4.0-RC1-bin-20230804-73967d5-NIGHTLY CC.scala
Compiling project (Scala 3.4.0-RC1-bin-20230804-73967d5-NIGHTLY, JVM)
Compiled project (Scala 3.4.0-RC1-bin-20230804-73967d5-NIGHTLY, JVM)
Exception in thread "main" java.io.IOException: Stream Closed
at java.base/java.io.FileOutputStream.write(Native Method)
at java.base/java.io.FileOutputStream.write(FileOutputStream.java:322)
at CC$package$.$anonfun$1$$anonfun$1(CC.scala:11)
at CC$package$.shouldGetAStaticErrorAsDocumented(CC.scala:12)
at CC$package$.CC(CC.scala:19)
at CC.main(CC.scala:14)
The following is the code I use:
import java.io.FileOutputStream
import language.experimental.captureChecking
def usingLogFile[T](op: FileOutputStream^ => T): T =
val logFile = FileOutputStream("log")
val result = op(logFile)
logFile.close()
result
def shouldGetAStaticErrorAsDocumented =
val later = usingLogFile { file => (x:Int) => file.write(x) }
later(0) // crash
@main def CC: Unit =
val xs = usingLogFile { f =>
List(1, 2, 3).map { x => f.write("x\n".getBytes()); x * x }
}
shouldGetAStaticErrorAsDocumented
It is ok to me. I just want to confirm here if it is just an issue of the NIGHTLY Scala 3 compiler.
I don’t think this is definitive, but the current version of the capture checker requires the use of sealed on the type parameter to prevent impure functions from escaping: def usingLogFile[sealed T](op: FileOutputStream^ => T): T =
11 | val later = usingLogFile { file => (x:Int) => file.write(x) }
| ^^^^^^^^^^^^
|Sealed type variable T cannot be instantiated to box (x$0: Int) => Unit since
|that type captures the root capability `cap`.
|This is often caused by a local capability in an argument of method usingLogFile
|leaking as part of its result.