Skip to content

Commit e316f65

Browse files
committed
Space: Cache decompose/canDecompose on Typ
1 parent 23cee40 commit e316f65

File tree

1 file changed

+27
-13
lines changed
  • compiler/src/dotty/tools/dotc/transform/patmat

1 file changed

+27
-13
lines changed

compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,18 @@ case object Empty extends Space
7777
* @param decomposed: does the space result from decomposition? Used for pretty print
7878
*
7979
*/
80-
case class Typ(tp: Type, decomposed: Boolean = true) extends Space
80+
case class Typ(tp: Type, decomposed: Boolean = true) extends Space:
81+
private var myCanDecompose: java.lang.Boolean = _
82+
private var myDecompose: List[Typ] = _
83+
84+
def canDecompose(using Context): Boolean =
85+
if myCanDecompose == null then myCanDecompose = SpaceEngine.canDecompose(tp)
86+
myCanDecompose
87+
88+
def decompose(using Context): List[Typ] =
89+
if myDecompose == null then myDecompose = SpaceEngine.decompose(tp)
90+
myDecompose
91+
end Typ
8192

8293
/** Space representing an extractor pattern */
8394
case class Prod(tp: Type, unappTp: TermRef, params: List[Space]) extends Space
@@ -101,7 +112,7 @@ object SpaceEngine {
101112
else if spaces2.lengthIs == 1 then spaces2.head
102113
else if spaces2.corresponds(spaces)(_ eq _) then space else Or(spaces2)
103114
case typ: Typ =>
104-
if canDecompose(typ.tp) && decompose(typ.tp).isEmpty then Empty
115+
if canDecompose(typ) && decompose(typ).isEmpty then Empty
105116
else space
106117
case _ => space
107118
})
@@ -152,12 +163,12 @@ object SpaceEngine {
152163
case (Or(ss), _) => ss.forall(isSubspace(_, b))
153164
case (a @ Typ(tp1, _), Or(ss)) => // optimization: don't go to subtraction too early
154165
ss.exists(isSubspace(a, _))
155-
|| canDecompose(tp1) && isSubspace(Or(decompose(tp1)), b)
166+
|| canDecompose(a) && isSubspace(Or(decompose(a)), b)
156167
case (_, Or(_)) => simplify(minus(a, b)) == Empty
157168
case (a @ Typ(tp1, _), b @ Typ(tp2, _)) =>
158169
isSubType(tp1, tp2)
159-
|| canDecompose(tp1) && isSubspace(Or(decompose(tp1)), b)
160-
|| canDecompose(tp2) && isSubspace(a, Or(decompose(tp2)))
170+
|| canDecompose(a) && isSubspace(Or(decompose(a)), b)
171+
|| canDecompose(b) && isSubspace(a, Or(decompose(b)))
161172
case (Prod(tp1, _, _), Typ(tp2, _)) =>
162173
isSubType(tp1, tp2)
163174
case (Typ(tp1, _), Prod(tp2, fun, ss)) =>
@@ -178,17 +189,17 @@ object SpaceEngine {
178189
case (a @ Typ(tp1, _), b @ Typ(tp2, _)) =>
179190
if isSubType(tp1, tp2) then a
180191
else if isSubType(tp2, tp1) then b
181-
else if canDecompose(tp1) then intersect(Or(decompose(tp1)), b)
182-
else if canDecompose(tp2) then intersect(a, Or(decompose(tp2)))
192+
else if canDecompose(a) then intersect(Or(decompose(a)), b)
193+
else if canDecompose(b) then intersect(a, Or(decompose(b)))
183194
else intersectUnrelatedAtomicTypes(tp1, tp2)(a)
184195
case (a @ Typ(tp1, _), Prod(tp2, fun, ss)) =>
185196
if isSubType(tp2, tp1) then b
186-
else if canDecompose(tp1) then intersect(Or(decompose(tp1)), b)
197+
else if canDecompose(a) then intersect(Or(decompose(a)), b)
187198
else if isSubType(tp1, tp2) then a // problematic corner case: inheriting a case class
188199
else intersectUnrelatedAtomicTypes(tp1, tp2)(b)
189200
case (Prod(tp1, fun, ss), b @ Typ(tp2, _)) =>
190201
if isSubType(tp1, tp2) then a
191-
else if canDecompose(tp2) then intersect(a, Or(decompose(tp2)))
202+
else if canDecompose(b) then intersect(a, Or(decompose(b)))
192203
else if isSubType(tp2, tp1) then a // problematic corner case: inheriting a case class
193204
else intersectUnrelatedAtomicTypes(tp1, tp2)(a)
194205
case (a @ Prod(tp1, fun1, ss1), Prod(tp2, fun2, ss2)) =>
@@ -207,20 +218,20 @@ object SpaceEngine {
207218
case (_, Or(ss)) => ss.foldLeft(a)(minus)
208219
case (a @ Typ(tp1, _), b @ Typ(tp2, _)) =>
209220
if isSubType(tp1, tp2) then Empty
210-
else if canDecompose(tp1) then minus(Or(decompose(tp1)), b)
211-
else if canDecompose(tp2) then minus(a, Or(decompose(tp2)))
221+
else if canDecompose(a) then minus(Or(decompose(a)), b)
222+
else if canDecompose(b) then minus(a, Or(decompose(b)))
212223
else a
213224
case (a @ Typ(tp1, _), Prod(tp2, fun, ss)) =>
214225
// rationale: every instance of `tp1` is covered by `tp2(_)`
215226
if isSubType(tp1, tp2) && covers(fun, tp1, ss.length) then
216227
minus(Prod(tp1, fun, signature(fun, tp1, ss.length).map(Typ(_, false))), b)
217-
else if canDecompose(tp1) then minus(Or(decompose(tp1)), b)
228+
else if canDecompose(a) then minus(Or(decompose(a)), b)
218229
else a
219230
case (Prod(tp1, fun, ss), b @ Typ(tp2, _)) =>
220231
// uncovered corner case: tp2 :< tp1, may happen when inheriting case class
221232
if isSubType(tp1, tp2) then Empty
222233
else if simplify(a) == Empty then Empty
223-
else if canDecompose(tp2) then minus(a, Or(decompose(tp2)))
234+
else if canDecompose(b) then minus(a, Or(decompose(b)))
224235
else a
225236
case (Prod(tp1, fun1, ss1), Prod(tp2, fun2, ss2))
226237
if !isSameUnapply(fun1, fun2) => a
@@ -568,6 +579,9 @@ object SpaceEngine {
568579
scrutineeTp <:< tp
569580
}
570581

582+
def canDecompose(typ: Typ)(using Context): Boolean = typ.canDecompose
583+
def decompose(typ: Typ)(using Context): List[Typ] = typ.decompose
584+
571585
/** Decompose a type into subspaces -- assume the type can be decomposed */
572586
def decompose(tp: Type)(using Context): List[Typ] = trace(i"decompose($tp)", debug, showSpaces) {
573587
def rec(tp: Type, mixins: List[Type]): List[Typ] = tp.dealias match {

0 commit comments

Comments
 (0)