Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -695,14 +697,16 @@ 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 _ =>
case _ =>
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
*/
Expand Down
11 changes: 11 additions & 0 deletions tests/neg-custom-args/captures/nicolas2.check
Original file line number Diff line number Diff line change
@@ -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.
11 changes: 11 additions & 0 deletions tests/neg-custom-args/captures/nicolas2.scala
Original file line number Diff line number Diff line change
@@ -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
11 changes: 11 additions & 0 deletions tests/pos-custom-args/captures/nicolas1.scala
Original file line number Diff line number Diff line change
@@ -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))
Loading