summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2009-11-12 21:04:26 +0000
committerAdriaan Moors <adriaan.moors@epfl.ch>2009-11-12 21:04:26 +0000
commitfe3b78b8644fe025e9ff742d79d9b69270993749 (patch)
treea1a4d2f1a63ac5b008792d053a1aacc828b58c27
parentd24de699d877477a1c321b81ff9740b753fda659 (diff)
downloadscala-fe3b78b8644fe025e9ff742d79d9b69270993749.tar.gz
scala-fe3b78b8644fe025e9ff742d79d9b69270993749.tar.bz2
scala-fe3b78b8644fe025e9ff742d79d9b69270993749.zip
Merge branch 'ticket/2594'
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala31
-rw-r--r--test/files/run/t2594_tcpoly.check0
-rw-r--r--test/files/run/t2594_tcpoly.scala18
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