Skip to content

Commit 7e3f5ab

Browse files
committed
Handle case where typevar instance is fully determined
It's possible that a type parameter in a constraint gets instantiated via a unification operation. In that case, the type parameter does not have a TypeBounds instance associated with it, so is not considered to be contained in the constraint. But it must still be possible to instantiate a type variable corresponding to this parameter. Test case in collection strawman: `List.empty ++ List.empty`.
1 parent 11e2526 commit 7e3f5ab

File tree

2 files changed

+25
-20
lines changed

2 files changed

+25
-20
lines changed

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -222,11 +222,16 @@ trait ConstraintHandling {
222222
}
223223
}
224224
}
225-
assert(constraint.contains(param))
226-
val bound = if (fromBelow) constraint.fullLowerBound(param) else constraint.fullUpperBound(param)
227-
val inst = avoidParam(bound)
228-
typr.println(s"approx ${param.show}, from below = $fromBelow, bound = ${bound.show}, inst = ${inst.show}")
229-
inst
225+
constraint.entry(param) match {
226+
case bounds: TypeBounds =>
227+
val bound = if (fromBelow) constraint.fullLowerBound(param) else constraint.fullUpperBound(param)
228+
val inst = avoidParam(bound)
229+
typr.println(s"approx ${param.show}, from below = $fromBelow, bound = ${bound.show}, inst = ${inst.show}")
230+
inst
231+
case inst =>
232+
assert(inst.exists, i"$param not in $constraint")
233+
inst
234+
}
230235
}
231236

232237
/** The instance type of `param` in the current constraint (which contains `param`).

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

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
160160
val origin = tvar.origin
161161
val entries = boundsMap(origin.binder)
162162
val pnum = origin.paramNum
163-
entries != null && isBounds(entries(pnum)) && (typeVar(entries, pnum) eq tvar)
163+
entries != null && entries(pnum).exists && (typeVar(entries, pnum) eq tvar)
164164
}
165165

166166
private def isBounds(tp: Type) = tp.isInstanceOf[TypeBounds]
@@ -507,19 +507,19 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
507507
(ps1 /: ps2)((ps1, p2) => if (ps1.contains(p2)) ps1 else p2 :: ps1)
508508

509509
def mergeEntries(e1: Type, e2: Type): Type = e1 match {
510-
case e1: TypeBounds =>
511-
e2 match {
512-
case e2: TypeBounds => e1 & e2
513-
case _ if e1 contains e2 => e2
514-
case _ => mergeError
515-
}
516-
case tv1: TypeVar =>
517-
e2 match {
518-
case tv2: TypeVar if tv1.instanceOpt eq tv2.instanceOpt => e1
519-
case _ => mergeError
520-
}
521-
case _ if e1 eq e2 => e1
522-
case _ => mergeError
510+
case e1: TypeBounds =>
511+
e2 match {
512+
case e2: TypeBounds => e1 & e2
513+
case _ if e1 contains e2 => e2
514+
case _ => mergeError
515+
}
516+
case tv1: TypeVar =>
517+
e2 match {
518+
case tv2: TypeVar if tv1.instanceOpt eq tv2.instanceOpt => e1
519+
case _ => mergeError
520+
}
521+
case _ if e1 eq e2 => e1
522+
case _ => mergeError
523523
}
524524

525525
def mergeError = throw new AssertionError(i"cannot merge $this with $other")
@@ -611,7 +611,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
611611
override def toString: String = {
612612
def entryText(tp: Type): String = tp match {
613613
case tp: TypeBounds => tp.toString
614-
case _ =>" := " + tp
614+
case _ => " := " + tp
615615
}
616616
val constrainedText =
617617
" constrained types = " + domainLambdas.mkString("\n")

0 commit comments

Comments
 (0)