summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-06-11 10:56:48 -0400
committerJason Zaugg <jzaugg@gmail.com>2013-06-19 22:48:38 +0200
commite7ac254349e56678824ade3027bca3908882e291 (patch)
tree9b7828b21d418f2ee8830cb07432048c72dea13d
parenta54d86b5508630a4815ca7f6ca3d5f05b74b1d9f (diff)
downloadscala-e7ac254349e56678824ade3027bca3908882e291.tar.gz
scala-e7ac254349e56678824ade3027bca3908882e291.tar.bz2
scala-e7ac254349e56678824ade3027bca3908882e291.zip
SI-7571 Allow nesting of anonymous classes in value classes
5d9cde105e added deep prohibition of nested classes within a value class. This has the undesirable side effect of prohibiting partial functions literals in method bodies of a value class. The intention of that prohibition was to avoid problems in code using Type Tests, such as: class C(val inner: A) extends AnyVal { class D } def foo(a: Any, other: C) = a match { case _ : other.D } Here, the pattern usually checks that `a.$outer == other`. But that is incongruent with the way that `other` is erased to `A`. However, not all nested classes could lead us into this trap. This commit slightly relaxes the restriction to allow anonymous classes, which can't appear in a type test. The test shows that the translation generates working code.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala4
-rw-r--r--test/files/neg/valueclasses-impl-restrictions.check8
-rw-r--r--test/files/neg/valueclasses-impl-restrictions.scala4
-rw-r--r--test/files/run/t7571.scala12
4 files changed, 19 insertions, 9 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 29cd3d4bfa..ed2963fb0f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1455,8 +1455,8 @@ trait Typers extends Modes with Adaptations with Tags {
implRestriction(tree, "nested object")
//see https://issues.scala-lang.org/browse/SI-6444
//see https://issues.scala-lang.org/browse/SI-6463
- case _: ClassDef =>
- implRestriction(tree, "nested class")
+ case cd: ClassDef if !cd.symbol.isAnonymousClass => // Don't warn about partial functions, etc. SI-7571
+ implRestriction(tree, "nested class") // avoiding Type Tests that might check the $outer pointer.
case Select(sup @ Super(qual, mix), selector) if selector != nme.CONSTRUCTOR && qual.symbol == clazz && mix != tpnme.EMPTY =>
//see https://issues.scala-lang.org/browse/SI-6483
implRestriction(sup, "qualified super reference")
diff --git a/test/files/neg/valueclasses-impl-restrictions.check b/test/files/neg/valueclasses-impl-restrictions.check
index 63924493aa..0af9173f74 100644
--- a/test/files/neg/valueclasses-impl-restrictions.check
+++ b/test/files/neg/valueclasses-impl-restrictions.check
@@ -6,12 +6,8 @@ valueclasses-impl-restrictions.scala:9: error: implementation restriction: neste
This restriction is planned to be removed in subsequent releases.
trait I2 {
^
-valueclasses-impl-restrictions.scala:15: error: implementation restriction: nested class is not allowed in value class
-This restriction is planned to be removed in subsequent releases.
- val i2 = new I2 { val q = x.s }
- ^
-valueclasses-impl-restrictions.scala:21: error: implementation restriction: nested class is not allowed in value class
+valueclasses-impl-restrictions.scala:23: error: implementation restriction: nested class is not allowed in value class
This restriction is planned to be removed in subsequent releases.
private[this] class I2(val q: String)
^
-four errors found
+three errors found
diff --git a/test/files/neg/valueclasses-impl-restrictions.scala b/test/files/neg/valueclasses-impl-restrictions.scala
index 137f3f854c..f0577a94aa 100644
--- a/test/files/neg/valueclasses-impl-restrictions.scala
+++ b/test/files/neg/valueclasses-impl-restrictions.scala
@@ -12,8 +12,10 @@ class X1(val s: String) extends AnyVal {
}
def y(x: X1) = {
- val i2 = new I2 { val q = x.s }
+ val i2 = new I2 { val q = x.s } // allowed as of SI-7571
i2.z
+
+ { case x => x } : PartialFunction[Int, Int] // allowed
}
}
diff --git a/test/files/run/t7571.scala b/test/files/run/t7571.scala
new file mode 100644
index 0000000000..00b9695168
--- /dev/null
+++ b/test/files/run/t7571.scala
@@ -0,0 +1,12 @@
+class Foo(val a: Int) extends AnyVal {
+ def foo = { {case x => x + a}: PartialFunction[Int, Int]}
+
+ def bar = (new {}).toString
+}
+
+object Test extends App {
+ val x = new Foo(1).foo.apply(2)
+ assert(x == 3, x)
+ val s = new Foo(1).bar
+ assert(s.nonEmpty, s)
+}