@@ -96,7 +96,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
9696 assert(canCompareAtoms == true )
9797 assert(successCount == 0 )
9898 assert(totalCount == 0 )
99- assert(approx == FreshApprox )
99+ assert(approx == ApproxState . Fresh )
100100 assert(leftRoot == null )
101101 assert(frozenGadt == false )
102102
@@ -136,7 +136,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
136136 else CompareResult .OK
137137
138138 /** The current approximation state. See `ApproxState`. */
139- private var approx : ApproxState = FreshApprox
139+ private var approx : ApproxState = ApproxState . Fresh
140140 protected def approxState : ApproxState = approx
141141
142142 /** The original left-hand type of the comparison. Gets reset
@@ -156,8 +156,8 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
156156 protected def isSubType (tp1 : Type , tp2 : Type , a : ApproxState ): Boolean = {
157157 val savedApprox = approx
158158 val savedLeftRoot = leftRoot
159- if (a == FreshApprox ) {
160- this .approx = NoApprox
159+ if (a == ApproxState . Fresh ) {
160+ this .approx = ApproxState . None
161161 this .leftRoot = tp1
162162 }
163163 else this .approx = a
@@ -171,7 +171,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
171171 }
172172 }
173173
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 )
175175
176176 override protected def isSub (tp1 : Type , tp2 : Type )(using Context ): Boolean = isSubType(tp1, tp2)
177177
@@ -190,7 +190,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
190190 * code would have two extra parameters for each of the many calls that go from
191191 * one sub-part of isSubType to another.
192192 */
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) {
194194
195195 def monitoredIsSubType = {
196196 if (pendingSubTypes == null ) {
@@ -2509,34 +2509,37 @@ object TypeComparer {
25092509 case _ => String .valueOf(res)
25102510 }
25112511
2512- private val LoApprox = 1
2513- private val HiApprox = 2
25142512
25152513 /** The approximation state indicates how the pair of types currently compared
25162514 * relates to the types compared originally.
2517- * - `NoApprox` : They are still the same types
2515+ * - `None` : They are still the same types
25182516 * - `LoApprox`: The left type is approximated (i.e widened)"
25192517 * - `HiApprox`: The right type is approximated (i.e narrowed)"
25202518 */
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
25322521
2533- val NoApprox : ApproxState = new ApproxState (0 )
2522+ val None : Repr = 0
2523+ private val LoApprox = 1
2524+ private val HiApprox = 2
25342525
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
25402543
25412544 def topLevelSubType (tp1 : Type , tp2 : Type )(using Context ): Boolean =
25422545 comparing(_.topLevelSubType(tp1, tp2))
@@ -2817,7 +2820,7 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
28172820 if Config .verboseExplainSubtype || ctx.settings.verbose.value
28182821 then s " ${tp1.getClass} ${tp2.getClass}"
28192822 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 " " }" ) {
28212824 super .isSubType(tp1, tp2, approx)
28222825 }
28232826
0 commit comments