@@ -104,7 +104,8 @@ sealed abstract class CaptureSet extends Showable:
104
104
105
105
final def isUnboxable (using Context ) =
106
106
elems.exists:
107
- case Existential .Var (_) => true
107
+ case Existential .VarOLD (_) => true
108
+ case Existential .Vble (_) => true
108
109
case elem => elem.isRootCapability
109
110
110
111
final def isReadOnly (using Context ): Boolean =
@@ -547,7 +548,7 @@ object CaptureSet:
547
548
final def addThisElem (elem : CaptureRef )(using Context , VarState ): CompareResult =
548
549
if isConst || ! recordElemsState() then // Fail if variable is solved or given VarState is frozen
549
550
addIfHiddenOrFail(elem)
550
- else if Existential .isBadExistential (elem) then // Fail if `elem` is an out-of-scope existential
551
+ else if Existential .isBadExistentialOLD (elem) then // Fail if `elem` is an out-of-scope existential
551
552
CompareResult .Fail (this :: Nil )
552
553
else if ! levelOK(elem) then
553
554
CompareResult .LevelError (this , elem) // or `elem` is not visible at the level of the set.
@@ -567,15 +568,21 @@ object CaptureSet:
567
568
elems -= elem
568
569
res.addToTrace(this )
569
570
571
+ // TODO: Also track allowable TermParamRefs and Existential.Vbles in capture sets
570
572
private def levelOK (elem : CaptureRef )(using Context ): Boolean =
571
573
if elem.isRootCapability then
572
574
! noUniversal
573
575
else elem match
574
- case Existential .Var (bv) =>
576
+ case Existential .VarOLD (bv) =>
575
577
! noUniversal
576
578
&& ! TypeComparer .isOpenedExistential(bv)
577
579
// Opened existentials on the left cannot be added to nested capture sets on the right
578
580
// of a comparison. Test case is open-existential.scala.
581
+ case elem @ Existential .Vble (mt) =>
582
+ ! noUniversal
583
+ && ! TypeComparer .isOpenedExistential(elem)
584
+ // Opened existentials on the left cannot be added to nested capture sets on the right
585
+ // of a comparison. Test case is open-existential.scala.
579
586
case elem : TermRef if level.isDefined =>
580
587
elem.prefix match
581
588
case prefix : CaptureRef =>
@@ -629,7 +636,8 @@ object CaptureSet:
629
636
try
630
637
val approx = computeApprox(origin).ensuring(_.isConst)
631
638
if approx.elems.exists:
632
- case Existential .Var (_) => true
639
+ case Existential .VarOLD (_) => true
640
+ case Existential .Vble (_) => true
633
641
case _ => false
634
642
then
635
643
ccState.approxWarnings +=
@@ -1304,7 +1312,7 @@ object CaptureSet:
1304
1312
ref1.captureSetOfInfo.map(ReadOnlyMap ())
1305
1313
case _ =>
1306
1314
if ref.isMaxCapability then ref.singletonCaptureSet
1307
- else ofType(ref.underlying, followResult = true )
1315
+ else ofType(ref.underlying, followResult = true ) // TODO: why followResult = true?
1308
1316
1309
1317
/** Capture set of a type */
1310
1318
def ofType (tp : Type , followResult : Boolean )(using Context ): CaptureSet =
@@ -1317,7 +1325,9 @@ object CaptureSet:
1317
1325
case tp : (TypeRef | TypeParamRef ) =>
1318
1326
if tp.derivesFrom(defn.Caps_CapSet ) then tp.captureSet
1319
1327
else empty
1320
- case tp @ Existential .Var (_) =>
1328
+ case tp @ Existential .VarOLD (_) =>
1329
+ tp.captureSet
1330
+ case tp @ Existential .Vble (_) =>
1321
1331
tp.captureSet
1322
1332
case CapturingType (parent, refs) =>
1323
1333
recur(parent) ++ refs
@@ -1332,8 +1342,11 @@ object CaptureSet:
1332
1342
CaptureSet .ofTypeDeeply(parent.widen)
1333
1343
case tpd @ defn.RefinedFunctionOf (rinfo : MethodType ) if followResult =>
1334
1344
ofType(tpd.parent, followResult = false ) // pick up capture set from parent type
1335
- ++ (recur(rinfo.resType) // add capture set of result
1336
- -- CaptureSet (rinfo.paramRefs.filter(_.isTracked)* )) // but disregard bound parameters
1345
+ ++ recur(rinfo.resType) // add capture set of result
1346
+ .filter:
1347
+ case TermParamRef (binder, _) => binder ne rinfo
1348
+ case Existential .Vble (binder) => binder ne rinfo
1349
+ case _ => true
1337
1350
case tpd @ AppliedType (tycon, args) =>
1338
1351
if followResult && defn.isNonRefinedFunction(tpd) then
1339
1352
recur(args.last)
@@ -1359,7 +1372,7 @@ object CaptureSet:
1359
1372
* capture sets. Nested existential sets are approximated with `cap`.
1360
1373
* NOTE: The traversal logic needs to be in sync with narrowCaps in CaptureOps, which
1361
1374
* replaces caps with reach capabilties. The one exception to this is invariant
1362
- * arguments. This have to be included to be conservative in dcs but must be
1375
+ * arguments. These have to be included to be conservative in dcs but must be
1363
1376
* excluded in narrowCaps.
1364
1377
*/
1365
1378
def ofTypeDeeply (tp : Type , includeTypevars : Boolean = false )(using Context ): CaptureSet =
@@ -1377,9 +1390,9 @@ object CaptureSet:
1377
1390
val upper = t.info.bounds.hi
1378
1391
if includeTypevars && upper.isExactlyAny then CaptureSet .fresh(t.symbol)
1379
1392
else this (cs, upper)
1380
- case t @ FunctionOrMethod (args, res @ Existential (_, _))
1381
- if args.forall(_.isAlwaysPure) =>
1382
- this (cs, Existential .toCap(res))
1393
+ case t @ FunctionOrMethod (args, res) =>
1394
+ if args.forall(_.isAlwaysPure) then this (cs, Existential .toCap(res))
1395
+ else cs
1383
1396
case t @ Existential (_, _) =>
1384
1397
cs
1385
1398
case _ =>
0 commit comments