summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2015-10-27 14:37:44 +1000
committerJason Zaugg <jzaugg@gmail.com>2015-10-27 16:08:15 +1000
commit639e52ae7e128025f6eb57957a590b808d83a9a4 (patch)
tree19958923ec2beea7b770ccf2197fef6930e830f1
parentb194a4e7230334e441cd31b617fdce8e329dfa3a (diff)
downloadscala-639e52ae7e128025f6eb57957a590b808d83a9a4.tar.gz
scala-639e52ae7e128025f6eb57957a590b808d83a9a4.tar.bz2
scala-639e52ae7e128025f6eb57957a590b808d83a9a4.zip
SI-9178 Don't eta expand param-less method types to SAMs
Otherwise, we can end up with a subtle source incompatibility with the pre-SAM regime. Arguably we should phase out eta expansion to Function0 as well, but I'll leave that for another day.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala9
-rw-r--r--test/files/pos/t9178b.flags1
-rw-r--r--test/files/pos/t9178b.scala7
-rw-r--r--test/files/run/t9178a.flags1
-rw-r--r--test/files/run/t9178a.scala15
-rw-r--r--test/files/run/t9489.flags1
-rw-r--r--test/files/run/t9489/A.java3
-rw-r--r--test/files/run/t9489/B.java3
-rw-r--r--test/files/run/t9489/test.scala10
9 files changed, 49 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 45ebbd532d..d06a4a5d80 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -862,7 +862,14 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case Block(_, tree1) => tree1.symbol
case _ => tree.symbol
}
- if (!meth.isConstructor && (isFunctionType(pt) || samOf(pt).exists)) { // (4.2)
+ def shouldEtaExpandToSam: Boolean = {
+ // SI-9536 don't adapt parameterless method types to a to SAM's, fall through to empty application
+ // instead for backwards compatiblity with 2.11. See comments of that ticket and SI-7187
+ // for analogous trouble with non-SAM eta expansion. Suggestions there are: a) deprecate eta expansion to Function0,
+ // or b) switch the order of eta-expansion and empty application in this adaptation.
+ !mt.params.isEmpty && samOf(pt).exists
+ }
+ if (!meth.isConstructor && (isFunctionType(pt) || shouldEtaExpandToSam)) { // (4.2)
debuglog(s"eta-expanding $tree: ${tree.tpe} to $pt")
checkParamsConvertible(tree, tree.tpe)
val tree0 = etaExpand(context.unit, tree, this)
diff --git a/test/files/pos/t9178b.flags b/test/files/pos/t9178b.flags
new file mode 100644
index 0000000000..48fd867160
--- /dev/null
+++ b/test/files/pos/t9178b.flags
@@ -0,0 +1 @@
+-Xexperimental
diff --git a/test/files/pos/t9178b.scala b/test/files/pos/t9178b.scala
new file mode 100644
index 0000000000..cbeaed4f17
--- /dev/null
+++ b/test/files/pos/t9178b.scala
@@ -0,0 +1,7 @@
+abstract class Test{
+ val writeInput: java.io.OutputStream => Unit
+ def getOutputStream(): java.io.OutputStream
+
+ writeInput(getOutputStream)
+}
+
diff --git a/test/files/run/t9178a.flags b/test/files/run/t9178a.flags
new file mode 100644
index 0000000000..48fd867160
--- /dev/null
+++ b/test/files/run/t9178a.flags
@@ -0,0 +1 @@
+-Xexperimental
diff --git a/test/files/run/t9178a.scala b/test/files/run/t9178a.scala
new file mode 100644
index 0000000000..4788841f8d
--- /dev/null
+++ b/test/files/run/t9178a.scala
@@ -0,0 +1,15 @@
+trait Sam { def apply(): Unit }
+abstract class Test {
+ def foo(): Sam
+ // no parens, instantiateToMethodType would wrap in a `new Sam { def apply = foo }`
+ // rather than applying to an empty param list() */
+ val f: Sam = foo
+}
+
+object Test extends Test {
+ lazy val samIAm = new Sam { def apply() {} }
+ def foo() = samIAm
+ def main(args: Array[String]): Unit = {
+ assert(f eq samIAm, f)
+ }
+}
diff --git a/test/files/run/t9489.flags b/test/files/run/t9489.flags
new file mode 100644
index 0000000000..48fd867160
--- /dev/null
+++ b/test/files/run/t9489.flags
@@ -0,0 +1 @@
+-Xexperimental
diff --git a/test/files/run/t9489/A.java b/test/files/run/t9489/A.java
new file mode 100644
index 0000000000..c3536faa14
--- /dev/null
+++ b/test/files/run/t9489/A.java
@@ -0,0 +1,3 @@
+public class A {
+ public B b() { return null; }
+}
diff --git a/test/files/run/t9489/B.java b/test/files/run/t9489/B.java
new file mode 100644
index 0000000000..e5d1278cd7
--- /dev/null
+++ b/test/files/run/t9489/B.java
@@ -0,0 +1,3 @@
+public abstract class B {
+ public abstract int m();
+}
diff --git a/test/files/run/t9489/test.scala b/test/files/run/t9489/test.scala
new file mode 100644
index 0000000000..1b745af865
--- /dev/null
+++ b/test/files/run/t9489/test.scala
@@ -0,0 +1,10 @@
+class T {
+ def f(a: A) = g(a.b) // was: "found Int, required B"
+ def g(b: => B) = null
+}
+
+object Test extends T {
+ def main(args: Array[String]): Unit = {
+ f(new A)
+ }
+}