diff options
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r-- | src/dotty/tools/dotc/core/ConstraintHandling.scala | 11 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 48 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Implicits.scala | 8 |
3 files changed, 53 insertions, 14 deletions
diff --git a/src/dotty/tools/dotc/core/ConstraintHandling.scala b/src/dotty/tools/dotc/core/ConstraintHandling.scala index 66767d58a..44b6abe12 100644 --- a/src/dotty/tools/dotc/core/ConstraintHandling.scala +++ b/src/dotty/tools/dotc/core/ConstraintHandling.scala @@ -6,6 +6,7 @@ import Types._, Contexts._, Symbols._ import Decorators._ import config.Config import config.Printers._ +import TypeApplications.EtaExpansion import collection.mutable /** Methods for adding constraints and solving them. @@ -239,8 +240,6 @@ trait ConstraintHandling { def addParamBound(bound: PolyParam) = if (fromBelow) addLess(bound, param) else addLess(param, bound) - assert(param.isHK == bound.isHK, s"$param / $bound / $fromBelow") - /** Drop all constrained parameters that occur at the toplevel in `bound` and * handle them by `addLess` calls. * The preconditions make sure that such parameters occur only @@ -297,7 +296,13 @@ trait ConstraintHandling { case bound: PolyParam if constraint contains bound => addParamBound(bound) case _ => - val pbound = prune(bound) + var pbound = prune(bound) + if (pbound.isHK && !param.isHK) { + param match { + case EtaExpansion(tycon) if tycon.symbol.isClass => pbound = tycon + case _ => + } + } pbound.exists && ( if (fromBelow) addLowerBound(param, pbound) else addUpperBound(param, pbound)) } diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index 12e9e638a..e6cd0a0df 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -392,12 +392,12 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { case tp2 @ HKApply(tycon2, args2) => compareHkApply2(tp1, tp2, tycon2, args2) case tp2 @ TypeLambda(tparams2, body2) => - def compareHkLambda = tp1.stripTypeVar match { + def compareHkLambda: Boolean = tp1.stripTypeVar match { case tp1 @ TypeLambda(tparams1, body1) => // Don't compare bounds of lambdas, or t2994 will fail // The issue is that, logically, bounds should compare contravariantly, // so the bounds checking should look like this: - // + // // tparams1.corresponds(tparams2)((tparam1, tparam2) => // isSubType(tparam2.memberBounds.subst(tp2, tp1), tparam1.memberBounds)) // @@ -408,6 +408,13 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { // bounds of * types are checked. variancesConform(tparams1, tparams2) && isSubType(body1, body2.subst(tp2, tp1)) case _ => + if (!tp1.isHK) { + tp2 match { + case EtaExpansion(tycon2) if tycon2.symbol.isClass => + return isSubType(tp1, tycon2) + case _ => + } + } fourthTry(tp1, tp2) } compareHkLambda @@ -1269,7 +1276,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { val t2 = distributeAnd(tp2, tp1) if (t2.exists) t2 else if (erased) erasedGlb(tp1, tp2, isJava = false) - else liftIfHK(tp1, tp2, AndType(_, _)) + else liftIfHK(tp1, tp2, AndType(_, _), _ & _) } } @@ -1293,7 +1300,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { val t2 = distributeOr(tp2, tp1) if (t2.exists) t2 else if (erased) erasedLub(tp1, tp2) - else liftIfHK(tp1, tp2, OrType(_, _)) + else liftIfHK(tp1, tp2, OrType(_, _), _ | _) } } @@ -1314,11 +1321,24 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { * allowing both interpretations. A possible remedy is to be somehow stricter * in where we allow which interpretation. */ - private def liftIfHK(tp1: Type, tp2: Type, op: (Type, Type) => Type) = { + private def liftIfHK(tp1: Type, tp2: Type, op: (Type, Type) => Type, original: (Type, Type) => Type) = { val tparams1 = tp1.typeParams val tparams2 = tp2.typeParams - if (tparams1.isEmpty || tparams2.isEmpty) op(tp1, tp2) - else if (tparams1.length != tparams2.length) mergeConflict(tp1, tp2) + if (!Config.newHK && tparams1.isEmpty || tparams2.isEmpty) op(tp1, tp2) + else if (Config.newHK && tparams1.isEmpty) + if (tparams2.isEmpty) op(tp1, tp2) + else tp2 match { + case EtaExpansion(tycon2) if tycon2.symbol.isClass => original(tp1, tycon2) // TODO: Roll isClass into EtaExpansion? + case _ => mergeConflict(tp1, tp2) + } + else if (Config.newHK && tparams2.isEmpty) { + tp1 match { + case EtaExpansion(tycon1) if tycon1.symbol.isClass => original(tycon1, tp2) + case _ => mergeConflict(tp1, tp2) + } + } + else if (!Config.newHK && (tparams1.isEmpty || tparams2.isEmpty)) op(tp1, tp2) + else if (!Config.newHK && tparams1.length != tparams2.length) mergeConflict(tp1, tp2) else if (Config.newHK) { val numArgs = tparams1.length def argRefs(tl: GenericType) = List.range(0, numArgs).map(PolyParam(tl, _)) @@ -1330,7 +1350,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { tl.lifted(tparams1, tparam1.memberBoundsAsSeenFrom(tp1)).bounds & tl.lifted(tparams2, tparam2.memberBoundsAsSeenFrom(tp2)).bounds), resultTypeExp = tl => - op(tl.lifted(tparams1, tp1).appliedTo(argRefs(tl)), + original(tl.lifted(tparams1, tp1).appliedTo(argRefs(tl)), tl.lifted(tparams2, tp2).appliedTo(argRefs(tl)))) } else { @@ -1389,12 +1409,18 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { mergeNames(names1, names2, nme.syntheticParamName), formals1, tp1.resultType & tp2.resultType.subst(tp2, tp1)) case _ => + tp2 match { + case tp2 @ MethodType(names2, formals2) => + println( + TypeComparer.explained(implicit ctx => isSameType(formals1.head, formals2.head))) + case _ => + } mergeConflict(tp1, tp2) } - case tp1: GenericType => + case tp1: PolyType => tp2 match { - case tp2: GenericType if matchingTypeParams(tp1, tp2) => - tp1.derivedGenericType( + case tp2: PolyType if matchingTypeParams(tp1, tp2) => + tp1.derivedPolyType( mergeNames(tp1.paramNames, tp2.paramNames, tpnme.syntheticTypeParamName), tp1.paramBounds, tp1.resultType & tp2.resultType.subst(tp2, tp1)) case _ => diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala index a5246cf6b..d3f9fd777 100644 --- a/src/dotty/tools/dotc/typer/Implicits.scala +++ b/src/dotty/tools/dotc/typer/Implicits.scala @@ -292,6 +292,14 @@ trait ImplicitRunInfo { self: RunInfo => (lead /: tp.classSymbols)(joinClass) case tp: TypeVar => apply(tp.underlying) + case tp: HKApply => + def applyArg(arg: Type) = arg match { + case TypeBounds(lo, hi) => AndType.make(lo, hi) + case _ => arg + } + (apply(tp.tycon) /: tp.args)((tc, arg) => AndType.make(tc, applyArg(arg))) + case tp: TypeLambda => + apply(tp.resType) case _ => mapOver(tp) } |