summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2013-01-25 09:11:04 -0800
committerPaul Phillips <paulp@improving.org>2013-01-25 09:11:04 -0800
commit3753efc060af39d9247273cdc8da74ce57f627c5 (patch)
treed45a68bb01cc8eb1ba8142d76fde9f6361dc6fb4
parent0e6015d46df35a57c5acaf4fea2b0555ddd9b18e (diff)
parentf6168b8a4d661985b0fb4d6d3cbba256bfc69607 (diff)
downloadscala-3753efc060af39d9247273cdc8da74ce57f627c5.tar.gz
scala-3753efc060af39d9247273cdc8da74ce57f627c5.tar.bz2
scala-3753efc060af39d9247273cdc8da74ce57f627c5.zip
Merge pull request #1946 from retronym/ticket/6231
SI-6231 Report unsupported free var capture by a trait.
-rw-r--r--src/compiler/scala/tools/nsc/transform/LambdaLift.scala3
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala19
-rw-r--r--test/files/neg/t6231.check6
-rw-r--r--test/files/neg/t6231.scala15
4 files changed, 40 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
index a4f75f424f..952ca96f54 100644
--- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
+++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
@@ -364,6 +364,7 @@ abstract class LambdaLift extends InfoTransform {
copyDefDef(tree)(vparamss = List(vparams ++ freeParams))
case ClassDef(_, _, _, _) =>
+ // SI-6231
// Disabled attempt to to add getters to freeParams
// this does not work yet. Problem is that local symbols need local names
// and references to local symbols need to be transformed into
@@ -381,7 +382,7 @@ abstract class LambdaLift extends InfoTransform {
tree
}
-/* Something like this will be necessary to eliminate the implementation
+/* SI-6231: Something like this will be necessary to eliminate the implementation
* restiction from paramGetter above:
* We need to pass getters to the interface of an implementation class.
private def fixTraitGetters(lifted: List[Tree]): List[Tree] =
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index 57bdaea17a..3cd943aa74 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -1215,9 +1215,24 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
// refer to fields in some implementation class via an abstract
// getter in the interface.
val iface = toInterface(sym.owner.tpe).typeSymbol
- val getter = sym getter iface orElse abort("No getter for " + sym + " in " + iface)
+ val ifaceGetter = sym getter iface
+
+ def si6231Restriction() {
+ // See SI-6231 comments in LamdaLift for ideas on how to lift the restriction.
+ val msg = sm"""Implementation restriction: local ${iface.fullLocationString} is unable to automatically capture the
+ |free variable ${sym} on behalf of ${currentClass}. You can manually assign it to a val inside the trait,
+ |and refer that that val in ${currentClass}. For more details, see SI-6231."""
+ reporter.error(tree.pos, msg)
+ }
- typedPos(tree.pos)((qual DOT getter)())
+ if (ifaceGetter == NoSymbol) {
+ if (sym.isParamAccessor) {
+ si6231Restriction()
+ EmptyTree
+ }
+ else abort("No getter for " + sym + " in " + iface)
+ }
+ else typedPos(tree.pos)((qual DOT ifaceGetter)())
case Assign(Apply(lhs @ Select(qual, _), List()), rhs) =>
// assign to fields in some implementation class via an abstract
diff --git a/test/files/neg/t6231.check b/test/files/neg/t6231.check
new file mode 100644
index 0000000000..b27961d393
--- /dev/null
+++ b/test/files/neg/t6231.check
@@ -0,0 +1,6 @@
+t6231.scala:4: error: Implementation restriction: local trait Bug$X$1 is unable to automatically capture the
+free variable value ev$1 on behalf of anonymous class anonfun$qux$1. You can manually assign it to a val inside the trait,
+and refer that that val in anonymous class anonfun$qux$1. For more details, see SI-6231.
+ def qux = { () => ev }
+ ^
+one error found
diff --git a/test/files/neg/t6231.scala b/test/files/neg/t6231.scala
new file mode 100644
index 0000000000..1e5b4e0e1a
--- /dev/null
+++ b/test/files/neg/t6231.scala
@@ -0,0 +1,15 @@
+object Bug {
+ def bar(ev: Any) = {
+ trait X {
+ def qux = { () => ev }
+ }
+ new X {}.qux()
+
+ // workaround
+ trait Y {
+ val ev2 = ev // manually capture `ev` so that `ev2` is added to the trait interface.
+ def qux = { () => ev2 }
+ }
+ }
+}
+