Skip to content

Commit 0ff1e2a

Browse files
authored
Merge pull request #9591 from dotty-staging/optimize-ApproxState
Make AproxState an opaque type
2 parents 6f35436 + 1552aee commit 0ff1e2a

File tree

1 file changed

+30
-27
lines changed

1 file changed

+30
-27
lines changed

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

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

Comments
 (0)