Skip to content

Commit 092b358

Browse files
committed
Add constraint to capsOf
1 parent 8a15af3 commit 092b358

File tree

7 files changed

+53
-22
lines changed

7 files changed

+53
-22
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,9 @@ sealed abstract class CaptureSet extends Showable:
161161
def debugInfo(using Context) = i"$this accountsFor $x, which has capture set ${x.captureSetOfInfo}"
162162
def test(using Context) = reporting.trace(debugInfo):
163163
elems.exists(_.subsumes(x))
164-
|| !x.isMaxCapability && x.captureSetOfInfo.subCaptures(this, frozen = true).isOK
164+
|| !x.isMaxCapability
165+
&& !x.derivesFrom(defn.Caps_CapSet)
166+
&& x.captureSetOfInfo.subCaptures(this, frozen = true).isOK
165167
comparer match
166168
case comparer: ExplainingTypeComparer => comparer.traceIndented(debugInfo)(test)
167169
case _ => test

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
117117
* The info of these symbols is made fluid.
118118
*/
119119
def isPreCC(sym: Symbol)(using Context): Boolean =
120+
// TODO: check type members as well
120121
sym.isTerm && sym.maybeOwner.isClass
121122
&& !sym.is(Module)
122123
&& !sym.owner.is(CaptureChecked)
@@ -866,7 +867,9 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
866867
if others.accountsFor(ref) then
867868
report.warning(em"redundant capture: $dom already accounts for $ref", pos)
868869

869-
if ref.captureSetOfInfo.elems.isEmpty && !ref.derivesFrom(defn.Caps_Capability) then
870+
if ref.captureSetOfInfo.elems.isEmpty
871+
&& !ref.derivesFrom(defn.Caps_Capability)
872+
&& !ref.derivesFrom(defn.Caps_CapSet) then
870873
val deepStr = if ref.isReach then " deep" else ""
871874
report.error(em"$ref cannot be tracked since its$deepStr capture set is empty", pos)
872875
check(parent.captureSet, parent)

library/src/scala/caps.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import annotation.{experimental, compileTimeOnly, retainsCap}
3333
* @retains annotation. E.g. `^{x, Y^}` is represented as `@retains(x, capsOf[Y])`.
3434
*/
3535
@compileTimeOnly("Should be be used only internally by the Scala compiler")
36-
def capsOf[CS]: Any = ???
36+
def capsOf[CS >: CapSet <: CapSet @retainsCap]: Any = ???
3737

3838
/** Reach capabilities x* which appear as terms in @retains annotations are encoded
3939
* as `caps.reachCapability(x)`. When converted to CaptureRef types in capture sets

tests/neg-custom-args/captures/capset-members.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ class Concrete3 extends Abstract[CapSet^{}]:
1616
type C = CapSet^{} | CapSet^{}
1717
def boom() = ()
1818

19-
class Concrete4 extends Abstract[CapSet^{}]:
20-
type C = Nothing // error
19+
class Concrete4 extends Abstract[CapSet^]:
20+
type C = CapSet // error
2121
def boom() = ()
Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import caps.*
22

33
trait AbstractWrong:
4-
type C <: CapSet
5-
def boom(): Unit^{C^} // error
4+
type C <: CapSet
5+
def f(): Unit^{C^} // error
66

7-
trait Abstract:
8-
type C <: CapSet^
9-
def boom(): Unit^{C^}
10-
11-
class Concrete extends Abstract:
12-
type C = Nothing
13-
def boom() = () // error
7+
trait Abstract1:
8+
type C^
9+
def f(): Unit^{C^}
1410

11+
class Abstract2:
12+
type C >: CapSet <: CapSet^
13+
def f(): Unit^{C^}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import caps.*
2+
3+
class IO
4+
5+
class File
6+
7+
trait Abstract:
8+
type C >: CapSet <: CapSet^
9+
def f(file: File^{C^}): Unit
10+
11+
class Concrete1 extends Abstract:
12+
type C = CapSet
13+
def f(file: File) = ()
14+
15+
class Concrete2(io: IO^) extends Abstract:
16+
type C = CapSet^{io}
17+
def f(file: File^{io}) = ()
18+
19+
class Concrete3(io: IO^) extends Abstract:
20+
type C = CapSet^{io}
21+
def f(file: File) = () // error
22+
23+
trait Abstract2(io: IO^):
24+
type C >: CapSet <: CapSet^{io}
25+
def f(file: File^{C^}): Unit
26+
27+
class Concrete4(io: IO^) extends Abstract2(io):
28+
type C = CapSet
29+
def f(file: File) = ()
30+
31+
class Concrete5(io1: IO^, io2: IO^) extends Abstract2(io1):
32+
type C = CapSet^{io2} // error
33+
def f(file: File^{io2}) = ()

tests/pos-custom-args/captures/cc-poly-varargs.scala

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,7 @@ def either[T1, T2, Cap^](
1313
val left = src1.transformValuesWith(Left(_))
1414
val right = src2.transformValuesWith(Right(_))
1515
race[Either[T1, T2], Cap](left, right)
16-
// An explcit type argument is required here because the second argument is
17-
// inferred as `CapSet^{Cap^}` instead of `Cap`.
16+
// Explcit type arguments are required here because the second argument
17+
// is inferred as `CapSet^{Cap^}` instead of `Cap`.
1818
// Although `CapSet^{Cap^}` subsums `Cap` in terms of capture set,
1919
// `Cap` is not a subtype of `CapSet^{Cap^}` in terms of subtyping.
20-
21-
22-
23-
24-
25-

0 commit comments

Comments
 (0)