Skip to content

Commit 9c55ded

Browse files
authored
Handle capture parameters in dcs (#24328)
Fixes #24309.
2 parents 2b66611 + cb3b183 commit 9c55ded

File tree

8 files changed

+86
-1
lines changed

8 files changed

+86
-1
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1703,7 +1703,8 @@ object CaptureSet:
17031703
else this(acc, parent)
17041704

17051705
def abstractTypeCase(acc: CaptureSet, t: TypeRef, upperBound: Type) =
1706-
if includeTypevars && upperBound.isExactlyAny then fresh(Origin.DeepCS(t))
1706+
if t.derivesFrom(defn.Caps_CapSet) then t.singletonCaptureSet
1707+
else if includeTypevars && upperBound.isExactlyAny then fresh(Origin.DeepCS(t))
17071708
else this(acc, upperBound)
17081709

17091710
collect(CaptureSet.empty, tp)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-- Error: tests/neg-custom-args/captures/i24309-region-orig.scala:17:36 ------------------------------------------------
2+
17 | val x = r1.subregion[Ref^{r1.R}]: r2 => // error, limitation
3+
| ^
4+
| Local reach capability r1.R leaks into capture scope of an enclosing function.
5+
| You could try to abstract the capabilities referred to by r1.R in a capset variable.
6+
18 | var a: Ref^{r1.R} = r1.alloc(0)
7+
19 | var b: Ref^{r2.R} = r2.alloc(0)
8+
20 | val c: Ref^{r1.R} = b
9+
21 | a
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import language.experimental.captureChecking
2+
import caps.*
3+
class Ref(private var x: Int):
4+
def get = x
5+
def set(y: Int) = x = y
6+
trait Region extends SharedCapability:
7+
r: Region^ =>
8+
type R^
9+
def alloc(x: Int): Ref^{R} = Ref(x)
10+
def subregion[T](f: (Region { type R >: r.R }) => T): T =
11+
class R2 extends Region:
12+
type R = r.R
13+
f(new R2)
14+
def withRegion[T](f: Region => T): T = f(new Region {})
15+
@main def main() =
16+
withRegion: r1 =>
17+
val x = r1.subregion[Ref^{r1.R}]: r2 => // error, limitation
18+
var a: Ref^{r1.R} = r1.alloc(0)
19+
var b: Ref^{r2.R} = r2.alloc(0)
20+
val c: Ref^{r1.R} = b
21+
a
22+
0
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-- Error: tests/neg-custom-args/captures/i24309a.scala:4:34 ------------------------------------------------------------
2+
4 |def runOps2[C^](): Unit = runOps[{C}](???) // error
3+
| ^
4+
| Capture set parameter C leaks into capture scope of method runOps2.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import language.experimental.captureChecking
2+
def runOps[C^](ops: List[() ->{C} Unit]): Unit = ???
3+
def runOps1[C^](xs: Object^{C}): Unit = runOps[{C}](???) // ok
4+
def runOps2[C^](): Unit = runOps[{C}](???) // error
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import language.experimental.captureChecking
2+
import language.experimental.separationChecking
3+
4+
import caps.*
5+
6+
object Regions:
7+
class Ref(private var x: Int):
8+
def get = x
9+
def set(y: Int) = x = y
10+
11+
trait Region[R^] extends SharedCapability:
12+
region: Region[R]^ =>
13+
def alloc(value: Int): Ref^{R} = Ref(value)
14+
15+
def subregion[T](f: [R2^ >: R] => (Region[R2]) => T): T =
16+
val r = new Region[R] {}
17+
f(r)
18+
19+
20+
object Region:
21+
def apply[T](f: [R^] => Region[R] => T): T =
22+
val r = new Region[{}] {}
23+
f(r)
24+
25+
@main def main() =
26+
import Region.*
27+
Region: [R^] =>
28+
r1 =>
29+
val x = r1.subregion: [R2^ >: R] =>
30+
r2 =>
31+
val a = r1.alloc(0)
32+
val b = r2.alloc(0)
33+
a
34+
0
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 Region[R^]
3+
def id[T](x: T): T = ???
4+
def foo[R^](r: Region[R]): Unit =
5+
val t2 = () => id[Object^{R}](???) // was error, now ok
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import language.experimental.captureChecking
2+
def runOps[C^](ops: List[() ->{C} Unit]): Unit = ops.foreach(_()) // ok
3+
trait Ops[C^] { def toList: List[() ->{C} Unit] }
4+
def runOpsAlt1[C1^](ops: Ops[C1]): Unit = runOps[{C1}](???) // was error, now ok
5+
def runOpsAlt2[C2^](ops: Ops[{}]^{C2}): Unit = runOps[{C2}](???) // ok
6+
def runOpsAlt3[C3^](ops: Ops[C3]^{C3}): Unit = runOps[{C3}](???) // was error, no ok

0 commit comments

Comments
 (0)