Skip to content

Commit f008bbc

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 9ed0993 commit f008bbc

File tree

3 files changed

+48
-50
lines changed

3 files changed

+48
-50
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)
@@ -164,7 +164,7 @@ trait ConstraintHandling {
164164
/** Make p2 = p1, transfer all bounds of p2 to p1
165165
* @pre less(p1)(p2)
166166
*/
167-
private def unify(p1: TypeParamRef, p2: TypeParamRef): Boolean = {
167+
private def unify(p1: TypeParamRef, p2: TypeParamRef)(implicit actx: AbstractContext): Boolean = {
168168
constr_println(s"unifying $p1 $p2")
169169
assert(constraint.isLess(p1, p2))
170170
val down = constraint.exclusiveLower(p2, p1)
@@ -179,7 +179,7 @@ trait ConstraintHandling {
179179
}
180180

181181

182-
protected def isSubType(tp1: Type, tp2: Type, whenFrozen: Boolean): Boolean = {
182+
protected def isSubType(tp1: Type, tp2: Type, whenFrozen: Boolean)(implicit actx: AbstractContext): Boolean = {
183183
if (whenFrozen)
184184
isSubTypeWhenFrozen(tp1, tp2)
185185
else
@@ -198,13 +198,13 @@ trait ConstraintHandling {
198198
}
199199
}
200200

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

204204
/** Test whether the lower bounds of all parameters in this
205205
* constraint are a solution to the constraint.
206206
*/
207-
protected final def isSatisfiable: Boolean =
207+
protected final def isSatisfiable(implicit actx: AbstractContext): Boolean =
208208
constraint.forallParams { param =>
209209
val TypeBounds(lo, hi) = constraint.entry(param)
210210
isSubType(lo, hi) || {
@@ -223,7 +223,7 @@ trait ConstraintHandling {
223223
* @return the instantiating type
224224
* @pre `param` is in the constraint's domain.
225225
*/
226-
final def approximation(param: TypeParamRef, fromBelow: Boolean): Type = {
226+
final def approximation(param: TypeParamRef, fromBelow: Boolean)(implicit actx: AbstractContext): Type = {
227227
val avoidParam = new TypeMap {
228228
override def stopAtStatic = true
229229
def avoidInArg(arg: Type): Type =
@@ -277,7 +277,7 @@ trait ConstraintHandling {
277277
* 2. If `tp` is a union type, yet upper bound is not a union type,
278278
* approximate the union type from above by an intersection of all common base types.
279279
*/
280-
def widenInferred(tp: Type, bound: Type): Type = {
280+
def widenInferred(tp: Type, bound: Type)(implicit actx: AbstractContext): Type = {
281281
def isMultiSingleton(tp: Type): Boolean = tp.stripAnnots match {
282282
case tp: SingletonType => true
283283
case AndType(tp1, tp2) => isMultiSingleton(tp1) | isMultiSingleton(tp2)
@@ -310,7 +310,7 @@ trait ConstraintHandling {
310310
* a lower bound instantiation can be a singleton type only if the upper bound
311311
* is also a singleton type.
312312
*/
313-
def instanceType(param: TypeParamRef, fromBelow: Boolean): Type = {
313+
def instanceType(param: TypeParamRef, fromBelow: Boolean)(implicit actx: AbstractContext): Type = {
314314
val inst = approximation(param, fromBelow).simplified
315315
if (fromBelow) widenInferred(inst, constraint.fullUpperBound(param)) else inst
316316
}
@@ -325,7 +325,7 @@ trait ConstraintHandling {
325325
* Both `c1` and `c2` are required to derive from constraint `pre`, possibly
326326
* narrowing it with further bounds.
327327
*/
328-
protected final def subsumes(c1: Constraint, c2: Constraint, pre: Constraint): Boolean =
328+
protected final def subsumes(c1: Constraint, c2: Constraint, pre: Constraint)(implicit actx: AbstractContext): Boolean =
329329
if (c2 eq pre) true
330330
else if (c1 eq pre) false
331331
else {
@@ -339,7 +339,7 @@ trait ConstraintHandling {
339339
}
340340

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

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

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

519519
/** Check that constraint is fully propagated. See comment in Config.checkConstraintsPropagated */
520-
def checkPropagated(msg: => String)(result: Boolean): Boolean = {
520+
def checkPropagated(msg: => String)(result: Boolean)(implicit actx: AbstractContext): Boolean = {
521521
if (Config.checkConstraintsPropagated && result && addConstraintInvocations == 0) {
522522
inFrozenConstraint {
523523
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

+13-8
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

@@ -185,7 +190,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling {
185190
def firstTry: Boolean = tp2 match {
186191
case tp2: NamedType =>
187192
def compareNamed(tp1: Type, tp2: NamedType): Boolean = {
188-
implicit val ctx = this.ctx
193+
implicit val ctx: Context = this.ctx
189194
tp2.info match {
190195
case info2: TypeAlias => recur(tp1, info2.alias)
191196
case _ => tp1 match {
@@ -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)