summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2016-03-16 16:14:27 +1000
committerJason Zaugg <jzaugg@gmail.com>2016-03-18 11:49:33 +1000
commitc8e6050c3c190dd064642b6b77fc179f27b0495d (patch)
tree467cd7042e9d889c797bde34bc00be676d668cac /src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
parent699a5d907943330c59cea8e7b1abb536af8e5885 (diff)
downloadscala-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/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala')
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala15
1 files changed, 5 insertions, 10 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
index 3c2ee89b05..85563be428 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
@@ -172,7 +172,6 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
*/
def primitiveOrClassToBType(sym: Symbol): BType = {
assertClassNotArray(sym)
- assert(!sym.isImplClass, sym)
primitiveTypeToBType.getOrElse(sym, classBTypeFromSymbol(sym))
}
@@ -337,7 +336,7 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
// Check for hasAnnotationFlag for SI-9393: the classfile / java source parsers add
// scala.annotation.Annotation as superclass to java annotations. In reality, java
// annotation classfiles have superclass Object (like any interface classfile).
- val superClassSym = if (classSym.isImplClass || classSym.hasJavaAnnotationFlag) ObjectClass else {
+ val superClassSym = if (classSym.hasJavaAnnotationFlag) ObjectClass else {
val sc = classSym.superClass
// SI-9393: Java annotation classes don't have the ABSTRACT/INTERFACE flag, so they appear
// (wrongly) as superclasses. Fix this for BTypes: the java annotation will appear as interface
@@ -603,11 +602,7 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
*/
final def isTopLevelModuleClass(sym: Symbol): Boolean = exitingPickler {
// phase travel to pickler required for isNestedClass (looks at owner)
- val r = sym.isModuleClass && !sym.isNestedClass
- // The mixin phase adds the `lateMODULE` flag to trait implementation classes. Since the flag
- // is late, it should not be visible here inside the time travel. We check this.
- if (r) assert(!sym.isImplClass, s"isModuleClass should be false for impl class $sym")
- r
+ sym.isModuleClass && !sym.isNestedClass
}
/**
@@ -684,7 +679,7 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
val finalFlag = (
(((sym.rawflags & symtab.Flags.FINAL) != 0) || isTopLevelModuleClass(sym))
- && !sym.enclClass.isInterface
+ && !sym.enclClass.isTrait
&& !sym.isClassConstructor
&& !sym.isMutable // lazy vals and vars both
)
@@ -697,12 +692,12 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
GenBCode.mkFlags(
if (privateFlag) ACC_PRIVATE else ACC_PUBLIC,
if ((sym.isDeferred && !sym.hasFlag(symtab.Flags.JAVA_DEFAULTMETHOD))|| sym.hasAbstractFlag) ACC_ABSTRACT else 0,
- if (sym.isInterface) ACC_INTERFACE else 0,
+ if (sym.isTraitOrInterface) ACC_INTERFACE else 0,
if (finalFlag && !sym.hasAbstractFlag) ACC_FINAL else 0,
if (sym.isStaticMember) ACC_STATIC else 0,
if (sym.isBridge) ACC_BRIDGE | ACC_SYNTHETIC else 0,
if (sym.isArtifact) ACC_SYNTHETIC else 0,
- if (sym.isClass && !sym.isInterface) ACC_SUPER else 0,
+ if (sym.isClass && !sym.isTraitOrInterface) ACC_SUPER else 0,
if (sym.hasJavaEnumFlag) ACC_ENUM else 0,
if (sym.isVarargsMethod) ACC_VARARGS else 0,
if (sym.hasFlag(symtab.Flags.SYNCHRONIZED)) ACC_SYNCHRONIZED else 0,