Skip to content
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

Inline traits for specialization in Scala 3 #17329

Draft
wants to merge 106 commits into
base: main
Choose a base branch
from

Conversation

timotheeandres
Copy link
Contributor

@timotheeandres timotheeandres commented Apr 24, 2023

Master's project on the dotty compiler. The goal is to create a new construct, inline trait, that can specialize code in a more space-efficient way than the @specialized annotation in Scala 2.

See https://infoscience.epfl.ch/record/303591?ln=en for more information. Original idea and draft in #15532.

Inline defs without their bodies, from non-generic inline trait
Inline defs without their bodies, from generic inline trait
By marking the methods to inline inside an inline trait with the BodyAnnotation, we can leverage the current code that inlines bodies

To do so, we mark the methods, and let the overriding methods call their super counterpart. The inliner then handles the rest
Allows for private trait parameters and private inner classes
Blacklists inline trait tests from the pickling test, because spans are not working as expected right now... Might be a HUGE pain to deal with now.

Please roll me back before merging with main :(
Traits cannot have by-name parameters
The test for generic inner trait is currently disabled: generic inner traits do not work yet
For some reason, this is not needed anymore (don't know why at all...)
When "transforming" an inner class into an inner trait, we need to adapt its parents as well.

When declaring its parents, a trait cannot call their constructor, therefore the different Apply and other trees should be pruned from them.

For example:
```
inline trait A:
  class InnerA extends Object
```
will result in the following code after Inlining:
```
inline trait A:
  trait InnerA$trait extends Object
  type InnerA <: InnerA$trait
```
The tree for `Object` in the first case is
```
Apply(Select(New(Ident(Object)),<init>),List())
```
but if we make InnerA a trait instead, it is simply
```
Ident(Object)
```

The goal is therefore to strip the different "concrete" elements of the parents when transforming a class into a trait.
This way, we have a benchmark test that does not rely on inner classes
Non-local private fields can be accessed by other instances of the class.
However, this creates the following issue:

```
inline trait A:
  private val x = 1
  def eq(o: A) = o.x == x

class B extends A
```

In the code above, when we inline the code into B, `o.x` accesses a private field of A from B, which is not allowed.
To allow this, we'd need to either make x protected, or change the signature of `eq` to take a B instead.
The current check allowed the user to override vars, we don't want that

Only the compiler should be allowed to do this, and for inline traits only
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants