@@ -518,9 +518,43 @@ object Types extends TypeUtils {
518
518
def isDeclaredVarianceLambda : Boolean = false
519
519
520
520
/** Is this type a CaptureRef that can be tracked?
521
- * This is true for all ThisTypes or ParamRefs but only for some NamedTypes.
521
+ * This is true for
522
+ * - all ThisTypes and all TermParamRef,
523
+ * - stable TermRefs with NoPrefix or ThisTypes as prefixes,
524
+ * - the root capability `caps.cap`
525
+ * - abstract or parameter TypeRefs that derive from caps.CapSet
526
+ * - annotated types that represent reach or maybe capabilities
527
+ */
528
+ final def isTrackableRef (using Context ): Boolean = this match
529
+ case _ : (ThisType | TermParamRef ) =>
530
+ true
531
+ case tp : TermRef =>
532
+ ((tp.prefix eq NoPrefix )
533
+ || tp.symbol.is(ParamAccessor ) && tp.prefix.isThisTypeOf(tp.symbol.owner)
534
+ || tp.isRootCapability
535
+ ) && ! tp.symbol.isOneOf(UnstableValueFlags )
536
+ case tp : TypeRef =>
537
+ tp.symbol.isAbstractOrParamType && tp.derivesFrom(defn.Caps_CapSet )
538
+ case tp : TypeParamRef =>
539
+ tp.derivesFrom(defn.Caps_CapSet )
540
+ case AnnotatedType (parent, annot) =>
541
+ annot.symbol == defn.ReachCapabilityAnnot
542
+ || annot.symbol == defn.MaybeCapabilityAnnot
543
+ case _ =>
544
+ false
545
+
546
+ /** The capture set of a type. This is:
547
+ * - For trackable capture references: The singleton capture set consisting of
548
+ * just the reference, provided the underlying capture set of their info is not empty.
549
+ * - For other capture references: The capture set of their info
550
+ * - For all other types: The result of CaptureSet.ofType
522
551
*/
523
- def isTrackableRef (using Context ): Boolean = false
552
+ final def captureSet (using Context ): CaptureSet = this match
553
+ case tp : CaptureRef if tp.isTrackableRef =>
554
+ val cs = tp.captureSetOfInfo
555
+ if cs.isAlwaysEmpty then cs else tp.singletonCaptureSet
556
+ case tp : SingletonCaptureRef => tp.captureSetOfInfo
557
+ case _ => CaptureSet .ofType(this , followResult = false )
524
558
525
559
/** Does this type contain wildcard types? */
526
560
final def containsWildcardTypes (using Context ) =
@@ -1657,9 +1691,6 @@ object Types extends TypeUtils {
1657
1691
case _ => if (isRepeatedParam) this .argTypesHi.head else this
1658
1692
}
1659
1693
1660
- /** The capture set of this type. Overridden and cached in CaptureRef */
1661
- def captureSet (using Context ): CaptureSet = CaptureSet .ofType(this , followResult = false )
1662
-
1663
1694
// ----- Normalizing typerefs over refined types ----------------------------
1664
1695
1665
1696
/** If this normalizes* to a refinement type that has a refinement for `name` (which might be followed
@@ -2275,31 +2306,54 @@ object Types extends TypeUtils {
2275
2306
isTrackableRef && (isMaxCapability || ! captureSetOfInfo.isAlwaysEmpty)
2276
2307
2277
2308
/** Is this a reach reference of the form `x*`? */
2278
- def isReach (using Context ): Boolean = false // overridden in AnnotatedType
2309
+ final def isReach (using Context ): Boolean = this match
2310
+ case AnnotatedType (_, annot) => annot.symbol == defn.ReachCapabilityAnnot
2311
+ case _ => false
2279
2312
2280
2313
/** Is this a maybe reference of the form `x?`? */
2281
- def isMaybe (using Context ): Boolean = false // overridden in AnnotatedType
2314
+ final def isMaybe (using Context ): Boolean = this match
2315
+ case AnnotatedType (_, annot) => annot.symbol == defn.MaybeCapabilityAnnot
2316
+ case _ => false
2282
2317
2283
- def stripReach (using Context ): CaptureRef = this // overridden in AnnotatedType
2284
- def stripMaybe (using Context ): CaptureRef = this // overridden in AnnotatedType
2318
+ final def stripReach (using Context ): CaptureRef =
2319
+ if isReach then
2320
+ val AnnotatedType (parent : CaptureRef , _) = this : @ unchecked
2321
+ parent
2322
+ else this
2323
+
2324
+ final def stripMaybe (using Context ): CaptureRef =
2325
+ if isMaybe then
2326
+ val AnnotatedType (parent : CaptureRef , _) = this : @ unchecked
2327
+ parent
2328
+ else this
2285
2329
2286
2330
/** Is this reference the generic root capability `cap` ? */
2287
- def isRootCapability (using Context ): Boolean = false
2331
+ final def isRootCapability (using Context ): Boolean = this match
2332
+ case tp : TermRef => tp.name == nme.CAPTURE_ROOT && tp.symbol == defn.captureRoot
2333
+ case _ => false
2288
2334
2289
2335
/** Is this reference capability that does not derive from another capability ? */
2290
- def isMaxCapability (using Context ): Boolean = false
2336
+ final def isMaxCapability (using Context ): Boolean = this match
2337
+ case tp : TermRef => tp.isRootCapability || tp.info.derivesFrom(defn.Caps_Exists )
2338
+ case tp : TermParamRef => tp.underlying.derivesFrom(defn.Caps_Exists )
2339
+ case _ => false
2291
2340
2292
2341
/** Normalize reference so that it can be compared with `eq` for equality */
2293
- def normalizedRef (using Context ): CaptureRef = this
2342
+ final def normalizedRef (using Context ): CaptureRef = this match
2343
+ case tp @ AnnotatedType (parent : CaptureRef , annot) if isTrackableRef =>
2344
+ tp.derivedAnnotatedType(parent.normalizedRef, annot)
2345
+ case tp : TermRef if isTrackableRef =>
2346
+ tp.symbol.termRef
2347
+ case _ => this
2294
2348
2295
2349
/** The capture set consisting of exactly this reference */
2296
- def singletonCaptureSet (using Context ): CaptureSet .Const =
2350
+ final def singletonCaptureSet (using Context ): CaptureSet .Const =
2297
2351
if mySingletonCaptureSet == null then
2298
2352
mySingletonCaptureSet = CaptureSet (this .normalizedRef)
2299
2353
mySingletonCaptureSet.uncheckedNN
2300
2354
2301
2355
/** The capture set of the type underlying this reference */
2302
- def captureSetOfInfo (using Context ): CaptureSet =
2356
+ final def captureSetOfInfo (using Context ): CaptureSet =
2303
2357
if ctx.runId == myCaptureSetRunId then myCaptureSet.nn
2304
2358
else if myCaptureSet.asInstanceOf [AnyRef ] eq CaptureSet .Pending then CaptureSet .empty
2305
2359
else
@@ -2312,17 +2366,9 @@ object Types extends TypeUtils {
2312
2366
myCaptureSetRunId = ctx.runId
2313
2367
computed
2314
2368
2315
- def invalidateCaches () =
2369
+ final def invalidateCaches () =
2316
2370
myCaptureSetRunId = NoRunId
2317
2371
2318
- override def captureSet (using Context ): CaptureSet =
2319
- val cs = captureSetOfInfo
2320
- if isTrackableRef then
2321
- if cs.isAlwaysEmpty then cs else singletonCaptureSet
2322
- else dealias match
2323
- case _ : (TypeRef | TypeParamRef ) => CaptureSet .empty
2324
- case _ => cs
2325
-
2326
2372
end CaptureRef
2327
2373
2328
2374
trait SingletonCaptureRef extends SingletonType , CaptureRef
@@ -3015,26 +3061,6 @@ object Types extends TypeUtils {
3015
3061
def implicitName (using Context ): TermName = name
3016
3062
def underlyingRef : TermRef = this
3017
3063
3018
- /** A term reference can be tracked if it is a local term ref to a value
3019
- * or a method term parameter. References to term parameters of classes
3020
- * cannot be tracked individually.
3021
- * They are subsumed in the capture sets of the enclosing class.
3022
- * TODO: ^^^ What about call-by-name?
3023
- */
3024
- override def isTrackableRef (using Context ) =
3025
- ((prefix eq NoPrefix )
3026
- || symbol.is(ParamAccessor ) && prefix.isThisTypeOf(symbol.owner)
3027
- || isRootCapability
3028
- ) && ! symbol.isOneOf(UnstableValueFlags )
3029
-
3030
- override def isRootCapability (using Context ): Boolean =
3031
- name == nme.CAPTURE_ROOT && symbol == defn.captureRoot
3032
-
3033
- override def isMaxCapability (using Context ): Boolean =
3034
- symbol == defn.captureRoot || info.derivesFrom(defn.Caps_Exists )
3035
-
3036
- override def normalizedRef (using Context ): CaptureRef =
3037
- if isTrackableRef then symbol.termRef else this
3038
3064
}
3039
3065
3040
3066
abstract case class TypeRef (override val prefix : Type ,
@@ -3089,8 +3115,6 @@ object Types extends TypeUtils {
3089
3115
def validated (using Context ): this .type =
3090
3116
this
3091
3117
3092
- override def isTrackableRef (using Context ) =
3093
- symbol.isAbstractOrParamType && derivesFrom(defn.Caps_CapSet )
3094
3118
}
3095
3119
3096
3120
final class CachedTermRef (prefix : Type , designator : Designator , hc : Int ) extends TermRef (prefix, designator) {
@@ -3192,8 +3216,6 @@ object Types extends TypeUtils {
3192
3216
// can happen in IDE if `cls` is stale
3193
3217
}
3194
3218
3195
- override def isTrackableRef (using Context ) = true
3196
-
3197
3219
override def computeHash (bs : Binders ): Int = doHash(bs, tref)
3198
3220
3199
3221
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)
@@ -5834,30 +5851,6 @@ object Types extends TypeUtils {
5834
5851
isRefiningCache
5835
5852
}
5836
5853
5837
- override def isTrackableRef (using Context ) =
5838
- (isReach || isMaybe) && parent.isTrackableRef
5839
-
5840
- /** Is this a reach reference of the form `x*`? */
5841
- override def isReach (using Context ): Boolean =
5842
- annot.symbol == defn.ReachCapabilityAnnot
5843
-
5844
- /** Is this a reach reference of the form `x*`? */
5845
- override def isMaybe (using Context ): Boolean =
5846
- annot.symbol == defn.MaybeCapabilityAnnot
5847
-
5848
- override def stripReach (using Context ): CaptureRef =
5849
- if isReach then parent.asInstanceOf [CaptureRef ] else this
5850
-
5851
- override def stripMaybe (using Context ): CaptureRef =
5852
- if isMaybe then parent.asInstanceOf [CaptureRef ] else this
5853
-
5854
- override def normalizedRef (using Context ): CaptureRef =
5855
- if isReach then AnnotatedType (stripReach.normalizedRef, annot) else this
5856
-
5857
- override def captureSet (using Context ): CaptureSet =
5858
- if isReach then super .captureSet
5859
- else CaptureSet .ofType(this , followResult = false )
5860
-
5861
5854
// equals comes from case class; no matching override is needed
5862
5855
5863
5856
override def computeHash (bs : Binders ): Int =
0 commit comments