@@ -720,14 +720,16 @@ object Contexts {
720
720
final class SmartGADTMap private (
721
721
private [this ] var myConstraint : Constraint ,
722
722
private [this ] var mapping : SimpleIdentityMap [Symbol , TypeVar ],
723
- private [this ] var reverseMapping : SimpleIdentityMap [TypeParamRef , Symbol ]
723
+ private [this ] var reverseMapping : SimpleIdentityMap [TypeParamRef , Symbol ],
724
+ private [this ] var boundCache : SimpleIdentityMap [Symbol , TypeBounds ]
724
725
) extends GADTMap with ConstraintHandling {
725
726
import dotty .tools .dotc .config .Printers .{gadts , gadtsConstr }
726
727
727
728
def this () = this (
728
729
myConstraint = new OrderingConstraint (SimpleIdentityMap .Empty , SimpleIdentityMap .Empty , SimpleIdentityMap .Empty ),
729
730
mapping = SimpleIdentityMap .Empty ,
730
- reverseMapping = SimpleIdentityMap .Empty
731
+ reverseMapping = SimpleIdentityMap .Empty ,
732
+ boundCache = SimpleIdentityMap .Empty
731
733
)
732
734
733
735
// TODO: clean up this dirty kludge
@@ -748,7 +750,9 @@ object Contexts {
748
750
749
751
override def addEmptyBounds (sym : Symbol )(implicit ctx : Context ): Unit = tvar(sym)
750
752
751
- override def addBound (sym : Symbol , bound : Type , isUpper : Boolean )(implicit ctx : Context ): Boolean = inCtx(ctx) {
753
+ override def addBound (sym : Symbol , bound : Type , isUpper : Boolean )(implicit ctx : Context ): Boolean = try { inCtx(ctx) {
754
+ boundCache = SimpleIdentityMap .Empty
755
+ boundAdditionInProgress = true
752
756
@ annotation.tailrec def stripInst (tp : Type ): Type = tp match {
753
757
case tv : TypeVar =>
754
758
val inst = instType(tv)
@@ -807,14 +811,25 @@ object Contexts {
807
811
i " adding $descr bound $sym $op $bound = $res\t ( $symTvar $op $internalizedBound ) "
808
812
}
809
813
res
810
- }
814
+ }} finally boundAdditionInProgress = false
811
815
812
816
override def bounds (sym : Symbol )(implicit ctx : Context ): TypeBounds = inCtx(ctx) {
813
817
mapping(sym) match {
814
818
case null => null
815
819
case tv =>
816
- val tb = constraint.fullBounds(tv.origin)
817
- val res = removeTypeVars(tb).asInstanceOf [TypeBounds ]
820
+ def retrieveBounds : TypeBounds = {
821
+ val tb = constraint.fullBounds(tv.origin)
822
+ removeTypeVars(tb).asInstanceOf [TypeBounds ]
823
+ }
824
+ val res =
825
+ if (boundAdditionInProgress || ctx.mode.is(Mode .GADTflexible )) retrieveBounds
826
+ else boundCache(sym) match {
827
+ case tb : TypeBounds => tb
828
+ case null =>
829
+ val bounds = retrieveBounds
830
+ boundCache = boundCache.updated(sym, bounds)
831
+ bounds
832
+ }
818
833
// gadts.println(i"gadt bounds $sym: $res")
819
834
res
820
835
}
@@ -825,7 +840,8 @@ object Contexts {
825
840
override def fresh : GADTMap = new SmartGADTMap (
826
841
myConstraint,
827
842
mapping,
828
- reverseMapping
843
+ reverseMapping,
844
+ boundCache
829
845
)
830
846
831
847
// ---- Private ----------------------------------------------------------
@@ -882,6 +898,8 @@ object Contexts {
882
898
override def apply (tp : Type ): Type = removeTypeVars(tp, this )
883
899
}
884
900
901
+ private [this ] var boundAdditionInProgress = false
902
+
885
903
// ---- Debug ------------------------------------------------------------
886
904
887
905
override def constr_println (msg : => String ): Unit = gadtsConstr.println(msg)
0 commit comments