@@ -720,14 +720,16 @@ object Contexts {
720720 final class SmartGADTMap private (
721721 private [this ] var myConstraint : Constraint ,
722722 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 ]
724725 ) extends GADTMap with ConstraintHandling {
725726 import dotty .tools .dotc .config .Printers .{gadts , gadtsConstr }
726727
727728 def this () = this (
728729 myConstraint = new OrderingConstraint (SimpleIdentityMap .Empty , SimpleIdentityMap .Empty , SimpleIdentityMap .Empty ),
729730 mapping = SimpleIdentityMap .Empty ,
730- reverseMapping = SimpleIdentityMap .Empty
731+ reverseMapping = SimpleIdentityMap .Empty ,
732+ boundCache = SimpleIdentityMap .Empty
731733 )
732734
733735 // TODO: clean up this dirty kludge
@@ -748,7 +750,9 @@ object Contexts {
748750
749751 override def addEmptyBounds (sym : Symbol )(implicit ctx : Context ): Unit = tvar(sym)
750752
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
752756 @ annotation.tailrec def stripInst (tp : Type ): Type = tp match {
753757 case tv : TypeVar =>
754758 val inst = instType(tv)
@@ -807,14 +811,25 @@ object Contexts {
807811 i " adding $descr bound $sym $op $bound = $res\t ( $symTvar $op $internalizedBound ) "
808812 }
809813 res
810- }
814+ }} finally boundAdditionInProgress = false
811815
812816 override def bounds (sym : Symbol )(implicit ctx : Context ): TypeBounds = inCtx(ctx) {
813817 mapping(sym) match {
814818 case null => null
815819 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+ }
818833 // gadts.println(i"gadt bounds $sym: $res")
819834 res
820835 }
@@ -825,7 +840,8 @@ object Contexts {
825840 override def fresh : GADTMap = new SmartGADTMap (
826841 myConstraint,
827842 mapping,
828- reverseMapping
843+ reverseMapping,
844+ boundCache
829845 )
830846
831847 // ---- Private ----------------------------------------------------------
@@ -882,6 +898,8 @@ object Contexts {
882898 override def apply (tp : Type ): Type = removeTypeVars(tp, this )
883899 }
884900
901+ private [this ] var boundAdditionInProgress = false
902+
885903 // ---- Debug ------------------------------------------------------------
886904
887905 override def constr_println (msg : => String ): Unit = gadtsConstr.println(msg)
0 commit comments