@@ -717,13 +717,23 @@ object Contexts {
717717 def derived : GADTMap
718718 }
719719
720- final class SmartGADTMap (
721- private [this ] var myConstraint : Constraint = new OrderingConstraint (SimpleIdentityMap .Empty , SimpleIdentityMap .Empty , SimpleIdentityMap .Empty ),
722- private [this ] var mapping : SimpleIdentityMap [Symbol , TypeVar ] = SimpleIdentityMap .Empty ,
723- private [this ] var reverseMapping : SimpleIdentityMap [TypeParamRef , Symbol ] = SimpleIdentityMap .Empty
720+ final class SmartGADTMap private (
721+ private [this ] var myConstraint : Constraint ,
722+ private [this ] var mapping : SimpleIdentityMap [Symbol , TypeVar ],
723+ private [this ] var reverseMapping : SimpleIdentityMap [TypeParamRef , Symbol ],
724+ private [this ] var boundCache : SimpleIdentityMap [Symbol , TypeBounds ],
725+ private [this ] var dirtyFlag : Boolean
724726 ) extends GADTMap with ConstraintHandling {
725727 import dotty .tools .dotc .config .Printers .gadts
726728
729+ def this () = this (
730+ myConstraint = new OrderingConstraint (SimpleIdentityMap .Empty , SimpleIdentityMap .Empty , SimpleIdentityMap .Empty ),
731+ mapping = SimpleIdentityMap .Empty ,
732+ reverseMapping = SimpleIdentityMap .Empty ,
733+ boundCache = SimpleIdentityMap .Empty ,
734+ dirtyFlag = false
735+ )
736+
727737 override def debugBoundsDescription (implicit ctx : Context ): String = {
728738 val sb = new mutable.StringBuilder
729739 sb ++= constraint.show
@@ -734,6 +744,8 @@ object Contexts {
734744 sb.result
735745 }
736746
747+ private [this ] var checkInProgress = false
748+
737749 // TODO: dirty kludge - should this class be an inner class of TyperState instead?
738750 private [this ] var myCtx : Context = null
739751 implicit override def ctx = myCtx
@@ -749,9 +761,10 @@ object Contexts {
749761 override def isSubType (tp1 : Type , tp2 : Type ): Boolean = ctx.typeComparer.isSubType(tp1, tp2)
750762 override def isSameType (tp1 : Type , tp2 : Type ): Boolean = ctx.typeComparer.isSameType(tp1, tp2)
751763
752- private [this ] def tvar (sym : Symbol )(implicit ctx : Context ): TypeVar = inCtx(ctx) {
753- val res = mapping(sym) match {
754- case tv : TypeVar => tv
764+ private [this ] def tvar (sym : Symbol )(implicit ctx : Context ): TypeVar = {
765+ mapping(sym) match {
766+ case tv : TypeVar =>
767+ tv
755768 case null =>
756769 val res = {
757770 import NameKinds .DepParamName
@@ -769,12 +782,13 @@ object Contexts {
769782 reverseMapping = reverseMapping.updated(res.origin, sym)
770783 res
771784 }
772- res
773785 }
774786
775787 override def addEmptyBounds (sym : Symbol )(implicit ctx : Context ): Unit = tvar(sym)
776788
777- override def addBound (sym : Symbol , bound : Type , isUpper : Boolean )(implicit ctx : Context ): Boolean = inCtx(ctx) {
789+ override def addBound (sym : Symbol , bound : Type , isUpper : Boolean )(implicit ctx : Context ): Boolean = try inCtx(ctx) {
790+ dirtyFlag = true
791+ checkInProgress = true
778792 @ annotation.tailrec def stripInst (tp : Type ): Type = tp match {
779793 case tv : TypeVar =>
780794 val inst = instType(tv)
@@ -795,8 +809,8 @@ object Contexts {
795809
796810 val outerCtx = ctx
797811 val res = {
798- implicit val ctx : Context =
799- if (allowNarrowing) outerCtx else outerCtx.fresh.retractMode(Mode .GADTflexible )
812+ // implicit val ctx : Context =
813+ // if (allowNarrowing) outerCtx else outerCtx.fresh.retractMode(Mode.GADTflexible)
800814
801815 // TypeComparer.explain[Boolean](gadts.println) { implicit ctx =>
802816 if (isSubtype) externalizedTp1 frozen_<:< externalizedTp2
@@ -811,6 +825,7 @@ object Contexts {
811825 case tv : TypeVar => tv
812826 case inst =>
813827 gadts.println(i " instantiated: $sym -> $inst" )
828+ // return true
814829 return cautiousSubtype(inst, bound, isSubtype = isUpper, allowNarrowing = true )
815830 }
816831
@@ -847,25 +862,47 @@ object Contexts {
847862 i " adding $descr bound $sym $op $bound = $res\t ( $symTvar $op $tvarBound ) "
848863 }
849864 res
850- }
865+ } finally checkInProgress = false
851866
852867 override def bounds (sym : Symbol )(implicit ctx : Context ): TypeBounds = inCtx(ctx) {
853868 mapping(sym) match {
854869 case null => null
855870 case tv =>
856- val tb = constraint.fullBounds(tv.origin)
857- val res = (new TypeVarRemovingMap )(tb).asInstanceOf [TypeBounds ]
858- // gadts.println(i"gadt bounds $sym: $res\t( $tv: $tb )")
871+ def retrieveBounds : TypeBounds = {
872+ val tb = constraint.fullBounds(tv.origin)
873+ (new TypeVarRemovingMap )(tb).asInstanceOf [TypeBounds ]
874+ }
875+ val res =
876+ // retrieveBounds
877+ if (checkInProgress || ctx.mode.is(Mode .GADTflexible )) retrieveBounds
878+ else {
879+ if (dirtyFlag) {
880+ dirtyFlag = false
881+ val bounds = retrieveBounds
882+ boundCache = SimpleIdentityMap .Empty .updated(sym, bounds)
883+ bounds
884+ } else boundCache(sym) match {
885+ case tb : TypeBounds =>
886+ tb
887+ case null =>
888+ val bounds = retrieveBounds
889+ boundCache = boundCache.updated(sym, bounds)
890+ bounds
891+ }
892+ }
893+ // gadts.println(i"gadt bounds $sym: $res")
859894 res
860895 }
861896 }
862897
863898 override def contains (sym : Symbol )(implicit ctx : Context ): Boolean = mapping(sym) ne null
864899
865900 override def derived : GADTMap = new SmartGADTMap (
866- this .myConstraint,
867- this .mapping,
868- this .reverseMapping
901+ myConstraint,
902+ mapping,
903+ reverseMapping,
904+ boundCache,
905+ dirtyFlag
869906 )
870907
871908 private final class TypeVarInsertingMap extends TypeMap {
0 commit comments