Skip to content

Commit 42041c0

Browse files
alvinjb-studios
authored andcommitted
A brief ‘TASTy for End Users’ page, per Anatolii’s request
1 parent 95465ee commit 42041c0

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
If you create a Scala 3 source code file named _Hello.scala_:
2+
3+
```scala
4+
@main def hello = println("Hello, world")
5+
```
6+
7+
and then compile that file with `scalac`:
8+
9+
```bash
10+
$ scalac Hello.scala
11+
```
12+
13+
you’ll notice that amongst other resulting files, `scalac` creates files with the _.tasty_ extension:
14+
15+
```bash
16+
$ ls -1
17+
Hello$package$.class
18+
Hello$package.class
19+
Hello$package.tasty
20+
Hello.scala
21+
hello.class
22+
hello.tasty
23+
```
24+
25+
This leads to the natural question, “What is tasty?”
26+
27+
28+
29+
## What is TASTy?
30+
31+
TASTy is an acronym that comes from the term, _Typed Abstract Syntax Trees_.
32+
It’s a high-level interchange format for Scala 3, and in this document we’ll refer to it as _Tasty_.
33+
34+
A first important thing to know is that Tasty files are generated by the `scalac` compiler, and contain _all_ of the information about your source code, including the syntactic structure of your program, and _complete_ information about types, positions, and even documentation. Tasty files contain much more information than _.class_ files, which are generated to run on the JVM. (More on this shortly.)
35+
36+
In Scala 3, the compilation process looks like this:
37+
38+
```
39+
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
40+
$ scalac │ Pizza.scala │ ──> │ Pizza.tasty │ ──> │ Pizza.class │
41+
└─────────────┘ └─────────────┘ └─────────────┘
42+
▲ ▲ ▲
43+
│ │ │
44+
45+
Your source TASTy file Class file
46+
code for scalac for the JVM
47+
(contains (incomplete
48+
complete information)
49+
information)
50+
```
51+
52+
### The issue with _.class_ files
53+
54+
Because of issues such as type erasure, _.class_ files are actually an incomplete representation of your code. A simple way to demonstrate this is with a `List` example.
55+
56+
_Type erasure_ means that when you write Scala code like this that’s supposed to run on the JVM:
57+
58+
```scala
59+
val xs: List[Int] = List(1, 2, 3)
60+
```
61+
62+
that code is compiled to a _.class_ file that needs to be compatible with the JVM. As a result of that compatibility requirement, the code inside that class file --- which you can see with a `javap` command --- ends up looking like this:
63+
64+
```java
65+
public scala.collection.immutable.List<java.lang.Object> xs();
66+
```
67+
68+
That `javap` command output shows a Java representation of what’s contained in the class file. Notice in this output that `xs` _is not_ defined as a `List[Int]` any more; it’s essentially represented as a `List[java.lang.Object]`. For your Scala code to work with the JVM, the `Int` type has been erased.
69+
70+
Later, when you access an element of your `List[Int]` in your Scala code, like this:
71+
72+
```scala
73+
val x = xs(0)
74+
```
75+
76+
the resulting class file will have a casting operation for this line of code, which you can think of being like this:
77+
78+
```
79+
int x = (Int) xs.get(0) // Java-ish
80+
val x = xs.get(0).asInstanceOf[Int] // more Scala-like
81+
```
82+
83+
Again, this is done for compatibility, so your Scala code can run on the JVM.
84+
85+
And this discussion only covers the topic of type erasure. There are similar issues for every other Scala construct that the JVM isn’t aware of, including constructs like unions, intersections, traits with parameters, and many more Scala 3 features.
86+
87+
88+
### Key points
89+
90+
So that’s the first takeaway from this section: The types you specify in your Scala code aren’t represented completely accurately in _.class_ files.
91+
92+
A second key point is to understand that there are differences between the information that’s available at _compile time_ and _run time_:
93+
94+
- At **compile time**, as `scalac` reads and analyzes your code, it knows that `xs` is a `List[Int]`
95+
- When the compiler writes your code to a class file, it writes that `xs` is a `List[Object]`, and it adds casting information everywhere else `xs` is accessed
96+
- Then at **run time** --- with your code running inside the JVM --- the JVM doesn’t know that your list is a `List[Int]`
97+
98+
With Scala 3 and Tasty, here’s another important note about compile time:
99+
100+
- When you write Scala 3 code that uses other Scala 3 libraries, `scalac` doesn’t have to read their _.class_ files any more; it can read their _.tasty_ files, which, as mentioned, are an _exact_ representation of your code. This helps in many ways.
101+
102+
{% comment %}
103+
NOTE: In regards to the previous paragraphs, I’ve read that there’s also metadata in the class files, but I don’t know those details.
104+
{% endcomment %}
105+
106+
107+
108+
## Tasty benefits
109+
110+
As you can imagine, having a complete representation of your code in a platform-neutral form has many benefits:
111+
112+
{% comment %}
113+
TODO: These lines mostly come from https://www.scala-lang.org/blog/2018/04/30/in-a-nutshell.html, and I don’t know exactly what the first bullet point means:
114+
{% endcomment %}
115+
116+
- The compiler uses it to support separate compilation.
117+
- The Scala _Language Server Protocol_-based language server uses it to support hyperlinking, command completion, documentation, and also for global operations such as find-references and renaming.
118+
- Tasty makes an excellent foundation for a new generation of reflection-based macros.
119+
- A build tool can use it to cross-build on different platforms and migrate code from one binary version to another.
120+
- Optimizers and analyzers can use it for deep code analysis and advanced code generation.
121+
122+
There’s one more big benefit:
123+
124+
- Because the Scala 2.13.4 compiler can read Tasty files, and the Scala 3 compiler can read Scala 2.13 class files, you can intermix Scala 3 and Scala 2.13 code in the same project.
125+
126+
127+
128+
## More information
129+
130+
In summary, Tasty is a high-level interchange format for Scala 3, and _.tasty_ files contain a complete representation of your source code, leading to the benefits outlined in the previous section.
131+
132+
For more details, see these resources:
133+
134+
- In this [this video](https://www.youtube.com/watch?v=YQmVrUdx8TU), Jamie Thompson of the Scala Center provides a thorough discussion of how Tasty works, and its benefits
135+
- [Binary Compatibility for library authors][binary] discusses binary compatibility, source compatibility, and the JVM execution model
136+
- [Forward Compatibility for the Scala 3 Transition](https://www.scala-lang.org/blog/2020/11/19/scala-3-forward-compat.html) demonstrates techniques for using Scala 2.13 and Scala 3 in the same project
137+
138+
These articles provide more information about Scala 3 macros:
139+
140+
- [Scala Macro Libraries](https://scalacenter.github.io/scala-3-migration-guide/docs/macros/macro-libraries.html)
141+
- [Macros: The Plan for Scala 3](https://www.scala-lang.org/blog/2018/04/30/in-a-nutshell.html)
142+
- [The reference documentation on TASTy Reflect][tasty-reflect]
143+
- [The reference documentation on macros](macros)
144+
145+
146+
147+
[binary]: {% link _overviews/core/binary-compatibility-for-library-authors.md %}
148+
[tasty-reflect]: {{ site.scala3ref }}/metaprogramming/tasty-reflect.html
149+
[macros]: {{ site.scala3ref }}/metaprogramming/macros.html
150+

0 commit comments

Comments
 (0)