Skip to content

Commit

Permalink
SI-7571 Allow nesting of anonymous classes in value classes
Browse files Browse the repository at this point in the history
5d9cde1 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.
  • Loading branch information
retronym committed Jun 19, 2013
1 parent a54d86b commit e7ac254
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 9 deletions.
4 changes: 2 additions & 2 deletions src/compiler/scala/tools/nsc/typechecker/Typers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
8 changes: 2 additions & 6 deletions test/files/neg/valueclasses-impl-restrictions.check
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 3 additions & 1 deletion test/files/neg/valueclasses-impl-restrictions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

Expand Down
12 changes: 12 additions & 0 deletions test/files/run/t7571.scala
Original file line number Diff line number Diff line change
@@ -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)
}

0 comments on commit e7ac254

Please sign in to comment.