diff --git a/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala b/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala index 9790f366fb21..6dddd4835830 100644 --- a/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala +++ b/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala @@ -663,6 +663,8 @@ class CheckCaptures extends Recheck, SymTransformer: if param.isUseParam then markFree(arg.nuType.deepCaptureSet, errTree) end markFreeTypeArgs +// ---- Check for leakages of reach capabilities ------------------------------ + /** If capability `c` refers to a parameter that is not implicitly or explicitly * @use declared, report an error. */ @@ -695,7 +697,7 @@ class CheckCaptures extends Recheck, SymTransformer: case tp: TermRef => report.warning( em"""Reach capability $ref in function result refers to ${tp.symbol}. - |To avoid errors of the form "Local reach capability $ref leaks into capture set ..." + |To avoid errors of the form "Local reach capability $ref leaks into capture scope ..." |you should replace the reach capability with a new capset variable in ${tree.symbol}.""", tree.tpt.srcPos) case _ => @@ -703,6 +705,8 @@ class CheckCaptures extends Recheck, SymTransformer: tpt.nuType.foreachPart(checkType, StopAt.Static) case _ => +// ---- Rechecking operations for different kinds of trees---------------------- + /** If `tp` (possibly after widening singletons) is an ExprType * of a parameterless method, map Result instances in it to Fresh instances */ diff --git a/tests/neg-custom-args/captures/nicolas2.check b/tests/neg-custom-args/captures/nicolas2.check new file mode 100644 index 000000000000..1b8d23c24bda --- /dev/null +++ b/tests/neg-custom-args/captures/nicolas2.check @@ -0,0 +1,11 @@ +-- Warning: tests/neg-custom-args/captures/nicolas2.scala:9:53 --------------------------------------------------------- +9 |def oneOf[A](head: Rand ?=> A, tail: (Rand ?=> A)*): Rand ?->{head, tail*} A = + | ^^^^^^^^^^^^^^^^^^^^^^^ + | Reach capability tail* in function result refers to parameter tail. + | To avoid errors of the form "Local reach capability tail* leaks into capture scope ..." + | you should replace the reach capability with a new capset variable in method oneOf. +-- Error: tests/neg-custom-args/captures/nicolas2.scala:11:5 ----------------------------------------------------------- +11 | all(nextInt(all.length)) // error + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | Local reach capability tail* leaks into capture scope of method oneOf. + | You could try to abstract the capabilities referred to by tail* in a capset variable. diff --git a/tests/neg-custom-args/captures/nicolas2.scala b/tests/neg-custom-args/captures/nicolas2.scala new file mode 100644 index 000000000000..409357327813 --- /dev/null +++ b/tests/neg-custom-args/captures/nicolas2.scala @@ -0,0 +1,11 @@ +import caps.* + +trait Rand extends SharedCapability: + def range(min: Int, max: Int): Int + +def nextInt(max: Int): Rand ?-> Int = + r ?=> r.range(0, max) + +def oneOf[A](head: Rand ?=> A, tail: (Rand ?=> A)*): Rand ?->{head, tail*} A = + val all: Seq[Rand ?->{head, tail*} A] = head +: tail + all(nextInt(all.length)) // error diff --git a/tests/pos-custom-args/captures/nicolas1.scala b/tests/pos-custom-args/captures/nicolas1.scala new file mode 100644 index 000000000000..52ff62c9aebb --- /dev/null +++ b/tests/pos-custom-args/captures/nicolas1.scala @@ -0,0 +1,11 @@ +import caps.* + +trait Rand extends SharedCapability: + def range(min: Int, max: Int): Int + +def nextInt(max: Int): Rand ?-> Int = + r ?=> r.range(0, max) + +def oneOf[A, B^](head: Rand ?=> A, tail: (Rand ?->{B} A)*): Rand ?->{head, B} A = + val all: Seq[Rand ?->{head, B} A] = head +: tail // error + all(nextInt(all.length)) \ No newline at end of file