From ca9c8efac5694d6dbfe1d0393c2e7485a01c3ef5 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 26 Mar 2013 10:45:17 +0100 Subject: SI-6793 Don't use super param accessors if inaccessible. "Alias replacement" has been with us since 2005 (13c59adf9). Given: package a { class C1(val v0: String) class C2(v1: String) extends a.C1(v1) { v1 } } The reference to `v1` is rewritten as `C2.super.v0()`, and no field is generated in `C2`. (Oddly, this optimization doesn't seem to kick in if these classes are in the empty package. That's probably a distinct bug.) However, this rewriting is done without consideration of the accessibility of `v0` from `C2`. This commit disables this optimization if there if `v0` is not accessible. --- src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala | 11 +++++++++-- test/files/run/t6793.scala | 9 +++++++++ test/files/run/t6793b.scala | 11 +++++++++++ test/files/run/t6793c.scala | 11 +++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 test/files/run/t6793.scala create mode 100644 test/files/run/t6793b.scala create mode 100644 test/files/run/t6793c.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index 67639eb530..fa72ad64bf 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -267,9 +267,16 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT } } - // direct calls to aliases of param accessors to the superclass in order to avoid + + def isAccessibleFromSuper(sym: Symbol) = { + val pre = SuperType(sym.owner.tpe, qual.tpe) + localTyper.context.isAccessible(sym, pre, superAccess = true) + } + + // Direct calls to aliases of param accessors to the superclass in order to avoid // duplicating fields. - if (sym.isParamAccessor && sym.alias != NoSymbol) { + // ... but, only if accessible (SI-6793) + if (sym.isParamAccessor && sym.alias != NoSymbol && isAccessibleFromSuper(sym.alias)) { val result = (localTyper.typedPos(tree.pos) { Select(Super(qual, tpnme.EMPTY) setPos qual.pos, sym.alias) }).asInstanceOf[Select] diff --git a/test/files/run/t6793.scala b/test/files/run/t6793.scala new file mode 100644 index 0000000000..0b1f1619af --- /dev/null +++ b/test/files/run/t6793.scala @@ -0,0 +1,9 @@ +package a { class C1(private[a] val v0: String) } +package b { class C2(v1: String) extends a.C1(v1) { def foo = v1 } } + +object Test extends App { + new b.C2("x") + + val c2Fields = classOf[b.C2].getDeclaredFields + assert(c2Fields.size == 1, c2Fields.map(_.getName).toList) +} diff --git a/test/files/run/t6793b.scala b/test/files/run/t6793b.scala new file mode 100644 index 0000000000..cb3f2fb2fa --- /dev/null +++ b/test/files/run/t6793b.scala @@ -0,0 +1,11 @@ +package a { + class C1(val v0: String) + class C2(v1: String) extends a.C1(v1) { def foo = v1 } +} + +object Test extends App { + new a.C2("x") + + val c2Fields = classOf[a.C2].getDeclaredFields + assert(c2Fields.isEmpty, c2Fields.map(_.getName).mkString(", ")) +} diff --git a/test/files/run/t6793c.scala b/test/files/run/t6793c.scala new file mode 100644 index 0000000000..e28c7c81a1 --- /dev/null +++ b/test/files/run/t6793c.scala @@ -0,0 +1,11 @@ +package a { + class C1(private[a] val v0: String) + class C2(v1: String) extends a.C1(v1) { def foo = v1 } +} + +object Test extends App { + new a.C2("x").foo + + val c2Fields = classOf[a.C2].getDeclaredFields + assert(c2Fields.isEmpty, c2Fields.map(_.getName).toList) +} -- cgit v1.2.3