-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix #2099: Make param forwarders override the param they forward to #2102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Previously, in the following code: class A(val member: Int) class SubA(member: Int) extends A(member) We created a forwarder in SubA like this: private[this] def member: Int = super.member Since a private method cannot have the same name as an inherited non-private one, we subsequently name-mangled the forwarder in ExpandPrivate. However, this was only done in the TreeTransformer, not in the DenotTransformer, this lead to separate compilation issues (see added testcase). Since we cannot detect that a ParamAccessor is a forwarder in a DenotTransformer, we cannot fix the problem locally in ExpandPrivate. Instead, we change ParamForwarding so that the forwarder now looks like: override def member: Int = super.member To make this work we restrict ParamForwarding to only create forwarders for non-final fields.
Hah! I am smitten by my own diabolical tests. Here's a minimization: class A(val theValue: Int)
class NonVal(theValue: Int) extends A(theValue) {
def getTheValueInNonVal = theValue
}
class X(override val theValue: Int) extends NonVal(0)
object Test {
def main(args: Array[String]): Unit = {
val x14 = new X(14)
assert(x14.getTheValueInNonVal == 0)
}
} In both scalac and dotty before this PR, the assertion succeeds. But it now fails because calling |
Yes, I guess 0 is right. |
@odersky Then I don't think the proposed approach of making forwarders override the param they forward to can work. |
@smarter, I've proposed an approach to name-mangle forwarders while keeping them public. |
@DarkDimius This makes things more complicated because we look for an inherited accessor by name in ParamForwarding (see |
Making param forwarders override the param they forward like we did in the previous commit changes semantics. Instead, we do the same thing that ExpandPrivate previously did, but early in ParamForwarding, so separate compilation still works.
ec762e3
to
5f9d66b
Compare
@DarkDimius I give up, I've tried various things but I can't get .ensureNotPrivate to work correctly before pickling, too many things break. Could you give it a try? |
@smarter, I'll have a look. |
Closed in favor of #2106 |
Previously, in the following code:
We created a forwarder in SubA like this:
Since a private method cannot have the same name as an inherited
non-private one, we subsequently name-mangled the forwarder in
ExpandPrivate. However, this was only done in the TreeTransformer, not
in the DenotTransformer, this lead to separate compilation issues (see
added testcase).
Since we cannot detect that a ParamAccessor is a forwarder in a
DenotTransformer, we cannot fix the problem locally in ExpandPrivate.
Instead, we change ParamForwarding so that the forwarder now looks like:
To make this work we restrict ParamForwarding to only create forwarders
for non-final fields.