From ce87f2a6c3bb9bb69b43db60e0864457988ecca6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 3 Oct 2017 17:46:05 +0200 Subject: [PATCH 1/2] Fix #3213: Make PolyTypes generative Because PolyTypes are used as carriers of constrained parameter references, we must make sure that we can duplicate them so that the duplicate is different from the original. Hence, it's useless to cache PolyTypes. --- .../src/dotty/tools/dotc/core/Types.scala | 83 +++++++------------ 1 file changed, 29 insertions(+), 54 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 9f1a1a2229b4..54c3113ddfe0 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2599,57 +2599,8 @@ object Types { final override def toString = s"$prefixString($paramNames, $paramInfos, $resType)" } - abstract class HKLambda extends CachedProxyType with LambdaType { - final override def underlying(implicit ctx: Context) = resType - - final override def computeHash = doHash(paramNames, resType, paramInfos) - - // Defined here instead of in LambdaType for efficiency - final override def equals(that: Any) = that match { - case that: HKLambda => - paramNames == that.paramNames && - paramInfos == that.paramInfos && - resType == that.resType && - companion.eq(that.companion) - case _ => - false - } - - final override def eql(that: Type) = that match { - case that: HKLambda => - paramNames.equals(that.paramNames) && - paramInfos.equals(that.paramInfos) && - resType.equals(that.resType) && - companion.eq(that.companion) - case _ => - false - } - } - - abstract class MethodOrPoly extends CachedGroundType with LambdaType with MethodicType { - final override def computeHash = doHash(paramNames, resType, paramInfos) - - // Defined here instead of in LambdaType for efficiency - final override def equals(that: Any) = that match { - case that: MethodOrPoly => - paramNames == that.paramNames && - paramInfos == that.paramInfos && - resType == that.resType && - companion.eq(that.companion) - case _ => - false - } - - final override def eql(that: Type) = that match { - case that: MethodOrPoly => - paramNames.eqElements(that.paramNames) && - paramInfos.eqElements(that.paramInfos) && - resType.eq(that.resType) && - companion.eq(that.companion) - case _ => - false - } - } + trait HKLambda extends LambdaType + trait MethodOrPoly extends LambdaType with MethodicType trait TermLambda extends LambdaType { thisLambdaType => import DepStatus._ @@ -2752,7 +2703,7 @@ object Types { abstract case class MethodType(paramNames: List[TermName])( paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type) - extends MethodOrPoly with TermLambda with NarrowCached { thisMethodType => + extends CachedGroundType with MethodOrPoly with TermLambda with NarrowCached { thisMethodType => import MethodType._ type This = MethodType @@ -2764,6 +2715,28 @@ object Types { def computeSignature(implicit ctx: Context): Signature = resultSignature.prepend(paramInfos, isJava) + final override def computeHash = doHash(paramNames, resType, paramInfos) + + final override def equals(that: Any) = that match { + case that: MethodType => + paramNames == that.paramNames && + paramInfos == that.paramInfos && + resType == that.resType && + companion.eq(that.companion) + case _ => + false + } + + final override def eql(that: Type) = that match { + case that: MethodType => + paramNames.eqElements(that.paramNames) && + paramInfos.eqElements(that.paramInfos) && + resType.eq(that.resType) && + companion.eq(that.companion) + case _ => + false + } + protected def prefixString = "MethodType" } @@ -2936,7 +2909,7 @@ object Types { */ class HKTypeLambda(val paramNames: List[TypeName])( paramInfosExp: HKTypeLambda => List[TypeBounds], resultTypeExp: HKTypeLambda => Type) - extends HKLambda with TypeLambda { + extends UncachedProxyType with HKLambda with TypeLambda { type This = HKTypeLambda def companion = HKTypeLambda @@ -2946,6 +2919,8 @@ object Types { assert(resType.isInstanceOf[TermType], this) assert(paramNames.nonEmpty) + final override def underlying(implicit ctx: Context) = resType + protected def prefixString = "HKTypeLambda" } @@ -2954,7 +2929,7 @@ object Types { */ class PolyType(val paramNames: List[TypeName])( paramInfosExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type) - extends MethodOrPoly with TypeLambda { + extends UncachedGroundType with MethodOrPoly with TypeLambda { type This = PolyType def companion = PolyType From ff03ed57738e3910fc64a9df2663bcc9613eb712 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Wed, 4 Oct 2017 14:33:51 +0200 Subject: [PATCH 2/2] Add test case for issue fixed in previous commit Fixes #2981 which was a duplicate of #3213 --- tests/pos/i2981.scala | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 tests/pos/i2981.scala diff --git a/tests/pos/i2981.scala b/tests/pos/i2981.scala new file mode 100644 index 000000000000..99cd93831fbc --- /dev/null +++ b/tests/pos/i2981.scala @@ -0,0 +1,16 @@ +trait HList +trait HNil extends HList + +trait FromTraversable[Out <: HList] +object FromTraversable { + implicit def hnilFromTraversable[T]: FromTraversable[HNil] = + new FromTraversable[HNil]{} +} + +object Filter { + def apply[A <: HList, O <: HList]()(implicit ftA: FromTraversable[A], + ftO: FromTraversable[O]): Unit = () +} +object Main { + def main = Filter[HNil, HNil]() +}