@@ -480,7 +480,7 @@ object Contexts {
480
480
def setTyper (typer : Typer ): this .type = { this .scope = typer.scope; setTypeAssigner(typer) }
481
481
def setImportInfo (importInfo : ImportInfo ): this .type = { this .importInfo = importInfo; this }
482
482
def setGadt (gadt : GADTMap ): this .type = { this .gadt = gadt; this }
483
- def setFreshGADTBounds : this .type = setGadt(new GADTMap ( gadt.bounds) )
483
+ def setFreshGADTBounds : this .type = setGadt(gadt.derived )
484
484
def setSearchHistory (searchHistory : SearchHistory ): this .type = { this .searchHistory = searchHistory; this }
485
485
def setTypeComparerFn (tcfn : Context => TypeComparer ): this .type = { this .typeComparer = tcfn(this ); this }
486
486
private def setMoreProperties (moreProperties : Map [Key [Any ], Any ]): this .type = { this .moreProperties = moreProperties; this }
@@ -708,14 +708,88 @@ object Contexts {
708
708
else assert(thread == Thread .currentThread(), " illegal multithreaded access to ContextBase" )
709
709
}
710
710
711
- class GADTMap ( initBounds : SimpleIdentityMap [ Symbol , TypeBounds ]) {
712
- private [ this ] var myBounds = initBounds
713
- def setBounds (sym : Symbol , b : TypeBounds ): Unit =
714
- myBounds = myBounds.updated (sym, b)
715
- def bounds : SimpleIdentityMap [ Symbol , TypeBounds ] = myBounds
711
+ sealed abstract class GADTMap {
712
+ def setBounds ( sym : Symbol , b : TypeBounds )( implicit ctx : Context ) : Unit
713
+ def bounds (sym : Symbol )( implicit ctx : Context ): TypeBounds
714
+ def contains (sym : Symbol )( implicit ctx : Context ) : Boolean
715
+ def derived : GADTMap
716
716
}
717
717
718
- @ sharable object EmptyGADTMap extends GADTMap (SimpleIdentityMap .Empty ) {
719
- override def setBounds (sym : Symbol , b : TypeBounds ): Unit = unsupported(" EmptyGADTMap.setBounds" )
718
+ class SmartGADTMap (
719
+ private [this ] var myConstraint : Constraint = new OrderingConstraint (SimpleIdentityMap .Empty , SimpleIdentityMap .Empty , SimpleIdentityMap .Empty ),
720
+ private [this ] var mapping : SimpleIdentityMap [Symbol , TypeVar ] = SimpleIdentityMap .Empty
721
+ ) extends GADTMap with ConstraintHandling {
722
+ def log (str : String ): Unit = {
723
+ import dotty .tools .dotc .config .Printers .gadts
724
+ gadts.println(s " GADTMap: $str" )
725
+ }
726
+
727
+ // TODO: dirty kludge - should this class be an inner class of TyperState instead?
728
+ private [this ] var myCtx : Context = null
729
+ implicit override def ctx = myCtx
730
+ @ forceInline private [this ] final def inCtx [T ](_ctx : Context )(op : => T ) = {
731
+ val savedCtx = myCtx
732
+ myCtx = _ctx
733
+ try op finally myCtx = savedCtx
734
+ }
735
+
736
+ override protected def constraint = myConstraint
737
+ override protected def constraint_= (c : Constraint ) = myConstraint = c
738
+
739
+ override def isSubType (tp1 : Type , tp2 : Type ): Boolean = ctx.typeComparer.isSubType(tp1, tp2)
740
+ override def isSameType (tp1 : Type , tp2 : Type ): Boolean = ctx.typeComparer.isSameType(tp1, tp2)
741
+
742
+ private [this ] def tvar (sym : Symbol )(implicit ctx : Context ) = inCtx(ctx) {
743
+ val res = mapping(sym) match {
744
+ case tv : TypeVar => tv
745
+ case null =>
746
+ log(i " creating tvar for: $sym" )
747
+ val res = {
748
+ import NameKinds .DepParamName
749
+ // do not use newTypeVar:
750
+ // it registers the TypeVar with TyperState, we don't want that since it instantiates them (TODO: when?)
751
+ // (see pos/i3500.scala)
752
+ // it registers the TypeVar with TyperState Constraint, which we don't care for but it's needless
753
+ val poly = PolyType (DepParamName .fresh().toTypeName :: Nil )(
754
+ pt => TypeBounds .empty :: Nil ,
755
+ pt => defn.AnyType )
756
+ // null out creatorState, we don't need it anyway (and TypeVar can null it too)
757
+ new TypeVar (poly.paramRefs.head, creatorState = null )
758
+ }
759
+ constraint = constraint.add(res.origin.binder, res :: Nil )
760
+ mapping = mapping.updated(sym, res)
761
+ res
762
+ }
763
+ log(i " tvar: $sym -> $res" )
764
+ res
765
+ }
766
+
767
+ override def setBounds (sym : Symbol , b : TypeBounds )(implicit ctx : Context ): Unit = inCtx(ctx) {
768
+ val tv = tvar(sym)
769
+ log(i " setBounds ` $sym` ` $tv`: ` $b` " )
770
+ addUpperBound(tv.origin, b.hi)
771
+ addLowerBound(tv.origin, b.lo)
772
+ }
773
+
774
+ override def bounds (sym : Symbol )(implicit ctx : Context ): TypeBounds = inCtx(ctx) {
775
+ mapping(sym) match {
776
+ case null => null
777
+ case tv => constraint.fullBounds(tv.origin)
778
+ }
779
+ }
780
+
781
+ override def contains (sym : Symbol )(implicit ctx : Context ) = mapping(sym) ne null
782
+
783
+ override def derived : GADTMap = new SmartGADTMap (
784
+ this .myConstraint,
785
+ this .mapping
786
+ )
787
+ }
788
+
789
+ @ sharable object EmptyGADTMap extends GADTMap {
790
+ override def setBounds (sym : Symbol , b : TypeBounds )(implicit ctx : Context ) = unsupported(" EmptyGADTMap.setBounds" )
791
+ override def bounds (sym : Symbol )(implicit ctx : Context ) = null
792
+ override def contains (sym : Symbol )(implicit ctx : Context ) = false
793
+ override def derived = new SmartGADTMap
720
794
}
721
795
}
0 commit comments