Skip to content

Commit bb94805

Browse files
committed
Refactor CaptureRef operations
Make all operations final methods on Type or CaptureRef
1 parent bc818a9 commit bb94805

File tree

2 files changed

+69
-88
lines changed

2 files changed

+69
-88
lines changed

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

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2834,18 +2834,6 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
28342834
false
28352835
Existential.isExistentialVar(tp1) && canInstantiateWith(assocExistentials)
28362836

2837-
/** Are tp1, tp2 termRefs that can be linked? This should never be called
2838-
* normally, since exietential variables appear only in capture sets
2839-
* which are in annotations that are ignored during normal typing. The real
2840-
* work is done in CaptureSet#subsumes which calls linkOK directly.
2841-
*/
2842-
private def existentialVarsConform(tp1: Type, tp2: Type) =
2843-
tp2 match
2844-
case tp2: TermParamRef => tp1 match
2845-
case tp1: CaptureRef if tp1.isTrackableRef => subsumesExistentially(tp2, tp1)
2846-
case _ => false
2847-
case _ => false
2848-
28492837
/** bi-map taking existentials to the left of a comparison to matching
28502838
* existentials on the right. This is not a bijection. However
28512839
* we have `forwards(backwards(bv)) == bv` for an existentially bound `bv`.

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

Lines changed: 69 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)