@@ -96,7 +96,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
96
96
assert(canCompareAtoms == true )
97
97
assert(successCount == 0 )
98
98
assert(totalCount == 0 )
99
- assert(approx == FreshApprox )
99
+ assert(approx == ApproxState . Fresh )
100
100
assert(leftRoot == null )
101
101
assert(frozenGadt == false )
102
102
@@ -136,7 +136,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
136
136
else CompareResult .OK
137
137
138
138
/** The current approximation state. See `ApproxState`. */
139
- private var approx : ApproxState = FreshApprox
139
+ private var approx : ApproxState = ApproxState . Fresh
140
140
protected def approxState : ApproxState = approx
141
141
142
142
/** The original left-hand type of the comparison. Gets reset
@@ -156,8 +156,8 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
156
156
protected def isSubType (tp1 : Type , tp2 : Type , a : ApproxState ): Boolean = {
157
157
val savedApprox = approx
158
158
val savedLeftRoot = leftRoot
159
- if (a == FreshApprox ) {
160
- this .approx = NoApprox
159
+ if (a == ApproxState . Fresh ) {
160
+ this .approx = ApproxState . None
161
161
this .leftRoot = tp1
162
162
}
163
163
else this .approx = a
@@ -171,7 +171,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
171
171
}
172
172
}
173
173
174
- def isSubType (tp1 : Type , tp2 : Type ): Boolean = isSubType(tp1, tp2, FreshApprox )
174
+ def isSubType (tp1 : Type , tp2 : Type ): Boolean = isSubType(tp1, tp2, ApproxState . Fresh )
175
175
176
176
override protected def isSub (tp1 : Type , tp2 : Type )(using Context ): Boolean = isSubType(tp1, tp2)
177
177
@@ -190,7 +190,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
190
190
* code would have two extra parameters for each of the many calls that go from
191
191
* one sub-part of isSubType to another.
192
192
*/
193
- protected def recur (tp1 : Type , tp2 : Type ): Boolean = trace(s " isSubType ${traceInfo(tp1, tp2)} $approx" , subtyping) {
193
+ protected def recur (tp1 : Type , tp2 : Type ): Boolean = trace(s " isSubType ${traceInfo(tp1, tp2)} ${ approx.show} " , subtyping) {
194
194
195
195
def monitoredIsSubType = {
196
196
if (pendingSubTypes == null ) {
@@ -2442,34 +2442,37 @@ object TypeComparer {
2442
2442
case _ => String .valueOf(res)
2443
2443
}
2444
2444
2445
- private val LoApprox = 1
2446
- private val HiApprox = 2
2447
2445
2448
2446
/** The approximation state indicates how the pair of types currently compared
2449
2447
* relates to the types compared originally.
2450
- * - `NoApprox` : They are still the same types
2448
+ * - `None` : They are still the same types
2451
2449
* - `LoApprox`: The left type is approximated (i.e widened)"
2452
2450
* - `HiApprox`: The right type is approximated (i.e narrowed)"
2453
2451
*/
2454
- class ApproxState (private val bits : Int ) extends AnyVal {
2455
- override def toString : String = {
2456
- val lo = if ((bits & LoApprox ) != 0 ) " LoApprox" else " "
2457
- val hi = if ((bits & HiApprox ) != 0 ) " HiApprox" else " "
2458
- lo ++ hi
2459
- }
2460
- def addLow : ApproxState = new ApproxState (bits | LoApprox )
2461
- def addHigh : ApproxState = new ApproxState (bits | HiApprox )
2462
- def low : Boolean = (bits & LoApprox ) != 0
2463
- def high : Boolean = (bits & HiApprox ) != 0
2464
- }
2452
+ object ApproxState :
2453
+ opaque type Repr = Int
2465
2454
2466
- val NoApprox : ApproxState = new ApproxState (0 )
2455
+ val None : Repr = 0
2456
+ private val LoApprox = 1
2457
+ private val HiApprox = 2
2467
2458
2468
- /** A special approximation state to indicate that this is the first time we
2469
- * compare (approximations of) this pair of types. It's converted to `NoApprox`
2470
- * in `isSubType`, but also leads to `leftRoot` being set there.
2471
- */
2472
- val FreshApprox : ApproxState = new ApproxState (4 )
2459
+ /** A special approximation state to indicate that this is the first time we
2460
+ * compare (approximations of) this pair of types. It's converted to `None`
2461
+ * in `isSubType`, but also leads to `leftRoot` being set there.
2462
+ */
2463
+ val Fresh : Repr = 4
2464
+
2465
+ extension (approx : Repr ):
2466
+ def low : Boolean = (approx & LoApprox ) != 0
2467
+ def high : Boolean = (approx & HiApprox ) != 0
2468
+ def addLow : Repr = approx | LoApprox
2469
+ def addHigh : Repr = approx | HiApprox
2470
+ def show : String =
2471
+ val lo = if low then " LoApprox" else " "
2472
+ val hi = if high then " HiApprox" else " "
2473
+ lo ++ hi
2474
+ end ApproxState
2475
+ type ApproxState = ApproxState .Repr
2473
2476
2474
2477
def topLevelSubType (tp1 : Type , tp2 : Type )(using Context ): Boolean =
2475
2478
comparing(_.topLevelSubType(tp1, tp2))
@@ -2745,7 +2748,7 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
2745
2748
if Config .verboseExplainSubtype || ctx.settings.verbose.value
2746
2749
then s " ${tp1.getClass} ${tp2.getClass}"
2747
2750
else " "
2748
- traceIndented(s " ${show(tp1)} <:< ${show(tp2)}$moreInfo $approx ${if (frozenConstraint) " frozen" else " " }" ) {
2751
+ traceIndented(s " ${show(tp1)} <:< ${show(tp2)}$moreInfo ${ approx.show} ${if (frozenConstraint) " frozen" else " " }" ) {
2749
2752
super .isSubType(tp1, tp2, approx)
2750
2753
}
2751
2754
0 commit comments