diff options
author | Guillaume Martres <smarter@ubuntu.com> | 2017-03-15 18:21:02 +0100 |
---|---|---|
committer | Guillaume Martres <smarter@ubuntu.com> | 2017-03-16 01:00:34 +0100 |
commit | 90c1a5f97db02d4af1a6e05f79285c5229f74702 (patch) | |
tree | 9f0653ae570572788cca2ddc1ee096465bc9938b /tests/run | |
parent | c321653cee9f4596b046efdbb8c1913509fec5ef (diff) | |
download | dotty-90c1a5f97db02d4af1a6e05f79285c5229f74702.tar.gz dotty-90c1a5f97db02d4af1a6e05f79285c5229f74702.tar.bz2 dotty-90c1a5f97db02d4af1a6e05f79285c5229f74702.zip |
Fix #2099: avoid loading a private member when recomputing a NamedType denot
ParamForwarding creates the following forwarder in B:
private[this] def member: Int = super.member
Where the type for `super.member` is `TermRef(SubA, member)` and the
symbol is the `val member` in `A`.
So far this is correct, but in later phases we might call `loadDenot` on
this `TermRef` which will end up calling `asMemberOf`, which before this
commit just did:
prefix.member(name)
This is incorrect in our case because `SubA` also happens to have a
private `def member`, which means that our forwarder in B now forwards
to a private method in a superclass, this subsequently crashes in
`ExpandPrivate`.
(Note: in the bytecode, a private method cannot have the same name as an
overriden method, but this is already worked around in EnsurePrivate.)
The fix is simple: when we recompute a member, we should only look at
private members if the previous denotation was private.
Diffstat (limited to 'tests/run')
-rw-r--r-- | tests/run/paramForwarding_separate.check | 6 | ||||
-rw-r--r-- | tests/run/paramForwarding_separate/A_1.scala | 3 | ||||
-rw-r--r-- | tests/run/paramForwarding_separate/B_2.scala | 19 |
3 files changed, 28 insertions, 0 deletions
diff --git a/tests/run/paramForwarding_separate.check b/tests/run/paramForwarding_separate.check new file mode 100644 index 000000000..8df0c3100 --- /dev/null +++ b/tests/run/paramForwarding_separate.check @@ -0,0 +1,6 @@ +# Fields in A: +private final int A.member$$local +# Fields in SubA: + +# Fields in B: + diff --git a/tests/run/paramForwarding_separate/A_1.scala b/tests/run/paramForwarding_separate/A_1.scala new file mode 100644 index 000000000..7e01f3ef1 --- /dev/null +++ b/tests/run/paramForwarding_separate/A_1.scala @@ -0,0 +1,3 @@ +class A(val member: Int) + +class SubA(member: Int) extends A(member) diff --git a/tests/run/paramForwarding_separate/B_2.scala b/tests/run/paramForwarding_separate/B_2.scala new file mode 100644 index 000000000..774967101 --- /dev/null +++ b/tests/run/paramForwarding_separate/B_2.scala @@ -0,0 +1,19 @@ +class B(member: Int) extends SubA(member) + +object Test { + def printFields(cls: Class[_]) = + println(cls.getDeclaredFields.map(_.toString).sorted.deep.mkString("\n")) + + def main(args: Array[String]): Unit = { + val a = new A(10) + val subA = new SubA(11) + val b = new B(12) + + println("# Fields in A:") + printFields(classOf[A]) + println("# Fields in SubA:") + printFields(classOf[SubA]) + println("# Fields in B:") + printFields(classOf[B]) + } +} |