@@ -8,6 +8,7 @@ import collection.mutable
8
8
import printing .Printer
9
9
import printing .Texts ._
10
10
import config .Config
11
+ import config .Printers .constr
11
12
import reflect .ClassTag
12
13
import annotation .tailrec
13
14
import annotation .internal .sharable
@@ -503,6 +504,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
503
504
}
504
505
505
506
def & (other : Constraint , otherHasErrors : Boolean )(implicit ctx : Context ): OrderingConstraint = {
507
+
506
508
def merge [T ](m1 : ArrayValuedMap [T ], m2 : ArrayValuedMap [T ], join : (T , T ) => T ): ArrayValuedMap [T ] = {
507
509
var merged = m1
508
510
def mergeArrays (xs1 : Array [T ], xs2 : Array [T ]) = {
@@ -527,21 +529,71 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
527
529
case (e1 : TypeBounds , e2 : TypeBounds ) => e1 & e2
528
530
case (e1 : TypeBounds , _) if e1 contains e2 => e2
529
531
case (_, e2 : TypeBounds ) if e2 contains e1 => e1
530
- case (tv1 : TypeVar , tv2 : TypeVar ) if tv1.instanceOpt eq tv2.instanceOpt => e1
532
+ case (tv1 : TypeVar , tv2 : TypeVar ) if tv1 eq tv2 => e1
531
533
case _ =>
532
534
if (otherHasErrors)
533
535
e1
534
536
else
535
537
throw new AssertionError (i " cannot merge $this with $other, mergeEntries( $e1, $e2) failed " )
536
538
}
537
539
538
- val that = other.asInstanceOf [OrderingConstraint ]
540
+ /** Ensure that constraint `c` does not associate different TypeVars for the
541
+ * same type lambda than this constraint. Do this by renaming type lambdas
542
+ * in `c` where necessary.
543
+ */
544
+ def ensureNotConflicting (c : OrderingConstraint ): OrderingConstraint = {
545
+ def hasConflictingTypeVarsFor (tl : TypeLambda ) =
546
+ this .typeVarOfParam(tl.paramRefs(0 )) ne c.typeVarOfParam(tl.paramRefs(0 ))
547
+ // Note: Since TypeVars are allocated in bulk for each type lambda, we only
548
+ // have to check the first one to find out if some of them are different.
549
+ val conflicting = c.domainLambdas.find(tl =>
550
+ this .contains(tl) && hasConflictingTypeVarsFor(tl))
551
+ conflicting match {
552
+ case Some (tl) => ensureNotConflicting(c.rename(tl))
553
+ case None => c
554
+ }
555
+ }
556
+
557
+ val that = ensureNotConflicting(other.asInstanceOf [OrderingConstraint ])
558
+
539
559
new OrderingConstraint (
540
560
merge(this .boundsMap, that.boundsMap, mergeEntries),
541
561
merge(this .lowerMap, that.lowerMap, mergeParams),
542
562
merge(this .upperMap, that.upperMap, mergeParams))
563
+ }.reporting(res => i " constraint merge $this with $other = $res" , constr)
564
+
565
+ def rename (tl : TypeLambda )(implicit ctx : Context ): OrderingConstraint = {
566
+ assert(contains(tl))
567
+ val tl1 = ensureFresh(tl)
568
+ def swapKey [T ](m : ArrayValuedMap [T ]) = m.remove(tl).updated(tl1, m(tl))
569
+ var current = newConstraint(swapKey(boundsMap), swapKey(lowerMap), swapKey(upperMap))
570
+ def subst [T <: Type ](x : T ): T = x.subst(tl, tl1).asInstanceOf [T ]
571
+ current.foreachParam {(p, i) =>
572
+ current = boundsLens.map(this , current, p, i, subst)
573
+ current = lowerLens.map(this , current, p, i, _.map(subst))
574
+ current = upperLens.map(this , current, p, i, _.map(subst))
575
+ }
576
+ current.foreachTypeVar { tvar =>
577
+ val TypeParamRef (binder, n) = tvar.origin
578
+ if (binder eq tl) tvar.setOrigin(tl1.paramRefs(n))
579
+ }
580
+ constr.println(i " renamd $this to $current" )
581
+ current
543
582
}
544
583
584
+ def ensureFresh (tl : TypeLambda )(implicit ctx : Context ): TypeLambda =
585
+ if (contains(tl)) {
586
+ var paramInfos = tl.paramInfos
587
+ if (tl.isInstanceOf [HKLambda ]) {
588
+ // HKLambdas are hash-consed, need to create an artificial difference by adding
589
+ // a LazyRef to a bound.
590
+ val TypeBounds (lo, hi) :: pinfos1 = tl.paramInfos
591
+ paramInfos = TypeBounds (lo, LazyRef (_ => hi)) :: pinfos1
592
+ }
593
+ ensureFresh(tl.newLikeThis(tl.paramNames, paramInfos, tl.resultType))
594
+ }
595
+ else tl
596
+
545
597
override def checkClosed ()(implicit ctx : Context ): Unit = {
546
598
def isFreeTypeParamRef (tp : Type ) = tp match {
547
599
case TypeParamRef (binder : TypeLambda , _) => ! contains(binder)
0 commit comments