Skip to content

Commit 4f1d91a

Browse files
committed
Refactor CaptureRef operations
Make all operations final methods on Type or CaptureRef
1 parent e8167e4 commit 4f1d91a

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
@@ -2831,18 +2831,6 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
28312831
false
28322832
Existential.isExistentialVar(tp1) && canInstantiateWith(assocExistentials)
28332833

2834-
/** Are tp1, tp2 termRefs that can be linked? This should never be called
2835-
* normally, since exietential variables appear only in capture sets
2836-
* which are in annotations that are ignored during normal typing. The real
2837-
* work is done in CaptureSet#subsumes which calls linkOK directly.
2838-
*/
2839-
private def existentialVarsConform(tp1: Type, tp2: Type) =
2840-
tp2 match
2841-
case tp2: TermParamRef => tp1 match
2842-
case tp1: CaptureRef if tp1.isTrackableRef => subsumesExistentially(tp2, tp1)
2843-
case _ => false
2844-
case _ => false
2845-
28462834
/** bi-map taking existentials to the left of a comparison to matching
28472835
* existentials on the right. This is not a bijection. However
28482836
* 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
@@ -523,9 +523,43 @@ object Types extends TypeUtils {
523523
def isDeclaredVarianceLambda: Boolean = false
524524

525525
/** 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
527556
*/
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)
529563

530564
/** Does this type contain wildcard types? */
531565
final def containsWildcardTypes(using Context) =
@@ -1653,9 +1687,6 @@ object Types extends TypeUtils {
16531687
case _ => if (isRepeatedParam) this.argTypesHi.head else this
16541688
}
16551689

1656-
/** The capture set of this type. Overridden and cached in CaptureRef */
1657-
def captureSet(using Context): CaptureSet = CaptureSet.ofType(this, followResult = false)
1658-
16591690
// ----- Normalizing typerefs over refined types ----------------------------
16601691

16611692
/** 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 {
22712302
isTrackableRef && (isMaxCapability || !captureSetOfInfo.isAlwaysEmpty)
22722303

22732304
/** 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
22752308

22762309
/** 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
22782313

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
22812325

22822326
/** 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
22842330

22852331
/** 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
22872336

22882337
/** 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
22902344

22912345
/** The capture set consisting of exactly this reference */
2292-
def singletonCaptureSet(using Context): CaptureSet.Const =
2346+
final def singletonCaptureSet(using Context): CaptureSet.Const =
22932347
if mySingletonCaptureSet == null then
22942348
mySingletonCaptureSet = CaptureSet(this.normalizedRef)
22952349
mySingletonCaptureSet.uncheckedNN
22962350

22972351
/** The capture set of the type underlying this reference */
2298-
def captureSetOfInfo(using Context): CaptureSet =
2352+
final def captureSetOfInfo(using Context): CaptureSet =
22992353
if ctx.runId == myCaptureSetRunId then myCaptureSet.nn
23002354
else if myCaptureSet.asInstanceOf[AnyRef] eq CaptureSet.Pending then CaptureSet.empty
23012355
else
@@ -2308,17 +2362,9 @@ object Types extends TypeUtils {
23082362
myCaptureSetRunId = ctx.runId
23092363
computed
23102364

2311-
def invalidateCaches() =
2365+
final def invalidateCaches() =
23122366
myCaptureSetRunId = NoRunId
23132367

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-
23222368
end CaptureRef
23232369

23242370
trait SingletonCaptureRef extends SingletonType, CaptureRef
@@ -3011,26 +3057,6 @@ object Types extends TypeUtils {
30113057
def implicitName(using Context): TermName = name
30123058
def underlyingRef: TermRef = this
30133059

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
30343060
}
30353061

30363062
abstract case class TypeRef(override val prefix: Type,
@@ -3085,8 +3111,6 @@ object Types extends TypeUtils {
30853111
def validated(using Context): this.type =
30863112
this
30873113

3088-
override def isTrackableRef(using Context) =
3089-
symbol.isAbstractOrParamType && derivesFrom(defn.Caps_CapSet)
30903114
}
30913115

30923116
final class CachedTermRef(prefix: Type, designator: Designator, hc: Int) extends TermRef(prefix, designator) {
@@ -3188,8 +3212,6 @@ object Types extends TypeUtils {
31883212
// can happen in IDE if `cls` is stale
31893213
}
31903214

3191-
override def isTrackableRef(using Context) = true
3192-
31933215
override def computeHash(bs: Binders): Int = doHash(bs, tref)
31943216

31953217
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)
@@ -5831,30 +5848,6 @@ object Types extends TypeUtils {
58315848
isRefiningCache
58325849
}
58335850

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-
58585851
// equals comes from case class; no matching override is needed
58595852

58605853
override def computeHash(bs: Binders): Int =

0 commit comments

Comments
 (0)