aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/ConstraintHandling.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-07-11 14:02:38 +0200
committerMartin Odersky <odersky@gmail.com>2016-07-11 16:16:16 +0200
commita200695677237922fdf6f995c690cb0108ec2fc4 (patch)
tree5c596d3534f0ba8bf6a5c50daf5a3886eff71143 /src/dotty/tools/dotc/core/ConstraintHandling.scala
parent540b38cbd769cee3e8bc72530829e65f7e87cddb (diff)
downloaddotty-a200695677237922fdf6f995c690cb0108ec2fc4.tar.gz
dotty-a200695677237922fdf6f995c690cb0108ec2fc4.tar.bz2
dotty-a200695677237922fdf6f995c690cb0108ec2fc4.zip
Fix SI-2712
Allows partially instantiated types as type constrictors when inferring higher-kinded types.
Diffstat (limited to 'src/dotty/tools/dotc/core/ConstraintHandling.scala')
-rw-r--r--src/dotty/tools/dotc/core/ConstraintHandling.scala37
1 files changed, 35 insertions, 2 deletions
diff --git a/src/dotty/tools/dotc/core/ConstraintHandling.scala b/src/dotty/tools/dotc/core/ConstraintHandling.scala
index d21f62440..1c3bd7384 100644
--- a/src/dotty/tools/dotc/core/ConstraintHandling.scala
+++ b/src/dotty/tools/dotc/core/ConstraintHandling.scala
@@ -35,6 +35,11 @@ trait ConstraintHandling {
/** If the constraint is frozen we cannot add new bounds to the constraint. */
protected var frozenConstraint = false
+ /** We are currently comparing lambdas. Used as a flag for
+ * optimization: when `false`, no need to do an expensive `pruneLambdaParams`
+ */
+ protected var comparingLambdas = false
+
private def addOneBound(param: PolyParam, bound: Type, isUpper: Boolean): Boolean =
!constraint.contains(param) || {
def occursIn(bound: Type): Boolean = {
@@ -289,6 +294,34 @@ trait ConstraintHandling {
checkPropagated(s"added $description") {
addConstraintInvocations += 1
+ /** When comparing lambdas we might get constraints such as
+ * `A <: X0` or `A = List[X0]` where `A` is a constrained parameter
+ * and `X0` is a lambda parameter. The constraint for `A` is not allowed
+ * to refer to such a lambda parameter because the lambda parameter is
+ * not visible where `A` is defined. Consequently, we need to
+ * approximate the bound so that the lambda parameter does not appear in it.
+ * Test case in neg/i94-nada.scala. This test crashes with an illegal instance
+ * error when the rest of the SI-2712 fix is applied but `pruneLambdaParams` is
+ * missing.
+ */
+ def pruneLambdaParams(tp: Type) =
+ if (comparingLambdas) {
+ val approx = new ApproximatingTypeMap {
+ def apply(t: Type): Type = t match {
+ case t @ PolyParam(tl: TypeLambda, n) =>
+ val effectiveVariance = if (fromBelow) -variance else variance
+ val bounds = tl.paramBounds(n)
+ if (effectiveVariance > 0) bounds.hi
+ else if (effectiveVariance < 0 ) bounds.lo
+ else NoType
+ case _ =>
+ mapOver(t)
+ }
+ }
+ approx(tp)
+ }
+ else tp
+
def addParamBound(bound: PolyParam) =
if (fromBelow) addLess(bound, param) else addLess(param, bound)
@@ -336,7 +369,7 @@ trait ConstraintHandling {
prune(bound.underlying)
case bound: PolyParam =>
constraint.entry(bound) match {
- case NoType => bound
+ case NoType => pruneLambdaParams(bound)
case _: TypeBounds =>
if (!addParamBound(bound)) NoType
else if (fromBelow) defn.NothingType
@@ -345,7 +378,7 @@ trait ConstraintHandling {
prune(inst)
}
case _ =>
- bound
+ pruneLambdaParams(bound)
}
try bound match {