diff options
author | Adriaan Moors <adriaan.moors@epfl.ch> | 2009-11-12 21:04:26 +0000 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2009-11-12 21:04:26 +0000 |
commit | fe3b78b8644fe025e9ff742d79d9b69270993749 (patch) | |
tree | a1a4d2f1a63ac5b008792d053a1aacc828b58c27 | |
parent | d24de699d877477a1c321b81ff9740b753fda659 (diff) | |
download | scala-fe3b78b8644fe025e9ff742d79d9b69270993749.tar.gz scala-fe3b78b8644fe025e9ff742d79d9b69270993749.tar.bz2 scala-fe3b78b8644fe025e9ff742d79d9b69270993749.zip |
Merge branch 'ticket/2594'
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/UnCurry.scala | 31 | ||||
-rw-r--r-- | test/files/run/t2594_tcpoly.check | 0 | ||||
-rw-r--r-- | test/files/run/t2594_tcpoly.scala | 18 |
3 files changed, 44 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index eec523a2b8..67c963acf5 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -47,9 +47,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { // ------ Type transformation -------------------------------------------------------- -//@MAT: uncurry and uncurryType fully expand type aliases in their input and output -// note: don't normalize higher-kined types -- @M TODO: maybe split those uses of normalize? -// OTOH, should be a problem as calls to normalize only occur on types with kind * in principle (in well-typed programs) +// uncurry and uncurryType expand type aliases private def expandAlias(tp: Type): Type = if (!tp.isHigherKinded) tp.normalize else tp private def isUnboundedGeneric(tp: Type) = tp match { @@ -68,9 +66,9 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { tp0 case mt: ImplicitMethodType => apply(MethodType(mt.params, mt.resultType)) - case PolyType(List(), restpe) => + case PolyType(List(), restpe) => // nullary method type apply(MethodType(List(), restpe)) - case PolyType(tparams, restpe) => + case PolyType(tparams, restpe) => // polymorphic nullary method type, since it didn't occur in a higher-kinded position PolyType(tparams, apply(MethodType(List(), restpe))) case TypeRef(pre, ByNameParamClass, List(arg)) => apply(functionType(List(), arg)) @@ -83,6 +81,29 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { expandAlias(mapOver(tp)) } } + +//@M TODO: better fix for the gross hack that conflates polymorphic nullary method types with type functions +// `[tpars] tref` (PolyType(tpars, tref)) could uncurry to either: +// - `[tpars]() tref` (PolyType(tpars, MethodType(List(), tref)) +// a nullary method types uncurry to a method with an empty argument list +// - `[tpars] tref` (PolyType(tpars, tref)) +// a proper type function -- see mapOverArgs: can only occur in args of TypeRef (right?)) +// the issue comes up when a partial type application gets normalised to a polytype, like `[A] Function1[X, A]` +// should not apply the uncurry transform to such a type +// see #2594 for an example + + // decide whether PolyType represents a nullary method type (only if type has kind *) + // for higher-kinded types, leave PolyType intact + override def mapOverArgs(args: List[Type], tparams: List[Symbol]): List[Type] = + map2Conserve(args, tparams) { (arg, tparam) => + arg match { + // is this a higher-kinded position? (TODO: confirm this is the only case) + case PolyType(tparams, restpe) if tparam.typeParams.nonEmpty => // higher-kinded type param + PolyType(tparams, apply(restpe)) // could not be a nullary method type + case _ => + this(arg) + } + } } private val uncurryType = new TypeMap { diff --git a/test/files/run/t2594_tcpoly.check b/test/files/run/t2594_tcpoly.check new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/files/run/t2594_tcpoly.check diff --git a/test/files/run/t2594_tcpoly.scala b/test/files/run/t2594_tcpoly.scala new file mode 100644 index 0000000000..e759ca8b0f --- /dev/null +++ b/test/files/run/t2594_tcpoly.scala @@ -0,0 +1,18 @@ +trait Monad[M[_]] { + def foo[A](a: M[A]): M[A] +} + +class Bar[A, B] +class Bar1[A] { type And[B] = Bar[A, B] } + +object Test { + // the combination of partial applications and anonymous class is essential to reproduce the bug + // problem: missing bridge method + // --> abstractmethoderror `Main$$anon$1.foo(Ljava/lang/Object;)Ljava/lang/Object;` + // the anonymous class only gets `public Bar foo(Bar a)` + def BarMonad[X] = new Monad[Bar1[X]#And] { + def foo[A](a: Bar[X, A]) = a + } + + def main(as: Array[String]) { BarMonad[Int] foo (new Bar[Int, Int]) } +}
\ No newline at end of file |