Skip to content

Commit 19e0c55

Browse files
committed
wip
1 parent 315ddb4 commit 19e0c55

File tree

1 file changed

+33
-48
lines changed

1 file changed

+33
-48
lines changed

_posts/2023-00-00-signature-polymorphic-methods.md

Lines changed: 33 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ This blog post explains the feature and why it exists. We also delve
1313
into how it is specified and implemented in both Scala 2 and Scala 3.
1414

1515
The Scala 3 implementation is new, and that's the occasion for this
16-
blog post. Thanks to this recent work, Scala 3 users can now access
17-
the entire Java reflection API, as of Scala 3.3.0-RC1.
16+
blog post. Thanks to this recent work, **Scala 3 users can now access
17+
the entire Java reflection API**, as of Scala 3.3.0.
1818

1919
## Should I keep reading?
2020

@@ -40,13 +40,13 @@ or stored.
4040
## Is signature polymorphism supported in Scala?
4141

4242
Yes: since Scala 2.11.5, and more fully since Scala 2.12.16. Scala 3
43-
now has the support too, as of Scala 3.3.0-RC1.
43+
now has the support too, as of Scala 3.3.0.
4444

4545
The initial Scala 2 implementation was done by [Jason Zaugg] in 2014
4646
and refined later by [Lukas Rytz]. The latest version, with all fixes,
4747
landed in Scala 2.12.16 (released June 2022).
4848

49-
Just recently, [Dale Wijnand] ported the feature to Scala 3, with the
49+
Recently, [Dale Wijnand] ported the feature to Scala 3, with the
5050
assistance of [Guillaume Martres] and myself, [Seth Tisue].
5151

5252
Jason, Lukas, Dale, and myself are members of the Scala compiler team
@@ -145,43 +145,25 @@ Great question!
145145

146146
Doesn't it seem puzzling that Oracle would go to so much trouble to
147147
make Java reflection faster? If I care so much about performance,
148-
surely I should avoid using reflection at all?
148+
surely I should avoid using reflection entirely?
149149

150150
The real reason these methods need to be fast is to aid efficient
151-
implementation of lambdas, in both Java and Scala. Additionally, they aid
152-
efficient implementation of dynamic languages on the
153-
JVM. `MethodHandle` was added to the JVM at the same time as
154-
`invokeDynamic`, which serves those same two purposes.
155-
156-
> TODO: Is this actually accurate? I suspect it is, but I should
157-
> dig around and confirm it, and perhaps add links.)
158-
159-
> TODO: I should improve the bit about "efficient implementation
160-
> of lambdas". Adam Vandervorst wrote:
161-
> > I'm a bit confused by the "Are these methods good for anything else" section
162-
> > I deduce Java only uses it in "MethodHandle and VarHandle" and Scala just gained the barebones implementation.
163-
> I replied:
164-
> That's a good point. I will try to improve that section. In order to improve it properly, I need to dig a little deeper into how MethodHandle and VarHandle are used internally in the Java and Scala compilers.
165-
> Jason (et al) definitely used MethodHandle when adding lambda support to the compiler back end for Scala 2.12, but I need to dig and see whether we are specifically using the signature polymorphic methods.
166-
> I don't want to get too deep into it in the blog post itself, but I would like to expand it a bit and need to do a bit more research in order to make the expansion accurate.
167-
168-
> TODO: I might rethink how I'm presenting the issue of speed here. As I wrote to
169-
> Adam:
170-
> that's kind of what I was getting at with the " If I care so much about performance, surely I should avoid using reflection at all?"
171-
> if I understand correctly, if you aren't a language implementer, then boxing overhead in reflection is probably the least of your worries
172-
> but the methods are signature polymorphic regardless
173-
> so we need the compiler support in Scala in order for the methods to even be callable at all by users who don't care about speed
174-
> it's a bit tricky to convey this without making the post overlong
151+
implementation of dynamic languages on the JVM. `MethodHandle` was
152+
added to the JVM at the same time as `invokeDynamic`, as part of
153+
[JSR-292](), which aimed to support efficient implementation of JRuby
154+
and other alternative JVM languages. (`invokeDynamic` is additionally
155+
used for implementing lambdas; see [this writeup on Stack Overflow]().)
175156

176-
## How is this implemented in Scala 2?
177-
178-
> TODO -- keep it brief
157+
[JSR-292]: https://www.infoq.com/articles/invokedynamic/
158+
[this writeup on Stack Overflow]: https://stackoverflow.com/questions/30002380/why-are-java-8-lambdas-invoked-using-invokedynamic
179159

180-
illustrates the following compiler internals/techniques:
160+
## How is this implemented in Scala 2?
181161

182-
> TODO
162+
Jason Zaugg describes his initial JDK 7 implementation in [PR 4139]()
163+
and shows how the resulting bytecode looks.
183164

184-
For details, see [PR 4139](), [PR 5594](), [PR 9530](), and [PR 9930]().
165+
See also these well-documented followups: [PR 5594]() for JDK 9, [PR
166+
9530]() for JDK 11, and [PR 9930]() for JDK 17.
185167

186168
[PR 4139]: https://github.com/scala/scala/pull/4139
187169
[PR 5594]: https://github.com/scala/scala/pull/5594
@@ -192,16 +174,18 @@ For details, see [PR 4139](), [PR 5594](), [PR 9530](), and [PR 9930]().
192174

193175
We had to work harder in Scala 3 because it wasn't enough to have an
194176
an in-memory representation for signature polymorphic call sites. The
195-
call sites must also have a representation in TASTy. (Scala 2
196-
pickles only represent method signatures; in contrast, TASTy
197-
represents method bodies too.)
198-
199-
Our initial implementation plan was to add a new node type to TASTy,
200-
and that's what we ended up doing.
177+
call sites must also have a representation in TASTy, so we had to add
178+
a new TASTy node type. (Scala 2 pickles only represent method
179+
signatures; in contrast, TASTy represents method bodies too.)
201180

202-
> TODO: point out what's interesting
181+
To represent a signature polymorphic call site internally, we
182+
synthesize a method type based on the types at the call site. One can
183+
imagine the original signature-polymorphic method as being infinitely
184+
overloaded, with each individual overload only being brought into
185+
existence as needed.
203186

204-
For details, see [the pull request](https://github.com/lampepfl/dotty/pull/16225).
187+
For details, see [the pull
188+
request](https://github.com/lampepfl/dotty/pull/16225).
205189

206190
### The path not taken
207191

@@ -231,16 +215,17 @@ product of this transform, drop the cast, and emit the correct
231215
bytecode.
232216

233217
In the end, we didn't go with this approach. As Sébastien Doeraene
234-
pointed out, we avoided a new tag but we gave new semantics to
235-
existing tags that older compilers wouldn't understand. Therefore the
236-
work still couldn't ship until the next minor version of the compiler.
237-
Besides, avoiding the new tag complicated the implementation.
218+
pointed out, although this approach avoided adding a new TASTy tag, it
219+
also gave new semantics to existing tags that older compilers wouldn't
220+
understand. Therefore the work still couldn't ship until the next
221+
minor version of the compiler. Besides, avoiding the new tag
222+
complicated the implementation.
238223

239224
## Questions? Discussion?
240225

241226
These are welcome on the Scala Contributors forum thread at:
242227

243-
* (Discourse link, with link back to this post)
228+
* (TODO Discourse link, with link back to this post)
244229

245230
> TODO: include a link to the relevant section of the JLS
246231

0 commit comments

Comments
 (0)