Skip to content

Commit efdfe0e

Browse files
committed
Fix dependency checking in OrderingConstraint's replace
1 parent 0402937 commit efdfe0e

File tree

3 files changed

+42
-22
lines changed

3 files changed

+42
-22
lines changed

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

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import config.Config
1111
import config.Printers.constr
1212
import reflect.ClassTag
1313
import Constraint.ReverseDeps
14+
import Substituters.SubstParamMap
1415
import annotation.tailrec
1516
import annotation.internal.sharable
1617
import cc.{CapturingType, derivedCapturingType}
@@ -37,7 +38,7 @@ object OrderingConstraint {
3738
}
3839

3940
/** The `current` constraint but with the entry for `param` updated to `entry`.
40-
* `current` is used linearly. If it is different from `prev` it is
41+
* `current` is used linearly. If it is different from `prev` then `current` is
4142
* known to be dead after the call. Hence it is OK to update destructively
4243
* parts of `current` which are not shared by `prev`.
4344
*/
@@ -133,6 +134,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
133134
private val lowerMap : ParamOrdering,
134135
private val upperMap : ParamOrdering,
135136
private val hardVars : TypeVars) extends Constraint {
137+
thisConstraint =>
136138

137139
import UnificationDirection.*
138140

@@ -243,7 +245,9 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
243245
//.showing(i"outer depends on $tv with ${tvdeps.toList}%, % = $result")
244246
if co then test(coDeps, upperLens) else test(contraDeps, lowerLens)
245247

246-
private class Adjuster(srcParam: TypeParamRef)(using Context) extends TypeTraverser:
248+
private class Adjuster(srcParam: TypeParamRef)(using Context)
249+
extends TypeTraverser, ConstraintAwareTraversal:
250+
247251
var add: Boolean = compiletime.uninitialized
248252
val seen = util.HashSet[LazyRef]()
249253

@@ -411,7 +415,6 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
411415
tvars.copyToArray(entries1, nparams)
412416
newConstraint(boundsMap = this.boundsMap.updated(poly, entries1))
413417
.init(poly)
414-
.adjustDeps(poly, entries1, add = true)
415418
}
416419

