Skip to content

Commit

Permalink
Merge pull request #9226 from lrytz/t12002b
Browse files Browse the repository at this point in the history
Keep `private[this] var` class parameter fields that are only read
  • Loading branch information
lrytz committed Sep 28, 2020
2 parents 4674f45 + 9a11180 commit 8c86b7d
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 27 deletions.
20 changes: 1 addition & 19 deletions src/compiler/scala/tools/nsc/transform/Constructors.scala
Expand Up @@ -172,7 +172,7 @@ abstract class Constructors extends Statics with Transform with TypingTransforme
// class Outer { def test = {class LocalParent; class LocalChild extends LocalParent } }
//
// See run/t9408.scala for related test cases.
def omittableParamAcc(sym: Symbol) = sym.isParamAccessor && sym.isPrivateLocal
def omittableParamAcc(sym: Symbol) = sym.isParamAccessor && sym.isPrivateLocal && !sym.isVariable
def omittableOuterAcc(sym: Symbol) = isEffectivelyFinal && sym.isOuterAccessor && !sym.isOverridingSymbol
val omittables = mutable.Set.empty[Symbol] ++ (decls filter (sym => omittableParamAcc(sym) || omittableOuterAcc(sym))) // the closure only captures isEffectivelyFinal

Expand All @@ -192,28 +192,10 @@ abstract class Constructors extends Statics with Transform with TypingTransforme
}
}
}
class DetectAssigns(targets: mutable.Set[Symbol]) extends InternalTraverser {
override def traverse(tree: Tree): Unit = if (targets.nonEmpty) {
tree match {
case Assign(lhs, _) if targets(lhs.symbol) =>
targets -= lhs.symbol
omittables -= lhs.symbol
tree.traverse(this)
case _ => tree.traverse(this)
}
}
}

if (omittables.nonEmpty)
(defs.iterator ++ auxConstructors.iterator) foreach detectUsages.traverse

if (omittables.nonEmpty) {
val omittedVars = omittables.filter(_.isVariable)
if (omittedVars.nonEmpty) {
val detector = new DetectAssigns(omittedVars)
constructor.foreach(detector.traverse)
}
}
omittables.toSet
}
} // OmittablesHelper
Expand Down
9 changes: 9 additions & 0 deletions test/files/run/t12002.check
@@ -1 +1,10 @@
good boy!
List()
List()
List(private int C.x)
List(private int D.x)
List(private int E.x)
List(private int F.x)
List(private int G.x)
List(private final int H.x)
List(private int I.x)
23 changes: 15 additions & 8 deletions test/files/run/t12002.scala
@@ -1,17 +1,24 @@
// cf t6880
class C(private[this] var c: String) {
class C0(private[this] var c: String) {
private[this] var x: String = _
c = "good"
x = c + " boy!"
override def toString = x
}

class A(x: Int) { assert(x == 1) } // elided
class B(private[this] val x: Int) { assert(x == 1) } // elided
class C(private[this] var x: Int) { } // kept
class D(private[this] var x: Int) { assert(x == 1) } // kept
class E(private[this] var x: Int) { x = 2 } // kept
class F(private[this] var x: Int) { x = 2; assert(x == 2) } // kept
class G(private[this] var x: Int) { x = 2; assert(x == 2); def m() = assert(x == 2, "m" + x); m() } // kept
class H(private val x: Int) { } // kept
class I(private var x: Int) { } // kept

object Test {
def main(args: Array[String]) = println {
new C("bad")
def fs(o: AnyRef) = println(o.getClass.getDeclaredFields.toList)
def main(args: Array[String]): Unit = {
println(new C0("bad"))
List(new A(1), new B(1), new C(1), new D(1), new E(1), new F(1), new G(1), new H(1), new I(1)).foreach(fs)
}
}

// was
// java.lang.NoSuchFieldError: c
// at C.<init>(t12002.scala:6)

0 comments on commit 8c86b7d

Please sign in to comment.