diff options
Diffstat (limited to 'src/dotty')
-rw-r--r-- | src/dotty/tools/backend/jvm/CollectSuperCalls.scala | 37 | ||||
-rw-r--r-- | src/dotty/tools/backend/jvm/DottyBackendInterface.scala | 14 | ||||
-rw-r--r-- | src/dotty/tools/backend/jvm/GenBCode.scala | 10 | ||||
-rw-r--r-- | src/dotty/tools/dotc/Compiler.scala | 3 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeErasure.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/printing/SyntaxHighlighting.scala | 13 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala | 4 |
7 files changed, 71 insertions, 12 deletions
diff --git a/src/dotty/tools/backend/jvm/CollectSuperCalls.scala b/src/dotty/tools/backend/jvm/CollectSuperCalls.scala new file mode 100644 index 000000000..d19228364 --- /dev/null +++ b/src/dotty/tools/backend/jvm/CollectSuperCalls.scala @@ -0,0 +1,37 @@ +package dotty.tools.backend.jvm + +import dotty.tools.dotc.ast.tpd._ +import dotty.tools.dotc.ast.Trees +import dotty.tools.dotc.core.Contexts.Context +import dotty.tools.dotc.core.Symbols._ +import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, TransformerInfo} + +/** Collect all super calls except to the parent class. + * + * This information is used to know if it is safe to remove a redundant mixin class. + * A redundant mixin class is one that is implemented by another mixin class. As the + * methods in a redundant mixin class could be implemented with a default abstract method, + * the redundant mixin class could be required as a parent by the JVM. + */ +class CollectSuperCalls extends MiniPhaseTransform { + + def phaseName: String = "collectSuperCalls" + + override def transformSuper(tree: Super)(implicit ctx: Context, info: TransformerInfo): Tree = { + tree match { + case Trees.Super(qual: This, mix) if mix.nonEmpty => + val classSymbol = qual.symbol.asClass.classSymbol + registerSuperCall(classSymbol, tree.tpe.baseClasses.head) + case _ => + } + super.transformSuper(tree) + } + + private def registerSuperCall(sym: ClassSymbol, calls: ClassSymbol)(implicit ctx: Context) = { + ctx.genBCodePhase match { + case genBCodePhase: GenBCode => + genBCodePhase.registerSuperCall(sym, calls) + case _ => + } + } +} diff --git a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index 23073d317..f42a8eee2 100644 --- a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -34,8 +34,11 @@ import NameOps._ import StdNames.nme import NameOps._ import dotty.tools.dotc.core +import dotty.tools.dotc.core.Names.TypeName -class DottyBackendInterface(outputDirectory: AbstractFile)(implicit ctx: Context) extends BackendInterface{ +import scala.annotation.tailrec + +class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Map[Symbol, Set[ClassSymbol]])(implicit ctx: Context) extends BackendInterface{ type Symbol = Symbols.Symbol type Type = Types.Type type Tree = tpd.Tree @@ -738,9 +741,14 @@ class DottyBackendInterface(outputDirectory: AbstractFile)(implicit ctx: Context /** * All interfaces implemented by a class, except for those inherited through the superclass. - * + * Redundant interfaces are removed unless there is a super call to them. */ - def superInterfaces: List[Symbol] = decorateSymbol(sym).directlyInheritedTraits + def superInterfaces: List[Symbol] = { + val directlyInheritedTraits = decorateSymbol(sym).directlyInheritedTraits + val allBaseClasses = directlyInheritedTraits.iterator.flatMap(_.symbol.asClass.baseClasses.drop(1)).toSet + val superCalls = superCallsMap.getOrElse(sym, Set.empty) + directlyInheritedTraits.filter(t => !allBaseClasses(t) || superCalls(t)) + } /** * True for module classes of package level objects. The backend will generate a mirror class for diff --git a/src/dotty/tools/backend/jvm/GenBCode.scala b/src/dotty/tools/backend/jvm/GenBCode.scala index e5b227a97..902f73ae2 100644 --- a/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/src/dotty/tools/backend/jvm/GenBCode.scala @@ -4,6 +4,7 @@ import dotty.tools.dotc.CompilationUnit import dotty.tools.dotc.ast.Trees.{ValDef, PackageDef} import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Phases.Phase +import dotty.tools.dotc.core.Names.TypeName import scala.collection.mutable import scala.tools.asm.{CustomAttr, ClassVisitor, MethodVisitor, FieldVisitor} @@ -41,11 +42,18 @@ class GenBCode extends Phase { private val entryPoints = new mutable.HashSet[Symbol]() def registerEntryPoint(sym: Symbol) = entryPoints += sym + private val superCallsMap = new mutable.HashMap[Symbol, Set[ClassSymbol]]() + def registerSuperCall(sym: Symbol, calls: ClassSymbol) = { + val old = superCallsMap.getOrElse(sym, Set.empty) + superCallsMap.put(sym, old + calls) + } + def outputDir(implicit ctx: Context): AbstractFile = new PlainDirectory(new Directory(new JFile(ctx.settings.d.value))) def run(implicit ctx: Context): Unit = { - new GenBCodePipeline(entryPoints.toList, new DottyBackendInterface(outputDir)(ctx))(ctx).run(ctx.compilationUnit.tpdTree) + new GenBCodePipeline(entryPoints.toList, + new DottyBackendInterface(outputDir, superCallsMap.toMap)(ctx))(ctx).run(ctx.compilationUnit.tpdTree) entryPoints.clear() } } diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index ce9280d82..d447c3826 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -15,7 +15,7 @@ import transform.TreeTransforms.{TreeTransform, TreeTransformer} import core.DenotTransformers.DenotTransformer import core.Denotations.SingleDenotation -import dotty.tools.backend.jvm.{LabelDefs, GenBCode} +import dotty.tools.backend.jvm.{LabelDefs, GenBCode, CollectSuperCalls} import dotty.tools.backend.sjs.GenSJSIR /** The central class of the dotc compiler. The job of a compiler is to create @@ -92,6 +92,7 @@ class Compiler { new RestoreScopes), // Repair scopes rendered invalid by moving definitions in prior phases of the group List(new ExpandPrivate, // Widen private definitions accessed from nested classes new CollectEntryPoints, // Find classes with main methods + new CollectSuperCalls, // Find classes that are called with super new MoveStatics, // Move static methods to companion classes new LabelDefs), // Converts calls to labels to jumps List(new GenSJSIR), // Generate .js code diff --git a/src/dotty/tools/dotc/core/TypeErasure.scala b/src/dotty/tools/dotc/core/TypeErasure.scala index 2e84102f5..a1dab16cb 100644 --- a/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/src/dotty/tools/dotc/core/TypeErasure.scala @@ -389,7 +389,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean def arrayErasure(tpToErase: Type) = erasureFn(isJava, semiEraseVCs = false, isConstructor, wildcardOK)(tpToErase) if (elemtp derivesFrom defn.NullClass) JavaArrayType(defn.ObjectType) - else if (isUnboundedGeneric(elemtp)) defn.ObjectType + else if (isUnboundedGeneric(elemtp) && !isJava) defn.ObjectType else JavaArrayType(arrayErasure(elemtp)) } diff --git a/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala b/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala index 8a79e1ddc..67aa24243 100644 --- a/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala +++ b/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala @@ -77,10 +77,15 @@ object SyntaxHighlighting { (n: @switch) match { case '/' => if (remaining.nonEmpty) { - takeChar() match { - case '/' => eolComment() - case '*' => blockComment() - case x => newBuf += '/'; remaining = x #:: remaining + remaining.head match { + case '/' => + takeChar() + eolComment() + case '*' => + takeChar() + blockComment() + case x => + newBuf += '/' } } else newBuf += '/' case '=' => diff --git a/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala b/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala index 6765604c8..8bc4a2aa9 100644 --- a/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala +++ b/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala @@ -124,8 +124,8 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer => !(selector.typeSymbol is Trait) && !(selector.typeSymbol is Module) - val selClassNonFinal = scClass && !(selector.typeSymbol is Final) - val selFinalClass = scClass && (selector.typeSymbol is Final) + val selClassNonFinal = selClass && !(selector.typeSymbol is Final) + val selFinalClass = selClass && (selector.typeSymbol is Final) // Cases --------------------------------- val valueClassesOrAny = |