Skip to content

Commit 5d1d274

Browse files
authored
Fix #21868, #21869, and #21870: handle CapsOf in more places (#21875)
Fix #21868, #21869, and #21870
2 parents 2be2a60 + a163f0c commit 5d1d274

File tree

8 files changed

+70
-4
lines changed

8 files changed

+70
-4
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ extension (tp: Type)
198198
|| tp.isRootCapability
199199
) && !tp.symbol.isOneOf(UnstableValueFlags)
200200
case tp: TypeRef =>
201-
tp.symbol.isAbstractOrParamType && tp.derivesFrom(defn.Caps_CapSet)
201+
tp.symbol.isType && tp.derivesFrom(defn.Caps_CapSet)
202202
case tp: TypeParamRef =>
203203
tp.derivesFrom(defn.Caps_CapSet)
204204
case AnnotatedType(parent, annot) =>

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

+2
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ trait CaptureRef extends TypeProxy, ValueType:
140140
case ReachCapability(x1) => x1.subsumes(y.stripReach)
141141
case x: TermRef => viaInfo(x.info)(subsumingRefs(_, y))
142142
case x: TermParamRef => subsumesExistentially(x, y)
143+
case x: TypeRef if x.symbol.info.derivesFrom(defn.Caps_CapSet) =>
144+
x.captureSetOfInfo.elems.exists(_.subsumes(y))
143145
case x: TypeRef => assumedContainsOf(x).contains(y)
144146
case _ => false
145147
end subsumes

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ object CheckCaptures:
135135
elem match
136136
case CapsOfApply(arg) =>
137137
def isLegalCapsOfArg =
138-
arg.symbol.isAbstractOrParamType && arg.symbol.info.derivesFrom(defn.Caps_CapSet)
138+
arg.symbol.isType && arg.symbol.info.derivesFrom(defn.Caps_CapSet)
139139
if !isLegalCapsOfArg then
140140
report.error(
141141
em"""$arg is not a legal prefix for `^` here,

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

+6-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import reporting.Message
1818
import printing.{Printer, Texts}, Texts.{Text, Str}
1919
import collection.mutable
2020
import CCState.*
21+
import dotty.tools.dotc.util.NoSourcePosition
2122

2223
/** Operations accessed from CheckCaptures */
2324
trait SetupAPI:
@@ -323,7 +324,11 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
323324
val parent2 = stripImpliedCaptureSet(parent1)
324325
for tpt <- tptToCheck do
325326
checkWellformedLater(parent2, ann.tree, tpt)
326-
CapturingType(parent2, ann.tree.toCaptureSet)
327+
try
328+
CapturingType(parent2, ann.tree.toCaptureSet)
329+
catch case ex: IllegalCaptureRef =>
330+
report.error(em"Illegal capture reference: ${ex.getMessage.nn}", tptToCheck.fold(NoSourcePosition)(_.srcPos))
331+
parent2
327332
else
328333
t.derivedAnnotatedType(parent1, ann)
329334
case throwsAlias(res, exc) =>

compiler/src/dotty/tools/dotc/core/Types.scala

+3-1
Original file line numberDiff line numberDiff line change
@@ -4007,7 +4007,7 @@ object Types extends TypeUtils {
40074007
(compute(status, parent, theAcc) /: refs.elems) {
40084008
(s, ref) => ref.stripReach match
40094009
case tp: TermParamRef if tp.binder eq thisLambdaType => combine(s, CaptureDeps)
4010-
case _ => s
4010+
case tp => combine(s, compute(status, tp, theAcc))
40114011
}
40124012
case _ =>
40134013
if tp.annot.refersToParamOf(thisLambdaType) then TrueDeps
@@ -6078,6 +6078,8 @@ object Types extends TypeUtils {
60786078
case tp: CaptureRef =>
60796079
if tp.isTrackableRef then tp
60806080
else ensureTrackable(tp.underlying)
6081+
case tp: TypeAlias =>
6082+
ensureTrackable(tp.alias)
60816083
case _ =>
60826084
assert(false, i"not a trackable captureRef ref: $result, ${result.underlyingIterator.toList}")
60836085
ensureTrackable(result)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import caps.*
2+
3+
class IO
4+
5+
case class File(io: IO^)
6+
7+
def test(io1: IO^, io2: IO^) =
8+
def f[C >: CapSet^{io1} <: CapSet^](file: File^{C^}) = ???
9+
val f1: File^{io1} = ???
10+
val f2: File^{io2} = ???
11+
val f3: File^{io1, io2} = ???
12+
f[CapSet^{io1}](f1)
13+
f[CapSet^{io1}](f2) // error
14+
f[CapSet^{io1}](f3) // error
15+
f[CapSet^{io2}](f2) // error
16+
f[CapSet^{io1, io2}](f1)
17+
f[CapSet^{io1, io2}](f2)
18+
f[CapSet^{io1, io2}](f3)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import caps.*
2+
3+
trait Foo extends Capability
4+
5+
trait CaptureSet:
6+
type C <: CapSet^
7+
8+
def capturePoly[C^](a: Foo^{C^}): Foo^{C^} = a
9+
def capturePoly2(c: CaptureSet)(a: Foo^{c.C^}): Foo^{c.C^} = a
10+
11+
def test =
12+
val x: Foo^ = ???
13+
val y: Foo^ = ???
14+
15+
object X extends CaptureSet:
16+
type C = CapSet^{x}
17+
18+
val z1: Foo^{X.C^} = x
19+
val z2: Foo^{X.C^} = y // error
20+
21+
val z3: Foo^{x} = capturePoly(x)
22+
val z4: Foo^{x} = capturePoly(y) // error
23+
24+
val z5: Foo^{x} = capturePoly2(X)(x)
25+
val z6: Foo^{x} = capturePoly2(X)(y) // error
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import caps.*
2+
3+
trait AbstractWrong:
4+
type C <: CapSet
5+
def boom(): Unit^{C^} // error
6+
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
14+

0 commit comments

Comments
 (0)