diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2016-03-16 16:14:27 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2016-03-18 11:49:33 +1000 |
commit | c8e6050c3c190dd064642b6b77fc179f27b0495d (patch) | |
tree | 467cd7042e9d889c797bde34bc00be676d668cac /src/reflect/scala/reflect/internal/Flags.scala | |
parent | 699a5d907943330c59cea8e7b1abb536af8e5885 (diff) | |
download | scala-c8e6050c3c190dd064642b6b77fc179f27b0495d.tar.gz scala-c8e6050c3c190dd064642b6b77fc179f27b0495d.tar.bz2 scala-c8e6050c3c190dd064642b6b77fc179f27b0495d.zip |
New trait encoding: use default methods, jettison impl classes
Until now, concrete methods in traits were encoded with
"trait implementation classes".
- Such a trait would compile to two class files
- the trait interface, a Java interface, and
- the implementation class, containing "trait implementation methods"
- trait implementation methods are static methods has an explicit self
parameter.
- some methods don't require addition of an interface method, such as
private methods. Calls to these directly call the implementation method
- classes that mixin a trait install "trait forwarders", which implement
the abstract method in the interface by forwarding to the trait
implementation method.
The new encoding:
- no longer emits trait implementation classes or trait implementation
methods.
- instead, concrete methods are simply retained in the interface, as JVM 8
default interface methods (the JVM spec changes in
[JSR-335](http://download.oracle.com/otndocs/jcp/lambda-0_9_3-fr-eval-spec/index.html)
pave the way)
- use `invokespecial` to call private or particular super implementations
of a method (rather `invokestatic`)
- in cases when we `invokespecial` to a method in an indirect ancestor, we add
that ancestor redundantly as a direct parent. We are investigating alternatives
approaches here.
- we still emit trait fowrarders, although we are
[investigating](https://github.com/scala/scala-dev/issues/98) ways to only do
this when the JVM would be unable to resolve the correct method using its rules
for default method resolution.
Here's an example:
```
trait T {
println("T")
def m1 = m2
private def m2 = "m2"
}
trait U extends T {
println("T")
override def m1 = super[T].m1
}
class C extends U {
println("C")
def test = m1
}
```
The old and new encodings are displayed and diffed here: https://gist.github.com/retronym/f174d23f859f0e053580
Some notes in the implementation:
- No need to filter members from class decls at all in AddInterfaces
(although we do have to trigger side effecting info transformers)
- We can now emit an EnclosingMethod attribute for classes nested
in private trait methods
- Created a factory method for an AST shape that is used in
a number of places to symbolically bind to a particular
super method without needed to specify the qualifier of
the `Super` tree (which is too limiting, as it only allows
you to refer to direct parents.)
- I also found a similar tree shape created in Delambdafy,
that is better expressed with an existing tree creation
factory method, mkSuperInit.
Diffstat (limited to 'src/reflect/scala/reflect/internal/Flags.scala')
-rw-r--r-- | src/reflect/scala/reflect/internal/Flags.scala | 12 |
1 files changed, 4 insertions, 8 deletions
diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala index b022ba2981..35c927a5c3 100644 --- a/src/reflect/scala/reflect/internal/Flags.scala +++ b/src/reflect/scala/reflect/internal/Flags.scala @@ -157,7 +157,6 @@ class Flags extends ModifierFlags { final val MIXEDIN = 1L << 35 // term member has been mixed in final val EXISTENTIAL = 1L << 35 // type is an existential parameter or skolem final val EXPANDEDNAME = 1L << 36 // name has been expanded with class suffix - final val IMPLCLASS = 1L << 37 // symbol is an implementation class final val TRANS_FLAG = 1L << 38 // transient flag guaranteed to be reset after each phase. final val LOCKED = 1L << 39 // temporary flag to catch cyclic dependencies @@ -199,8 +198,7 @@ class Flags extends ModifierFlags { // 17: CONTRAVARIANT/M INCONSTRUCTOR LABEL // 25: DEFAULTPARAM/M TRAIT/M // 35: EXISTENTIAL MIXEDIN - // 37: IMPLCLASS PRESUPER/M - val OverloadedFlagsMask = 0L | BYNAMEPARAM | CONTRAVARIANT | DEFAULTPARAM | EXISTENTIAL | IMPLCLASS + val OverloadedFlagsMask = 0L | BYNAMEPARAM | CONTRAVARIANT | DEFAULTPARAM | EXISTENTIAL // ------- late flags (set by a transformer phase) --------------------------------- // @@ -210,7 +208,7 @@ class Flags extends ModifierFlags { // refchecks 7 [START] <latemethod> // specialize 13 [START] <latefinal> <notprivate> // explicitouter 14 [START] <notprotected> - // erasure 15 [START] <latedeferred> <lateinterface> + // erasure 15 [START] <latedeferred> // mixin 20 [START] <latemodule> <notoverride> // // lateMETHOD set in RefChecks#transformInfo. @@ -218,13 +216,11 @@ class Flags extends ModifierFlags { // notPRIVATE set in Symbols#makeNotPrivate, IExplicitOuter#transform, Inliners. // notPROTECTED set in ExplicitOuter#transform. // lateDEFERRED set in AddInterfaces, Mixin, etc. - // lateINTERFACE set in AddInterfaces#transformMixinInfo. // lateMODULE set in Mixin#transformInfo. // notOVERRIDE set in Mixin#preTransform. final val lateDEFERRED = (DEFERRED: Long) << LateShift final val lateFINAL = (FINAL: Long) << LateShift - final val lateINTERFACE = (INTERFACE: Long) << LateShift final val lateMETHOD = (METHOD: Long) << LateShift final val lateMODULE = (MODULE: Long) << LateShift @@ -439,7 +435,7 @@ class Flags extends ModifierFlags { case LIFTED => "<lifted>" // (1L << 34) case EXISTENTIAL => "<existential/mixedin>" // (1L << 35) case EXPANDEDNAME => "<expandedname>" // (1L << 36) - case IMPLCLASS => "<implclass/presuper>" // (1L << 37) + case PRESUPER => "<presuper>" // (1L << 37) case TRANS_FLAG => "<trans_flag>" // (1L << 38) case LOCKED => "<locked>" // (1L << 39) case SPECIALIZED => "<specialized>" // (1L << 40) @@ -456,7 +452,7 @@ class Flags extends ModifierFlags { case `lateDEFERRED` => "<latedeferred>" // (1L << 51) case `lateFINAL` => "<latefinal>" // (1L << 52) case `lateMETHOD` => "<latemethod>" // (1L << 53) - case `lateINTERFACE` => "<lateinterface>" // (1L << 54) + case 0x80000000000000L => "" // (1L << 54) case `lateMODULE` => "<latemodule>" // (1L << 55) case `notPROTECTED` => "<notprotected>" // (1L << 56) case `notOVERRIDE` => "<notoverride>" // (1L << 57) |