Skip to content

SI-8944 A more resiliant naming scheme for case accessors#4125

Merged
gkossakowski merged 1 commit intoscala:2.12.xfrom
retronym:ticket/8944
Jan 14, 2015
Merged

SI-8944 A more resiliant naming scheme for case accessors#4125
gkossakowski merged 1 commit intoscala:2.12.xfrom
retronym:ticket/8944

Conversation

@retronym
Copy link
Member

Case class parameters that are less that public have an extra
accessor method created to ensure universal pattern matchability.
See #4081 for more background.

Currently, this is given a fresh name based on the parameter name.
However, this is fragile and the name can change based on unrelated
edits higher up in the source file.

This commit switches to a stable naming scheme for these methods.

A non-public case field foo has a corresponding accessor
foo$access$N, where N is the index of the parameter within
the constructor parameter list.

The enclosed tests show a case that used to trigger a linkage
error under separate compilation that now works; shows that by
choosing the foo$access$1 rather than foo$1 we don't clash with
lambda lifted methods in the class; and shows the names of the
accessor methods as seen via Java reflection.

Just submitting for a test run for now.

/cc @gkossakowski who is usually has some good insights when it
comes to accessor naming schemes. This is one of the cross
compilation unit use cases that we have to deal with that Java
doesn't.

Case class parameters that are less that public have an extra
accessor method created to ensure universal pattern matchability.
See scala#4081 for more background.

Currently, this is given a fresh name based on the parameter name.
However, this is fragile and the name can change based on unrelated
edits higher up in the source file.

This commit switches to a stable naming scheme for these methods.

A non-public case field `foo` has a corresponding accessor
`foo$access$N`, where `N` is the index of the parameter within
the constructor parameter list.

The enclosed tests show a case that used to trigger a linkage
error under separate compilation that now works; shows that by
choosing the `foo$access$1` rather than `foo$1` we don't clash with
lambda lifted methods in the class; and shows the names of the
accessor methods as seen via Java reflection.
@gkossakowski
Copy link
Contributor

@retronym, this looks fine to me. Would you like to merge?

Also, would you consider deprecating private parameters to constructors of case classes? I think they make little sense.

@retronym
Copy link
Member Author

Let's get another opinion from @lrytz on the new scheme. It should be noted that :: has one of these private parameters, so we might have a hard time deprecating unless we found another way to express that.

@lrytz
Copy link
Member

lrytz commented Dec 19, 2014

We could make :: a non-case class and write the synthetics by hand, but that would hamper exhaustivity analysis.

@lrytz
Copy link
Member

lrytz commented Dec 19, 2014

LGTM too

@Ichoran
Copy link
Contributor

Ichoran commented Dec 19, 2014

I'm not sure protected makes any more sense than private. And what about private[package]? I would just leave it alone. private[this] is impossible due to what case classes need to do (and is already forbidden); everything else is sane if weird in most circumstances.

I'm all for adding an abide check, though, for those who don't mean to be weird.

gkossakowski added a commit that referenced this pull request Jan 14, 2015
SI-8944 A more resiliant naming scheme for case accessors
@gkossakowski gkossakowski merged commit b810c92 into scala:2.12.x Jan 14, 2015
@gkossakowski
Copy link
Contributor

My heart sank when I learnt about this Scala feature but I give in to your reasons. :)

retronym added a commit to retronym/scala that referenced this pull request Mar 5, 2015
Case class parameters may be declared as non-public. If this is the
case, the case accessor method is still synthesized as public, but
it has a mangled name of the form `origName$N`.

See also SI-8944 / scala#4125.

The compiler maps from case fields to the corresponding accessors
with this naming convention in mind. However, it is too lenient, and
assumes that only one accessor will be of the form "origName\$.*".

If, however, a regular, public case parameter is named `a b`, it will
have a name `a$u0020b`, which spurously matches that overly permissive
pattern.

This commit changes tightens up the logic to expect "origName\$\d+".
@adriaanm adriaanm added the 2.12 label Oct 29, 2016
adriaanm pushed a commit to adriaanm/scala that referenced this pull request Jan 10, 2017
Case class parameters may be declared as non-public. If this is the
case, the case accessor method is still synthesized as public, but
it has a mangled name of the form `origName$N`.

See also SI-8944 / scala#4125.

The compiler maps from case fields to the corresponding accessors
with this naming convention in mind. However, it is too lenient, and
assumes that only one accessor will be of the form "origName\$.*".

If, however, a regular, public case parameter is named `a b`, it will
have a name `a$u0020b`, which spurously matches that overly permissive
pattern.

This commit changes tightens up the logic to expect "origName\$\d+".
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.

6 participants