Skip to content

Commit b05630b

Browse files
author
Aleksander Boruch-Gruszecki
committed
Parameterize Constraint with constrained VarRef
1 parent 42a4d3f commit b05630b

10 files changed

+256
-153
lines changed

compiler/src/dotty/tools/dotc/core/Constraint.scala

+9-16
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@ package core
55
import Types._, Contexts._
66
import printing.Showable
77

8-
object Constraint {
9-
type VarRef = TypeVarRef
10-
type Binder = TypeVarRefBinder
11-
}
12-
138
/** Constraint over undetermined type parameters. Constraints are built
149
* over values of the following types:
1510
*
@@ -18,19 +13,17 @@ object Constraint {
1813
* - TypeVar Every constrained parameter might be associated with a TypeVar
1914
* that has the TypeParamRef as origin.
2015
*/
21-
abstract class Constraint extends Showable {
22-
import Constraint._
23-
24-
type This <: Constraint
16+
abstract class Constraint[VarRef <: TypeVarRef, RefBinder <: TypeVarRefBinder] extends Showable {
17+
type This <: Constraint[VarRef, RefBinder]
2518

2619
/** Does the constraint's domain contain the type parameters of `pt`? */
27-
def contains(pt: Binder): Boolean
20+
def contains(pt: RefBinder): Boolean
2821

2922
/** Does the constraint's domain contain the type parameter `param`? */
3023
def contains(param: VarRef): Boolean
3124

3225
/** Does this constraint contain the type variable `tvar` and is it uninstantiated? */
33-
def contains(tvar: TypeVar): Boolean
26+
def contains(tvar: TypeVarHandle[VarRef]): Boolean
3427

3528
/** The constraint entry for given type parameter `param`, or NoType if `param` is not part of
3629
* the constraint domain. Note: Low level, implementation dependent.
@@ -80,7 +73,7 @@ abstract class Constraint extends Showable {
8073
* satisfiability but will solved to give instances of
8174
* type variables.
8275
*/
83-
def add(poly: Binder, tvars: List[TypeVar])(implicit ctx: Context): This
76+
def add(poly: RefBinder, tvars: List[TypeVarHandle[VarRef]])(implicit ctx: Context): This
8477

8578
/** A new constraint which is derived from this constraint by updating
8679
* the entry for parameter `param` to `tp`.
@@ -116,13 +109,13 @@ abstract class Constraint extends Showable {
116109
* all type parameters of the entry are associated with type variables
117110
* which have their `inst` fields set.
118111
*/
119-
def isRemovable(pt: Binder): Boolean
112+
def isRemovable(pt: RefBinder): Boolean
120113

121114
/** A new constraint with all entries coming from `pt` removed. */
122-
def remove(pt: Binder)(implicit ctx: Context): This
115+
def remove(pt: RefBinder)(implicit ctx: Context): This
123116

124117
/** The type lambdas constrained by this constraint */
125-
def domainLambdas: List[Binder]
118+
def domainLambdas: List[RefBinder]
126119

127120
/** The type lambda parameters constrained by this constraint */
128121
def domainParams: List[VarRef]
@@ -143,7 +136,7 @@ abstract class Constraint extends Showable {
143136
* returning an approximate constraint, instead of
144137
* failing with an exception
145138
*/
146-
def & (other: Constraint, otherHasErrors: Boolean)(implicit ctx: Context): Constraint
139+
def & (other: Constraint[VarRef, RefBinder], otherHasErrors: Boolean)(implicit ctx: Context): Constraint[VarRef, RefBinder]
147140

148141
/** Check that no constrained parameter contains itself as a bound */
149142
def checkNonCyclic()(implicit ctx: Context): Unit

compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala

+23-17
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,22 @@ import config.Printers.{constr, typr}
1818
* By comparison: Constraint handlers are parts of type comparers and can use their functionality.
1919
* Constraint handlers update the current constraint as a side effect.
2020
*/
21-
trait ConstraintHandling {
22-
import Constraint._
21+
trait ConstraintHandling[VarRef <: TypeVarRef.Of[VarRef, RefBinder], RefBinder <: TypeVarRefBinder.Of[VarRef, RefBinder]] {
22+
protected final type OwnConstraint = Constraint[VarRef, RefBinder]
2323

24-
def constr_println(msg: => String): Unit = constr.println(msg)
25-
def typr_println(msg: => String): Unit = typr.println(msg)
24+
protected def isVarRef(r: Type): Boolean = r.isInstanceOf[TypeVarRef]
25+
protected def isRefBinder(r: Type): Boolean = r.isInstanceOf[TypeVarRefBinder]
26+
27+
protected def constr_println(msg: => String): Unit = constr.println(msg)
28+
protected def typr_println(msg: => String): Unit = typr.println(msg)
2629

2730
implicit def ctx: Context
2831

2932
protected def isSubType(tp1: Type, tp2: Type): Boolean
3033
protected def isSameType(tp1: Type, tp2: Type): Boolean
3134

32-
protected def constraint: Constraint
33-
protected def constraint_=(c: Constraint): Unit
35+
protected def constraint: OwnConstraint
36+
protected def constraint_=(c: OwnConstraint): Unit
3437

3538
private[this] var addConstraintInvocations = 0
3639

@@ -59,9 +62,10 @@ trait ConstraintHandling {
5962
* is done only in a temporary way for contexts that may be retracted
6063
* without also retracting the type var as a whole.
6164
*/
62-
def instType(tvar: TypeVar): Type = constraint.entry(tvar.origin) match {
65+
def instType(tvar: TypeVarHandle[VarRef]): Type = constraint.entry(tvar.origin) match {
6366
case _: TypeBounds => NoType
64-
case tp: VarRef =>
67+
case tp_ if isVarRef(tp_) =>
68+
val tp = tp_.asInstanceOf[VarRef]
6569
var tvar1 = constraint.typeVarOfParam(tp)
6670
if (tvar1.exists) tvar1 else tp
6771
case tp => tp
@@ -284,9 +288,9 @@ trait ConstraintHandling {
284288
case tp: SingletonType => true
285289
case AndType(tp1, tp2) => isMultiSingleton(tp1) | isMultiSingleton(tp2)
286290
case OrType(tp1, tp2) => isMultiSingleton(tp1) & isMultiSingleton(tp2)
287-
case tp: TypeRef if !constraint.contains(tp : VarRef) => isMultiSingleton(tp.info.hiBound)
291+
case tp_ if isVarRef(tp_) => isMultiSingleton(bounds(tp_.asInstanceOf[VarRef]).hi)
292+
case tp: TypeRef => isMultiSingleton(tp.info.hiBound)
288293
case tp: TypeVar => isMultiSingleton(tp.underlying)
289-
case tp: VarRef => isMultiSingleton(bounds(tp).hi)
290294
case _ => false
291295
}
292296
def isOrType(tp: Type): Boolean = tp.dealias match {
@@ -327,7 +331,7 @@ trait ConstraintHandling {
327331
* Both `c1` and `c2` are required to derive from constraint `pre`, possibly
328332
* narrowing it with further bounds.
329333
*/
330-
protected final def subsumes(c1: Constraint, c2: Constraint, pre: Constraint): Boolean =
334+
protected final def subsumes(c1: OwnConstraint, c2: OwnConstraint, pre: OwnConstraint): Boolean =
331335
if (c2 eq pre) true
332336
else if (c1 eq pre) false
333337
else {
@@ -355,7 +359,7 @@ trait ConstraintHandling {
355359
* and propagate all bounds.
356360
* @param tvars See Constraint#add
357361
*/
358-
def addToConstraint(tl: Binder, tvars: List[TypeVar]): Boolean =
362+
def addToConstraint(tl: RefBinder, tvars: List[TypeVarHandle[VarRef]]): Boolean =
359363
checkPropagated(i"initialized $tl") {
360364
constraint = constraint.add(tl, tvars)
361365
tl.boundRefs.forall { param =>
@@ -427,7 +431,7 @@ trait ConstraintHandling {
427431
}
428432
else tp
429433

430-
def addParamBound(bound: TypeParamRef) =
434+
def addParamBound(bound: VarRef) =
431435
constraint.entry(param) match {
432436
case _: TypeBounds =>
433437
if (fromBelow) addLess(bound, param) else addLess(param, bound)
@@ -480,9 +484,10 @@ trait ConstraintHandling {
480484
val p2 = prune(bound.tp2)
481485
if (p1.exists && p2.exists) bound.derivedOrType(p1, p2)
482486
else NoType
483-
case bound: TypeVar if constraint contains bound.origin =>
487+
case bound: TypeVar if constraint contains bound.origin.asInstanceOf[VarRef] =>
484488
prune(bound.underlying)
485-
case bound: TypeParamRef =>
489+
case bound_ : TypeParamRef =>
490+
val bound = bound_.asInstanceOf[VarRef]
486491
constraint.entry(bound) match {
487492
case NoType => pruneLambdaParams(bound)
488493
case _: TypeBounds =>
@@ -497,7 +502,8 @@ trait ConstraintHandling {
497502
}
498503

499504
try bound match {
500-
case bound: TypeParamRef if constraint contains bound =>
505+
case bound_ : TypeParamRef if constraint contains bound_.asInstanceOf[VarRef] =>
506+
val bound = bound_.asInstanceOf[VarRef]
501507
addParamBound(bound)
502508
case _ =>
503509
val pbound = prune(bound)
@@ -509,7 +515,7 @@ trait ConstraintHandling {
509515
}
510516

511517
/** Instantiate `param` to `tp` if the constraint stays satisfiable */
512-
protected def tryInstantiate(param: TypeParamRef, tp: Type): Boolean = {
518+
protected def tryInstantiate(param: VarRef, tp: Type): Boolean = {
513519
val saved = constraint
514520
constraint =
515521
if (addConstraint(param, tp, fromBelow = true) &&

compiler/src/dotty/tools/dotc/core/ConstraintRunInfo.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import config.Printers.{default, typr}
66

77
trait ConstraintRunInfo { self: Run =>
88
private[this] var maxSize = 0
9-
private[this] var maxConstraint: Constraint = _
10-
def recordConstraintSize(c: Constraint, size: Int): Unit =
9+
private[this] var maxConstraint: Constraint[_, _] = _
10+
def recordConstraintSize(c: Constraint[_, _], size: Int): Unit =
1111
if (size > maxSize) {
1212
maxSize = size
1313
maxConstraint = c

compiler/src/dotty/tools/dotc/core/Contexts.scala

+22-22
Original file line numberDiff line numberDiff line change
@@ -717,12 +717,21 @@ object Contexts {
717717
def derived: GADTMap
718718
}
719719

720+
case class TvHandle(origin: TypeVarRef) extends Type with TypeVarHandle[TypeVarRef] {
721+
override def computeHash(bs: Hashable.Binders): Int = 0
722+
override def hash: Int = 0
723+
}
724+
720725
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-
) extends GADTMap with ConstraintHandling {
726+
private[this] var myConstraint: Constraint[TypeVarRef, TypeVarRefBinder] =
727+
new OrderingConstraint[TypeVarRef, TypeVarRefBinder](SimpleIdentityMap.Empty, SimpleIdentityMap.Empty, SimpleIdentityMap.Empty),
728+
private[this] var mapping: SimpleIdentityMap[Symbol, TvHandle] = SimpleIdentityMap.Empty,
729+
) extends GADTMap with ConstraintHandling[TypeVarRef, TypeVarRefBinder] {
724730
import dotty.tools.dotc.config.Printers.gadts
725731

732+
override def isVarRef(r: Type): Boolean = r.isInstanceOf[TypeParamRef] ||
733+
(r.isInstanceOf[TypeRef] && mapping.contains(r.typeSymbol(ctx)))
734+
726735
override def debugBoundsDescription(implicit ctx: Context): String = {
727736
val sb = new mutable.StringBuilder
728737
sb ++= constraint.show
@@ -742,17 +751,18 @@ object Contexts {
742751
try op finally myCtx = savedCtx
743752
}
744753

745-
override protected def constraint = myConstraint
746-
override protected def constraint_=(c: Constraint) = myConstraint = c
754+
override protected def constraint: OwnConstraint = myConstraint
755+
override protected def constraint_=(c: OwnConstraint) = myConstraint = c
747756

748757
override def isSubType(tp1: Type, tp2: Type): Boolean = ctx.typeComparer.isSubType(tp1, tp2)
749758
override def isSameType(tp1: Type, tp2: Type): Boolean = ctx.typeComparer.isSameType(tp1, tp2)
750759

751-
private[this] def tvar(sym: Symbol)(implicit ctx: Context): TypeVar = inCtx(ctx) {
760+
private[this] def tvar(sym: Symbol)(implicit ctx: Context): TvHandle = inCtx(ctx) {
752761
val res = mapping(sym) match {
753-
case tv: TypeVar => tv
762+
case tv: TvHandle => tv
754763
case null =>
755-
val res = new TypeVar(sym.typeRef, creatorState = null)
764+
// val res = new TypeVar(sym.typeRef, creatorState = null)
765+
val res = TvHandle(sym.typeRef)
756766
gadts.println(i"GADTMap: created tvar $sym -> $res")
757767
constraint = constraint.add(res.origin.binder, res :: Nil)
758768
mapping = mapping.updated(sym, res)
@@ -773,7 +783,7 @@ object Contexts {
773783
}
774784

775785
@annotation.tailrec def firstUninst(tp: Type): Type = tp match {
776-
case tv: TypeVar =>
786+
case tv: TypeVarHandle[_] =>
777787
val inst = _instType(tv.origin)
778788
if (inst.exists) firstUninst(inst) else tv
779789
case ref: TypeVarRef =>
@@ -805,15 +815,15 @@ object Contexts {
805815
}
806816

807817
val symRef: TypeVarRef = firstUninst(tvar(sym)) match {
808-
case tv: TypeVar => tv.origin
818+
case tv: TypeVarHandle[_] => tv.origin
809819
case inst =>
810820
gadts.println(i"instantiated: $sym -> $inst")
811821
return cautiousSubtype(inst, bound, isSubtype = isUpper, allowNarrowing = true)
812822
}
813823

814824
def doAddBound(bound: Type): Boolean = {
815825
val realBound = firstUninst(bound) match {
816-
case tv: TypeVar => tv.origin
826+
case tv: TypeVarHandle[_] => tv.origin
817827
case tp => tp
818828
}
819829

@@ -838,7 +848,7 @@ object Contexts {
838848

839849
val tvarBound = bound
840850
val res = tvarBound match {
841-
case boundTvar: TypeVar =>
851+
case boundTvar: TypeVarHandle[_] =>
842852
doAddBound(boundTvar)
843853
case tp => doAddBound(tp)
844854
}
@@ -864,16 +874,6 @@ object Contexts {
864874
this.myConstraint,
865875
this.mapping
866876
)
867-
868-
private final class TypeVarInsertingMap extends TypeMap {
869-
override def apply(tp: Type): Type = tp match {
870-
case tp: TypeRef =>
871-
val sym = tp.typeSymbol
872-
if (contains(sym)) tvar(sym) else tp
873-
case _ =>
874-
mapOver(tp)
875-
}
876-
}
877877
}
878878

879879
@sharable object EmptyGADTMap extends GADTMap {

0 commit comments

Comments
 (0)