Skip to content

Commit 2e24bea

Browse files
committed
Relax @use checking for curried functions
1 parent 7968f22 commit 2e24bea

File tree

3 files changed

+27
-2
lines changed

3 files changed

+27
-2
lines changed

compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ class CheckCaptures extends Recheck, SymTransformer:
555555
//println(i"Include call or box capture $included from $cs in ${env.owner}/${env.captured}/${env.captured.owner}/${env.kind}")
556556
checkSubset(included, env.captured, tree.srcPos, provenance(env))
557557
capt.println(i"Include call or box capture $included from $cs in ${env.owner} --> ${env.captured}")
558-
if !isOfNestedMethod(env) && !ccConfig.caplessLike then
558+
if !isOfNestedMethod(env) && (!ccConfig.caplessLike || env.kind == EnvKind.NestedInOwner) then
559559
val nextEnv = nextEnvToCharge(env)
560560
if nextEnv != null && !nextEnv.owner.isStaticOwner then
561561
recur(included, nextEnv, env)
@@ -2107,6 +2107,12 @@ class CheckCaptures extends Recheck, SymTransformer:
21072107
if !boxedOwner(env).isContainedIn(croot.symbol.owner) then
21082108
checkUseDeclared(c, tree.srcPos)
21092109

2110+
def checkUse(c: Capability, croot: NamedType) =
2111+
if ccConfig.caplessLike then
2112+
if !env.owner.isProperlyContainedIn(croot.symbol.owner) then
2113+
checkUseDeclared(c, tree.srcPos)
2114+
else checkUseUnlessBoxed(c, croot)
2115+
21102116
def check(cs: CaptureSet): Unit = cs.elems.foreach(checkElem)
21112117

21122118
def checkElem(c: Capability): Unit =
@@ -2115,7 +2121,7 @@ class CheckCaptures extends Recheck, SymTransformer:
21152121
c match
21162122
case Reach(c1) =>
21172123
c1.paramPathRoot match
2118-
case croot: NamedType => checkUseUnlessBoxed(c, croot)
2124+
case croot: NamedType => checkUse(c, croot)
21192125
case _ => check(CaptureSet.ofTypeDeeply(c1.widen))
21202126
case c: TypeRef =>
21212127
c.paramPathRoot match
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
-- Error: tests/neg-custom-args/captures/capless-strawman2.scala:3:53 ----------------------------------------
2+
3 |def test1(ops: List[() => Unit]): Unit = ops.foreach(op => op()) // error
3+
| ^^^^^^^^^^
4+
|Local reach capability ops* leaks into capture scope of method test1.
5+
|You could try to abstract the capabilities referred to by ops* in a capset variable.
6+
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/capless-strawman2.scala:4:49 ------------------------
7+
4 |def test2(ops: List[() => Unit]): () ->{} Unit = () => ops.foreach(f => f()) // error
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
9+
| Found: () ->{ops*} Unit
10+
| Required: () -> Unit
11+
|
12+
| Note that capability ops* is not included in capture set {}.
13+
|
14+
| longer explanation available when compiling with `-explain`
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import language.experimental.captureChecking
2+
trait IO { def println(msg: String): Unit }
3+
def test1(ops: List[() => Unit]): Unit = ops.foreach(op => op()) // error
4+
def test2(ops: List[() => Unit]): () ->{} Unit = () => ops.foreach(f => f()) // error
5+
def test3(ops: List[() => Unit]): () ->{ops*} Unit = () => ops.foreach(f => f()) // ok

0 commit comments

Comments
 (0)