Skip to content

Commit bee8173

Browse files
author
Aleksander Boruch-Gruszecki
committed
Cleanup SmartGADTMap#ctx
Parameterised ConstraintHandling on what context it needs. TypeComparer works by being manually cloned in Context#typeComparer whenever Context notices that TypeComparer#ctx is different from itself. Unlike TypeComparer, SmartGADTMap keeps its own internal variables, so we cannot apply the same trick.
1 parent 074c2c8 commit bee8173

File tree

3 files changed

+47
-49
lines changed

3 files changed

+47
-49
lines changed

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

+23-23
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ 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 {
21+
trait ConstraintHandling[AbstractContext] {
2222

2323
def constr_println(msg: => String): Unit = constr.println(msg)
2424
def typr_println(msg: => String): Unit = typr.println(msg)
2525

26-
implicit def ctx: Context
26+
implicit def ctx(implicit ac: AbstractContext): Context
2727

28-
protected def isSubType(tp1: Type, tp2: Type): Boolean
29-
protected def isSameType(tp1: Type, tp2: Type): Boolean
28+
protected def isSubType(tp1: Type, tp2: Type)(implicit actx: AbstractContext): Boolean
29+
protected def isSameType(tp1: Type, tp2: Type)(implicit actx: AbstractContext): Boolean
3030

3131
protected def constraint: Constraint
3232
protected def constraint_=(c: Constraint): Unit
@@ -66,7 +66,7 @@ trait ConstraintHandling {
6666
case tp => tp
6767
}
6868

69-
protected def addOneBound(param: TypeParamRef, bound: Type, isUpper: Boolean): Boolean =
69+
protected def addOneBound(param: TypeParamRef, bound: Type, isUpper: Boolean)(implicit actx: AbstractContext): Boolean =
7070
!constraint.contains(param) || {
7171
def occursIn(bound: Type): Boolean = {
7272
val b = bound.dealias
@@ -116,7 +116,7 @@ trait ConstraintHandling {
116116

117117
private def location(implicit ctx: Context) = "" // i"in ${ctx.typerState.stateChainStr}" // use for debugging
118118

119-
protected def addUpperBound(param: TypeParamRef, bound: Type): Boolean = {
119+
protected def addUpperBound(param: TypeParamRef, bound: Type)(implicit actx: AbstractContext): Boolean = {
120120
def description = i"constraint $param <: $bound to\n$constraint"
121121
if (bound.isRef(defn.NothingClass) && ctx.typerState.isGlobalCommittable) {
122122
def msg = s"!!! instantiated to Nothing: $param, constraint = ${constraint.show}"
@@ -132,7 +132,7 @@ trait ConstraintHandling {
132132
res
133133
}
134134

135-
protected def addLowerBound(param: TypeParamRef, bound: Type): Boolean = {
135+
protected def addLowerBound(param: TypeParamRef, bound: Type)(implicit actx: AbstractContext): Boolean = {
136136
def description = i"constraint $param >: $bound to\n$constraint"
137137
constr_println(i"adding $description")
138138
val upper = constraint.upper(param)
@@ -143,7 +143,7 @@ trait ConstraintHandling {
143143
res
144144
}
145145

146-
protected def addLess(p1: TypeParamRef, p2: TypeParamRef): Boolean = {
146+
protected def addLess(p1: TypeParamRef, p2: TypeParamRef)(implicit actx: AbstractContext): Boolean = {
147147
def description = i"ordering $p1 <: $p2 to\n$constraint"
148148
val res =
149149
if (constraint.isLess(p2, p1)) unify(p2, p1)
@@ -165,7 +165,7 @@ trait ConstraintHandling {
165165
/** Make p2 = p1, transfer all bounds of p2 to p1
166166
* @pre less(p1)(p2)
167167
*/
168-
private def unify(p1: TypeParamRef, p2: TypeParamRef): Boolean = {
168+
private def unify(p1: TypeParamRef, p2: TypeParamRef)(implicit actx: AbstractContext): Boolean = {
169169
constr_println(s"unifying $p1 $p2")
170170
assert(constraint.isLess(p1, p2))
171171
val down = constraint.exclusiveLower(p2, p1)
@@ -180,7 +180,7 @@ trait ConstraintHandling {
180180
}
181181

182182

183-
protected def isSubType(tp1: Type, tp2: Type, whenFrozen: Boolean): Boolean = {
183+
protected def isSubType(tp1: Type, tp2: Type, whenFrozen: Boolean)(implicit actx: AbstractContext): Boolean = {
184184
if (whenFrozen)
185185
isSubTypeWhenFrozen(tp1, tp2)
186186
else
@@ -199,13 +199,13 @@ trait ConstraintHandling {
199199
}
200200
}
201201

202-
final def isSubTypeWhenFrozen(tp1: Type, tp2: Type): Boolean = inFrozenConstraint(isSubType(tp1, tp2))
203-
final def isSameTypeWhenFrozen(tp1: Type, tp2: Type): Boolean = inFrozenConstraint(isSameType(tp1, tp2))
202+
final def isSubTypeWhenFrozen(tp1: Type, tp2: Type)(implicit actx: AbstractContext): Boolean = inFrozenConstraint(isSubType(tp1, tp2))
203+
final def isSameTypeWhenFrozen(tp1: Type, tp2: Type)(implicit actx: AbstractContext): Boolean = inFrozenConstraint(isSameType(tp1, tp2))
204204

205205
/** Test whether the lower bounds of all parameters in this
206206
* constraint are a solution to the constraint.
207207
*/
208-
protected final def isSatisfiable: Boolean =
208+
protected final def isSatisfiable(implicit actx: AbstractContext): Boolean =
209209
constraint.forallParams { param =>
210210
val TypeBounds(lo, hi) = constraint.entry(param)
211211
isSubType(lo, hi) || {
@@ -224,7 +224,7 @@ trait ConstraintHandling {
224224
* @return the instantiating type
225225
* @pre `param` is in the constraint's domain.
226226
*/
227-
final def approximation(param: TypeParamRef, fromBelow: Boolean): Type = {
227+
final def approximation(param: TypeParamRef, fromBelow: Boolean)(implicit actx: AbstractContext): Type = {
228228
val avoidParam = new TypeMap {
229229
override def stopAtStatic = true
230230
def avoidInArg(arg: Type): Type =
@@ -278,7 +278,7 @@ trait ConstraintHandling {
278278
* 2. If `tp` is a union type, yet upper bound is not a union type,
279279
* approximate the union type from above by an intersection of all common base types.
280280
*/
281-
def widenInferred(tp: Type, bound: Type): Type = {
281+
def widenInferred(tp: Type, bound: Type)(implicit actx: AbstractContext): Type = {
282282
def isMultiSingleton(tp: Type): Boolean = tp.stripAnnots match {
283283
case tp: SingletonType => true
284284
case AndType(tp1, tp2) => isMultiSingleton(tp1) | isMultiSingleton(tp2)
@@ -311,7 +311,7 @@ trait ConstraintHandling {
311311
* a lower bound instantiation can be a singleton type only if the upper bound
312312
* is also a singleton type.
313313
*/
314-
def instanceType(param: TypeParamRef, fromBelow: Boolean): Type = {
314+
def instanceType(param: TypeParamRef, fromBelow: Boolean)(implicit actx: AbstractContext): Type = {
315315
val inst = approximation(param, fromBelow).simplified
316316
if (fromBelow) widenInferred(inst, constraint.fullUpperBound(param)) else inst
317317
}
@@ -326,7 +326,7 @@ trait ConstraintHandling {
326326
* Both `c1` and `c2` are required to derive from constraint `pre`, possibly
327327
* narrowing it with further bounds.
328328
*/
329-
protected final def subsumes(c1: Constraint, c2: Constraint, pre: Constraint): Boolean =
329+
protected final def subsumes(c1: Constraint, c2: Constraint, pre: Constraint)(implicit actx: AbstractContext): Boolean =
330330
if (c2 eq pre) true
331331
else if (c1 eq pre) false
332332
else {
@@ -340,7 +340,7 @@ trait ConstraintHandling {
340340
}
341341

342342
/** The current bounds of type parameter `param` */
343-
def bounds(param: TypeParamRef): TypeBounds = {
343+
def bounds(param: TypeParamRef)(implicit actx: AbstractContext): TypeBounds = {
344344
val e = constraint.entry(param)
345345
if (e.exists) e.bounds
346346
else {
@@ -354,7 +354,7 @@ trait ConstraintHandling {
354354
* and propagate all bounds.
355355
* @param tvars See Constraint#add
356356
*/
357-
def addToConstraint(tl: TypeLambda, tvars: List[TypeVar]): Boolean =
357+
def addToConstraint(tl: TypeLambda, tvars: List[TypeVar])(implicit actx: AbstractContext): Boolean =
358358
checkPropagated(i"initialized $tl") {
359359
constraint = constraint.add(tl, tvars)
360360
tl.paramRefs.forall { param =>
@@ -382,7 +382,7 @@ trait ConstraintHandling {
382382
* This holds if `TypeVarsMissContext` is set unless `param` is a part
383383
* of a MatchType that is currently normalized.
384384
*/
385-
final def assumedTrue(param: TypeParamRef): Boolean =
385+
final def assumedTrue(param: TypeParamRef)(implicit actx: AbstractContext): Boolean =
386386
ctx.mode.is(Mode.TypevarsMissContext) && (caseLambda `ne` param.binder)
387387

388388
/** Add constraint `param <: bound` if `fromBelow` is false, `param >: bound` otherwise.
@@ -392,7 +392,7 @@ trait ConstraintHandling {
392392
* not be AndTypes and lower bounds may not be OrTypes. This is assured by the
393393
* way isSubType is organized.
394394
*/
395-
protected def addConstraint(param: TypeParamRef, bound: Type, fromBelow: Boolean): Boolean = {
395+
protected def addConstraint(param: TypeParamRef, bound: Type, fromBelow: Boolean)(implicit actx: AbstractContext): Boolean = {
396396
def description = i"constr $param ${if (fromBelow) ">:" else "<:"} $bound:\n$constraint"
397397
//checkPropagated(s"adding $description")(true) // DEBUG in case following fails
398398
checkPropagated(s"added $description") {
@@ -508,7 +508,7 @@ trait ConstraintHandling {
508508
}
509509

510510
/** Instantiate `param` to `tp` if the constraint stays satisfiable */
511-
protected def tryInstantiate(param: TypeParamRef, tp: Type): Boolean = {
511+
protected def tryInstantiate(param: TypeParamRef, tp: Type)(implicit actx: AbstractContext): Boolean = {
512512
val saved = constraint
513513
constraint =
514514
if (addConstraint(param, tp, fromBelow = true) &&
@@ -518,7 +518,7 @@ trait ConstraintHandling {
518518
}
519519

520520
/** Check that constraint is fully propagated. See comment in Config.checkConstraintsPropagated */
521-
def checkPropagated(msg: => String)(result: Boolean): Boolean = {
521+
def checkPropagated(msg: => String)(result: Boolean)(implicit actx: AbstractContext): Boolean = {
522522
if (Config.checkConstraintsPropagated && result && addConstraintInvocations == 0) {
523523
inFrozenConstraint {
524524
for (p <- constraint.domainParams) {

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

+12-19
Original file line numberDiff line numberDiff line change
@@ -723,7 +723,7 @@ object Contexts {
723723
private[this] var reverseMapping: SimpleIdentityMap[TypeParamRef, Symbol],
724724
private[this] var boundCache: SimpleIdentityMap[Symbol, TypeBounds],
725725
private[this] var dirtyFlag: Boolean
726-
) extends GADTMap with ConstraintHandling {
726+
) extends GADTMap with ConstraintHandling[Context] {
727727
import dotty.tools.dotc.config.Printers.{gadts, gadtsConstr}
728728

729729
def this() = this(
@@ -748,20 +748,13 @@ object Contexts {
748748

749749
private[this] var checkInProgress = false
750750

751-
// TODO: clean up this dirty kludge
752-
private[this] var myCtx: Context = null
753-
implicit override def ctx = myCtx
754-
@forceInline private[this] final def inCtx[T](_ctx: Context)(op: => T) = {
755-
val savedCtx = myCtx
756-
myCtx = _ctx
757-
try op finally myCtx = savedCtx
758-
}
751+
implicit override def ctx(implicit ctx: Context): Context = ctx
759752

760753
override protected def constraint = myConstraint
761754
override protected def constraint_=(c: Constraint) = myConstraint = c
762755

763-
override def isSubType(tp1: Type, tp2: Type): Boolean = ctx.typeComparer.isSubType(tp1, tp2)
764-
override def isSameType(tp1: Type, tp2: Type): Boolean = ctx.typeComparer.isSameType(tp1, tp2)
756+
override def isSubType(tp1: Type, tp2: Type)(implicit ctx: Context): Boolean = ctx.typeComparer.isSubType(tp1, tp2)
757+
override def isSameType(tp1: Type, tp2: Type)(implicit ctx: Context): Boolean = ctx.typeComparer.isSameType(tp1, tp2)
765758

766759
private[this] def tvar(sym: Symbol)(implicit ctx: Context): TypeVar = {
767760
mapping(sym) match {
@@ -788,7 +781,7 @@ object Contexts {
788781

789782
override def addEmptyBounds(sym: Symbol)(implicit ctx: Context): Unit = tvar(sym)
790783

791-
override def addBound(sym: Symbol, bound: Type, isUpper: Boolean)(implicit ctx: Context): Boolean = try inCtx(ctx) {
784+
override def addBound(sym: Symbol, bound: Type, isUpper: Boolean)(implicit ctx: Context): Boolean = try {
792785
dirtyFlag = true
793786
checkInProgress = true
794787
@annotation.tailrec def stripInst(tp: Type): Type = tp match {
@@ -799,8 +792,8 @@ object Contexts {
799792
}
800793

801794
def cautiousSubtype(tp1: Type, tp2: Type, isSubtype: Boolean): Boolean = {
802-
val externalizedTp1 = (new TypeVarRemovingMap)(tp1)
803-
val externalizedTp2 = (new TypeVarRemovingMap)(tp2)
795+
val externalizedTp1 = (new TypeVarRemovingMap()(ctx))(tp1)
796+
val externalizedTp2 = (new TypeVarRemovingMap()(ctx))(tp2)
804797

805798
def descr = {
806799
def op = s"frozen_${if (isSubtype) "<:<" else ">:>"}"
@@ -846,7 +839,7 @@ object Contexts {
846839
constraint = constraint.updateEntry(tv.origin, tp)
847840
}
848841

849-
val tvarBound = (new TypeVarInsertingMap)(bound)
842+
val tvarBound = (new TypeVarInsertingMap()(ctx))(bound)
850843
val res = tvarBound match {
851844
case boundTvar: TypeVar =>
852845
doAddBound(boundTvar)
@@ -861,13 +854,13 @@ object Contexts {
861854
res
862855
} finally checkInProgress = false
863856

864-
override def bounds(sym: Symbol)(implicit ctx: Context): TypeBounds = inCtx(ctx) {
857+
override def bounds(sym: Symbol)(implicit ctx: Context): TypeBounds = {
865858
mapping(sym) match {
866859
case null => null
867860
case tv =>
868861
def retrieveBounds: TypeBounds = {
869862
val tb = constraint.fullBounds(tv.origin)
870-
(new TypeVarRemovingMap)(tb).asInstanceOf[TypeBounds]
863+
(new TypeVarRemovingMap()(ctx))(tb).asInstanceOf[TypeBounds]
871864
}
872865
val res =
873866
if (checkInProgress || ctx.mode.is(Mode.GADTflexible)) retrieveBounds
@@ -900,7 +893,7 @@ object Contexts {
900893
dirtyFlag
901894
)
902895

903-
private final class TypeVarInsertingMap extends TypeMap {
896+
private final class TypeVarInsertingMap(implicit ctx: Context) extends TypeMap {
904897
override def apply(tp: Type): Type = tp match {
905898
case tp: TypeRef =>
906899
val sym = tp.typeSymbol
@@ -910,7 +903,7 @@ object Contexts {
910903
}
911904
}
912905

913-
private final class TypeVarRemovingMap extends TypeMap {
906+
private final class TypeVarRemovingMap(implicit ctx: Context) extends TypeMap {
914907
override def apply(tp: Type): Type = tp match {
915908
case tpr: TypeParamRef =>
916909
reverseMapping(tpr) match {

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

+12-7
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,16 @@ import scala.util.control.NonFatal
1717
import typer.ProtoTypes.constrained
1818
import reporting.trace
1919

20+
final class AbsentContext
21+
object AbsentContext {
22+
implicit val absentContext: AbsentContext = new AbsentContext
23+
}
24+
2025
/** Provides methods to compare types.
2126
*/
22-
class TypeComparer(initctx: Context) extends ConstraintHandling {
27+
class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
2328
import TypeComparer._
24-
implicit val ctx: Context = initctx
29+
implicit def ctx(implicit nc: AbsentContext): Context = initctx
2530

2631
val state = ctx.typerState
2732
def constraint: Constraint = state.constraint
@@ -138,7 +143,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling {
138143
finally this.approx = saved
139144
}
140145

141-
def isSubType(tp1: Type, tp2: Type): Boolean = isSubType(tp1, tp2, NoApprox)
146+
def isSubType(tp1: Type, tp2: Type)(implicit nc: AbsentContext): Boolean = isSubType(tp1, tp2, NoApprox)
142147

143148
protected def recur(tp1: Type, tp2: Type): Boolean = trace(s"isSubType ${traceInfo(tp1, tp2)} $approx", subtyping) {
144149

@@ -1323,7 +1328,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling {
13231328
// Type equality =:=
13241329

13251330
/** Two types are the same if are mutual subtypes of each other */
1326-
def isSameType(tp1: Type, tp2: Type): Boolean =
1331+
def isSameType(tp1: Type, tp2: Type)(implicit nc: AbsentContext): Boolean =
13271332
if (tp1 eq NoType) false
13281333
else if (tp1 eq tp2) true
13291334
else isSubType(tp1, tp2) && isSubType(tp2, tp1)
@@ -1844,12 +1849,12 @@ class TrackingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
18441849

18451850
val footprint: mutable.Set[Type] = mutable.Set[Type]()
18461851

1847-
override def bounds(param: TypeParamRef): TypeBounds = {
1852+
override def bounds(param: TypeParamRef)(implicit nc: AbsentContext): TypeBounds = {
18481853
if (param.binder `ne` caseLambda) footprint += param
18491854
super.bounds(param)
18501855
}
18511856

1852-
override def addOneBound(param: TypeParamRef, bound: Type, isUpper: Boolean): Boolean = {
1857+
override def addOneBound(param: TypeParamRef, bound: Type, isUpper: Boolean)(implicit nc: AbsentContext): Boolean = {
18531858
if (param.binder `ne` caseLambda) footprint += param
18541859
super.addOneBound(param, bound, isUpper)
18551860
}
@@ -1960,7 +1965,7 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
19601965
super.glb(tp1, tp2)
19611966
}
19621967

1963-
override def addConstraint(param: TypeParamRef, bound: Type, fromBelow: Boolean): Boolean =
1968+
override def addConstraint(param: TypeParamRef, bound: Type, fromBelow: Boolean)(implicit nc: AbsentContext): Boolean =
19641969
traceIndented(i"add constraint $param ${if (fromBelow) ">:" else "<:"} $bound $frozenConstraint, constraint = ${ctx.typerState.constraint}") {
19651970
super.addConstraint(param, bound, fromBelow)
19661971
}

0 commit comments

Comments
 (0)