Skip to content

Commit 6977ad1

Browse files
committed
Handle TypeVars in CaptureSets
1 parent 988c4c0 commit 6977ad1

File tree

4 files changed

+32
-28
lines changed

4 files changed

+32
-28
lines changed

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

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,6 @@ case class CaptureSet private (elems: CaptureSet.Refs) extends Showable:
1717
def isEmpty: Boolean = elems.isEmpty
1818
def nonEmpty: Boolean = !isEmpty
1919

20-
private var myClosure: Refs | Null = null
21-
22-
def closure(using Context): Refs =
23-
if myClosure == null then
24-
var cl = elems
25-
var seen: Refs = SimpleIdentitySet.empty
26-
while
27-
val prev = cl
28-
for ref <- cl do
29-
if !seen.contains(ref) then
30-
seen += ref
31-
cl = cl ++ ref.captureSetOfInfo.elems
32-
prev ne cl
33-
do ()
34-
myClosure = cl
35-
myClosure
36-
3720
def ++ (that: CaptureSet): CaptureSet =
3821
if this.isEmpty then that
3922
else if that.isEmpty then this
@@ -101,9 +84,7 @@ object CaptureSet:
10184

10285
def ofType(tp: Type)(using Context): CaptureSet =
10386
def recur(tp: Type): CaptureSet = tp match
104-
case tp: NamedType =>
105-
tp.captureSet
106-
case tp: ParamRef =>
87+
case tp: CaptureRef =>
10788
tp.captureSet
10889
case CapturingType(parent, ref) =>
10990
recur(parent) + ref

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

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3620,7 +3620,7 @@ object Types {
36203620
case tp: TermParamRef if tp.binder eq thisLambdaType => TrueDeps
36213621
case tp: CapturingType =>
36223622
val status1 = compute(status, tp.parent, theAcc)
3623-
tp.ref match
3623+
tp.ref.stripTypeVar match
36243624
case tp: TermParamRef if tp.binder eq thisLambdaType => combine(status1, CaptureDeps)
36253625
case _ => status1
36263626
case _: ThisType | _: BoundType | NoPrefix => status
@@ -4505,9 +4505,10 @@ object Types {
45054505
* @param origin The parameter that's tracked by the type variable.
45064506
* @param creatorState The typer state in which the variable was created.
45074507
*/
4508-
final class TypeVar private(initOrigin: TypeParamRef, creatorState: TyperState, nestingLevel: Int) extends CachedProxyType with ValueType {
4508+
final class TypeVar private(initOrigin: TypeParamRef, creatorState: TyperState, nestingLevel: Int)
4509+
extends CachedProxyType, CaptureRef {
45094510

4510-
private var currentOrigin = initOrigin
4511+
private var currentOrigin = initOrigin
45114512

45124513
def origin: TypeParamRef = currentOrigin
45134514

@@ -4689,6 +4690,26 @@ object Types {
46894690
if (inst.exists) inst else origin
46904691
}
46914692

4693+
// Capture ref methods
4694+
4695+
def canBeTracked(using Context): Boolean = underlying match
4696+
case ref: CaptureRef => ref.canBeTracked
4697+
case _ => false
4698+
4699+
override def normalizedRef(using Context): CaptureRef = instanceOpt match
4700+
case ref: CaptureRef => ref
4701+
case _ => this
4702+
4703+
override def singletonCaptureSet(using Context) = instanceOpt match
4704+
case ref: CaptureRef => ref.singletonCaptureSet
4705+
case _ => super.singletonCaptureSet
4706+
4707+
override def captureSetOfInfo(using Context): CaptureSet = instanceOpt match
4708+
case ref: CaptureRef => ref.captureSetOfInfo
4709+
case tp => tp.captureSet
4710+
4711+
// Object members
4712+
46924713
override def computeHash(bs: Binders): Int = identityHash(bs)
46934714
override def equals(that: Any): Boolean = this.eq(that.asInstanceOf[AnyRef])
46944715

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,12 @@ class CheckCaptures extends RefineTypes:
9999
def checkWellFormed(whole: Type, pos: SrcPos)(using Context): Unit =
100100
def checkRelativeVariance(mt: MethodType) = new TypeTraverser:
101101
def traverse(tp: Type): Unit = tp match
102-
case CapturingType(parent, ref @ TermParamRef(`mt`, _)) =>
103-
if variance <= 0 then
104-
val direction = if variance < 0 then "contra" else "in"
105-
report.error(em"captured reference $ref appears ${direction}variantly in type $whole", pos)
102+
case CapturingType(parent, ref) =>
103+
ref.stripTypeVar match
104+
case ref @ TermParamRef(`mt`, _) if variance <= 0 =>
105+
val direction = if variance < 0 then "contra" else "in"
106+
report.error(em"captured reference $ref appears ${direction}variantly in type $whole", pos)
107+
case _ =>
106108
traverse(parent)
107109
case _ =>
108110
traverseChildren(tp)

tests/neg-custom-args/captures/try3.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import java.io.IOException
33
class CanThrow[E] extends Retains[*]
44
type Top = Any retains *
55

6-
def handle[E <: Exception, T <: Top](op: CanThrow[E] ?=> T)(handler: E => T): T =
6+
def handle[E <: Exception, T <: Top](op: (CanThrow[E] ?=> T) retains T)(handler: (E => T) retains T): T =
77
val x: CanThrow[E] = ???
88
try op(using x)
99
catch case ex: E => handler(ex)

0 commit comments

Comments
 (0)