417420
/** Split dependent parameters off the bounds for parameters in `poly`.
@@ -433,7 +436,8 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
433436
todos.dropInPlace(1)
434437
i += 1
435438
}
436-
current.checkWellFormed()
439+
current.adjustDeps(poly, current.boundsMap(poly).nn, add = true)
440+
.checkWellFormed()
437441
}
438442

439443
// ---------- Updates ------------------------------------------------------------
@@ -591,30 +595,33 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
591595
if param == replacement then this.checkWellFormed()
592596
else
593597
assert(replacement.isValueTypeOrLambda)
594-
var current =
595-
if isRemovable(param.binder) then remove(param.binder)
596-
else updateEntry(this, param, replacement)
597598

598-
def removeParam(ps: List[TypeParamRef]) = ps.filterConserve(param ne _)
599+
val droppedTypeVar = typeVarOfParam(param)
599600

600-
def replaceParam(entry: Type, atPoly: TypeLambda, atIdx: Int): Type =
601-
val pref = atPoly.paramRefs(atIdx)
602-
val newEntry = current.ensureNonCyclic(pref, entry.substParam(param, replacement))
603-
adjustDeps(newEntry, entry, pref)
604-
newEntry
601+
//println(i"replace $param, $droppedTypeVar with $replacement in $this")
602+
val dropTypeVar = new TypeMap:
603+
override def apply(t: Type): Type =
604+
if t.exists && (t eq droppedTypeVar) then param else mapOver(t)
605605

606+
var current = this
607+
608+
def removeParam(ps: List[TypeParamRef]) = ps.filterConserve(param ne _)
606609
for lo <- lower(param) do
607610
current = upperLens.map(this, current, lo, removeParam)
608611
for hi <- upper(param) do
609612
current = lowerLens.map(this, current, hi, removeParam)
610613

611614
current.foreachParam { (p, i) =>
612-
current = boundsLens.map(this, current, p, i,
613-
entry =>
614-
val newEntry = replaceParam(entry, p, i)
615-
adjustDeps(newEntry, entry, p.paramRefs(i))
616-
newEntry)
615+
val other = p.paramRefs(i)
616+
if other != param then
617+
val oldEntry = current.entry(other)
618+
val newEntry = current.ensureNonCyclic(other, oldEntry.substParam(param, replacement))
619+
current = updateEntryNoOrdering(current, other, newEntry, dropTypeVar(oldEntry))
617620
}
621+
622+
current =
623+
if isRemovable(param.binder) then current.remove(param.binder)
624+
else updateEntry(current, param, replacement)
618625
current.dropDeps(param)
619626
current.checkWellFormed()
620627
end replace

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ object Substituters:
193193
def apply(tp: Type): Type = substRecThis(tp, from, to, this)(using mapCtx)
194194
}
195195

196-
final class SubstParamMap(from: ParamRef, to: Type)(using Context) extends DeepTypeMap, IdempotentCaptRefMap {
196+
class SubstParamMap(from: ParamRef, to: Type)(using Context) extends DeepTypeMap, IdempotentCaptRefMap {
197197
def apply(tp: Type): Type = substParam(tp, from, to, this)(using mapCtx)
198198
}
199199

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

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5497,8 +5497,21 @@ object Types {
54975497
stop == StopAt.Static && tp.currentSymbol.isStatic && isStaticPrefix(tp.prefix)
54985498
|| stop == StopAt.Package && tp.currentSymbol.is(Package)
54995499
}
5500+
5501+
protected def tyconTypeParams(tp: AppliedType)(using Context): List[ParamInfo] =
5502+
tp.tyconTypeParams
55005503
end VariantTraversal
55015504

5505+
trait ConstraintAwareTraversal extends VariantTraversal:
5506+
override def tyconTypeParams(tp: AppliedType)(using Context): List[ParamInfo] =
5507+
tp.tycon match
5508+
case tycon: TypeParamRef =>
5509+
ctx.typerState.constraint.entry(tycon) match
5510+
case _: TypeBounds =>
5511+
case tp1 => if tp1.typeParams.nonEmpty then return tp1.typeParams
5512+
case _ =>
5513+
tp.tyconTypeParams
5514+
55025515
/** A supertrait for some typemaps that are bijections. Used for capture checking.
55035516
* BiTypeMaps should map capture references to capture references.
55045517
*/
@@ -5614,7 +5627,7 @@ object Types {
56145627
derivedSelect(tp, prefix1)
56155628

56165629
case tp: AppliedType =>
5617-
derivedAppliedType(tp, this(tp.tycon), mapArgs(tp.args, tp.tyconTypeParams))
5630+
derivedAppliedType(tp, this(tp.tycon), mapArgs(tp.args, tyconTypeParams(tp)))
56185631

56195632
case tp: LambdaType =>
56205633
mapOverLambda(tp)
@@ -5941,7 +5954,7 @@ object Types {
59415954
case nil =>
59425955
true
59435956
}
5944-
if (distributeArgs(args, tp.tyconTypeParams))
5957+
if (distributeArgs(args, tyconTypeParams(tp)))
59455958
range(tp.derivedAppliedType(tycon, loBuf.toList),
59465959
tp.derivedAppliedType(tycon, hiBuf.toList))
59475960
else if tycon.isLambdaSub || args.exists(isRangeOfNonTermTypes) then
@@ -6087,7 +6100,7 @@ object Types {
60876100
}
60886101
foldArgs(acc, tparams.tail, args.tail)
60896102
}
6090-
foldArgs(this(x, tycon), tp.tyconTypeParams, args)
6103+
foldArgs(this(x, tycon), tyconTypeParams(tp), args)
60916104

60926105
case _: BoundType | _: ThisType => x
60936106

0 commit comments

Comments
 (0)