aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/TypeComparer.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/TypeComparer.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/TypeComparer.scala')
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala53
1 files changed, 40 insertions, 13 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 3036cf878..3a0311977 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -398,7 +398,12 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
// This wpuld mean that there is no convenient means anymore to express a kind
// as a supertype. The fix is to delay the checking of bounds so that only
// bounds of * types are checked.
- variancesConform(tparams1, tparams2) && isSubType(body1, body2.subst(tp2, tp1))
+ val saved = comparingLambdas
+ comparingLambdas = true
+ try
+ variancesConform(tparams1, tparams2) &&
+ isSubType(body1, body2.subst(tp2, tp1))
+ finally comparingLambdas = saved
case _ =>
if (!tp1.isHK) {
tp2 match {
@@ -592,32 +597,54 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
false
}
- /** `param2` can be instantiated to the type constructor of the LHS
- * or to the type constructor of one of the LHS base class instances
+ /** `param2` can be instantiated to a type application prefix of the LHS
+ * or to a type application prefix of one of the LHS base class instances
* and the resulting type application is a supertype of `tp1`,
* or fallback to fourthTry.
*/
def canInstantiate(param2: PolyParam): Boolean = {
- /** `param2` can be instantiated to `tycon1a`.
- * and the resulting type application is a supertype of `tp1`.
+ /** Let
+ *
+ * `tparams_1, ..., tparams_k-1` be the type parameters of the rhs
+ * `tparams1_1, ..., tparams1_n-1` be the type parameters of the constructor of the lhs
+ * `args1_1, ..., args1_n-1` be the type arguments of the lhs
+ * `d = n - k`
+ *
+ * Returns `true` iff `d >= 0` and `param2` can be instantiated to
+ *
+ * [tparams1_d, ... tparams1_n-1] -> tycon1a[args_1, ..., args_d-1, tparams_d, ... tparams_n-1]
+ *
+ * such that the resulting type application is a supertype of `tp1`.
*/
- def tyconOK(tycon1a: Type) =
- variancesConform(tycon1a.typeParams, tparams) && {
- (ctx.mode.is(Mode.TypevarsMissContext) ||
- tryInstantiate(param2, tycon1a.ensureHK)) &&
- isSubType(tp1, tycon1a.appliedTo(args2))
+ def tyconOK(tycon1a: Type, args1: List[Type]) = {
+ var tycon1b = tycon1a
+ val tparams1a = tycon1a.typeParams
+ val lengthDiff = tparams1a.length - tparams.length
+ lengthDiff >= 0 && {
+ val tparams1 = tparams1a.drop(lengthDiff)
+ variancesConform(tparams1, tparams) && {
+ if (lengthDiff > 0)
+ tycon1b = tycon1a
+ .appliedTo(args1.take(lengthDiff) ++ tparams1.map(_.paramRef))
+ .LambdaAbstract(tparams1)
+ (ctx.mode.is(Mode.TypevarsMissContext) ||
+ tryInstantiate(param2, tycon1b.ensureHK)) &&
+ isSubType(tp1, tycon1b.appliedTo(args2))
+ }
}
+ }
tp1.widen match {
- case tp1w @ HKApply(tycon1, _) =>
- tyconOK(tycon1)
+ case tp1w @ HKApply(tycon1, args1) =>
+ tyconOK(tycon1, args1)
case tp1w =>
tp1w.typeSymbol.isClass && {
val classBounds = tycon2.classSymbols
def liftToBase(bcs: List[ClassSymbol]): Boolean = bcs match {
case bc :: bcs1 =>
- classBounds.exists(bc.derivesFrom) && tyconOK(tp1w.baseTypeRef(bc)) ||
+ classBounds.exists(bc.derivesFrom) &&
+ tyconOK(tp1w.baseTypeRef(bc), tp1w.baseArgInfos(bc)) ||
liftToBase(bcs1)
case _ =>
false