@@ -8,6 +8,7 @@ import collection.mutable
88import printing .Printer
99import printing .Texts ._
1010import config .Config
11+ import config .Printers .constr
1112import reflect .ClassTag
1213import annotation .tailrec
1314import annotation .internal .sharable
@@ -503,6 +504,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
503504 }
504505
505506 def & (other : Constraint , otherHasErrors : Boolean )(implicit ctx : Context ): OrderingConstraint = {
507+
506508 def merge [T ](m1 : ArrayValuedMap [T ], m2 : ArrayValuedMap [T ], join : (T , T ) => T ): ArrayValuedMap [T ] = {
507509 var merged = m1
508510 def mergeArrays (xs1 : Array [T ], xs2 : Array [T ]) = {
@@ -527,21 +529,71 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
527529 case (e1 : TypeBounds , e2 : TypeBounds ) => e1 & e2
528530 case (e1 : TypeBounds , _) if e1 contains e2 => e2
529531 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
531533 case _ =>
532534 if (otherHasErrors)
533535 e1
534536 else
535537 throw new AssertionError (i " cannot merge $this with $other, mergeEntries( $e1, $e2) failed " )
536538 }
537539
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+
539559 new OrderingConstraint (
540560 merge(this .boundsMap, that.boundsMap, mergeEntries),
541561 merge(this .lowerMap, that.lowerMap, mergeParams),
542562 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
543582 }
544583
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+
545597 override def checkClosed ()(implicit ctx : Context ): Unit = {
546598 def isFreeTypeParamRef (tp : Type ) = tp match {
547599 case TypeParamRef (binder : TypeLambda , _) => ! contains(binder)
0 commit comments