Skip to content

Alternative fix for #2099: avoid loading a private member when recomputing a NamedType denot #2106

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

Merged
merged 3 commits into from
Mar 16, 2017

Conversation

smarter
Copy link
Member

@smarter smarter commented Mar 15, 2017

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.

Copy link
Contributor

@odersky odersky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍 (except the tests don't agree with me 😢 )

@smarter smarter force-pushed the fix/param-forwarder-access-take-2 branch 2 times, most recently from 78642a8 to 582bcac Compare March 15, 2017 23:31
smarter added 2 commits March 16, 2017 01:00
…edType 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.
This was introduced in the previous commit and caused unpickling
failures, we are now more conservative and only check the Private flag
on SymDenotations so we don't have to load any other denotation.
@smarter smarter force-pushed the fix/param-forwarder-access-take-2 branch from 582bcac to 1821944 Compare March 16, 2017 00:00
// We shouldn't go from a non-private denotation to a private one
prefix.nonPrivateMember(name)
case _ =>
prefix.member(name)
Copy link
Contributor

@odersky odersky Mar 16, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought, I think we should revert to the previous scheme where allowPrivate was passed as a boolean to asMemberOf. There are 3 calls to asMemberOf. The ones in recomputeDenot and newLikeThis can get the parameter from the symbol. The third one, in loadDenot should unconditionally pass true for
allowPrivate. After all, it could be that a definition was public in run 1, but private in run 2. We need to be able to pick up the new definition in loadDenot.

@smarter
Copy link
Member Author

smarter commented Mar 16, 2017

Review addressed. However I'm wondering if it wouldn't make sense to take advantage of the existing shadowed mechanism. In ParamForwarder we manually look for an accessible denotation using isAccessibleFrom, but this is sort of what TypeAssigner#ensureAccessible already does.

@odersky odersky merged commit 2325863 into scala:master Mar 16, 2017
@allanrenucci allanrenucci deleted the fix/param-forwarder-access-take-2 branch December 14, 2017 19:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants