@@ -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 ) {
@@ -2509,34 +2509,37 @@ object TypeComparer {
2509
2509
case _ => String .valueOf(res)
2510
2510
}
2511
2511
2512
- private val LoApprox = 1
2513
- private val HiApprox = 2
2514
2512
2515
2513
/** The approximation state indicates how the pair of types currently compared
2516
2514
* relates to the types compared originally.
2517
- * - `NoApprox` : They are still the same types
2515
+ * - `None` : They are still the same types
2518
2516
* - `LoApprox`: The left type is approximated (i.e widened)"
2519
2517
* - `HiApprox`: The right type is approximated (i.e narrowed)"
2520
2518
*/
2521
- class ApproxState (private val bits : Int ) extends AnyVal {
2522
- override def toString : String = {
2523
- val lo = if ((bits & LoApprox ) != 0 ) " LoApprox" else " "
2524
- val hi = if ((bits & HiApprox ) != 0 ) " HiApprox" else " "
2525
- lo ++ hi
2526
- }
2527
- def addLow : ApproxState = new ApproxState (bits | LoApprox )
2528
- def addHigh : ApproxState = new ApproxState (bits | HiApprox )
2529
- def low : Boolean = (bits & LoApprox ) != 0
2530
- def high : Boolean = (bits & HiApprox ) != 0
2531
- }
2519
+ object ApproxState :
2520
+ opaque type Repr = Int
2532
2521
2533
- val NoApprox : ApproxState = new ApproxState (0 )
2522
+ val None : Repr = 0
2523
+ private val LoApprox = 1
2524
+ private val HiApprox = 2
2534
2525
2535
- /** A special approximation state to indicate that this is the first time we
2536
- * compare (approximations of) this pair of types. It's converted to `NoApprox`
2537
- * in `isSubType`, but also leads to `leftRoot` being set there.
2538
- */
2539
- val FreshApprox : ApproxState = new ApproxState (4 )
2526
+ /** A special approximation state to indicate that this is the first time we
2527
+ * compare (approximations of) this pair of types. It's converted to `None`
2528
+ * in `isSubType`, but also leads to `leftRoot` being set there.
2529
+ */
2530
+ val Fresh : Repr = 4
2531
+
2532
+ extension (approx : Repr ):
2533
+ def low : Boolean = (approx & LoApprox ) != 0
2534
+ def high : Boolean = (approx & HiApprox ) != 0
2535
+ def addLow : Repr = approx | LoApprox
2536
+ def addHigh : Repr = approx | HiApprox
2537
+ def show : String =
2538
+ val lo = if low then " LoApprox" else " "
2539
+ val hi = if high then " HiApprox" else " "
2540
+ lo ++ hi
2541
+ end ApproxState
2542
+ type ApproxState = ApproxState .Repr
2540
2543
2541
2544
def topLevelSubType (tp1 : Type , tp2 : Type )(using Context ): Boolean =
2542
2545
comparing(_.topLevelSubType(tp1, tp2))
@@ -2817,7 +2820,7 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
2817
2820
if Config .verboseExplainSubtype || ctx.settings.verbose.value
2818
2821
then s " ${tp1.getClass} ${tp2.getClass}"
2819
2822
else " "
2820
- traceIndented(s " ${show(tp1)} <:< ${show(tp2)}$moreInfo $approx ${if (frozenConstraint) " frozen" else " " }" ) {
2823
+ traceIndented(s " ${show(tp1)} <:< ${show(tp2)}$moreInfo ${ approx.show} ${if (frozenConstraint) " frozen" else " " }" ) {
2821
2824
super .isSubType(tp1, tp2, approx)
2822
2825
}
2823
2826
0 commit comments