Skip to content

Commit eef9be9

Browse files
committed
Implement constraint merging
Not used yet, but we might use it as an alternative to typedArg invalidation later.
1 parent 959ea0c commit eef9be9

File tree

3 files changed

+48
-5
lines changed

3 files changed

+48
-5
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ abstract class Constraint extends Showable {
143143
/** The uninstantiated typevars of this constraint */
144144
def uninstVars: collection.Seq[TypeVar]
145145

146+
/** The weakest constraint that subsumes both this constraint and `other` */
147+
def & (other: Constraint)(implicit ctx: Context): Constraint
148+
146149
/** Check that no constrained parameter contains itself as a bound */
147150
def checkNonCyclic()(implicit ctx: Context): Unit
148151

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

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@ import annotation.tailrec
1515

1616
object OrderingConstraint {
1717

18+
type ArrayValuedMap[T] = SimpleMap[GenericType, Array[T]]
19+
1820
/** The type of `OrderingConstraint#boundsMap` */
19-
type ParamBounds = SimpleMap[GenericType, Array[Type]]
21+
type ParamBounds = ArrayValuedMap[Type]
2022

2123
/** The type of `OrderingConstraint#lowerMap`, `OrderingConstraint#upperMap` */
22-
type ParamOrdering = SimpleMap[GenericType, Array[List[PolyParam]]]
24+
type ParamOrdering = ArrayValuedMap[List[PolyParam]]
2325

2426
/** A new constraint with given maps */
2527
private def newConstraint(boundsMap: ParamBounds, lowerMap: ParamOrdering, upperMap: ParamOrdering)(implicit ctx: Context) : OrderingConstraint = {
@@ -495,6 +497,44 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
495497
}
496498
}
497499

500+
def & (other: Constraint)(implicit ctx: Context) = {
501+
def merge[T](m1: ArrayValuedMap[T], m2: ArrayValuedMap[T], join: (T, T) => T): ArrayValuedMap[T] = {
502+
var merged = m1
503+
def mergeArrays(xs1: Array[T], xs2: Array[T]) = {
504+
val xs = xs1.clone
505+
for (i <- xs.indices) xs(i) = join(xs1(i), xs2(i))
506+
xs
507+
}
508+
m2.foreachBinding { (poly, xs2) =>
509+
merged = merged.updated(poly,
510+
if (m1.contains(poly)) mergeArrays(m1(poly), xs2) else xs2)
511+
}
512+
merged
513+
}
514+
515+
def mergeParams(ps1: List[PolyParam], ps2: List[PolyParam]) =
516+
(ps1 /: ps2)((ps1, p2) => if (ps1.contains(p2)) ps1 else p2 :: ps1)
517+
518+
def mergeEntries(e1: Type, e2: Type): Type = e1 match {
519+
case e1: TypeBounds =>
520+
e2 match {
521+
case e2: TypeBounds => e1 & e2
522+
case _ if e1 contains e2 => e2
523+
case _ => mergeError
524+
}
525+
case _ if e1 eq e2 => e1
526+
case _ => mergeError
527+
}
528+
529+
def mergeError = throw new AssertionError(i"cannot merge $this with $other")
530+
531+
val that = other.asInstanceOf[OrderingConstraint]
532+
new OrderingConstraint(
533+
merge(this.boundsMap, that.boundsMap, mergeEntries),
534+
merge(this.lowerMap, that.lowerMap, mergeParams),
535+
merge(this.upperMap, that.upperMap, mergeParams))
536+
}
537+
498538
override def checkClosed()(implicit ctx: Context): Unit = {
499539
def isFreePolyParam(tp: Type) = tp match {
500540
case PolyParam(binder: GenericType, _) => !contains(binder)

src/dotty/tools/dotc/core/TyperState.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,14 @@ extends TyperState(r) {
128128
*/
129129
override def commit()(implicit ctx: Context) = {
130130
val targetState = ctx.typerState
131-
assert(targetState eq previous)
132131
assert(isCommittable)
133-
targetState.constraint = constraint
132+
if (targetState eq previous) targetState.constraint = constraint
133+
else targetState.constraint &= constraint
134134
constraint foreachTypeVar { tvar =>
135135
if (tvar.owningState eq this)
136136
tvar.owningState = targetState
137137
}
138-
targetState.ephemeral = ephemeral
138+
targetState.ephemeral |= ephemeral
139139
targetState.gc()
140140
reporter.flush()
141141
myIsCommitted = true

0 commit comments

Comments
 (0)