Skip to content

Commit 26e2030

Browse files
committed
Make dependency checks level-independent
1 parent 7d2872f commit 26e2030

File tree

3 files changed

+56
-13
lines changed

3 files changed

+56
-13
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,13 @@ abstract class Constraint extends Showable {
181181
/** A string showing the `coDeps` and `contraDeps` maps */
182182
def depsToString(using Context): String
183183

184+
/** Does the constraint restricted to variables outside `except` depend on `tv`
185+
* in the given direction `co`?
186+
* @param `co` If true, test whether the constraint would change if the variable is made larger
187+
* otherwise, test whether the constraint would change if the variable is made smaller.
188+
*/
189+
def dependsOn(tv: TypeVar, except: TypeVars, co: Boolean)(using Context): Boolean
190+
184191
/** If the type variable `tv` would be instantiated to a larger type, the
185192
* constraint over outer type variables would be narrowed.
186193
*/

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,15 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
249249
//.showing(i"outer depends on $tv ${tv.initNestingLevel} with ${tvdeps.toList.map(_.initNestingLevel)}%, % = $result")
250250
end outerDependsOn
251251

252+
def dependsOn(tv: TypeVar, except: TypeVars, co: Boolean)(using Context): Boolean =
253+
def test(deps: TypeVarDeps, lens: ConstraintLens[List[TypeParamRef]]) =
254+
val tvdeps = deps(tv)
255+
null != tvdeps && tvdeps.exists(!except.contains(_))
256+
|| lens(this, tv.origin.binder, tv.origin.paramNum).exists(
257+
p => !except.contains(typeVarOfParam(p)))
258+
//.showing(i"outer depends on $tv with ${tvdeps.toList}%, % = $result")
259+
if co then test(coDeps, upperLens) else test(contraDeps, lowerLens)
260+
252261
def outerDependsCovariantlyOn(tv: TypeVar)(using Context) =
253262
outerDependsOn(tv, tv.nestingLevel, coDeps, upperLens, SimpleIdentitySet.empty)
254263

compiler/src/dotty/tools/dotc/typer/Inferencing.scala

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import reporting._
1616
import collection.mutable
1717

1818
import scala.annotation.internal.sharable
19+
import dotty.tools.dotc.util.SimpleIdentitySet
1920

2021
object Inferencing {
2122

@@ -619,7 +620,7 @@ trait Inferencing { this: Typer =>
619620
if state.reporter.hasUnreportedErrors then return tree
620621

621622
def constraint = state.constraint
622-
type InstantiateQueue = mutable.ListBuffer[(TypeVar, Boolean)]
623+
type InstantiateQueue = mutable.ListBuffer[(TypeVar, Int)]
623624
val toInstantiate = new InstantiateQueue
624625
for tvar <- qualifying do
625626
if !tvar.isInstantiated && constraint.contains(tvar) && tvar.nestingLevel >= ctx.nestingLevel then
@@ -637,18 +638,16 @@ trait Inferencing { this: Typer =>
637638
// instantiate it in the direction corresponding to the
638639
// original variable which might be further constrained later.
639640
// Otherwise, we simply rely on `hasLowerBound`.
640-
val name = tvar.origin.paramName
641-
val fromBelow =
642-
if name.is(AvoidNameKind.UpperBound) then true
643-
else if name.is(AvoidNameKind.LowerBound) then false
644-
else if constraint.outerDependsCovariantlyOn(tvar) then true
645-
else if constraint.outerDependsContravariantlyOn(tvar) then false
646-
else tvar.hasLowerBound
647-
typr.println(i"interpolate non-occurring $tvar in $state in $tree: $tp, fromBelow = $fromBelow, $constraint")
648-
toInstantiate += ((tvar, fromBelow))
641+
//val name = tvar.origin.paramName
642+
//val fromBelow =
643+
// if name.is(AvoidNameKind.UpperBound) then true
644+
// else if name.is(AvoidNameKind.LowerBound) then false
645+
// else if constraint.outerDependsCovariantlyOn(tvar) then true
646+
// else if constraint.outerDependsContravariantlyOn(tvar) then false
647+
// else tvar.hasLowerBound
648+
toInstantiate += ((tvar, 0))
649649
else if v.intValue != 0 then
650-
typr.println(i"interpolate $tvar in $state in $tree: $tp, fromBelow = ${v.intValue == 1}, $constraint")
651-
toInstantiate += ((tvar, v.intValue == 1))
650+
toInstantiate += ((tvar, v.intValue))
652651
else comparing(cmp =>
653652
if !cmp.levelOK(tvar.nestingLevel, ctx.nestingLevel) then
654653
// Invariant: The type of a tree whose enclosing scope is level
@@ -689,10 +688,38 @@ trait Inferencing { this: Typer =>
689688
* V2 := V3, O2 := O3
690689
*/
691690
def doInstantiate(buf: InstantiateQueue): Unit =
691+
val varsToInstantiate = buf.foldLeft(SimpleIdentitySet.empty: TypeVars) {
692+
case (tvs, (tv, _)) => tvs + tv
693+
}
692694
if buf.nonEmpty then
693695
val suspended = new InstantiateQueue
694696
while buf.nonEmpty do
695-
val first @ (tvar, fromBelow) = buf.head
697+
val first @ (tvar, v) = buf.head
698+
val fromBelow =
699+
if v == 0 then
700+
val aboveOK = !constraint.dependsOn(tvar, varsToInstantiate, co = true)
701+
val belowOK = !constraint.dependsOn(tvar, varsToInstantiate, co = false)
702+
val now =
703+
if aboveOK == belowOK then tvar.hasLowerBound
704+
else belowOK
705+
/*
706+
val was =
707+
val name = tvar.origin.paramName
708+
val depCo = constraint.outerDependsCovariantlyOn(tvar)
709+
val depContra = constraint.outerDependsContravariantlyOn(tvar)
710+
if name.is(AvoidNameKind.UpperBound) then true
711+
else if name.is(AvoidNameKind.LowerBound) then false
712+
else if constraint.outerDependsCovariantlyOn(tvar) then true
713+
else if constraint.outerDependsContravariantlyOn(tvar) then false
714+
else tvar.hasLowerBound
715+
if now != was then
716+
println(i"diff for $tvar, was $was, aboveOK = $aboveOK, belowOK = $belowOK, depCo = $depCo, depContra = $depContra")
717+
*/
718+
now
719+
else
720+
v == 1
721+
typr.println(
722+
i"interpolate${if v == 0 then "non-occurring" else ""} $tvar in $state in $tree: $tp, fromBelow = $fromBelow, $constraint")
696723
buf.dropInPlace(1)
697724
if !tvar.isInstantiated then
698725
val suspend = buf.exists{ (following, _) =>

0 commit comments

Comments
 (0)