@@ -518,9 +518,43 @@ object Types extends TypeUtils {
518518 def isDeclaredVarianceLambda : Boolean = false
519519
520520 /** 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
522551 */
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 )
524558
525559 /** Does this type contain wildcard types? */
526560 final def containsWildcardTypes (using Context ) =
@@ -1657,9 +1691,6 @@ object Types extends TypeUtils {
16571691 case _ => if (isRepeatedParam) this .argTypesHi.head else this
16581692 }
16591693
1660- /** The capture set of this type. Overridden and cached in CaptureRef */
1661- def captureSet (using Context ): CaptureSet = CaptureSet .ofType(this , followResult = false )
1662-
16631694 // ----- Normalizing typerefs over refined types ----------------------------
16641695
16651696 /** 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 {
22752306 isTrackableRef && (isMaxCapability || ! captureSetOfInfo.isAlwaysEmpty)
22762307
22772308 /** 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
22792312
22802313 /** 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
22822317
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
22852329
22862330 /** 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
22882334
22892335 /** 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
22912340
22922341 /** 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
22942348
22952349 /** The capture set consisting of exactly this reference */
2296- def singletonCaptureSet (using Context ): CaptureSet .Const =
2350+ final def singletonCaptureSet (using Context ): CaptureSet .Const =
22972351 if mySingletonCaptureSet == null then
22982352 mySingletonCaptureSet = CaptureSet (this .normalizedRef)
22992353 mySingletonCaptureSet.uncheckedNN
23002354
23012355 /** The capture set of the type underlying this reference */
2302- def captureSetOfInfo (using Context ): CaptureSet =
2356+ final def captureSetOfInfo (using Context ): CaptureSet =
23032357 if ctx.runId == myCaptureSetRunId then myCaptureSet.nn
23042358 else if myCaptureSet.asInstanceOf [AnyRef ] eq CaptureSet .Pending then CaptureSet .empty
23052359 else
@@ -2312,17 +2366,9 @@ object Types extends TypeUtils {
23122366 myCaptureSetRunId = ctx.runId
23132367 computed
23142368
2315- def invalidateCaches () =
2369+ final def invalidateCaches () =
23162370 myCaptureSetRunId = NoRunId
23172371
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-
23262372 end CaptureRef
23272373
23282374 trait SingletonCaptureRef extends SingletonType , CaptureRef
@@ -3015,26 +3061,6 @@ object Types extends TypeUtils {
30153061 def implicitName (using Context ): TermName = name
30163062 def underlyingRef : TermRef = this
30173063
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
30383064 }
30393065
30403066 abstract case class TypeRef (override val prefix : Type ,
@@ -3089,8 +3115,6 @@ object Types extends TypeUtils {
30893115 def validated (using Context ): this .type =
30903116 this
30913117
3092- override def isTrackableRef (using Context ) =
3093- symbol.isAbstractOrParamType && derivesFrom(defn.Caps_CapSet )
30943118 }
30953119
30963120 final class CachedTermRef (prefix : Type , designator : Designator , hc : Int ) extends TermRef (prefix, designator) {
@@ -3192,8 +3216,6 @@ object Types extends TypeUtils {
31923216 // can happen in IDE if `cls` is stale
31933217 }
31943218
3195- override def isTrackableRef (using Context ) = true
3196-
31973219 override def computeHash (bs : Binders ): Int = doHash(bs, tref)
31983220
31993221 override def eql (that : Type ): Boolean = that match {
@@ -4836,9 +4858,6 @@ object Types extends TypeUtils {
48364858 type BT = TermLambda
48374859 def kindString : String = " Term"
48384860 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 )
48424861 }
48434862
48444863 private final class TermParamRefImpl (binder : TermLambda , paramNum : Int ) extends TermParamRef (binder, paramNum)
@@ -4867,8 +4886,6 @@ object Types extends TypeUtils {
48674886 case bound : OrType => occursIn(bound.tp1, fromBelow) || occursIn(bound.tp2, fromBelow)
48684887 case _ => false
48694888 }
4870-
4871- override def isTrackableRef (using Context ) = derivesFrom(defn.Caps_CapSet )
48724889 }
48734890
48744891 private final class TypeParamRefImpl (binder : TypeLambda , paramNum : Int ) extends TypeParamRef (binder, paramNum)
@@ -5834,30 +5851,6 @@ object Types extends TypeUtils {
58345851 isRefiningCache
58355852 }
58365853
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-
58615854 // equals comes from case class; no matching override is needed
58625855
58635856 override def computeHash (bs : Binders ): Int =
0 commit comments