@@ -523,9 +523,43 @@ object Types extends TypeUtils {
523
523
def isDeclaredVarianceLambda : Boolean = false
524
524
525
525
/** Is this type a CaptureRef that can be tracked?
526
- * This is true for all ThisTypes or ParamRefs but only for some NamedTypes.
526
+ * This is true for
527
+ * - all ThisTypes and all TermParamRef,
528
+ * - stable TermRefs with NoPrefix or ThisTypes as prefixes,
529
+ * - the root capability `caps.cap`
530
+ * - abstract or parameter TypeRefs that derive from caps.CapSet
531
+ * - annotated types that represent reach or maybe capabilities
532
+ */
533
+ final def isTrackableRef (using Context ): Boolean = this match
534
+ case _ : (ThisType | TermParamRef ) =>
535
+ true
536
+ case tp : TermRef =>
537
+ ((tp.prefix eq NoPrefix )
538
+ || tp.symbol.is(ParamAccessor ) && tp.prefix.isThisTypeOf(tp.symbol.owner)
539
+ || tp.isRootCapability
540
+ ) && ! tp.symbol.isOneOf(UnstableValueFlags )
541
+ case tp : TypeRef =>
542
+ tp.symbol.isAbstractOrParamType && tp.derivesFrom(defn.Caps_CapSet )
543
+ case tp : TypeParamRef =>
544
+ tp.derivesFrom(defn.Caps_CapSet )
545
+ case AnnotatedType (parent, annot) =>
546
+ annot.symbol == defn.ReachCapabilityAnnot
547
+ || annot.symbol == defn.MaybeCapabilityAnnot
548
+ case _ =>
549
+ false
550
+
551
+ /** The capture set of a type. This is:
552
+ * - For trackable capture references: The singleton capture set consisting of
553
+ * just the reference, provided the underlying capture set of their info is not empty.
554
+ * - For other capture references: The capture set of their info
555
+ * - For all other types: The result of CaptureSet.ofType
527
556
*/
528
- def isTrackableRef (using Context ): Boolean = false
557
+ final def captureSet (using Context ): CaptureSet = this match
558
+ case tp : CaptureRef if tp.isTrackableRef =>
559
+ val cs = tp.captureSetOfInfo
560
+ if cs.isAlwaysEmpty then cs else tp.singletonCaptureSet
561
+ case tp : SingletonCaptureRef => tp.captureSetOfInfo
562
+ case _ => CaptureSet .ofType(this , followResult = false )
529
563
530
564
/** Does this type contain wildcard types? */
531
565
final def containsWildcardTypes (using Context ) =
@@ -1653,9 +1687,6 @@ object Types extends TypeUtils {
1653
1687
case _ => if (isRepeatedParam) this .argTypesHi.head else this
1654
1688
}
1655
1689
1656
- /** The capture set of this type. Overridden and cached in CaptureRef */
1657
- def captureSet (using Context ): CaptureSet = CaptureSet .ofType(this , followResult = false )
1658
-
1659
1690
// ----- Normalizing typerefs over refined types ----------------------------
1660
1691
1661
1692
/** If this normalizes* to a refinement type that has a refinement for `name` (which might be followed
@@ -2271,31 +2302,54 @@ object Types extends TypeUtils {
2271
2302
isTrackableRef && (isMaxCapability || ! captureSetOfInfo.isAlwaysEmpty)
2272
2303
2273
2304
/** Is this a reach reference of the form `x*`? */
2274
- def isReach (using Context ): Boolean = false // overridden in AnnotatedType
2305
+ final def isReach (using Context ): Boolean = this match
2306
+ case AnnotatedType (_, annot) => annot.symbol == defn.ReachCapabilityAnnot
2307
+ case _ => false
2275
2308
2276
2309
/** Is this a maybe reference of the form `x?`? */
2277
- def isMaybe (using Context ): Boolean = false // overridden in AnnotatedType
2310
+ final def isMaybe (using Context ): Boolean = this match
2311
+ case AnnotatedType (_, annot) => annot.symbol == defn.MaybeCapabilityAnnot
2312
+ case _ => false
2278
2313
2279
- def stripReach (using Context ): CaptureRef = this // overridden in AnnotatedType
2280
- def stripMaybe (using Context ): CaptureRef = this // overridden in AnnotatedType
2314
+ final def stripReach (using Context ): CaptureRef =
2315
+ if isReach then
2316
+ val AnnotatedType (parent : CaptureRef , _) = this : @ unchecked
2317
+ parent
2318
+ else this
2319
+
2320
+ final def stripMaybe (using Context ): CaptureRef =
2321
+ if isMaybe then
2322
+ val AnnotatedType (parent : CaptureRef , _) = this : @ unchecked
2323
+ parent
2324
+ else this
2281
2325
2282
2326
/** Is this reference the generic root capability `cap` ? */
2283
- def isRootCapability (using Context ): Boolean = false
2327
+ final def isRootCapability (using Context ): Boolean = this match
2328
+ case tp : TermRef => tp.name == nme.CAPTURE_ROOT && tp.symbol == defn.captureRoot
2329
+ case _ => false
2284
2330
2285
2331
/** Is this reference capability that does not derive from another capability ? */
2286
- def isMaxCapability (using Context ): Boolean = false
2332
+ final def isMaxCapability (using Context ): Boolean = this match
2333
+ case tp : TermRef => tp.isRootCapability || tp.info.derivesFrom(defn.Caps_Exists )
2334
+ case tp : TermParamRef => tp.underlying.derivesFrom(defn.Caps_Exists )
2335
+ case _ => false
2287
2336
2288
2337
/** Normalize reference so that it can be compared with `eq` for equality */
2289
- def normalizedRef (using Context ): CaptureRef = this
2338
+ final def normalizedRef (using Context ): CaptureRef = this match
2339
+ case tp @ AnnotatedType (parent : CaptureRef , annot) if isTrackableRef =>
2340
+ tp.derivedAnnotatedType(parent.normalizedRef, annot)
2341
+ case tp : TermRef if isTrackableRef =>
2342
+ tp.symbol.termRef
2343
+ case _ => this
2290
2344
2291
2345
/** The capture set consisting of exactly this reference */
2292
- def singletonCaptureSet (using Context ): CaptureSet .Const =
2346
+ final def singletonCaptureSet (using Context ): CaptureSet .Const =
2293
2347
if mySingletonCaptureSet == null then
2294
2348
mySingletonCaptureSet = CaptureSet (this .normalizedRef)
2295
2349
mySingletonCaptureSet.uncheckedNN
2296
2350
2297
2351
/** The capture set of the type underlying this reference */
2298
- def captureSetOfInfo (using Context ): CaptureSet =
2352
+ final def captureSetOfInfo (using Context ): CaptureSet =
2299
2353
if ctx.runId == myCaptureSetRunId then myCaptureSet.nn
2300
2354
else if myCaptureSet.asInstanceOf [AnyRef ] eq CaptureSet .Pending then CaptureSet .empty
2301
2355
else
@@ -2308,17 +2362,9 @@ object Types extends TypeUtils {
2308
2362
myCaptureSetRunId = ctx.runId
2309
2363
computed
2310
2364
2311
- def invalidateCaches () =
2365
+ final def invalidateCaches () =
2312
2366
myCaptureSetRunId = NoRunId
2313
2367
2314
- override def captureSet (using Context ): CaptureSet =
2315
- val cs = captureSetOfInfo
2316
- if isTrackableRef then
2317
- if cs.isAlwaysEmpty then cs else singletonCaptureSet
2318
- else dealias match
2319
- case _ : (TypeRef | TypeParamRef ) => CaptureSet .empty
2320
- case _ => cs
2321
-
2322
2368
end CaptureRef
2323
2369
2324
2370
trait SingletonCaptureRef extends SingletonType , CaptureRef
@@ -3011,26 +3057,6 @@ object Types extends TypeUtils {
3011
3057
def implicitName (using Context ): TermName = name
3012
3058
def underlyingRef : TermRef = this
3013
3059
3014
- /** A term reference can be tracked if it is a local term ref to a value
3015
- * or a method term parameter. References to term parameters of classes
3016
- * cannot be tracked individually.
3017
- * They are subsumed in the capture sets of the enclosing class.
3018
- * TODO: ^^^ What about call-by-name?
3019
- */
3020
- override def isTrackableRef (using Context ) =
3021
- ((prefix eq NoPrefix )
3022
- || symbol.is(ParamAccessor ) && prefix.isThisTypeOf(symbol.owner)
3023
- || isRootCapability
3024
- ) && ! symbol.isOneOf(UnstableValueFlags )
3025
-
3026
- override def isRootCapability (using Context ): Boolean =
3027
- name == nme.CAPTURE_ROOT && symbol == defn.captureRoot
3028
-
3029
- override def isMaxCapability (using Context ): Boolean =
3030
- symbol == defn.captureRoot || info.derivesFrom(defn.Caps_Exists )
3031
-
3032
- override def normalizedRef (using Context ): CaptureRef =
3033
- if isTrackableRef then symbol.termRef else this
3034
3060
}
3035
3061
3036
3062
abstract case class TypeRef (override val prefix : Type ,
@@ -3085,8 +3111,6 @@ object Types extends TypeUtils {
3085
3111
def validated (using Context ): this .type =
3086
3112
this
3087
3113
3088
- override def isTrackableRef (using Context ) =
3089
- symbol.isAbstractOrParamType && derivesFrom(defn.Caps_CapSet )
3090
3114
}
3091
3115
3092
3116
final class CachedTermRef (prefix : Type , designator : Designator , hc : Int ) extends TermRef (prefix, designator) {
@@ -3188,8 +3212,6 @@ object Types extends TypeUtils {
3188
3212
// can happen in IDE if `cls` is stale
3189
3213
}
3190
3214
3191
- override def isTrackableRef (using Context ) = true
3192
-
3193
3215
override def computeHash (bs : Binders ): Int = doHash(bs, tref)
3194
3216
3195
3217
override def eql (that : Type ): Boolean = that match {
@@ -4836,9 +4858,6 @@ object Types extends TypeUtils {
4836
4858
type BT = TermLambda
4837
4859
def kindString : String = " Term"
4838
4860
def copyBoundType (bt : BT ): Type = bt.paramRefs(paramNum)
4839
- override def isTrackableRef (using Context ) = true
4840
- override def isMaxCapability (using Context ) =
4841
- underlying.derivesFrom(defn.Caps_Exists )
4842
4861
}
4843
4862
4844
4863
private final class TermParamRefImpl (binder : TermLambda , paramNum : Int ) extends TermParamRef (binder, paramNum)
@@ -4867,8 +4886,6 @@ object Types extends TypeUtils {
4867
4886
case bound : OrType => occursIn(bound.tp1, fromBelow) || occursIn(bound.tp2, fromBelow)
4868
4887
case _ => false
4869
4888
}
4870
-
4871
- override def isTrackableRef (using Context ) = derivesFrom(defn.Caps_CapSet )
4872
4889
}
4873
4890
4874
4891
private final class TypeParamRefImpl (binder : TypeLambda , paramNum : Int ) extends TypeParamRef (binder, paramNum)
@@ -5831,30 +5848,6 @@ object Types extends TypeUtils {
5831
5848
isRefiningCache
5832
5849
}
5833
5850
5834
- override def isTrackableRef (using Context ) =
5835
- (isReach || isMaybe) && parent.isTrackableRef
5836
-
5837
- /** Is this a reach reference of the form `x*`? */
5838
- override def isReach (using Context ): Boolean =
5839
- annot.symbol == defn.ReachCapabilityAnnot
5840
-
5841
- /** Is this a reach reference of the form `x*`? */
5842
- override def isMaybe (using Context ): Boolean =
5843
- annot.symbol == defn.MaybeCapabilityAnnot
5844
-
5845
- override def stripReach (using Context ): CaptureRef =
5846
- if isReach then parent.asInstanceOf [CaptureRef ] else this
5847
-
5848
- override def stripMaybe (using Context ): CaptureRef =
5849
- if isMaybe then parent.asInstanceOf [CaptureRef ] else this
5850
-
5851
- override def normalizedRef (using Context ): CaptureRef =
5852
- if isReach then AnnotatedType (stripReach.normalizedRef, annot) else this
5853
-
5854
- override def captureSet (using Context ): CaptureSet =
5855
- if isReach then super .captureSet
5856
- else CaptureSet .ofType(this , followResult = false )
5857
-
5858
5851
// equals comes from case class; no matching override is needed
5859
5852
5860
5853
override def computeHash (bs : Binders ): Int =
0 commit comments