@@ -139,9 +139,9 @@ object Contexts {
139139 final def importInfo : ImportInfo = _importInfo
140140
141141 /** The current bounds in force for type parameters appearing in a GADT */
142- private [this ] var _gadt : GADTMap = _
143- protected def gadt_= (gadt : GADTMap ): Unit = _gadt = gadt
144- final def gadt : GADTMap = _gadt
142+ private [this ] var _gadt : GadtConstraint = _
143+ protected def gadt_= (gadt : GadtConstraint ): Unit = _gadt = gadt
144+ final def gadt : GadtConstraint = _gadt
145145
146146 /** The history of implicit searches that are currently active */
147147 private [this ] var _searchHistory : SearchHistory = null
@@ -534,7 +534,7 @@ object Contexts {
534534 def setTypeAssigner (typeAssigner : TypeAssigner ): this .type = { this .typeAssigner = typeAssigner; this }
535535 def setTyper (typer : Typer ): this .type = { this .scope = typer.scope; setTypeAssigner(typer) }
536536 def setImportInfo (importInfo : ImportInfo ): this .type = { this .importInfo = importInfo; this }
537- def setGadt (gadt : GADTMap ): this .type = { this .gadt = gadt; this }
537+ def setGadt (gadt : GadtConstraint ): this .type = { this .gadt = gadt; this }
538538 def setFreshGADTBounds : this .type = setGadt(gadt.fresh)
539539 def setSearchHistory (searchHistory : SearchHistory ): this .type = { this .searchHistory = searchHistory; this }
540540 def setSource (source : SourceFile ): this .type = { this .source = source; this }
@@ -617,7 +617,7 @@ object Contexts {
617617 store = initialStore.updated(settingsStateLoc, settingsGroup.defaultState)
618618 typeComparer = new TypeComparer (this )
619619 searchHistory = new SearchRoot
620- gadt = EmptyGADTMap
620+ gadt = EmptyGadtConstraint
621621 }
622622
623623 @ sharable object NoContext extends Context (null ) {
@@ -774,217 +774,4 @@ object Contexts {
774774 if (thread == null ) thread = Thread .currentThread()
775775 else assert(thread == Thread .currentThread(), " illegal multithreaded access to ContextBase" )
776776 }
777-
778- sealed abstract class GADTMap extends Showable {
779- def addEmptyBounds (sym : Symbol )(implicit ctx : Context ): Unit
780- def addBound (sym : Symbol , bound : Type , isUpper : Boolean )(implicit ctx : Context ): Boolean
781- def isLess (sym1 : Symbol , sym2 : Symbol )(implicit ctx : Context ): Boolean
782- def bounds (sym : Symbol )(implicit ctx : Context ): TypeBounds
783-
784- /** Full bounds of `sym`, including TypeRefs to other lower/upper symbols.
785- *
786- * Note that underlying operations perform subtype checks - for this reason, recursing on `fullBounds`
787- * of some symbol when comparing types might lead to infinite recursion. Consider `bounds` instead.
788- */
789- def fullBounds (sym : Symbol )(implicit ctx : Context ): TypeBounds
790- def contains (sym : Symbol )(implicit ctx : Context ): Boolean
791- def approximation (sym : Symbol , fromBelow : Boolean )(implicit ctx : Context ): Type
792- def debugBoundsDescription (implicit ctx : Context ): String
793- def fresh : GADTMap
794- def restore (other : GADTMap ): Unit
795- def isEmpty : Boolean
796- }
797-
798- final class SmartGADTMap private (
799- private var myConstraint : Constraint ,
800- private var mapping : SimpleIdentityMap [Symbol , TypeVar ],
801- private var reverseMapping : SimpleIdentityMap [TypeParamRef , Symbol ],
802- ) extends GADTMap with ConstraintHandling [Context ] {
803- import dotty .tools .dotc .config .Printers .{gadts , gadtsConstr }
804-
805- def subsumes (left : GADTMap , right : GADTMap , pre : GADTMap )(implicit ctx : Context ): Boolean = {
806- def extractConstraint (g : GADTMap ) = g match {
807- case s : SmartGADTMap => s.constraint
808- case EmptyGADTMap => OrderingConstraint .empty
809- }
810- subsumes(extractConstraint(left), extractConstraint(right), extractConstraint(pre))
811- }
812-
813- def this () = this (
814- myConstraint = new OrderingConstraint (SimpleIdentityMap .Empty , SimpleIdentityMap .Empty , SimpleIdentityMap .Empty ),
815- mapping = SimpleIdentityMap .Empty ,
816- reverseMapping = SimpleIdentityMap .Empty
817- )
818-
819- implicit override def ctx (implicit ctx : Context ): Context = ctx
820-
821- override protected def constraint = myConstraint
822- override protected def constraint_= (c : Constraint ) = myConstraint = c
823-
824- override protected def externalize (param : TypeParamRef )(implicit ctx : Context ): Type =
825- reverseMapping(param) match {
826- case sym : Symbol => sym.typeRef
827- case null => param
828- }
829-
830- override def isSubType (tp1 : Type , tp2 : Type )(implicit ctx : Context ): Boolean = ctx.typeComparer.isSubType(tp1, tp2)
831- override def isSameType (tp1 : Type , tp2 : Type )(implicit ctx : Context ): Boolean = ctx.typeComparer.isSameType(tp1, tp2)
832-
833- override def addEmptyBounds (sym : Symbol )(implicit ctx : Context ): Unit = tvar(sym)
834-
835- override def addBound (sym : Symbol , bound : Type , isUpper : Boolean )(implicit ctx : Context ): Boolean = {
836- @ annotation.tailrec def stripInternalTypeVar (tp : Type ): Type = tp match {
837- case tv : TypeVar =>
838- val inst = instType(tv)
839- if (inst.exists) stripInternalTypeVar(inst) else tv
840- case _ => tp
841- }
842-
843- val symTvar : TypeVar = stripInternalTypeVar(tvar(sym)) match {
844- case tv : TypeVar => tv
845- case inst =>
846- gadts.println(i " instantiated: $sym -> $inst" )
847- return if (isUpper) isSubType(inst , bound) else isSubType(bound, inst)
848- }
849-
850- val internalizedBound = bound match {
851- case nt : NamedType if contains(nt.symbol) =>
852- stripInternalTypeVar(tvar(nt.symbol))
853- case _ => bound
854- }
855- (
856- internalizedBound match {
857- case boundTvar : TypeVar =>
858- if (boundTvar eq symTvar) true
859- else if (isUpper) addLess(symTvar.origin, boundTvar.origin)
860- else addLess(boundTvar.origin, symTvar.origin)
861- case bound =>
862- val oldUpperBound = bounds(symTvar.origin)
863- // If we already have bounds `F >: [t] => List[t] <: [t] => Any`
864- // and we want to record that `F <: [+A] => List[A]`, we need to adapt
865- // type parameter variances of the bound. Consider that the following is valid:
866- //
867- // class Foo[F[t] >: List[t]]
868- // type T = Foo[List]
869- //
870- // precisely because `Foo[List]` is desugared to `Foo[[A] => List[A]]`.
871- val bound1 = bound.adaptHkVariances(oldUpperBound)
872- if (isUpper) addUpperBound(symTvar.origin, bound1)
873- else addLowerBound(symTvar.origin, bound1)
874- }
875- ).reporting({ res =>
876- val descr = if (isUpper) " upper" else " lower"
877- val op = if (isUpper) " <:" else " >:"
878- i " adding $descr bound $sym $op $bound = $res\t ( $symTvar $op $internalizedBound ) "
879- }, gadts)
880- }
881-
882- override def isLess (sym1 : Symbol , sym2 : Symbol )(implicit ctx : Context ): Boolean =
883- constraint.isLess(tvar(sym1).origin, tvar(sym2).origin)
884-
885- override def fullBounds (sym : Symbol )(implicit ctx : Context ): TypeBounds =
886- mapping(sym) match {
887- case null => null
888- case tv => fullBounds(tv.origin)
889- }
890-
891- override def bounds (sym : Symbol )(implicit ctx : Context ): TypeBounds = {
892- mapping(sym) match {
893- case null => null
894- case tv =>
895- def retrieveBounds : TypeBounds =
896- bounds(tv.origin) match {
897- case TypeAlias (tpr : TypeParamRef ) if reverseMapping.contains(tpr) =>
898- TypeAlias (reverseMapping(tpr).typeRef)
899- case tb => tb
900- }
901- retrieveBounds// .reporting({ res => i"gadt bounds $sym: $res" }, gadts)
902- }
903- }
904-
905- override def contains (sym : Symbol )(implicit ctx : Context ): Boolean = mapping(sym) ne null
906-
907- override def approximation (sym : Symbol , fromBelow : Boolean )(implicit ctx : Context ): Type = {
908- val res = approximation(tvar(sym).origin, fromBelow = fromBelow)
909- gadts.println(i " approximating $sym ~> $res" )
910- res
911- }
912-
913- override def fresh : GADTMap = new SmartGADTMap (
914- myConstraint,
915- mapping,
916- reverseMapping
917- )
918-
919- def restore (other : GADTMap ): Unit = other match {
920- case other : SmartGADTMap =>
921- this .myConstraint = other.myConstraint
922- this .mapping = other.mapping
923- this .reverseMapping = other.reverseMapping
924- case _ => ;
925- }
926-
927- override def isEmpty : Boolean = mapping.size == 0
928-
929- // ---- Private ----------------------------------------------------------
930-
931- private [this ] def tvar (sym : Symbol )(implicit ctx : Context ): TypeVar = {
932- mapping(sym) match {
933- case tv : TypeVar =>
934- tv
935- case null =>
936- val res = {
937- import NameKinds .DepParamName
938- // avoid registering the TypeVar with TyperState / TyperState#constraint
939- // - we don't want TyperState instantiating these TypeVars
940- // - we don't want TypeComparer constraining these TypeVars
941- val poly = PolyType (DepParamName .fresh(sym.name.toTypeName) :: Nil )(
942- pt => (sym.info match {
943- case tb @ TypeBounds (_, hi) if hi.isLambdaSub => tb
944- case _ => TypeBounds .empty
945- }) :: Nil ,
946- pt => defn.AnyType )
947- new TypeVar (poly.paramRefs.head, creatorState = null )
948- }
949- gadts.println(i " GADTMap: created tvar $sym -> $res" )
950- constraint = constraint.add(res.origin.binder, res :: Nil )
951- mapping = mapping.updated(sym, res)
952- reverseMapping = reverseMapping.updated(res.origin, sym)
953- res
954- }
955- }
956-
957- // ---- Debug ------------------------------------------------------------
958-
959- override def constr_println (msg : => String ): Unit = gadtsConstr.println(msg)
960-
961- override def toText (printer : Printer ): Texts .Text = constraint.toText(printer)
962-
963- override def debugBoundsDescription (implicit ctx : Context ): String = {
964- val sb = new mutable.StringBuilder
965- sb ++= constraint.show
966- sb += '\n '
967- mapping.foreachBinding { case (sym, _) =>
968- sb ++= i " $sym: ${fullBounds(sym)}\n "
969- }
970- sb.result
971- }
972- }
973-
974- @ sharable object EmptyGADTMap extends GADTMap {
975- override def addEmptyBounds (sym : Symbol )(implicit ctx : Context ): Unit = unsupported(" EmptyGADTMap.addEmptyBounds" )
976- override def addBound (sym : Symbol , bound : Type , isUpper : Boolean )(implicit ctx : Context ): Boolean = unsupported(" EmptyGADTMap.addBound" )
977- override def isLess (sym1 : Symbol , sym2 : Symbol )(implicit ctx : Context ): Boolean = unsupported(" EmptyGADTMap.isLess" )
978- override def bounds (sym : Symbol )(implicit ctx : Context ): TypeBounds = null
979- override def fullBounds (sym : Symbol )(implicit ctx : Context ): TypeBounds = null
980- override def contains (sym : Symbol )(implicit ctx : Context ) = false
981- override def approximation (sym : Symbol , fromBelow : Boolean )(implicit ctx : Context ): Type = unsupported(" EmptyGADTMap.approximation" )
982- override def toText (printer : Printer ): Texts .Text = " EmptyGADTMap"
983- override def debugBoundsDescription (implicit ctx : Context ): String = " EmptyGADTMap"
984- override def fresh = new SmartGADTMap
985- override def restore (other : GADTMap ): Unit = {
986- if (! other.isEmpty) sys.error(" cannot restore a non-empty GADTMap" )
987- }
988- override def isEmpty : Boolean = true
989- }
990777}
0 commit comments