From 0934483934a537f04b5c0dc54deb6213f690d811 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 21 Oct 2017 14:55:41 +0200 Subject: [PATCH 01/12] Add tag method to Tree nodes --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 108 ++++++++++++++++++ compiler/src/dotty/tools/dotc/ast/untpd.scala | 65 ++++++++--- 2 files changed, 158 insertions(+), 15 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 0fb504f62d12..1ab5c5bb1765 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -19,6 +19,72 @@ import language.implicitConversions object Trees { + type TreeTag = Int + + object Tag { + final val Ident = 0 + final val Select = 1 + final val This = 2 + final val Super = 3 + final val Apply = 4 + final val TypeApply = 5 + final val Literal = 6 + final val New = 7 + final val Typed = 8 + final val NamedArg = 9 + final val Assign = 10 + final val Block = 11 + final val If = 12 + final val Closure = 13 + final val Match = 14 + final val CaseDef = 15 + final val Return = 16 + final val Try = 17 + final val SeqLiteral = 18 + final val Inlined = 19 + final val TypeTree = 20 + final val SingletonTypeTree = 21 + final val AndTypeTree = 22 + final val OrTypeTree = 23 + final val RefinedTypeTree = 24 + final val AppliedTypeTree = 25 + final val LambdaTypeTree = 26 + final val ByNameTypeTree = 27 + final val TypeBoundsTree = 28 + final val Bind = 29 + final val Alternative = 30 + final val UnApply = 31 + final val ValDef = 32 + final val DefDef = 33 + final val TypeDef = 34 + final val Template = 35 + final val Import = 36 + final val PackageDef = 37 + final val Annotated = 38 + final val Thicket = 39 + + final val TypedSplice = 40 + final val ModuleDef = 41 + final val ParsedTry = 42 + final val SymbolLit = 43 + final val InterpolatedString = 44 + final val Function = 45 + final val InfixOp = 46 + final val PostfixOp = 47 + final val PrefixOp = 48 + final val Parens = 49 + final val Tuple = 50 + final val Throw = 51 + final val WhileDo = 42 + final val DoWhile = 43 + final val ForYield = 44 + final val ForDo = 45 + final val GenFrom = 46 + final val GenAlias = 47 + final val ContextBounds = 48 + final val PatDef = 49 + } + // Note: it would be more logical to make Untyped = Nothing. // However, this interacts in a bad way with Scala's current type inference. // In fact, we cannot write something like Select(pre, name), where pre is @@ -78,6 +144,8 @@ object Trees { /** The type constructor at the root of the tree */ type ThisTree[T >: Untyped] <: Tree[T] + def tag: TreeTag + private[this] var myTpe: T = _ /** Destructively set the type of the tree. This should be called only when it is known that @@ -357,6 +425,7 @@ object Trees { case class Ident[-T >: Untyped] private[ast] (name: Name) extends RefTree[T] { type ThisTree[-T >: Untyped] = Ident[T] + def tag = Tag.Ident def qualifier: Tree[T] = genericEmptyTree /** Is this a `BackquotedIdent` ? */ @@ -374,6 +443,7 @@ object Trees { case class Select[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name) extends RefTree[T] { type ThisTree[-T >: Untyped] = Select[T] + def tag = Tag.Select } class SelectWithSig[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name, val sig: Signature) @@ -385,6 +455,7 @@ object Trees { case class This[-T >: Untyped] private[ast] (qual: untpd.Ident) extends DenotingTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = This[T] + def tag = Tag.This // Denotation of a This tree is always the underlying class; needs correction for modules. override def denot(implicit ctx: Context): Denotation = { typeOpt match { @@ -400,6 +471,7 @@ object Trees { case class Super[-T >: Untyped] private[ast] (qual: Tree[T], mix: untpd.Ident) extends ProxyTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = Super[T] + def tag = Tag.Super def forwardTo = qual } @@ -414,30 +486,35 @@ object Trees { case class Apply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]]) extends GenericApply[T] { type ThisTree[-T >: Untyped] = Apply[T] + def tag = Tag.Apply } /** fun[args] */ case class TypeApply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]]) extends GenericApply[T] { type ThisTree[-T >: Untyped] = TypeApply[T] + def tag = Tag.TypeApply } /** const */ case class Literal[-T >: Untyped] private[ast] (const: Constant) extends TermTree[T] { type ThisTree[-T >: Untyped] = Literal[T] + def tag = Tag.Literal } /** new tpt, but no constructor call */ case class New[-T >: Untyped] private[ast] (tpt: Tree[T]) extends TermTree[T] { type ThisTree[-T >: Untyped] = New[T] + def tag = Tag.New } /** expr : tpt */ case class Typed[-T >: Untyped] private[ast] (expr: Tree[T], tpt: Tree[T]) extends ProxyTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = Typed[T] + def tag = Tag.Typed def forwardTo = expr } @@ -445,24 +522,28 @@ object Trees { case class NamedArg[-T >: Untyped] private[ast] (name: Name, arg: Tree[T]) extends Tree[T] { type ThisTree[-T >: Untyped] = NamedArg[T] + def tag = Tag.NamedArg } /** name = arg, outside a parameter list */ case class Assign[-T >: Untyped] private[ast] (lhs: Tree[T], rhs: Tree[T]) extends TermTree[T] { type ThisTree[-T >: Untyped] = Assign[T] + def tag = Tag.Assign } /** { stats; expr } */ case class Block[-T >: Untyped] private[ast] (stats: List[Tree[T]], expr: Tree[T]) extends TermTree[T] { type ThisTree[-T >: Untyped] = Block[T] + def tag = Tag.Block } /** if cond then thenp else elsep */ case class If[-T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T]) extends TermTree[T] { type ThisTree[-T >: Untyped] = If[T] + def tag = Tag.If } /** A closure with an environment and a reference to a method. @@ -477,18 +558,21 @@ object Trees { case class Closure[-T >: Untyped] private[ast] (env: List[Tree[T]], meth: Tree[T], tpt: Tree[T]) extends TermTree[T] { type ThisTree[-T >: Untyped] = Closure[T] + def tag = Tag.Closure } /** selector match { cases } */ case class Match[-T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]]) extends TermTree[T] { type ThisTree[-T >: Untyped] = Match[T] + def tag = Tag.Match } /** case pat if guard => body; only appears as child of a Match */ case class CaseDef[-T >: Untyped] private[ast] (pat: Tree[T], guard: Tree[T], body: Tree[T]) extends Tree[T] { type ThisTree[-T >: Untyped] = CaseDef[T] + def tag = Tag.CaseDef } /** return expr @@ -499,6 +583,7 @@ object Trees { case class Return[-T >: Untyped] private[ast] (expr: Tree[T], from: Tree[T] = genericEmptyTree) extends TermTree[T] { type ThisTree[-T >: Untyped] = Return[T] + def tag = Tag.Return } /** try block catch handler finally finalizer @@ -523,6 +608,7 @@ object Trees { case class Try[-T >: Untyped] private[ast] (expr: Tree[T], cases: List[CaseDef[T]], finalizer: Tree[T]) extends TermTree[T] { type ThisTree[-T >: Untyped] = Try[T] + def tag = Tag.Try } /** Seq(elems) @@ -531,6 +617,7 @@ object Trees { case class SeqLiteral[-T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T]) extends Tree[T] { type ThisTree[-T >: Untyped] = SeqLiteral[T] + def tag = Tag.SeqLiteral } /** Array(elems) */ @@ -558,12 +645,14 @@ object Trees { case class Inlined[-T >: Untyped] private[ast] (call: tpd.Tree, bindings: List[MemberDef[T]], expansion: Tree[T]) extends Tree[T] { type ThisTree[-T >: Untyped] = Inlined[T] + def tag = Tag.Inlined } /** A type tree that represents an existing or inferred type */ case class TypeTree[-T >: Untyped] () extends DenotingTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = TypeTree[T] + def tag = Tag.TypeTree override def isEmpty = !hasType override def toString = s"TypeTree${if (hasType) s"[$typeOpt]" else ""}" @@ -573,24 +662,28 @@ object Trees { case class SingletonTypeTree[-T >: Untyped] private[ast] (ref: Tree[T]) extends DenotingTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = SingletonTypeTree[T] + def tag = Tag.SingletonTypeTree } /** left & right */ case class AndTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T]) extends TypTree[T] { type ThisTree[-T >: Untyped] = AndTypeTree[T] + def tag = Tag.AndTypeTree } /** left | right */ case class OrTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T]) extends TypTree[T] { type ThisTree[-T >: Untyped] = OrTypeTree[T] + def tag = Tag.OrTypeTree } /** tpt { refinements } */ case class RefinedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], refinements: List[Tree[T]]) extends ProxyTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = RefinedTypeTree[T] + def tag = Tag.RefinedTypeTree def forwardTo = tpt } @@ -598,6 +691,7 @@ object Trees { case class AppliedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], args: List[Tree[T]]) extends ProxyTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = AppliedTypeTree[T] + def tag = Tag.AppliedTypeTree def forwardTo = tpt } @@ -605,24 +699,28 @@ object Trees { case class LambdaTypeTree[-T >: Untyped] private[ast] (tparams: List[TypeDef[T]], body: Tree[T]) extends TypTree[T] { type ThisTree[-T >: Untyped] = LambdaTypeTree[T] + def tag = Tag.LambdaTypeTree } /** => T */ case class ByNameTypeTree[-T >: Untyped] private[ast] (result: Tree[T]) extends TypTree[T] { type ThisTree[-T >: Untyped] = ByNameTypeTree[T] + def tag = Tag.ByNameTypeTree } /** >: lo <: hi */ case class TypeBoundsTree[-T >: Untyped] private[ast] (lo: Tree[T], hi: Tree[T]) extends TypTree[T] { type ThisTree[-T >: Untyped] = TypeBoundsTree[T] + def tag = Tag.TypeBoundsTree } /** name @ body */ case class Bind[-T >: Untyped] private[ast] (name: Name, body: Tree[T]) extends NameTree[T] with DefTree[T] with PatternTree[T] { type ThisTree[-T >: Untyped] = Bind[T] + def tag = Tag.Bind override def isType = name.isTypeName override def isTerm = name.isTermName } @@ -631,6 +729,7 @@ object Trees { case class Alternative[-T >: Untyped] private[ast] (trees: List[Tree[T]]) extends PatternTree[T] { type ThisTree[-T >: Untyped] = Alternative[T] + def tag = Tag.Alternative } /** The typed translation of `extractor(patterns)` in a pattern. The translation has the following @@ -650,12 +749,14 @@ object Trees { case class UnApply[-T >: Untyped] private[ast] (fun: Tree[T], implicits: List[Tree[T]], patterns: List[Tree[T]]) extends PatternTree[T] { type ThisTree[-T >: Untyped] = UnApply[T] + def tag = Tag.UnApply } /** mods val name: tpt = rhs */ case class ValDef[-T >: Untyped] private[ast] (name: TermName, tpt: Tree[T], private var preRhs: LazyTree) extends ValOrDefDef[T] { type ThisTree[-T >: Untyped] = ValDef[T] + def tag = Tag.ValDef assert(isEmpty || tpt != genericEmptyTree) def unforced = preRhs protected def force(x: AnyRef) = preRhs = x @@ -666,6 +767,7 @@ object Trees { vparamss: List[List[ValDef[T]]], tpt: Tree[T], private var preRhs: LazyTree) extends ValOrDefDef[T] { type ThisTree[-T >: Untyped] = DefDef[T] + def tag = Tag.DefDef assert(tpt != genericEmptyTree) def unforced = preRhs protected def force(x: AnyRef) = preRhs = x @@ -679,6 +781,7 @@ object Trees { case class TypeDef[-T >: Untyped] private[ast] (name: TypeName, rhs: Tree[T]) extends MemberDef[T] { type ThisTree[-T >: Untyped] = TypeDef[T] + def tag = Tag.TypeDef /** Is this a definition of a class? */ def isClassDef = rhs.isInstanceOf[Template[_]] @@ -688,6 +791,7 @@ object Trees { case class Template[-T >: Untyped] private[ast] (constr: DefDef[T], parents: List[Tree[T]], self: ValDef[T], private var preBody: LazyTreeList) extends DefTree[T] with WithLazyField[List[Tree[T]]] { type ThisTree[-T >: Untyped] = Template[T] + def tag = Tag.Template def unforcedBody = unforced def unforced = preBody protected def force(x: AnyRef) = preBody = x @@ -701,12 +805,14 @@ object Trees { case class Import[-T >: Untyped] private[ast] (expr: Tree[T], selectors: List[Tree[Untyped]]) extends DenotingTree[T] { type ThisTree[-T >: Untyped] = Import[T] + def tag = Tag.Import } /** package pid { stats } */ case class PackageDef[-T >: Untyped] private[ast] (pid: RefTree[T], stats: List[Tree[T]]) extends ProxyTree[T] { type ThisTree[-T >: Untyped] = PackageDef[T] + def tag = Tag.PackageDef def forwardTo = pid } @@ -714,6 +820,7 @@ object Trees { case class Annotated[-T >: Untyped] private[ast] (arg: Tree[T], annot: Tree[T]) extends ProxyTree[T] { type ThisTree[-T >: Untyped] = Annotated[T] + def tag = Tag.Annotated def forwardTo = arg } @@ -732,6 +839,7 @@ object Trees { case class Thicket[-T >: Untyped](trees: List[Tree[T]]) extends Tree[T] with WithoutTypeOrPos[T] { type ThisTree[-T >: Untyped] = Thicket[T] + def tag = Tag.Thicket override def isEmpty: Boolean = trees.isEmpty override def toList: List[Tree[T]] = flatten(trees) override def toString = if (isEmpty) "EmptyTree" else "Thicket(" + trees.mkString(", ") + ")" diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index bf40539679ec..6de2c5744074 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -25,6 +25,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { * @param owner The current owner at the time the tree was defined */ abstract case class TypedSplice(tree: tpd.Tree)(val owner: Symbol) extends ProxyTree { + def tag = Tag.TypedSplice def forwardTo = tree } @@ -37,20 +38,28 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { case class ModuleDef(name: TermName, impl: Template) extends MemberDef { type ThisTree[-T >: Untyped] <: Trees.NameTree[T] with Trees.MemberDef[T] with ModuleDef + def tag = Tag.ModuleDef def withName(name: Name)(implicit ctx: Context) = cpy.ModuleDef(this)(name.toTermName, impl) } - case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree) extends TermTree + case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree) extends TermTree { + def tag = Tag.ParsedTry + } - case class SymbolLit(str: String) extends TermTree + case class SymbolLit(str: String) extends TermTree { + def tag = Tag.SymbolLit + } /** An interpolated string * @param segments a list of two element tickets consisting of string literal and argument tree, * possibly with a simple string literal as last element of the list */ - case class InterpolatedString(id: TermName, segments: List[Tree]) extends TermTree + case class InterpolatedString(id: TermName, segments: List[Tree]) extends TermTree { + def tag = Tag.InterpolatedString + } case class Function(args: List[Tree], body: Tree) extends Tree { + def tag = Tag.Function override def isTerm = body.isTerm override def isType = body.isType } @@ -67,25 +76,51 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { */ class WildcardFunction(placeholderParams: List[ValDef], body: Tree) extends Function(placeholderParams, body) - case class InfixOp(left: Tree, op: Ident, right: Tree) extends OpTree - case class PostfixOp(od: Tree, op: Ident) extends OpTree - case class PrefixOp(op: Ident, od: Tree) extends OpTree + case class InfixOp(left: Tree, op: Ident, right: Tree) extends OpTree { + def tag = Tag.InfixOp + } + case class PostfixOp(od: Tree, op: Ident) extends OpTree { + def tag = Tag.PostfixOp + } + case class PrefixOp(op: Ident, od: Tree) extends OpTree { + def tag = Tag.PrefixOp + } case class Parens(t: Tree) extends ProxyTree { + def tag = Tag.Parens def forwardTo = t } case class Tuple(trees: List[Tree]) extends Tree { + def tag = Tag.Tuple override def isTerm = trees.isEmpty || trees.head.isTerm override def isType = !isTerm } - case class Throw(expr: Tree) extends TermTree - case class WhileDo(cond: Tree, body: Tree) extends TermTree - case class DoWhile(body: Tree, cond: Tree) extends TermTree - case class ForYield(enums: List[Tree], expr: Tree) extends TermTree - case class ForDo(enums: List[Tree], body: Tree) extends TermTree - case class GenFrom(pat: Tree, expr: Tree) extends Tree - case class GenAlias(pat: Tree, expr: Tree) extends Tree - case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree]) extends TypTree - case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree) extends DefTree + case class Throw(expr: Tree) extends TermTree { + def tag = Tag.Throw + } + case class WhileDo(cond: Tree, body: Tree) extends TermTree { + def tag = Tag.WhileDo + } + case class DoWhile(body: Tree, cond: Tree) extends TermTree { + def tag = Tag.DoWhile + } + case class ForYield(enums: List[Tree], expr: Tree) extends TermTree { + def tag = Tag.ForYield + } + case class ForDo(enums: List[Tree], body: Tree) extends TermTree { + def tag = Tag.ForDo + } + case class GenFrom(pat: Tree, expr: Tree) extends Tree { + def tag = Tag.GenFrom + } + case class GenAlias(pat: Tree, expr: Tree) extends Tree { + def tag = Tag.GenAlias + } + case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree]) extends TypTree { + def tag = Tag.ContextBounds + } + case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree) extends DefTree { + def tag = Tag.PatDef + } @sharable object EmptyTypeIdent extends Ident(tpnme.EMPTY) with WithoutTypeOrPos[Untyped] { override def isEmpty = true From 681ea263d79297452a52d0f85c26b9dff641e039 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 22 Oct 2017 17:26:21 +0200 Subject: [PATCH 02/12] Introduce SuperPhase --- .../tools/dotc/transform/SuperPhase.scala | 625 ++++++++++++++++++ 1 file changed, 625 insertions(+) create mode 100644 compiler/src/dotty/tools/dotc/transform/SuperPhase.scala diff --git a/compiler/src/dotty/tools/dotc/transform/SuperPhase.scala b/compiler/src/dotty/tools/dotc/transform/SuperPhase.scala new file mode 100644 index 000000000000..052445ad766d --- /dev/null +++ b/compiler/src/dotty/tools/dotc/transform/SuperPhase.scala @@ -0,0 +1,625 @@ +package dotty.tools +package dotc +package transform + +import core._ +import ast.Trees._ +import Contexts._, Phases._, Periods._, Symbols._, Decorators._ +import Flags.PackageVal +import scala.annotation.tailrec +import config.Printers.transforms +import scala.util.control.NonFatal +import reporting.trace + +/** A SuperPhase combines a number of mini-phases which are all executed in + * a single tree traversal. + * + * This is an evolution of the previous "TreeTransformers.scala", which was written by @DarkDimius and + * is described in his thesis. + */ +object SuperPhase { + import ast.tpd._ + + /** The base class of tree transforms. For each kind of tree K, there are + * two methods which can be overridden: + * + * prepareForK: return a new Context which gets passed to the node and its children + * transformK // transform node of type K + * + * There are also prepare/transform hooks for + * + * - Stats: to prepare/transform a statement sequence in a block, template, or package def, + * - Unit : to prepare/transform a whole compilation unit + * - Other: to prepape/transform a tree that does not have a specific prepare/transform + * method pair. + */ + abstract class MiniPhase extends Phase { + + private[SuperPhase] var superPhase: SuperPhase = _ + private[SuperPhase] var idxInGroup: Int = _ + + /** List of names of phases that should have finished their processing of all compilation units + * before this phase starts + */ + def runsAfterGroupsOf: Set[Class[_ <: Phase]] = Set.empty + + val cpy: TypedTreeCopier = cpyBetweenPhases + + def prepareForIdent(tree: Ident)(implicit ctx: Context): Context = ctx + def prepareForSelect(tree: Select)(implicit ctx: Context): Context = ctx + def prepareForThis(tree: This)(implicit ctx: Context) = ctx + def prepareForSuper(tree: Super)(implicit ctx: Context) = ctx + def prepareForApply(tree: Apply)(implicit ctx: Context) = ctx + def prepareForTypeApply(tree: TypeApply)(implicit ctx: Context) = ctx + def prepareForLiteral(tree: Literal)(implicit ctx: Context) = ctx + def prepareForNew(tree: New)(implicit ctx: Context) = ctx + def prepareForTyped(tree: Typed)(implicit ctx: Context) = ctx + def prepareForAssign(tree: Assign)(implicit ctx: Context) = ctx + def prepareForBlock(tree: Block)(implicit ctx: Context) = ctx + def prepareForIf(tree: If)(implicit ctx: Context) = ctx + def prepareForClosure(tree: Closure)(implicit ctx: Context) = ctx + def prepareForMatch(tree: Match)(implicit ctx: Context) = ctx + def prepareForCaseDef(tree: CaseDef)(implicit ctx: Context) = ctx + def prepareForReturn(tree: Return)(implicit ctx: Context) = ctx + def prepareForTry(tree: Try)(implicit ctx: Context) = ctx + def prepareForSeqLiteral(tree: SeqLiteral)(implicit ctx: Context) = ctx + def prepareForInlined(tree: Inlined)(implicit ctx: Context) = ctx + def prepareForTypeTree(tree: TypeTree)(implicit ctx: Context) = ctx + def prepareForBind(tree: Bind)(implicit ctx: Context) = ctx + def prepareForAlternative(tree: Alternative)(implicit ctx: Context) = ctx + def prepareForUnApply(tree: UnApply)(implicit ctx: Context) = ctx + def prepareForValDef(tree: ValDef)(implicit ctx: Context) = ctx + def prepareForDefDef(tree: DefDef)(implicit ctx: Context) = ctx + def prepareForTypeDef(tree: TypeDef)(implicit ctx: Context) = ctx + def prepareForTemplate(tree: Template)(implicit ctx: Context) = ctx + def prepareForPackageDef(tree: PackageDef)(implicit ctx: Context) = ctx + def prepareForStats(trees: List[Tree])(implicit ctx: Context) = ctx + def prepareForUnit(tree: Tree)(implicit ctx: Context) = ctx + def prepareForOther(tree: Tree)(implicit ctx: Context) = ctx + + def transformIdent(tree: Ident)(implicit ctx: Context): Tree = tree + def transformSelect(tree: Select)(implicit ctx: Context): Tree = tree + def transformThis(tree: This)(implicit ctx: Context): Tree = tree + def transformSuper(tree: Super)(implicit ctx: Context): Tree = tree + def transformApply(tree: Apply)(implicit ctx: Context): Tree = tree + def transformTypeApply(tree: TypeApply)(implicit ctx: Context): Tree = tree + def transformLiteral(tree: Literal)(implicit ctx: Context): Tree = tree + def transformNew(tree: New)(implicit ctx: Context): Tree = tree + def transformTyped(tree: Typed)(implicit ctx: Context): Tree = tree + def transformAssign(tree: Assign)(implicit ctx: Context): Tree = tree + def transformBlock(tree: Block)(implicit ctx: Context): Tree = tree + def transformIf(tree: If)(implicit ctx: Context): Tree = tree + def transformClosure(tree: Closure)(implicit ctx: Context): Tree = tree + def transformMatch(tree: Match)(implicit ctx: Context): Tree = tree + def transformCaseDef(tree: CaseDef)(implicit ctx: Context): Tree = tree + def transformReturn(tree: Return)(implicit ctx: Context): Tree = tree + def transformTry(tree: Try)(implicit ctx: Context): Tree = tree + def transformSeqLiteral(tree: SeqLiteral)(implicit ctx: Context): Tree = tree + def transformInlined(tree: Inlined)(implicit ctx: Context): Tree = tree + def transformTypeTree(tree: TypeTree)(implicit ctx: Context): Tree = tree + def transformBind(tree: Bind)(implicit ctx: Context): Tree = tree + def transformAlternative(tree: Alternative)(implicit ctx: Context): Tree = tree + def transformUnApply(tree: UnApply)(implicit ctx: Context): Tree = tree + def transformValDef(tree: ValDef)(implicit ctx: Context): Tree = tree + def transformDefDef(tree: DefDef)(implicit ctx: Context): Tree = tree + def transformTypeDef(tree: TypeDef)(implicit ctx: Context): Tree = tree + def transformTemplate(tree: Template)(implicit ctx: Context): Tree = tree + def transformPackageDef(tree: PackageDef)(implicit ctx: Context): Tree = tree + def transformStats(trees: List[Tree])(implicit ctx: Context): List[Tree] = trees + def transformUnit(tree: Tree)(implicit ctx: Context): Tree = tree + def transformOther(tree: Tree)(implicit ctx: Context): Tree = tree + + /** Transform tree using all transforms of current group (including this one) */ + def transformAllDeep(tree: Tree)(implicit ctx: Context): Tree = + superPhase.transformTree(tree, 0) + + /** Transform tree using all transforms following the current one in this group */ + def transformFollowingDeep(tree: Tree)(implicit ctx: Context): Tree = + superPhase.transformTree(tree, idxInGroup + 1) + + /** Transform single node using all transforms following the current one in this group */ + def transformFollowing(tree: Tree)(implicit ctx: Context): Tree = + superPhase.transformNode(tree, idxInGroup + 1) + + protected def singletonGroup = new SuperPhase(phaseName, Array(this)) + + override def run(implicit ctx: Context): Unit = + singletonGroup.run + } + + private type Transformer[-T, R] = (T, Context) => R + private type IndexedTransformer[-T, R] = MiniPhase => Transformer[T, R] + + private val idNodeTransformer: Transformer[AnyRef, AnyRef] = (t, ctx) => t + private val idContextTransformer: Transformer[AnyRef, Context] = (t, ctx) => ctx +} +import SuperPhase._ + +class SuperPhase(override val phaseName: String, val miniPhases: Array[MiniPhase]) extends Phase { + import ast.tpd._ + + private val cpy: TypedTreeCopier = cpyBetweenPhases + + /** Transform node using all phases in this group that have idxInGroup >= start */ + def transformNode(tree: Tree, start: Int)(implicit ctx: Context) = + nodeTransformer(tree.tag)(start)(tree, ctx) + + /** Transform full tree using all phases in this group that have idxInGroup >= start */ + def transformTree(tree: Tree, start: Int)(implicit ctx: Context): Tree = { + val tag = tree.tag + val nestedCtx = contextTransformer(tag)(start)(tree, ctx) + val transformer = nodeTransformer(tag)(start) + + def trans(tree: Tree)(implicit ctx: Context) = transformer(tree, ctx) + + def localContext(implicit ctx: Context) = { + val sym = tree.symbol + val owner = if (sym is PackageVal) sym.moduleClass else sym + ctx.fresh.setOwner(owner) + } + + { implicit val ctx = nestedCtx + tag match { + case Tag.Select => + val tree1 = tree.asInstanceOf[Select] + val qual = transformTree(tree1.qualifier, start) + trans(cpy.Select(tree1)(qual, tree1.name)) + case Tag.Super => + val tree1 = tree.asInstanceOf[Super] + val qual = transformTree(tree1.qual, start) + trans(cpy.Super(tree1)(qual, tree1.mix)) + case Tag.Apply => + val tree1 = tree.asInstanceOf[Apply] + val fun = transformTree(tree1.fun, start) + val args = transformTrees(tree1.args, start) + trans(cpy.Apply(tree1)(fun, args)) + case Tag.TypeApply => + val tree1 = tree.asInstanceOf[TypeApply] + val fun = transformTree(tree1.fun, start) + val args = transformTrees(tree1.args, start) + trans(cpy.TypeApply(tree1)(fun, args)) + case Tag.New => + val tree1 = tree.asInstanceOf[New] + val tpt = transformTree(tree1.tpt, start) + trans(cpy.New(tree1)(tpt)) + case Tag.Typed => + val tree1 = tree.asInstanceOf[Typed] + val expr = transformTree(tree1.expr, start) + val tpt = transformTree(tree1.tpt, start) + trans(cpy.Typed(tree1)(expr, tpt)) + case Tag.Assign => + val tree1 = tree.asInstanceOf[Assign] + val lhs = transformTree(tree1.lhs, start) + val rhs = transformTree(tree1.rhs, start) + trans(cpy.Assign(tree1)(lhs, rhs)) + case Tag.Block => + val tree1 = tree.asInstanceOf[Block] + val stats = transformStats(tree1.stats, ctx.owner, start) + val expr = transformTree(tree1.expr, start) + trans(cpy.Block(tree1)(stats, expr)) + case Tag.If => + val tree1 = tree.asInstanceOf[If] + val cond = transformTree(tree1.cond, start) + val thenp = transformTree(tree1.thenp, start) + val elsep = transformTree(tree1.elsep, start) + trans(cpy.If(tree1)(cond, thenp, elsep)) + case Tag.Closure => + val tree1 = tree.asInstanceOf[Closure] + val env = transformTrees(tree1.env, start) + val meth = transformTree(tree1.meth, start) + val tpt = transformTree(tree1.tpt, start) + trans(cpy.Closure(tree1)(env, meth, tpt)) + case Tag.Match => + val tree1 = tree.asInstanceOf[Match] + val selector = transformTree(tree1.selector, start) + val cases = transformSpecificTrees(tree1.cases, start) + trans(cpy.Match(tree1)(selector, cases)) + case Tag.CaseDef => + val tree1 = tree.asInstanceOf[CaseDef] + val pat = transformTree(tree1.pat, start) + val guard = transformTree(tree1.guard, start) + val body = transformTree(tree1.body, start) + trans(cpy.CaseDef(tree1)(pat, guard, body)) + case Tag.Return => + val tree1 = tree.asInstanceOf[Return] + val expr = transformTree(tree1.expr, start) + trans(cpy.Return(tree1)(expr, tree1.from)) + // don't transform `tree1.from`, as this is not a normal ident, but + // a pointer to the enclosing method. + case Tag.Try => + val tree1 = tree.asInstanceOf[Try] + val expr = transformTree(tree1.expr, start) + val cases = transformSpecificTrees(tree1.cases, start) + val finalizer = transformTree(tree1.finalizer, start) + trans(cpy.Try(tree1)(expr, cases, finalizer)) + case Tag.SeqLiteral => + val tree1 = tree.asInstanceOf[SeqLiteral] + val elems = transformTrees(tree1.elems, start) + val elemtpt = transformTree(tree1.elemtpt, start) + trans(cpy.SeqLiteral(tree1)(elems, elemtpt)) + case Tag.Inlined => + val tree1 = tree.asInstanceOf[Inlined] + val bindings = transformSpecificTrees(tree1.bindings, start) + val expansion = transformTree(tree1.expansion, start) + trans(cpy.Inlined(tree1)(tree1.call, bindings, expansion)) + case Tag.Bind => + val tree1 = tree.asInstanceOf[Bind] + val body = transformTree(tree1.body, start) + trans(cpy.Bind(tree1)(tree1.name, body)) + case Tag.Alternative => + val tree1 = tree.asInstanceOf[Alternative] + val trees = transformTrees(tree1.trees, start) + trans(cpy.Alternative(tree1)(trees)) + case Tag.UnApply => + val tree1 = tree.asInstanceOf[UnApply] + val fun = transformTree(tree1.fun, start) + val implicits = transformTrees(tree1.implicits, start) + val patterns = transformTrees(tree1.patterns, start) + trans(cpy.UnApply(tree1)(fun, implicits, patterns)) + case Tag.ValDef => + val tree1 = tree.asInstanceOf[ValDef] + def transformValDef(implicit ctx: Context) = { + val tpt = transformTree(tree1.tpt, start) + val rhs = transformTree(tree1.rhs, start) + trans(cpy.ValDef(tree1)(tree1.name, tpt, rhs)) + } + if (tree1.isEmpty) tree1 + else transformValDef(if (tree.symbol.exists) localContext else ctx) + case Tag.DefDef => + val tree1 = tree.asInstanceOf[DefDef] + def transformDefDef(implicit ctx: Context) = { + val tparams = transformSpecificTrees(tree1.tparams, start) + val vparamss = tree1.vparamss.mapConserve(transformSpecificTrees(_, start)) + val tpt = transformTree(tree1.tpt, start) + val rhs = transformTree(tree1.rhs, start) + trans(cpy.DefDef(tree1)(tree1.name, tparams, vparamss, tpt, rhs)) + } + transformDefDef(localContext) + case Tag.TypeDef => + val tree1 = tree.asInstanceOf[TypeDef] + def transformTypeDef(implicit ctx: Context) = { + val rhs = transformTree(tree1.rhs, start) + trans(cpy.TypeDef(tree1)(tree1.name, rhs)) + } + transformTypeDef(localContext) + case Tag.Template => + val tree1 = tree.asInstanceOf[Template] + val constr = transformSpecificTree(tree1.constr, start) + val parents = transformTrees(tree1.parents, start) + val self = transformSpecificTree(tree1.self, start) + val body = transformStats(tree1.body, tree1.symbol, start) + trans(cpy.Template(tree1)(constr, parents, self, body)) + case Tag.PackageDef => + val tree1 = tree.asInstanceOf[PackageDef] + def transformPackage(implicit ctx: Context) = { + val pid = transformSpecificTree(tree1.pid, start) + val stats = transformStats(tree1.stats, tree.symbol, start) + trans(cpy.PackageDef(tree1)(pid, stats)) + } + transformPackage(localContext) + case Tag.Thicket => + val tree1 = tree.asInstanceOf[Thicket] + cpy.Thicket(tree1)(transformTrees(tree1.trees, start)) + case _ => + trans(tree) + } + } + } + + def transformSpecificTree[T <: Tree](tree: T, start: Int)(implicit ctx: Context): T = + transformTree(tree, start).asInstanceOf[T] + + def transformStats(trees: List[Tree], exprOwner: Symbol, start: Int)(implicit ctx: Context): List[Tree] = { + def transformStat(stat: Tree)(implicit ctx: Context): Tree = stat match { + case _: Import | _: DefTree => transformTree(stat, start) + case Thicket(stats) => cpy.Thicket(stat)(stats.mapConserve(transformStat)) + case _ => transformTree(stat, start)(ctx.exprContext(stat, exprOwner)) + } + val nestedCtx = statsContextTransformer(start)(trees, ctx) + val newTrees = flatten(trees.mapConserve(transformStat(_)(nestedCtx))) + statsNodeTransformer(start)(newTrees, nestedCtx) + } + + def transformUnit(tree: Tree)(implicit ctx: Context) = { + val nestedCtx = unitContextTransformer(0)(tree, ctx) + val newTree = transformTree(tree, 0)(nestedCtx) + unitNodeTransformer(0)(newTree, nestedCtx) + } + + def transformTrees(trees: List[Tree], start: Int)(implicit ctx: Context): List[Tree] = + flatten(trees.mapConserve(transformTree(_, start))) + + def transformSpecificTrees[T <: Tree](trees: List[T], start: Int)(implicit ctx: Context): List[T] = + transformTrees(trees, start).asInstanceOf[List[T]] + + override def run(implicit ctx: Context): Unit = + ctx.compilationUnit.tpdTree = transformUnit(ctx.compilationUnit.tpdTree) + + // The rest of this class is all made up by initialization code + + for ((phase, idx) <- miniPhases.zipWithIndex) { + phase.superPhase = this + phase.idxInGroup = idx + } + + /** Class#getDeclaredMethods is slow, so we cache its output */ + private val clsMethodsCache = new java.util.IdentityHashMap[Class[_], Array[java.lang.reflect.Method]] + + /** Does `phase` contain a redefinition of method `name`? + * (which is a method of MiniPhase) + */ + private def defines(phase: MiniPhase, name: String) = { + def hasRedefinedMethod(cls: Class[_]): Boolean = + if (cls.eq(classOf[MiniPhase])) false + else { + var clsMethods = clsMethodsCache.get(cls) + if (clsMethods eq null) { + clsMethods = cls.getDeclaredMethods + clsMethodsCache.put(cls, clsMethods) + } + clsMethods.exists(_.getName == name) || + hasRedefinedMethod(cls.getSuperclass) + } + hasRedefinedMethod(phase.getClass) + } + + /** A transformer array is an array of node or context transformers. It has + * one more element than there are miniphases. It is constructed as follows: + * + * - the last element is always `last`, which is the identity transformer + * that returns the context or tree unchanged. + * - The element corresponding to phase P is `elemFn(P)` if `P` defines a + * method with name `methName`, or it the same as the following element + * if `P` does not define `methName`. + */ + private def newTransformerArray[T, R]( + methName: String, elemFn: IndexedTransformer[T, R], last: Transformer[T, R]) = { + val trans = new Array[Transformer[T, R]](miniPhases.length + 1) + trans(miniPhases.length) = last + for (idx <- miniPhases.length - 1 to 0 by -1) { + val subPhase = miniPhases(idx) + trans(idx) = if (defines(subPhase, methName)) elemFn(subPhase) else trans(idx + 1) + } + trans + } + + private def newContextTransformerArray[T](suffix: String, elemFn: IndexedTransformer[T, Context]) = + newTransformerArray[T, Context]("prepareFor" + suffix, elemFn, idContextTransformer.asInstanceOf[Transformer[T, Context]]) + + private def newNodeTransformerArray[T, R](suffix: String, elemFn: IndexedTransformer[T, R]) = + newTransformerArray[T, R]("transform" + suffix, elemFn, idNodeTransformer.asInstanceOf[Transformer[T, R]]) + + private val statsContextTransformer = newContextTransformerArray("Stats", prepForStats) + private val statsNodeTransformer = newNodeTransformerArray("Stats", transStats) + private val unitContextTransformer = newContextTransformerArray("Unit", prepForUnit) + private val unitNodeTransformer = newNodeTransformerArray("Unit", transUnit) + private val otherContextTransformer = newContextTransformerArray("Other", prepForOther) + private val otherNodeTransformer = newNodeTransformerArray("Other", transOther) + + private val contextTransformer: Array[Array[Transformer[Tree, Context]]] = + Array.fill(Tag.NumTags)(otherContextTransformer) + private val nodeTransformer: Array[Array[Transformer[Tree, Tree]]] = + Array.fill(Tag.NumTags)(otherNodeTransformer) + + private def init(name: String, tag: TreeTag, ctf: IndexedTransformer[_, Context], ntf: IndexedTransformer[_, Tree]): Unit = { + if (miniPhases.exists(defines(_, "prepareFor" + name))) + contextTransformer(tag) = newContextTransformerArray(name, ctf.asInstanceOf[IndexedTransformer[Tree, Context]]) + if (miniPhases.exists(defines(_, "transform" + name))) + nodeTransformer(tag) = newNodeTransformerArray(name, ntf.asInstanceOf[IndexedTransformer[Tree, Tree]]) + } + + init("Ident", Tag.Ident, prepForIdent, transIdent) + init("Select", Tag.Select, prepForSelect, transSelect) + init("This", Tag.This, prepForThis, transThis) + init("Super", Tag.Super, prepForSuper, transSuper) + init("Apply", Tag.Apply, prepForApply, transApply) + init("TypeApply", Tag.TypeApply, prepForTypeApply, transTypeApply) + init("Literal", Tag.Literal, prepForLiteral, transLiteral) + init("New", Tag.New, prepForNew, transNew) + init("Typed", Tag.Typed, prepForTyped, transTyped) + init("Assign", Tag.Assign, prepForAssign, transAssign) + init("Block", Tag.Block, prepForBlock, transBlock) + init("If", Tag.If, prepForIf, transIf) + init("Closure", Tag.Closure, prepForClosure, transClosure) + init("Match", Tag.Match, prepForMatch, transMatch) + init("CaseDef", Tag.CaseDef, prepForCaseDef, transCaseDef) + init("Return", Tag.Return, prepForReturn, transReturn) + init("Try", Tag.Try, prepForTry, transTry) + init("SeqLiteral", Tag.SeqLiteral, prepForSeqLiteral, transSeqLiteral) + init("Inlined", Tag.Inlined, prepForInlined, transInlined) + init("TypeTree", Tag.TypeTree, prepForTypeTree, transTypeTree) + init("Bind", Tag.Bind, prepForBind, transBind) + init("Alternative", Tag.Alternative, prepForAlternative, transAlternative) + init("UnApply", Tag.UnApply, prepForUnApply, transUnApply) + init("ValDef", Tag.ValDef, prepForValDef, transValDef) + init("DefDef", Tag.DefDef, prepForDefDef, transDefDef) + init("TypeDef", Tag.TypeDef, prepForTypeDef, transTypeDef) + init("Template", Tag.Template, prepForTemplate, transTemplate) + init("PackageDef", Tag.PackageDef, prepForPackageDef, transPackageDef) + + private def prepForIdent(phase: MiniPhase): Transformer[Ident, Context] = + (tree, ctx) => contextTransformer(Tag.Ident)(phase.idxInGroup + 1)(tree, phase.prepareForIdent(tree)(ctx)) + + private def prepForSelect(phase: MiniPhase): Transformer[Select, Context] = + (tree, ctx) => contextTransformer(Tag.Select)(phase.idxInGroup + 1)(tree, phase.prepareForSelect(tree)(ctx)) + + private def prepForThis(phase: MiniPhase): Transformer[This, Context] = + (tree, ctx) => contextTransformer(Tag.This)(phase.idxInGroup + 1)(tree, phase.prepareForThis(tree)(ctx)) + + private def prepForSuper(phase: MiniPhase): Transformer[Super, Context] = + (tree, ctx) => contextTransformer(Tag.Super)(phase.idxInGroup + 1)(tree, phase.prepareForSuper(tree)(ctx)) + + private def prepForApply(phase: MiniPhase): Transformer[Apply, Context] = + (tree, ctx) => contextTransformer(Tag.Apply)(phase.idxInGroup + 1)(tree, phase.prepareForApply(tree)(ctx)) + + private def prepForTypeApply(phase: MiniPhase): Transformer[TypeApply, Context] = + (tree, ctx) => contextTransformer(Tag.TypeApply)(phase.idxInGroup + 1)(tree, phase.prepareForTypeApply(tree)(ctx)) + + private def prepForLiteral(phase: MiniPhase): Transformer[Literal, Context] = + (tree, ctx) => contextTransformer(Tag.Literal)(phase.idxInGroup + 1)(tree, phase.prepareForLiteral(tree)(ctx)) + + private def prepForNew(phase: MiniPhase): Transformer[New, Context] = + (tree, ctx) => contextTransformer(Tag.New)(phase.idxInGroup + 1)(tree, phase.prepareForNew(tree)(ctx)) + + private def prepForTyped(phase: MiniPhase): Transformer[Typed, Context] = + (tree, ctx) => contextTransformer(Tag.Typed)(phase.idxInGroup + 1)(tree, phase.prepareForTyped(tree)(ctx)) + + private def prepForAssign(phase: MiniPhase): Transformer[Assign, Context] = + (tree, ctx) => contextTransformer(Tag.Assign)(phase.idxInGroup + 1)(tree, phase.prepareForAssign(tree)(ctx)) + + private def prepForBlock(phase: MiniPhase): Transformer[Block, Context] = + (tree, ctx) => contextTransformer(Tag.Block)(phase.idxInGroup + 1)(tree, phase.prepareForBlock(tree)(ctx)) + + private def prepForIf(phase: MiniPhase): Transformer[If, Context] = + (tree, ctx) => contextTransformer(Tag.If)(phase.idxInGroup + 1)(tree, phase.prepareForIf(tree)(ctx)) + + private def prepForClosure(phase: MiniPhase): Transformer[Closure, Context] = + (tree, ctx) => contextTransformer(Tag.Closure)(phase.idxInGroup + 1)(tree, phase.prepareForClosure(tree)(ctx)) + + private def prepForMatch(phase: MiniPhase): Transformer[Match, Context] = + (tree, ctx) => contextTransformer(Tag.Match)(phase.idxInGroup + 1)(tree, phase.prepareForMatch(tree)(ctx)) + + private def prepForCaseDef(phase: MiniPhase): Transformer[CaseDef, Context] = + (tree, ctx) => contextTransformer(Tag.CaseDef)(phase.idxInGroup + 1)(tree, phase.prepareForCaseDef(tree)(ctx)) + + private def prepForReturn(phase: MiniPhase): Transformer[Return, Context] = + (tree, ctx) => contextTransformer(Tag.Return)(phase.idxInGroup + 1)(tree, phase.prepareForReturn(tree)(ctx)) + + private def prepForTry(phase: MiniPhase): Transformer[Try, Context] = + (tree, ctx) => contextTransformer(Tag.Try)(phase.idxInGroup + 1)(tree, phase.prepareForTry(tree)(ctx)) + + private def prepForSeqLiteral(phase: MiniPhase): Transformer[SeqLiteral, Context] = + (tree, ctx) => contextTransformer(Tag.SeqLiteral)(phase.idxInGroup + 1)(tree, phase.prepareForSeqLiteral(tree)(ctx)) + + private def prepForInlined(phase: MiniPhase): Transformer[Inlined, Context] = + (tree, ctx) => contextTransformer(Tag.Inlined)(phase.idxInGroup + 1)(tree, phase.prepareForInlined(tree)(ctx)) + + private def prepForTypeTree(phase: MiniPhase): Transformer[TypeTree, Context] = + (tree, ctx) => contextTransformer(Tag.TypeTree)(phase.idxInGroup + 1)(tree, phase.prepareForTypeTree(tree)(ctx)) + + private def prepForBind(phase: MiniPhase): Transformer[Bind, Context] = + (tree, ctx) => contextTransformer(Tag.Bind)(phase.idxInGroup + 1)(tree, phase.prepareForBind(tree)(ctx)) + + private def prepForAlternative(phase: MiniPhase): Transformer[Alternative, Context] = + (tree, ctx) => contextTransformer(Tag.Alternative)(phase.idxInGroup + 1)(tree, phase.prepareForAlternative(tree)(ctx)) + + private def prepForUnApply(phase: MiniPhase): Transformer[UnApply, Context] = + (tree, ctx) => contextTransformer(Tag.UnApply)(phase.idxInGroup + 1)(tree, phase.prepareForUnApply(tree)(ctx)) + + private def prepForValDef(phase: MiniPhase): Transformer[ValDef, Context] = + (tree, ctx) => contextTransformer(Tag.ValDef)(phase.idxInGroup + 1)(tree, phase.prepareForValDef(tree)(ctx)) + + private def prepForDefDef(phase: MiniPhase): Transformer[DefDef, Context] = + (tree, ctx) => contextTransformer(Tag.DefDef)(phase.idxInGroup + 1)(tree, phase.prepareForDefDef(tree)(ctx)) + + private def prepForTypeDef(phase: MiniPhase): Transformer[TypeDef, Context] = + (tree, ctx) => contextTransformer(Tag.TypeDef)(phase.idxInGroup + 1)(tree, phase.prepareForTypeDef(tree)(ctx)) + + private def prepForTemplate(phase: MiniPhase): Transformer[Template, Context] = + (tree, ctx) => contextTransformer(Tag.Template)(phase.idxInGroup + 1)(tree, phase.prepareForTemplate(tree)(ctx)) + + private def prepForPackageDef(phase: MiniPhase): Transformer[PackageDef, Context] = + (tree, ctx) => contextTransformer(Tag.PackageDef)(phase.idxInGroup + 1)(tree, phase.prepareForPackageDef(tree)(ctx)) + + private def prepForStats(phase: MiniPhase): Transformer[List[Tree], Context] = + (trees, ctx) => statsContextTransformer(phase.idxInGroup + 1)(trees, phase.prepareForStats(trees)(ctx)) + + private def prepForUnit(phase: MiniPhase): Transformer[Tree, Context] = + (tree, ctx) => unitContextTransformer(phase.idxInGroup + 1)(tree, phase.prepareForUnit(tree)(ctx)) + + private def prepForOther(phase: MiniPhase): Transformer[Tree, Context] = + (tree, ctx) => otherContextTransformer(phase.idxInGroup + 1)(tree, phase.prepareForOther(tree)(ctx)) + + private def transIdent(phase: MiniPhase): Transformer[Ident, Tree] = + (tree, ctx) => transformNode(phase.transformIdent(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transSelect(phase: MiniPhase): Transformer[Select, Tree] = + (tree, ctx) => transformNode(phase.transformSelect(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transThis(phase: MiniPhase): Transformer[This, Tree] = + (tree, ctx) => transformNode(phase.transformThis(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transSuper(phase: MiniPhase): Transformer[Super, Tree] = + (tree, ctx) => transformNode(phase.transformSuper(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transApply(phase: MiniPhase): Transformer[Apply, Tree] = + (tree, ctx) => transformNode(phase.transformApply(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transTypeApply(phase: MiniPhase): Transformer[TypeApply, Tree] = + (tree, ctx) => transformNode(phase.transformTypeApply(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transLiteral(phase: MiniPhase): Transformer[Literal, Tree] = + (tree, ctx) => transformNode(phase.transformLiteral(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transNew(phase: MiniPhase): Transformer[New, Tree] = + (tree, ctx) => transformNode(phase.transformNew(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transTyped(phase: MiniPhase): Transformer[Typed, Tree] = + (tree, ctx) => transformNode(phase.transformTyped(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transAssign(phase: MiniPhase): Transformer[Assign, Tree] = + (tree, ctx) => transformNode(phase.transformAssign(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transBlock(phase: MiniPhase): Transformer[Block, Tree] = + (tree, ctx) => transformNode(phase.transformBlock(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transIf(phase: MiniPhase): Transformer[If, Tree] = + (tree, ctx) => transformNode(phase.transformIf(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transClosure(phase: MiniPhase): Transformer[Closure, Tree] = + (tree, ctx) => transformNode(phase.transformClosure(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transMatch(phase: MiniPhase): Transformer[Match, Tree] = + (tree, ctx) => transformNode(phase.transformMatch(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transCaseDef(phase: MiniPhase): Transformer[CaseDef, Tree] = + (tree, ctx) => transformNode(phase.transformCaseDef(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transReturn(phase: MiniPhase): Transformer[Return, Tree] = + (tree, ctx) => transformNode(phase.transformReturn(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transTry(phase: MiniPhase): Transformer[Try, Tree] = + (tree, ctx) => transformNode(phase.transformTry(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transSeqLiteral(phase: MiniPhase): Transformer[SeqLiteral, Tree] = + (tree, ctx) => transformNode(phase.transformSeqLiteral(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transInlined(phase: MiniPhase): Transformer[Inlined, Tree] = + (tree, ctx) => transformNode(phase.transformInlined(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transTypeTree(phase: MiniPhase): Transformer[TypeTree, Tree] = + (tree, ctx) => transformNode(phase.transformTypeTree(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transBind(phase: MiniPhase): Transformer[Bind, Tree] = + (tree, ctx) => transformNode(phase.transformBind(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transAlternative(phase: MiniPhase): Transformer[Alternative, Tree] = + (tree, ctx) => transformNode(phase.transformAlternative(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transUnApply(phase: MiniPhase): Transformer[UnApply, Tree] = + (tree, ctx) => transformNode(phase.transformUnApply(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transValDef(phase: MiniPhase): Transformer[ValDef, Tree] = + (tree, ctx) => transformNode(phase.transformValDef(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transDefDef(phase: MiniPhase): Transformer[DefDef, Tree] = + (tree, ctx) => transformNode(phase.transformDefDef(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transTypeDef(phase: MiniPhase): Transformer[TypeDef, Tree] = + (tree, ctx) => transformNode(phase.transformTypeDef(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transTemplate(phase: MiniPhase): Transformer[Template, Tree] = + (tree, ctx) => transformNode(phase.transformTemplate(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transPackageDef(phase: MiniPhase): Transformer[PackageDef, Tree] = + (tree, ctx) => transformNode(phase.transformPackageDef(tree)(ctx), phase.idxInGroup + 1)(ctx) + + private def transStats(phase: MiniPhase): Transformer[List[Tree], List[Tree]] = + (trees, ctx) => statsNodeTransformer(phase.idxInGroup + 1)(phase.transformStats(trees)(ctx), ctx) + + private def transUnit(phase: MiniPhase): Transformer[Tree, Tree] = + (tree, ctx) => unitNodeTransformer(phase.idxInGroup + 1)(phase.transformUnit(tree)(ctx), ctx) + + private def transOther(phase: MiniPhase): Transformer[Tree, Tree] = + (tree, ctx) => otherNodeTransformer(phase.idxInGroup + 1)(phase.transformOther(tree)(ctx), ctx) +} \ No newline at end of file From f020558a8176f2738f46d6761acd8fa069078bdb Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 22 Oct 2017 22:11:31 +0200 Subject: [PATCH 03/12] Use SuperPhase instead of TreeTransformer SuperPhase is a simplified version of TreeTransformer - about half of the size - no need for separate TransformerInfo arguments - simpler wiring logic The simplifications are largely due to two changes - use of function values, where wiring is done by a sort of staging - prepare... operations return a Context instead of a TreeTranform --- .../backend/jvm/CollectEntryPoints.scala | 6 +- .../tools/backend/jvm/CollectSuperCalls.scala | 6 +- .../dotty/tools/backend/jvm/LabelDefs.scala | 6 +- compiler/src/dotty/tools/dotc/Compiler.scala | 1 - compiler/src/dotty/tools/dotc/Run.scala | 1 - compiler/src/dotty/tools/dotc/ast/Trees.scala | 4 + .../dotty/tools/dotc/core/Decorators.scala | 4 +- .../src/dotty/tools/dotc/core/Phases.scala | 19 +- .../dotc/transform/ArrayConstructors.scala | 6 +- .../dotc/transform/AugmentScala2Traits.scala | 14 +- .../tools/dotc/transform/ByNameClosures.scala | 5 +- .../tools/dotc/transform/CapturedVars.scala | 202 +++++++-------- .../tools/dotc/transform/CheckReentrant.scala | 6 +- .../tools/dotc/transform/CheckStatic.scala | 8 +- .../dotty/tools/dotc/transform/ClassOf.scala | 6 +- .../dotc/transform/CollectEntryPoints.scala | 9 +- .../tools/dotc/transform/Constructors.scala | 16 +- .../tools/dotc/transform/CrossCastAnd.scala | 6 +- .../DropEmptyCompanions.scala.disabled | 8 +- .../tools/dotc/transform/DropInlined.scala | 6 +- .../tools/dotc/transform/ElimByName.scala | 12 +- .../dotc/transform/ElimErasedValueType.scala | 20 +- .../dotc/transform/ElimJavaPackages.scala | 6 +- .../dotc/transform/ElimOuterSelect.scala | 6 +- .../tools/dotc/transform/ElimRepeated.scala | 20 +- .../tools/dotc/transform/ElimStaticThis.scala | 8 +- .../dotty/tools/dotc/transform/Erasure.scala | 2 +- .../tools/dotc/transform/ExpandPrivate.scala | 19 +- .../tools/dotc/transform/ExpandSAMs.scala | 8 +- .../tools/dotc/transform/ExplicitOuter.scala | 10 +- .../tools/dotc/transform/ExplicitSelf.scala | 8 +- .../dotc/transform/ExtensionMethods.scala | 16 +- .../tools/dotc/transform/FirstTransform.scala | 44 ++-- .../dotty/tools/dotc/transform/Flatten.scala | 36 ++- .../transform/FunctionXXLForwarders.scala | 6 +- .../dotc/transform/FunctionalInterfaces.scala | 6 +- .../dotty/tools/dotc/transform/GetClass.scala | 6 +- .../dotty/tools/dotc/transform/Getters.scala | 8 +- .../tools/dotc/transform/HoistSuperArgs.scala | 10 +- .../dotc/transform/InterceptedMethods.scala | 13 +- .../transform/IsInstanceOfEvaluator.scala | 6 +- .../tools/dotc/transform/LambdaLift.scala | 240 +++++++++--------- .../dotty/tools/dotc/transform/LazyVals.scala | 14 +- .../dotty/tools/dotc/transform/LiftTry.scala | 71 +++--- .../dotc/transform/LinkScala2Impls.scala | 119 +++++---- .../dotc/transform/Literalize.scala.disabled | 14 +- .../dotty/tools/dotc/transform/Memoize.scala | 18 +- .../dotty/tools/dotc/transform/Mixin.scala | 16 +- .../dotty/tools/dotc/transform/MixinOps.scala | 8 +- .../tools/dotc/transform/MoveStatics.scala | 6 +- .../dotc/transform/NonLocalReturns.scala | 8 +- .../tools/dotc/transform/NormalizeFlags.scala | 4 +- .../dotc/transform/ParamForwarding.scala | 8 +- .../tools/dotc/transform/PatternMatcher.scala | 10 +- .../dotc/transform/PatternMatcherOld.scala | 6 +- .../tools/dotc/transform/PhantomArgLift.scala | 6 +- .../tools/dotc/transform/PostTyper.scala | 11 +- .../dotc/transform/PrimitiveForwarders.scala | 8 +- .../transform/PrivateToStatic.scala.disabled | 12 +- .../tools/dotc/transform/RenameLifted.scala | 4 +- .../tools/dotc/transform/ResolveSuper.scala | 12 +- .../tools/dotc/transform/RestoreScopes.scala | 11 +- .../tools/dotc/transform/SelectStatic.scala | 12 +- .../tools/dotc/transform/SeqLiterals.scala | 6 +- .../dotc/transform/ShortcutImplicits.scala | 208 +++++++-------- .../dotty/tools/dotc/transform/Splitter.scala | 10 +- .../tools/dotc/transform/SuperAccessors.scala | 14 +- .../tools/dotc/transform/SuperPhase.scala | 43 ++-- .../dotc/transform/SyntheticMethods.scala | 6 +- .../dotty/tools/dotc/transform/TailRec.scala | 10 +- .../dotc/transform/TransformByNameApply.scala | 8 +- .../dotc/transform/TransformWildcards.scala | 6 +- .../tools/dotc/transform/TreeChecker.scala | 4 +- .../dotc/transform/TryCatchPatterns.scala | 8 +- .../dotc/transform/VCElideAllocations.scala | 6 +- .../dotc/transform/VCInlineMethods.scala | 10 +- .../dotc/transform/localopt/Simplify.scala | 8 +- .../dotty/tools/dotc/typer/RefChecks.scala | 135 +++++----- .../CreateCompanionObjectsTest.scala | 1 - .../transform/PostTyperTransformerTest.scala | 1 - .../dotc/transform/TreeTransformerTest.scala | 77 ++---- .../dottydoc/core/DocImplicitsPhase.scala | 6 +- .../dotty/tools/dottydoc/core/transform.scala | 2 +- 83 files changed, 882 insertions(+), 914 deletions(-) diff --git a/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala b/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala index bd3a1894c2cc..5a02abc6c3e0 100644 --- a/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala +++ b/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala @@ -3,7 +3,7 @@ package dotty.tools.backend.jvm import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Types -import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, TreeTransform, MiniPhase, MiniPhaseTransform} +import dotty.tools.dotc.transform.SuperPhase._ import dotty.tools.dotc.ast.tpd import dotty.tools.dotc import dotty.tools.dotc.backend.jvm.DottyPrimitives @@ -35,10 +35,10 @@ import StdNames.nme /** * Created by dark on 26/11/14. */ -class CollectEntryPoints extends MiniPhaseTransform { +class CollectEntryPoints extends MiniPhase { def phaseName: String = "Collect entry points" - override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context): tpd.Tree = { if ((tree.symbol ne NoSymbol) && CollectEntryPoints.isJavaEntryPoint(tree.symbol)) { ctx.genBCodePhase.asInstanceOf[GenBCode].registerEntryPoint(tree.symbol) } diff --git a/compiler/src/dotty/tools/backend/jvm/CollectSuperCalls.scala b/compiler/src/dotty/tools/backend/jvm/CollectSuperCalls.scala index 8285bfe4b5e9..ef5ac908c4e0 100644 --- a/compiler/src/dotty/tools/backend/jvm/CollectSuperCalls.scala +++ b/compiler/src/dotty/tools/backend/jvm/CollectSuperCalls.scala @@ -5,7 +5,7 @@ import dotty.tools.dotc.ast.Trees._ import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Symbols._ import dotty.tools.dotc.core.Flags.Trait -import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, TransformerInfo} +import dotty.tools.dotc.transform.SuperPhase.MiniPhase /** Collect all super calls to trait members. * @@ -17,12 +17,12 @@ import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, Transforme * 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 { +class CollectSuperCalls extends MiniPhase { import tpd._ def phaseName: String = "collectSuperCalls" - override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformSelect(tree: Select)(implicit ctx: Context): Tree = { tree.qualifier match { case sup: Super => if (tree.symbol.owner.is(Trait)) diff --git a/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala b/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala index eabe1d3b0c3b..6be8d8e6ca4d 100644 --- a/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala +++ b/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala @@ -4,7 +4,7 @@ import dotty.tools.dotc.ast.Trees.Thicket import dotty.tools.dotc.ast.{Trees, tpd} import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Types -import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, TreeTransform, MiniPhase, MiniPhaseTransform} +import dotty.tools.dotc.transform.SuperPhase._ import dotty.tools.dotc import dotty.tools.dotc.backend.jvm.DottyPrimitives import dotty.tools.dotc.core.Flags.FlagSet @@ -81,14 +81,14 @@ import StdNames.nme * * @author Dmitry Petrashko */ -class LabelDefs extends MiniPhaseTransform { +class LabelDefs extends MiniPhase { def phaseName: String = "labelDef" val queue = new ArrayBuffer[Tree]() val beingAppended = new mutable.HashSet[Symbol]() var labelLevel = 0 - override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context): tpd.Tree = { if (tree.symbol is Flags.Label) tree else { collectLabelDefs.clear diff --git a/compiler/src/dotty/tools/dotc/Compiler.scala b/compiler/src/dotty/tools/dotc/Compiler.scala index f80e01a00d91..09e0741c7524 100644 --- a/compiler/src/dotty/tools/dotc/Compiler.scala +++ b/compiler/src/dotty/tools/dotc/Compiler.scala @@ -12,7 +12,6 @@ import reporting.{Reporter, ConsoleReporter} import Phases.Phase import transform._ import util.FreshNameCreator -import transform.TreeTransforms.{TreeTransform, TreeTransformer} import core.DenotTransformers.DenotTransformer import core.Denotations.SingleDenotation diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala index 28b74b1b38c6..d049c471de96 100644 --- a/compiler/src/dotty/tools/dotc/Run.scala +++ b/compiler/src/dotty/tools/dotc/Run.scala @@ -10,7 +10,6 @@ import Types._ import Scopes._ import typer.{FrontEnd, Typer, ImportInfo, RefChecks} import Decorators._ -import dotty.tools.dotc.transform.TreeTransforms.TreeTransformer import io.PlainFile import scala.io.Codec import util._ diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 1ab5c5bb1765..c1ba5bc666c5 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -63,6 +63,8 @@ object Trees { final val Annotated = 38 final val Thicket = 39 + final val NumTypedTreeTags = 40 + final val TypedSplice = 40 final val ModuleDef = 41 final val ParsedTry = 42 @@ -83,6 +85,8 @@ object Trees { final val GenAlias = 47 final val ContextBounds = 48 final val PatDef = 49 + + final val NumTags = 50 } // Note: it would be more logical to make Untyped = Nothing. diff --git a/compiler/src/dotty/tools/dotc/core/Decorators.scala b/compiler/src/dotty/tools/dotc/core/Decorators.scala index d721f97b44f5..b4dda6d4d880 100644 --- a/compiler/src/dotty/tools/dotc/core/Decorators.scala +++ b/compiler/src/dotty/tools/dotc/core/Decorators.scala @@ -6,7 +6,7 @@ import Symbols._ import Contexts._, Names._, Phases._, printing.Texts._, printing.Printer, printing.Showable import util.Positions.Position, util.SourcePosition import collection.mutable.ListBuffer -import dotty.tools.dotc.transform.TreeTransforms._ +import dotty.tools.dotc.transform.SuperPhase import ast.tpd._ import scala.language.implicitConversions import printing.Formatting._ @@ -152,7 +152,7 @@ object Decorators { */ implicit class PhaseListDecorator(val names: List[String]) extends AnyVal { def containsPhase(phase: Phase): Boolean = phase match { - case phase: TreeTransformer => phase.miniPhases.exists(containsPhase) + case phase: SuperPhase => phase.miniPhases.exists(containsPhase) case _ => names exists { name => name == "all" || { diff --git a/compiler/src/dotty/tools/dotc/core/Phases.scala b/compiler/src/dotty/tools/dotc/core/Phases.scala index 10c7b7416325..757461ad526a 100644 --- a/compiler/src/dotty/tools/dotc/core/Phases.scala +++ b/compiler/src/dotty/tools/dotc/core/Phases.scala @@ -11,7 +11,7 @@ import Denotations._ import Decorators._ import config.Printers.config import scala.collection.mutable.{ListBuffer, ArrayBuffer} -import dotty.tools.dotc.transform.TreeTransforms.{TreeTransformer, MiniPhase, TreeTransform} +import dotty.tools.dotc.transform.SuperPhase._ import dotty.tools.dotc.transform._ import Periods._ import typer.{FrontEnd, RefChecks} @@ -111,12 +111,9 @@ object Phases { assert(false, s"Only tree transforms can be squashed, ${phase.phaseName} can not be squashed") } } - val block = new TreeTransformer { - override def phaseName: String = miniPhases.map(_.phaseName).mkString("TreeTransform:{", ", ", "}") - override def miniPhases: Array[MiniPhase] = filteredPhaseBlock.asInstanceOf[List[MiniPhase]].toArray - } + val superPhase = new SuperPhase(filteredPhaseBlock.asInstanceOf[List[MiniPhase]].toArray) prevPhases ++= filteredPhaseBlock.map(_.getClazz) - block + superPhase } else { // block of a single phase, no squashing val phase = filteredPhaseBlock.head prevPhases += phase.getClazz @@ -144,7 +141,7 @@ object Phases { val flatPhases = collection.mutable.ListBuffer[Phase]() phasess.foreach(p => p match { - case t: TreeTransformer => flatPhases ++= t.miniPhases + case p: SuperPhase => flatPhases ++= p.miniPhases case _ => flatPhases += p }) @@ -172,12 +169,12 @@ object Phases { while (i < phasess.length) { val phase = phasess(i) phase match { - case t: TreeTransformer => - val miniPhases = t.miniPhases + case p: SuperPhase => + val miniPhases = p.miniPhases miniPhases.foreach{ phase => checkRequirements(phase) phase.init(this, nextPhaseId)} - t.init(this, miniPhases.head.id, miniPhases.last.id) + p.init(this, miniPhases.head.id, miniPhases.last.id) case _ => phase.init(this, nextPhaseId) checkRequirements(phase) @@ -345,7 +342,7 @@ object Phases { final def sameParentsStartId = mySameParentsStartId // id of first phase where all symbols are guaranteed to have the same parents as in this phase - protected[Phases] def init(base: ContextBase, start: Int, end:Int): Unit = { + protected[Phases] def init(base: ContextBase, start: Int, end: Int): Unit = { if (start >= FirstPhaseId) assert(myPeriod == Periods.InvalidPeriod, s"phase $this has already been used once; cannot be reused") assert(start <= Periods.MaxPossiblePhaseId, s"Too many phases, Period bits overflow") diff --git a/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala b/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala index 74213d332925..93248439dbfa 100644 --- a/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala +++ b/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import core._ -import TreeTransforms._ +import SuperPhase._ import Contexts.Context import Flags._ import SymUtils._ @@ -29,12 +29,12 @@ import scala.collection.immutable.:: * It assummes that generic arrays have already been handled by typer(see Applications.convertNewGenericArray). * Additionally it optimizes calls to scala.Array.ofDim functions by replacing them with calls to newArray with specific dimensions */ -class ArrayConstructors extends MiniPhaseTransform { thisTransform => +class ArrayConstructors extends MiniPhase { import ast.tpd._ override def phaseName: String = "arrayConstructors" - override def transformApply(tree: tpd.Apply)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformApply(tree: tpd.Apply)(implicit ctx: Context): tpd.Tree = { def rewrite(elemType: Type, dims: List[Tree]) = tpd.newArray(elemType, tree.tpe, tree.pos, JavaSeqLiteral(dims, TypeTree(defn.IntClass.typeRef))) diff --git a/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala b/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala index c5226f756d63..7ea8bf666cda 100644 --- a/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala +++ b/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import core._ -import TreeTransforms._ +import SuperPhase._ import Contexts.Context import Flags._ import SymUtils._ @@ -28,7 +28,7 @@ import ast.Trees._ * Furthermore, it expands the names of all private getters and setters as well as super accessors in the trait and makes * them not-private. */ -class AugmentScala2Traits extends MiniPhaseTransform with IdentityDenotTransformer with FullParameterization { thisTransform => +class AugmentScala2Traits extends MiniPhase with IdentityDenotTransformer with FullParameterization { thisPhase => import ast.tpd._ override def changesMembers = true @@ -37,7 +37,7 @@ class AugmentScala2Traits extends MiniPhaseTransform with IdentityDenotTransform override def rewiredTarget(referenced: Symbol, derived: Symbol)(implicit ctx: Context) = NoSymbol - override def transformTemplate(impl: Template)(implicit ctx: Context, info: TransformerInfo) = { + override def transformTemplate(impl: Template)(implicit ctx: Context) = { val cls = impl.symbol.owner.asClass for (mixin <- cls.mixins) if (mixin.is(Scala2x)) @@ -49,7 +49,7 @@ class AugmentScala2Traits extends MiniPhaseTransform with IdentityDenotTransform if (mixin.implClass.is(Scala2x)) () // nothing to do, mixin was already augmented else { //println(i"creating new implclass for $mixin ${mixin.implClass}") - val ops = new MixinOps(cls, thisTransform) + val ops = new MixinOps(cls, thisPhase) import ops._ val implClass = ctx.newCompleteClassSymbol( @@ -57,7 +57,7 @@ class AugmentScala2Traits extends MiniPhaseTransform with IdentityDenotTransform name = mixin.name.implClassName, flags = Abstract | Scala2x | ImplClass, parents = defn.ObjectType :: Nil, - assocFile = mixin.assocFile).enteredAfter(thisTransform) + assocFile = mixin.assocFile).enteredAfter(thisPhase) def implMethod(meth: TermSymbol): Symbol = { val mold = @@ -91,11 +91,11 @@ class AugmentScala2Traits extends MiniPhaseTransform with IdentityDenotTransform } else if (!sym.is(Deferred) && !sym.setter.exists && !sym.info.resultType.isInstanceOf[ConstantType]) - traitSetter(sym.asTerm).enteredAfter(thisTransform) + traitSetter(sym.asTerm).enteredAfter(thisPhase) if ((sym.is(PrivateAccessor) && !sym.name.is(ExpandedName) && (sym.isGetter || sym.isSetter)) // strangely, Scala 2 fields are also methods that have Accessor set. || sym.isSuperAccessor) // scala2 superaccessors are pickled as private, but are compiled as public expanded - sym.ensureNotPrivate.installAfter(thisTransform) + sym.ensureNotPrivate.installAfter(thisPhase) } ctx.log(i"Scala2x trait decls of $mixin = ${mixin.info.decls.toList.map(_.showDcl)}%\n %") ctx.log(i"Scala2x impl decls of $mixin = ${implClass.info.decls.toList.map(_.showDcl)}%\n %") diff --git a/compiler/src/dotty/tools/dotc/transform/ByNameClosures.scala b/compiler/src/dotty/tools/dotc/transform/ByNameClosures.scala index d8499369d051..c548fce4f9d1 100644 --- a/compiler/src/dotty/tools/dotc/transform/ByNameClosures.scala +++ b/compiler/src/dotty/tools/dotc/transform/ByNameClosures.scala @@ -1,7 +1,6 @@ package dotty.tools.dotc package transform -import TreeTransforms._ import core._ import Symbols._ import SymDenotations._ @@ -24,7 +23,7 @@ import core.StdNames.nme * * is a synthetic method defined in Definitions. Erasure will later strip the wrappers. */ -class ByNameClosures extends TransformByNameApply with IdentityDenotTransformer { thisTransformer => +class ByNameClosures extends TransformByNameApply with IdentityDenotTransformer { thisPhase => import ast.tpd._ override def phaseName: String = "byNameClosures" @@ -32,6 +31,6 @@ class ByNameClosures extends TransformByNameApply with IdentityDenotTransformer override def mkByNameClosure(arg: Tree, argType: Type)(implicit ctx: Context): Tree = { val meth = ctx.newSymbol( ctx.owner, nme.ANON_FUN, Synthetic | Method, MethodType(Nil, Nil, argType)) - Closure(meth, _ => arg.changeOwnerAfter(ctx.owner, meth, thisTransformer)) + Closure(meth, _ => arg.changeOwnerAfter(ctx.owner, meth, thisPhase)) } } diff --git a/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala b/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala index f0e69330adab..aae00f0e51ce 100644 --- a/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala +++ b/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import TreeTransforms._ +import SuperPhase._ import core.DenotTransformers._ import core.Symbols._ import core.Contexts._ @@ -15,18 +15,24 @@ import core.NameOps._ import core.NameKinds.TempResultName import ast.Trees._ import SymUtils._ +import util.Property import collection.{ mutable, immutable } import collection.mutable.{ LinkedHashMap, LinkedHashSet, TreeSet } +object CapturedVars { + val Captured = new Property.Key[collection.Set[Symbol]] + def captured(implicit ctx: Context) = ctx.property(Captured).getOrElse(Set.empty) +} + /** This phase translates variables that are captured in closures to * heap-allocated refs. */ -class CapturedVars extends MiniPhase with IdentityDenotTransformer { thisTransform => +class CapturedVars extends MiniPhase with IdentityDenotTransformer { thisPhase => + import CapturedVars._ import ast.tpd._ /** the following two members override abstract members in Transform */ val phaseName: String = "capturedVars" - val treeTransform = new Transform(Set()) private class RefInfo(implicit ctx: Context) { /** The classes for which a Ref type exists. */ @@ -43,114 +49,110 @@ class CapturedVars extends MiniPhase with IdentityDenotTransformer { thisTransfo refClassKeys.flatMap(k => Set(refClass(k), volatileRefClass(k))) } - class Transform(captured: collection.Set[Symbol]) extends TreeTransform { - def phase = thisTransform - - private[this] var myRefInfo: RefInfo = null - private def refInfo(implicit ctx: Context) = { - if (myRefInfo == null) myRefInfo = new RefInfo() - myRefInfo - } + private[this] var myRefInfo: RefInfo = null + private def refInfo(implicit ctx: Context) = { + if (myRefInfo == null) myRefInfo = new RefInfo() + myRefInfo + } - private class CollectCaptured extends TreeTraverser { - private val captured = mutable.HashSet[Symbol]() - def traverse(tree: Tree)(implicit ctx: Context) = tree match { - case id: Ident => - val sym = id.symbol - if (sym.is(Mutable, butNot = Method) && sym.owner.isTerm) { - val enclMeth = ctx.owner.enclosingMethod - if (sym.enclosingMethod != enclMeth) { - ctx.log(i"capturing $sym in ${sym.enclosingMethod}, referenced from $enclMeth") - captured += sym - } + private class CollectCaptured extends TreeTraverser { + private val captured = mutable.HashSet[Symbol]() + def traverse(tree: Tree)(implicit ctx: Context) = tree match { + case id: Ident => + val sym = id.symbol + if (sym.is(Mutable, butNot = Method) && sym.owner.isTerm) { + val enclMeth = ctx.owner.enclosingMethod + if (sym.enclosingMethod != enclMeth) { + ctx.log(i"capturing $sym in ${sym.enclosingMethod}, referenced from $enclMeth") + captured += sym } - case _ => - traverseChildren(tree) - } - def runOver(tree: Tree)(implicit ctx: Context): collection.Set[Symbol] = { - traverse(tree) - captured - } + } + case _ => + traverseChildren(tree) } - - override def prepareForUnit(tree: Tree)(implicit ctx: Context) = { - val captured = (new CollectCaptured) - .runOver(ctx.compilationUnit.tpdTree)(ctx.withPhase(thisTransform)) - new Transform(captured) + def runOver(tree: Tree)(implicit ctx: Context): collection.Set[Symbol] = { + traverse(tree) + captured } + } - /** The {Volatile|}{Int|Double|...|Object}Ref class corresponding to the class `cls`, - * depending on whether the reference should be @volatile - */ - def refClass(cls: Symbol, isVolatile: Boolean)(implicit ctx: Context): Symbol = { - val refMap = if (isVolatile) refInfo.volatileRefClass else refInfo.refClass - if (cls.isClass) { - refMap.getOrElse(cls, refMap(defn.ObjectClass)) - } - else refMap(defn.ObjectClass) - } + override def prepareForUnit(tree: Tree)(implicit ctx: Context) = { + val captured = (new CollectCaptured) + .runOver(ctx.compilationUnit.tpdTree)(ctx.withPhase(thisPhase)) + ctx.fresh.setProperty(Captured, captured) + } - override def prepareForValDef(vdef: ValDef)(implicit ctx: Context) = { - val sym = vdef.symbol(ctx.withPhase(thisTransform)) - if (captured contains sym) { - val newd = sym.denot(ctx.withPhase(thisTransform)).copySymDenotation( - info = refClass(sym.info.classSymbol, sym.hasAnnotation(defn.VolatileAnnot)).typeRef, - initFlags = sym.flags &~ Mutable) - newd.removeAnnotation(defn.VolatileAnnot) - newd.installAfter(thisTransform) - } - this + /** The {Volatile|}{Int|Double|...|Object}Ref class corresponding to the class `cls`, + * depending on whether the reference should be @volatile + */ + def refClass(cls: Symbol, isVolatile: Boolean)(implicit ctx: Context): Symbol = { + val refMap = if (isVolatile) refInfo.volatileRefClass else refInfo.refClass + if (cls.isClass) { + refMap.getOrElse(cls, refMap(defn.ObjectClass)) } + else refMap(defn.ObjectClass) + } - override def transformValDef(vdef: ValDef)(implicit ctx: Context, info: TransformerInfo): Tree = { - val vble = vdef.symbol - if (captured contains vble) { - def boxMethod(name: TermName): Tree = - ref(vble.info.classSymbol.companionModule.info.member(name).symbol) - cpy.ValDef(vdef)( - rhs = vdef.rhs match { - case EmptyTree => boxMethod(nme.zero).appliedToNone.withPos(vdef.pos) - case arg => boxMethod(nme.create).appliedTo(arg) - }, - tpt = TypeTree(vble.info).withPos(vdef.tpt.pos)) - } else vdef + override def prepareForValDef(vdef: ValDef)(implicit ctx: Context) = { + val sym = vdef.symbol(ctx.withPhase(thisPhase)) + if (captured contains sym) { + val newd = sym.denot(ctx.withPhase(thisPhase)).copySymDenotation( + info = refClass(sym.info.classSymbol, sym.hasAnnotation(defn.VolatileAnnot)).typeRef, + initFlags = sym.flags &~ Mutable) + newd.removeAnnotation(defn.VolatileAnnot) + newd.installAfter(thisPhase) } + ctx + } - override def transformIdent(id: Ident)(implicit ctx: Context, info: TransformerInfo): Tree = { - val vble = id.symbol - if (captured(vble)) - id.select(nme.elem).ensureConforms(vble.denot(ctx.withPhase(thisTransform)).info) - else id - } + override def transformValDef(vdef: ValDef)(implicit ctx: Context): Tree = { + val vble = vdef.symbol + if (captured.contains(vble)) { + def boxMethod(name: TermName): Tree = + ref(vble.info.classSymbol.companionModule.info.member(name).symbol) + cpy.ValDef(vdef)( + rhs = vdef.rhs match { + case EmptyTree => boxMethod(nme.zero).appliedToNone.withPos(vdef.pos) + case arg => boxMethod(nme.create).appliedTo(arg) + }, + tpt = TypeTree(vble.info).withPos(vdef.tpt.pos)) + } else vdef + } + + override def transformIdent(id: Ident)(implicit ctx: Context): Tree = { + val vble = id.symbol + if (captured.contains(vble)) + id.select(nme.elem).ensureConforms(vble.denot(ctx.withPhase(thisPhase)).info) + else id + } - /** If assignment is to a boxed ref type, e.g. - * - * intRef.elem = expr - * - * rewrite using a temporary var to - * - * val ev$n = expr - * intRef.elem = ev$n - * - * That way, we avoid the problem that `expr` might contain a `try` that would - * run on a non-empty stack (which is illegal under JVM rules). Note that LiftTry - * has already run before, so such `try`s would not be eliminated. - * - * Also: If the ref type lhs is followed by a cast (can be an artifact of nested translation), - * drop the cast. - */ - override def transformAssign(tree: Assign)(implicit ctx: Context, info: TransformerInfo): Tree = { - def recur(lhs: Tree): Tree = lhs match { - case TypeApply(Select(qual, nme.asInstanceOf_), _) => - val Select(_, nme.elem) = qual - recur(qual) - case Select(_, nme.elem) if refInfo.boxedRefClasses.contains(lhs.symbol.maybeOwner) => - val tempDef = transformFollowing(SyntheticValDef(TempResultName.fresh(), tree.rhs)) - transformFollowing(Block(tempDef :: Nil, cpy.Assign(tree)(lhs, ref(tempDef.symbol)))) - case _ => - tree - } - recur(tree.lhs) + /** If assignment is to a boxed ref type, e.g. + * + * intRef.elem = expr + * + * rewrite using a temporary var to + * + * val ev$n = expr + * intRef.elem = ev$n + * + * That way, we avoid the problem that `expr` might contain a `try` that would + * run on a non-empty stack (which is illegal under JVM rules). Note that LiftTry + * has already run before, so such `try`s would not be eliminated. + * + * Also: If the ref type lhs is followed by a cast (can be an artifact of nested translation), + * drop the cast. + */ + override def transformAssign(tree: Assign)(implicit ctx: Context): Tree = { + def recur(lhs: Tree): Tree = lhs match { + case TypeApply(Select(qual, nme.asInstanceOf_), _) => + val Select(_, nme.elem) = qual + recur(qual) + case Select(_, nme.elem) if refInfo.boxedRefClasses.contains(lhs.symbol.maybeOwner) => + val tempDef = transformFollowing(SyntheticValDef(TempResultName.fresh(), tree.rhs)) + transformFollowing(Block(tempDef :: Nil, cpy.Assign(tree)(lhs, ref(tempDef.symbol)))) + case _ => + tree } + recur(tree.lhs) } } diff --git a/compiler/src/dotty/tools/dotc/transform/CheckReentrant.scala b/compiler/src/dotty/tools/dotc/transform/CheckReentrant.scala index 92228b9a8463..8727e94911b2 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckReentrant.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckReentrant.scala @@ -3,7 +3,7 @@ package transform import core._ import Names._ -import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, MiniPhaseTransform, TreeTransformer} +import dotty.tools.dotc.transform.SuperPhase._ import ast.Trees._ import Flags._ import Types._ @@ -40,7 +40,7 @@ import StdNames._ * in an immutable way anyway. To do better, it would be helpful to have a type * for immutable array. */ -class CheckReentrant extends MiniPhaseTransform { thisTransformer => +class CheckReentrant extends MiniPhase { import ast.tpd._ override def phaseName = "checkReentrant" @@ -87,7 +87,7 @@ class CheckReentrant extends MiniPhaseTransform { thisTransformer => } } - override def transformTemplate(tree: Template)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformTemplate(tree: Template)(implicit ctx: Context): Tree = { if (ctx.settings.YcheckReentrant.value && tree.symbol.owner.isStaticOwner) addVars(tree.symbol.owner.asClass) tree diff --git a/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala b/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala index b1dc3b578f41..6bd73ea3ecb2 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala @@ -5,7 +5,7 @@ import core._ import Names._ import StdNames.nme import Types._ -import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, MiniPhaseTransform, TreeTransformer} +import dotty.tools.dotc.transform.SuperPhase._ import ast.Trees._ import Flags._ import Contexts.Context @@ -34,12 +34,12 @@ import TypeUtils._ * Java8 supports those, but not vars, and JavaScript does not have interfaces at all. * 6. `@static` Lazy vals are currently unsupported. */ -class CheckStatic extends MiniPhaseTransform { thisTransformer => +class CheckStatic extends MiniPhase { import ast.tpd._ override def phaseName = "checkStatic" - override def transformTemplate(tree: tpd.Template)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformTemplate(tree: tpd.Template)(implicit ctx: Context): tpd.Tree = { val defns = tree.body.collect{case t: ValOrDefDef => t} var hadNonStaticField = false for(defn <- defns) { @@ -72,7 +72,7 @@ class CheckStatic extends MiniPhaseTransform { thisTransformer => tree } - override def transformSelect(tree: tpd.Select)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformSelect(tree: tpd.Select)(implicit ctx: Context): tpd.Tree = { if (tree.symbol.hasAnnotation(defn.ScalaStaticAnnot)) { val symbolWhitelist = tree.symbol.ownersIterator.flatMap(x => if (x.is(Flags.Module)) List(x, x.companionModule) else List(x)).toSet def isSafeQual(t: Tree): Boolean = { // follow the desugared paths created by typer diff --git a/compiler/src/dotty/tools/dotc/transform/ClassOf.scala b/compiler/src/dotty/tools/dotc/transform/ClassOf.scala index e7b6977c7b5b..766c9495f312 100644 --- a/compiler/src/dotty/tools/dotc/transform/ClassOf.scala +++ b/compiler/src/dotty/tools/dotc/transform/ClassOf.scala @@ -7,7 +7,7 @@ import core.Contexts.Context import core.StdNames.nme import core.Symbols.{defn,TermSymbol} import core.TypeErasure -import TreeTransforms.{MiniPhaseTransform, TransformerInfo, TreeTransform} +import SuperPhase._ /** Rewrite `classOf` calls as follow: * @@ -16,12 +16,12 @@ import TreeTransforms.{MiniPhaseTransform, TransformerInfo, TreeTransform} * For every non-primitive class D: * classOf[D] -> Literal(Constant(erasure(D))) */ -class ClassOf extends MiniPhaseTransform { +class ClassOf extends MiniPhase { import tpd._ override def phaseName: String = "classOf" - override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformTypeApply(tree: TypeApply)(implicit ctx: Context): Tree = if (tree.symbol eq defn.Predef_classOf) { val targ = tree.args.head.tpe clsOf(targ).ensureConforms(tree.tpe).withPos(tree.pos) diff --git a/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala index 893e79ce0282..2b835c0444d6 100644 --- a/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala +++ b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala @@ -1,6 +1,5 @@ package dotty.tools.dotc.transform -import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, TreeTransform, TreeTransformer, MiniPhaseTransform} import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Contexts.Context import scala.collection.mutable.ListBuffer @@ -9,7 +8,7 @@ import dotty.tools.dotc.core.Symbols.NoSymbol import scala.annotation.tailrec import dotty.tools.dotc.core._ import Symbols._ -import dotty.tools.dotc.transform.TreeTransforms.{NXTransformations, TransformerInfo, TreeTransform, TreeTransformer} +import dotty.tools.dotc.transform.SuperPhase._ import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Contexts.Context import scala.collection.mutable @@ -22,13 +21,13 @@ import StdNames._ import dotty.tools.dotc.util.Positions.Position import dotty.tools.dotc.config.JavaPlatform -class CollectEntryPoints extends MiniPhaseTransform { +class CollectEntryPoints extends MiniPhase { /** perform context-dependant initialization */ override def prepareForUnit(tree: tpd.Tree)(implicit ctx: Context) = { entryPoints = collection.immutable.TreeSet.empty[Symbol](new SymbolOrdering()) assert(ctx.platform.isInstanceOf[JavaPlatform], "Java platform specific phase") - this + ctx } private[this] var entryPoints: Set[Symbol] = _ @@ -36,7 +35,7 @@ class CollectEntryPoints extends MiniPhaseTransform { def getEntryPoints = entryPoints.toList override def phaseName: String = "collectEntryPoints" - override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context): tpd.Tree = { if (tree.symbol.owner.isClass && isJavaEntryPoint(tree.symbol)) { // collecting symbols for entry points here (as opposed to GenBCode where they are used) // has the advantage of saving an additional pass over all ClassDefs. diff --git a/compiler/src/dotty/tools/dotc/transform/Constructors.scala b/compiler/src/dotty/tools/dotc/transform/Constructors.scala index 969f4f548a07..ad08bbf32646 100644 --- a/compiler/src/dotty/tools/dotc/transform/Constructors.scala +++ b/compiler/src/dotty/tools/dotc/transform/Constructors.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import core._ -import TreeTransforms._ +import SuperPhase._ import dotty.tools.dotc.ast.tpd._ import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.StdNames._ @@ -26,7 +26,7 @@ import collection.mutable * - also moves private fields that are accessed only from constructor * into the constructor if possible. */ -class Constructors extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform => +class Constructors extends MiniPhase with IdentityDenotTransformer { thisPhase => import tpd._ override def phaseName: String = "constructors" @@ -78,17 +78,17 @@ class Constructors extends MiniPhaseTransform with IdentityDenotTransformer { th } } - override def transformIdent(tree: tpd.Ident)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformIdent(tree: tpd.Ident)(implicit ctx: Context): tpd.Tree = { markUsedPrivateSymbols(tree) tree } - override def transformSelect(tree: tpd.Select)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformSelect(tree: tpd.Select)(implicit ctx: Context): tpd.Tree = { markUsedPrivateSymbols(tree) tree } - override def transformValDef(tree: tpd.ValDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformValDef(tree: tpd.ValDef)(implicit ctx: Context): tpd.Tree = { if (mightBeDropped(tree.symbol)) seenPrivateVals += tree.symbol tree } @@ -121,7 +121,7 @@ class Constructors extends MiniPhaseTransform with IdentityDenotTransformer { th private final val MutableParamAccessor = allOf(Mutable, ParamAccessor) - override def transformTemplate(tree: Template)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformTemplate(tree: Template)(implicit ctx: Context): Tree = { val cls = ctx.owner.asClass val constr @ DefDef(nme.CONSTRUCTOR, Nil, vparams :: Nil, _, EmptyTree) = tree.constr @@ -158,7 +158,7 @@ class Constructors extends MiniPhaseTransform with IdentityDenotTransformer { th } def apply(tree: Tree, prevOwner: Symbol)(implicit ctx: Context): Tree = { - transform(tree).changeOwnerAfter(prevOwner, constr.symbol, thisTransform) + transform(tree).changeOwnerAfter(prevOwner, constr.symbol, thisPhase) } } @@ -200,7 +200,7 @@ class Constructors extends MiniPhaseTransform with IdentityDenotTransformer { th dropped += sym sym.copySymDenotation( initFlags = sym.flags &~ Private, - owner = constr.symbol).installAfter(thisTransform) + owner = constr.symbol).installAfter(thisPhase) constrStats += intoConstr(stat, sym) } case DefDef(nme.CONSTRUCTOR, _, ((outerParam @ ValDef(nme.OUTER, _, _)) :: _) :: Nil, _, _) => diff --git a/compiler/src/dotty/tools/dotc/transform/CrossCastAnd.scala b/compiler/src/dotty/tools/dotc/transform/CrossCastAnd.scala index 838286e81181..05d5bf3c940f 100644 --- a/compiler/src/dotty/tools/dotc/transform/CrossCastAnd.scala +++ b/compiler/src/dotty/tools/dotc/transform/CrossCastAnd.scala @@ -4,7 +4,7 @@ import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Flags import dotty.tools.dotc.core.Types.{NoType, Type, AndType} -import dotty.tools.dotc.transform.TreeTransforms._ +import dotty.tools.dotc.transform.SuperPhase._ import tpd._ import scala.collection.mutable.ListBuffer @@ -15,11 +15,11 @@ import scala.collection.mutable.ListBuffer * AndTypes are performed from the first component of AndType. * This is needed for correctness of erasure. See `tests/run/PrivateAnd.scala` */ -class CrossCastAnd extends MiniPhaseTransform { thisTransform => +class CrossCastAnd extends MiniPhase { override def phaseName: String = "crossCast" - override def transformSelect(tree: tpd.Select)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformSelect(tree: tpd.Select)(implicit ctx: Context): tpd.Tree = { lazy val qtype = tree.qualifier.tpe.widen val sym = tree.symbol diff --git a/compiler/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled b/compiler/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled index 7b37c5881dc9..68d777db1612 100644 --- a/compiler/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled +++ b/compiler/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled @@ -12,8 +12,8 @@ import ast.Trees._ import collection.mutable import Decorators._ import NameOps._ -import TreeTransforms.MiniPhaseTransform -import dotty.tools.dotc.transform.TreeTransforms.TransformerInfo +import SuperPhase.MiniPhase +import dotty.tools.dotc.transform.SuperPhase.TransformerInfo /** Remove companion objects that are empty * Lots of constraints here: @@ -28,12 +28,12 @@ import dotty.tools.dotc.transform.TreeTransforms.TransformerInfo * level, so we know that all objects moved by LambdaLift and Flatten have arrived * at their destination. */ -class DropEmptyCompanions extends MiniPhaseTransform { thisTransform => +class DropEmptyCompanions extends MiniPhase { thisTransform => import ast.tpd._ override def phaseName = "dropEmptyCompanions" override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[Flatten]) - override def transformPackageDef(pdef: PackageDef)(implicit ctx: Context, info: TransformerInfo) = { + override def transformPackageDef(pdef: PackageDef)(implicit ctx: Context) = { /** Is `tree` an empty companion object? */ def isEmptyCompanion(tree: Tree) = tree match { diff --git a/compiler/src/dotty/tools/dotc/transform/DropInlined.scala b/compiler/src/dotty/tools/dotc/transform/DropInlined.scala index 775663b5c261..4d9fbc92ca03 100644 --- a/compiler/src/dotty/tools/dotc/transform/DropInlined.scala +++ b/compiler/src/dotty/tools/dotc/transform/DropInlined.scala @@ -3,13 +3,13 @@ package transform import typer.Inliner import core.Contexts.Context -import TreeTransforms.{MiniPhaseTransform, TransformerInfo} +import SuperPhase.MiniPhase /** Drop Inlined nodes */ -class DropInlined extends MiniPhaseTransform { +class DropInlined extends MiniPhase { import ast.tpd._ override def phaseName = "dropInlined" - override def transformInlined(tree: Inlined)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformInlined(tree: Inlined)(implicit ctx: Context): Tree = Inliner.dropInlined(tree) } diff --git a/compiler/src/dotty/tools/dotc/transform/ElimByName.scala b/compiler/src/dotty/tools/dotc/transform/ElimByName.scala index 4202b9f91bb4..c98b5fca0c30 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimByName.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimByName.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import TreeTransforms._ +import SuperPhase._ import core._ import DenotTransformers.InfoTransformer import Symbols._ @@ -37,7 +37,7 @@ import ast.Trees._ * Option 2: Merge ElimByName with erasure, or have it run immediately before. This has not been * tried yet. */ -class ElimByName extends TransformByNameApply with InfoTransformer { thisTransformer => +class ElimByName extends TransformByNameApply with InfoTransformer { import ast.tpd._ override def phaseName: String = "elimByName" @@ -51,13 +51,13 @@ class ElimByName extends TransformByNameApply with InfoTransformer { thisTransfo ctx.atPhase(next) { implicit ctx => tree.select(defn.Function0_apply).appliedToNone } else tree - override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformIdent(tree: Ident)(implicit ctx: Context): Tree = applyIfFunction(tree, tree) - override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformSelect(tree: Select)(implicit ctx: Context): Tree = applyIfFunction(tree, tree) - override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree = tree match { + override def transformTypeApply(tree: TypeApply)(implicit ctx: Context): Tree = tree match { case TypeApply(Select(_, nme.asInstanceOf_), arg :: Nil) => // tree might be of form e.asInstanceOf[x.type] where x becomes a function. // See pos/t296.scala @@ -65,7 +65,7 @@ class ElimByName extends TransformByNameApply with InfoTransformer { thisTransfo case _ => tree } - override def transformValDef(tree: ValDef)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformValDef(tree: ValDef)(implicit ctx: Context): Tree = ctx.atPhase(next) { implicit ctx => if (exprBecomesFunction(tree.symbol)) cpy.ValDef(tree)(tpt = tree.tpt.withType(tree.symbol.info)) diff --git a/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala b/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala index 913264081207..4c434827fb2c 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala @@ -3,7 +3,7 @@ package transform import ast.{Trees, tpd} import core._, core.Decorators._ -import TreeTransforms._, Phases.Phase +import SuperPhase._, Phases.Phase import Types._, Contexts._, Constants._, Names._, NameOps._, Flags._, DenotTransformers._ import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Scopes._, Denotations._ import TypeErasure.ErasedValueType, ValueClasses._ @@ -15,7 +15,7 @@ import TypeErasure.ErasedValueType, ValueClasses._ * of methods that now have the same signature but were not considered matching * before erasure. */ -class ElimErasedValueType extends MiniPhaseTransform with InfoTransformer { +class ElimErasedValueType extends MiniPhase with InfoTransformer { import tpd._ @@ -57,7 +57,7 @@ class ElimErasedValueType extends MiniPhaseTransform with InfoTransformer { def transformTypeOfTree(tree: Tree)(implicit ctx: Context): Tree = tree.withType(elimEVT(tree.tpe)) - override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformApply(tree: Apply)(implicit ctx: Context): Tree = { val Apply(fun, args) = tree // The casts to and from ErasedValueType are no longer needed once ErasedValueType @@ -117,23 +117,23 @@ class ElimErasedValueType extends MiniPhaseTransform with InfoTransformer { } } - override def transformTypeDef(tree: TypeDef)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformTypeDef(tree: TypeDef)(implicit ctx: Context): Tree = { checkNoClashes(tree.symbol) tree } - override def transformInlined(tree: Inlined)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformInlined(tree: Inlined)(implicit ctx: Context): Tree = transformTypeOfTree(tree) // FIXME: transformIf and transformBlock won't be required anymore once #444 is fixed. - override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformIdent(tree: Ident)(implicit ctx: Context): Tree = transformTypeOfTree(tree) - override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformSelect(tree: Select)(implicit ctx: Context): Tree = transformTypeOfTree(tree) - override def transformBlock(tree: Block)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformBlock(tree: Block)(implicit ctx: Context): Tree = transformTypeOfTree(tree) - override def transformIf(tree: If)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformIf(tree: If)(implicit ctx: Context): Tree = transformTypeOfTree(tree) - override def transformTypeTree(tree: TypeTree)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformTypeTree(tree: TypeTree)(implicit ctx: Context): Tree = transformTypeOfTree(tree) } diff --git a/compiler/src/dotty/tools/dotc/transform/ElimJavaPackages.scala b/compiler/src/dotty/tools/dotc/transform/ElimJavaPackages.scala index 237760c35fc3..a3339c7c8118 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimJavaPackages.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimJavaPackages.scala @@ -4,17 +4,17 @@ import dotty.tools.dotc.ast.tpd._ import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Flags._ import dotty.tools.dotc.core.Types.{Type, TypeRef} -import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, TransformerInfo} +import dotty.tools.dotc.transform.SuperPhase.MiniPhase /** * Eliminates syntactic references to Java packages, so that there's no chance * they accidentally end up in the backend. */ -class ElimJavaPackages extends MiniPhaseTransform { +class ElimJavaPackages extends MiniPhase { override def phaseName: String = "elimJavaPackages" - override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformSelect(tree: Select)(implicit ctx: Context): Tree = { if (isJavaPackage(tree)) { assert(tree.tpe.isInstanceOf[TypeRef], s"Expected tree with type TypeRef, but got ${tree.tpe.show}") Ident(tree.tpe.asInstanceOf[TypeRef]) diff --git a/compiler/src/dotty/tools/dotc/transform/ElimOuterSelect.scala b/compiler/src/dotty/tools/dotc/transform/ElimOuterSelect.scala index 2ef5c8192bff..bc6cb1f3162f 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimOuterSelect.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimOuterSelect.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import core._ -import TreeTransforms.{MiniPhaseTransform, TransformerInfo} +import SuperPhase.MiniPhase import Contexts.Context import Types._ import Decorators._ @@ -12,7 +12,7 @@ import ast.Trees._ /** This phase rewrites outer selects `E.n_` which were introduced by * inlining to outer paths. */ -class ElimOuterSelect extends MiniPhaseTransform { thisTransform => +class ElimOuterSelect extends MiniPhase { import ast.tpd._ override def phaseName: String = "elimOuterSelect" @@ -24,7 +24,7 @@ class ElimOuterSelect extends MiniPhaseTransform { thisTransform => /** Convert a selection of the form `qual.n_` to an outer path from `qual` of * length `n`. */ - override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) = + override def transformSelect(tree: Select)(implicit ctx: Context) = tree.name match { case OuterSelectName(_, nhops) => val SkolemType(tp) = tree.tpe diff --git a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala index b4b274031b84..a33a88f7fa17 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala @@ -5,7 +5,7 @@ import core._ import Names._ import StdNames.nme import Types._ -import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, MiniPhaseTransform, TreeTransformer} +import dotty.tools.dotc.transform.SuperPhase._ import ast.Trees._ import Flags._ import Contexts.Context @@ -25,7 +25,7 @@ import TypeUtils._ /** A transformer that removes repeated parameters (T*) from all types, replacing * them with Seq types. */ -class ElimRepeated extends MiniPhaseTransform with InfoTransformer { thisTransformer => +class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase => import ast.tpd._ override def phaseName = "elimRepeated" @@ -67,15 +67,15 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer { thisTransfo def transformTypeOfTree(tree: Tree)(implicit ctx: Context): Tree = tree.withType(elimRepeated(tree.tpe)) - override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformIdent(tree: Ident)(implicit ctx: Context): Tree = transformTypeOfTree(tree) - override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformSelect(tree: Select)(implicit ctx: Context): Tree = transformTypeOfTree(tree) - override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformApply(tree: Apply)(implicit ctx: Context): Tree = { val formals = - ctx.atPhase(thisTransformer) { implicit ctx => + ctx.atPhase(thisPhase) { implicit ctx => tree.fun.tpe.widen.asInstanceOf[MethodType].paramInfos } val args1 = tree.args.zipWithConserve(formals) { (arg, formal) => @@ -106,14 +106,14 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer { thisTransfo // Because of phantomclasses, the Java array's type might not conform to the return type } - override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformTypeApply(tree: TypeApply)(implicit ctx: Context): Tree = transformTypeOfTree(tree) /** If method overrides a Java varargs method, add a varargs bridge. * Also transform trees inside method annotation */ - override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = - ctx.atPhase(thisTransformer) { implicit ctx => + override def transformDefDef(tree: DefDef)(implicit ctx: Context): Tree = + ctx.atPhase(thisPhase) { implicit ctx => if (tree.symbol.info.isVarArgsMethod && overridesJava(tree.symbol)) addVarArgsBridge(tree) else @@ -131,7 +131,7 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer { thisTransfo val original = ddef.symbol.asTerm val bridge = original.copy( flags = ddef.symbol.flags &~ Private | Artifact, - info = toJavaVarArgs(ddef.symbol.info)).enteredAfter(thisTransformer).asTerm + info = toJavaVarArgs(ddef.symbol.info)).enteredAfter(thisPhase).asTerm val bridgeDef = polyDefDef(bridge, trefs => vrefss => { val (vrefs :+ varArgRef) :: vrefss1 = vrefss val elemtp = varArgRef.tpe.widen.argTypes.head diff --git a/compiler/src/dotty/tools/dotc/transform/ElimStaticThis.scala b/compiler/src/dotty/tools/dotc/transform/ElimStaticThis.scala index 49a1df32a9e8..5fe2a2b654a4 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimStaticThis.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimStaticThis.scala @@ -7,24 +7,24 @@ import Flags._ import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.StdNames._ import dotty.tools.dotc.core.SymDenotations.SymDenotation -import TreeTransforms.{MiniPhaseTransform, TransformerInfo} +import SuperPhase.MiniPhase import dotty.tools.dotc.core.Types.{ThisType, TermRef} /** Replace This references to module classes in static methods by global identifiers to the * corresponding modules. */ -class ElimStaticThis extends MiniPhaseTransform { +class ElimStaticThis extends MiniPhase { import ast.tpd._ def phaseName: String = "elimStaticThis" - override def transformThis(tree: This)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformThis(tree: This)(implicit ctx: Context): Tree = if (!tree.symbol.is(Package) && ctx.owner.enclosingMethod.is(JavaStatic)) { assert(tree.symbol.is(ModuleClass)) ref(tree.symbol.sourceModule) } else tree - override def transformIdent(tree: tpd.Ident)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformIdent(tree: tpd.Ident)(implicit ctx: Context): tpd.Tree = { if (ctx.owner.enclosingMethod.is(JavaStatic)) { tree.tpe match { case TermRef(thiz: ThisType, _) if thiz.cls.is(ModuleClass, JavaDefined) => diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index 7545b36246a4..ecb40b52a910 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -31,7 +31,7 @@ import core.Mode import core.PhantomErasure import reporting.trace -class Erasure extends Phase with DenotTransformer { thisTransformer => +class Erasure extends Phase with DenotTransformer { override def phaseName: String = "erasure" diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala index 04b574d6fbbd..db107c809688 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala @@ -13,10 +13,9 @@ import SymDenotations._ import Types._ import collection.mutable -import TreeTransforms._ import Decorators._ import ast.Trees._ -import TreeTransforms._ +import SuperPhase._ import java.io.File.separatorChar import ValueClasses._ @@ -36,7 +35,7 @@ import dotty.tools.dotc.core.Phases.Phase * See discussion in https://github.com/lampepfl/dotty/pull/784 * and https://github.com/lampepfl/dotty/issues/783 */ -class ExpandPrivate extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform => +class ExpandPrivate extends MiniPhase with IdentityDenotTransformer { thisPhase => import ast.tpd._ override def phaseName: String = "expandPrivate" @@ -74,7 +73,7 @@ class ExpandPrivate extends MiniPhaseTransform with IdentityDenotTransformer { t */ private def ensurePrivateAccessible(d: SymDenotation)(implicit ctx: Context) = if (isVCPrivateParamAccessor(d)) - d.ensureNotPrivate.installAfter(thisTransform) + d.ensureNotPrivate.installAfter(thisPhase) else if (d.is(PrivateTerm) && !d.owner.is(Package) && d.owner != ctx.owner.enclosingClass) { // Paths `p1` and `p2` are similar if they have a common suffix that follows // possibly different directory paths. That is, their common suffix extends @@ -93,28 +92,28 @@ class ExpandPrivate extends MiniPhaseTransform with IdentityDenotTransformer { t assert(d.symbol.sourceFile != null && isSimilar(d.symbol.sourceFile.path, ctx.source.file.path), s"private ${d.symbol.showLocated} in ${d.symbol.sourceFile} accessed from ${ctx.owner.showLocated} in ${ctx.source.file}") - d.ensureNotPrivate.installAfter(thisTransform) + d.ensureNotPrivate.installAfter(thisPhase) } - override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo) = { + override def transformIdent(tree: Ident)(implicit ctx: Context) = { ensurePrivateAccessible(tree.symbol) tree } - override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) = { + override def transformSelect(tree: Select)(implicit ctx: Context) = { ensurePrivateAccessible(tree.symbol) tree } - override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo) = { + override def transformDefDef(tree: DefDef)(implicit ctx: Context) = { val sym = tree.symbol tree.rhs match { case Apply(sel @ Select(_: Super, _), _) if sym.is(PrivateParamAccessor) && sel.symbol.is(ParamAccessor) && sym.name == sel.symbol.name => - sym.ensureNotPrivate.installAfter(thisTransform) + sym.ensureNotPrivate.installAfter(thisPhase) case _ => if (isVCPrivateParamAccessor(sym)) - sym.ensureNotPrivate.installAfter(thisTransform) + sym.ensureNotPrivate.installAfter(thisPhase) } tree } diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala index 76ba7245d6c8..38b1e0491570 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala @@ -4,7 +4,7 @@ package transform import core._ import Contexts._, Symbols._, Types._, Flags._, Decorators._, StdNames._, Constants._ import SymDenotations.SymDenotation -import TreeTransforms._ +import SuperPhase._ import SymUtils._ import ast.untpd import ast.Trees._ @@ -21,7 +21,7 @@ import dotty.tools.dotc.util.Positions.Position * 5. Closures that get synthesized abstract methods in the transformation pipeline. These methods can be * (1) superaccessors, (2) outer references, (3) accessors for fields. */ -class ExpandSAMs extends MiniPhaseTransform { thisTransformer => +class ExpandSAMs extends MiniPhase { override def phaseName = "expandSAMs" import ast.tpd._ @@ -30,7 +30,7 @@ class ExpandSAMs extends MiniPhaseTransform { thisTransformer => def isPlatformSam(cls: ClassSymbol)(implicit ctx: Context): Boolean = ctx.platform.isSam(cls) - override def transformBlock(tree: Block)(implicit ctx: Context, info: TransformerInfo): Tree = tree match { + override def transformBlock(tree: Block)(implicit ctx: Context): Tree = tree match { case Block(stats @ (fn: DefDef) :: Nil, Closure(_, fnRef, tpt)) if fnRef.symbol == fn.symbol => tpt.tpe match { case NoType => tree // it's a plain function @@ -50,7 +50,7 @@ class ExpandSAMs extends MiniPhaseTransform { thisTransformer => tree } - private def toPartialFunction(tree: Block)(implicit ctx: Context, info: TransformerInfo): Tree = { + private def toPartialFunction(tree: Block)(implicit ctx: Context): Tree = { val Block( (applyDef @ DefDef(nme.ANON_FUN, Nil, List(List(param)), _, _)) :: Nil, Closure(_, _, tpt)) = tree diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala index 54e474888654..ba757f31d0e1 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import TreeTransforms._ +import SuperPhase._ import core.DenotTransformers._ import core.Symbols._ import core.Contexts._ @@ -34,7 +34,7 @@ import scala.annotation.tailrec * replacement of outer this by outer paths is done in Erasure. * needs to run after pattern matcher as it can add outer checks and force creation of $outer */ -class ExplicitOuter extends MiniPhaseTransform with InfoTransformer { thisTransformer => +class ExplicitOuter extends MiniPhase with InfoTransformer { thisPhase => import ExplicitOuter._ import ast.tpd._ @@ -72,7 +72,7 @@ class ExplicitOuter extends MiniPhaseTransform with InfoTransformer { thisTransf * a separate phase which needs to run after erasure. However, we make sure here * that the super class constructor is indeed a New, and not just a type. */ - override def transformTemplate(impl: Template)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformTemplate(impl: Template)(implicit ctx: Context): Tree = { val cls = ctx.owner.asClass val isTrait = cls.is(Trait) if (needsOuterIfReferenced(cls) && @@ -97,7 +97,7 @@ class ExplicitOuter extends MiniPhaseTransform with InfoTransformer { thisTransf for (parentTrait <- cls.mixins) { if (needsOuterIfReferenced(parentTrait)) { val parentTp = cls.denot.thisType.baseType(parentTrait) - val outerAccImpl = newOuterAccessor(cls, parentTrait).enteredAfter(thisTransformer) + val outerAccImpl = newOuterAccessor(cls, parentTrait).enteredAfter(thisPhase) newDefs += DefDef(outerAccImpl, singleton(fixThis(outerPrefix(parentTp)))) } } @@ -118,7 +118,7 @@ class ExplicitOuter extends MiniPhaseTransform with InfoTransformer { thisTransf else impl } - override def transformClosure(tree: Closure)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformClosure(tree: Closure)(implicit ctx: Context): tpd.Tree = { if (tree.tpt ne EmptyTree) { val cls = tree.tpt.asInstanceOf[TypeTree].tpe.classSymbol if (cls.exists && hasOuter(cls.asClass)) diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitSelf.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitSelf.scala index 3592471823ff..48d68a0d7aa7 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExplicitSelf.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExplicitSelf.scala @@ -4,7 +4,7 @@ package transform import core._ import Contexts.Context import Types._ -import TreeTransforms._ +import SuperPhase._ import Decorators._ import ast.Trees._ import Flags._ @@ -23,19 +23,19 @@ import Flags._ * * Also replaces idents referring to the self type with ThisTypes. */ -class ExplicitSelf extends MiniPhaseTransform { thisTransform => +class ExplicitSelf extends MiniPhase { import ast.tpd._ override def phaseName = "explicitSelf" - override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo) = tree.tpe match { + override def transformIdent(tree: Ident)(implicit ctx: Context) = tree.tpe match { case tp: ThisType => ctx.debuglog(s"owner = ${ctx.owner}, context = ${ctx}") This(tp.cls) withPos tree.pos case _ => tree } - override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree = tree match { + override def transformSelect(tree: Select)(implicit ctx: Context): Tree = tree match { case Select(thiz: This, name) if name.isTermName => val cls = thiz.symbol.asClass if (cls.givenSelfType.exists && !cls.derivesFrom(tree.symbol.owner)) diff --git a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala index d1ff4b72c938..fe620c1d42c6 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala @@ -5,7 +5,7 @@ package dotty.tools.dotc package transform -import dotty.tools.dotc.transform.TreeTransforms._ +import dotty.tools.dotc.transform.SuperPhase._ import ValueClasses._ import dotty.tools.dotc.ast.{Trees, tpd} import scala.collection.{ mutable, immutable } @@ -37,7 +37,7 @@ import SymUtils._ * Finally, if the constructor of a value class is private pr protected * it is widened to public. */ -class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with FullParameterization { thisTransformer => +class ExtensionMethods extends MiniPhase with DenotTransformer with FullParameterization { thisPhase => import tpd._ import ExtensionMethods._ @@ -61,17 +61,17 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful var newSuperClass: Type = null - ctx.atPhase(thisTransformer.next) { implicit ctx => + ctx.atPhase(thisPhase.next) { implicit ctx => // In Scala 2, extension methods are added before pickling so we should // not generate them again. - if (!(valueClass is Scala2x)) ctx.atPhase(thisTransformer) { implicit ctx => + if (!(valueClass is Scala2x)) ctx.atPhase(thisPhase) { implicit ctx => for (decl <- valueClass.classInfo.decls) { if (isMethodWithExtension(decl)) { val meth = createExtensionMethod(decl, moduleClassSym.symbol) decls1.enter(meth) // Workaround #1895: force denotation of `meth` to be // at phase where `meth` is entered into the decls of a class - meth.denot(ctx.withPhase(thisTransformer.next)) + meth.denot(ctx.withPhase(thisPhase.next)) } } } @@ -134,7 +134,7 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful (imeth.flags | Final) &~ (Override | Protected | AbsOverride), fullyParameterizedType(imeth.info, imeth.owner.asClass), privateWithin = imeth.privateWithin, coord = imeth.coord) - extensionMeth.addAnnotations(imeth.annotations)(ctx.withPhase(thisTransformer)) + extensionMeth.addAnnotations(imeth.annotations)(ctx.withPhase(thisPhase)) // need to change phase to add tailrec annotation which gets removed from original method in the same phase. extensionMeth } @@ -143,7 +143,7 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful // TODO: this is state and should be per-run // todo: check that when transformation finished map is empty - override def transformTemplate(tree: tpd.Template)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformTemplate(tree: tpd.Template)(implicit ctx: Context): tpd.Tree = { if (isDerivedValueClass(ctx.owner)) { /* This is currently redundant since value classes may not wrap over other value classes anyway. @@ -160,7 +160,7 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful } else tree } - override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context): tpd.Tree = { if (isMethodWithExtension(tree.symbol)) { val origMeth = tree.symbol val origClass = ctx.owner.asClass diff --git a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala index 35e2d8653d0e..40d52eb0d985 100644 --- a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala +++ b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala @@ -5,7 +5,7 @@ import core._ import Names._ import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Phases.NeedsCompanions -import dotty.tools.dotc.transform.TreeTransforms._ +import dotty.tools.dotc.transform.SuperPhase._ import ast.Trees._ import Flags._ import Types._ @@ -35,7 +35,7 @@ import StdNames._ * if (true) A else B ==> A * if (false) A else B ==> B */ -class FirstTransform extends MiniPhaseTransform with InfoTransformer { thisTransformer => +class FirstTransform extends MiniPhase with InfoTransformer { thisPhase => import ast.tpd._ override def phaseName = "firstTransform" @@ -47,9 +47,9 @@ class FirstTransform extends MiniPhaseTransform with InfoTransformer { thisTrans def needsCompanion(cls: ClassSymbol)(implicit ctx: Context) = addCompanionPhases.exists(_.isCompanionNeeded(cls)) - override def prepareForUnit(tree: tpd.Tree)(implicit ctx: Context): TreeTransform = { + override def prepareForUnit(tree: Tree)(implicit ctx: Context) = { addCompanionPhases = ctx.phasePlan.flatMap(_ collect { case p: NeedsCompanions => p }) - this + ctx } /** eliminate self symbol in ClassInfo */ @@ -123,9 +123,9 @@ class FirstTransform extends MiniPhaseTransform with InfoTransformer { thisTrans def registerCompanion(name: TermName, forClass: Symbol): TermSymbol = { val (modul, mcCompanion, classCompanion) = newCompanion(name, forClass) - if (ctx.owner.isClass) modul.enteredAfter(thisTransformer) - mcCompanion.enteredAfter(thisTransformer) - classCompanion.enteredAfter(thisTransformer) + if (ctx.owner.isClass) modul.enteredAfter(thisPhase) + mcCompanion.enteredAfter(thisPhase) + classCompanion.enteredAfter(thisPhase) modul } @@ -157,15 +157,15 @@ class FirstTransform extends MiniPhaseTransform with InfoTransformer { thisTrans } /** elimiate self in Template */ - override def transformTemplate(impl: Template)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformTemplate(impl: Template)(implicit ctx: Context): Tree = { cpy.Template(impl)(self = EmptyValDef) } /** Eliminate empty package definitions that may have been stored in the TASTY trees */ - override def transformPackageDef(tree: PackageDef)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformPackageDef(tree: PackageDef)(implicit ctx: Context): Tree = if (tree.stats.isEmpty) EmptyTree else tree - override def transformDefDef(ddef: DefDef)(implicit ctx: Context, info: TransformerInfo) = { + override def transformDefDef(ddef: DefDef)(implicit ctx: Context) = { if (ddef.symbol.hasAnnotation(defn.NativeAnnot)) { ddef.symbol.resetFlag(Deferred) DefDef(ddef.symbol.asTerm, @@ -174,7 +174,7 @@ class FirstTransform extends MiniPhaseTransform with InfoTransformer { thisTrans } else ddef } - override def transformValDef(vdef: tpd.ValDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformValDef(vdef: tpd.ValDef)(implicit ctx: Context): tpd.Tree = { if (vdef.tpt.tpe.isPhantom) { if (vdef.symbol.is(Mutable)) ctx.error("var fields cannot have Phantom types", vdef.pos) else if (vdef.symbol.hasAnnotation(defn.VolatileAnnot)) ctx.error("Phantom fields cannot be @volatile", vdef.pos) @@ -182,36 +182,36 @@ class FirstTransform extends MiniPhaseTransform with InfoTransformer { thisTrans vdef } - override def transformStats(trees: List[Tree])(implicit ctx: Context, info: TransformerInfo): List[Tree] = - ast.Trees.flatten(reorderAndComplete(trees)(ctx.withPhase(thisTransformer.next))) + override def transformStats(trees: List[Tree])(implicit ctx: Context): List[Tree] = + ast.Trees.flatten(reorderAndComplete(trees)(ctx.withPhase(thisPhase.next))) - override def transformOther(tree: Tree)(implicit ctx: Context, info: TransformerInfo) = tree match { + override def transformOther(tree: Tree)(implicit ctx: Context) = tree match { case tree: Import => EmptyTree - case tree: NamedArg => transform(tree.arg) + case tree: NamedArg => transformAllDeep(tree.arg) case tree => if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos) else tree } - override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo) = + override def transformIdent(tree: Ident)(implicit ctx: Context) = if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos) else constToLiteral(tree) - override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) = + override def transformSelect(tree: Select)(implicit ctx: Context) = if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos) else constToLiteral(tree) - override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo) = + override def transformTypeApply(tree: TypeApply)(implicit ctx: Context) = constToLiteral(tree) - override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo) = + override def transformApply(tree: Apply)(implicit ctx: Context) = constToLiteral(foldCondition(tree)) - override def transformTyped(tree: Typed)(implicit ctx: Context, info: TransformerInfo) = + override def transformTyped(tree: Typed)(implicit ctx: Context) = constToLiteral(tree) - override def transformBlock(tree: Block)(implicit ctx: Context, info: TransformerInfo) = + override def transformBlock(tree: Block)(implicit ctx: Context) = constToLiteral(tree) - override def transformIf(tree: If)(implicit ctx: Context, info: TransformerInfo) = + override def transformIf(tree: If)(implicit ctx: Context) = tree.cond match { case Literal(Constant(c: Boolean)) => if (c) tree.thenp else tree.elsep case _ => tree diff --git a/compiler/src/dotty/tools/dotc/transform/Flatten.scala b/compiler/src/dotty/tools/dotc/transform/Flatten.scala index 49261cc5276a..c518d8dc6db2 100644 --- a/compiler/src/dotty/tools/dotc/transform/Flatten.scala +++ b/compiler/src/dotty/tools/dotc/transform/Flatten.scala @@ -8,12 +8,20 @@ import Contexts.Context import Flags._ import SymDenotations.SymDenotation import collection.mutable -import TreeTransforms.MiniPhaseTransform -import dotty.tools.dotc.transform.TreeTransforms.TransformerInfo +import SuperPhase.MiniPhase +import util.Property + +object Flatten { + import ast.tpd._ + val LiftedDefs = new Property.Key[mutable.ListBuffer[Tree]] + def liftedDefs(implicit ctx: Context) = ctx.property(LiftedDefs).get +} /** Lift nested classes to toplevel */ -class Flatten extends MiniPhaseTransform with SymTransformer { thisTransform => +class Flatten extends MiniPhase with SymTransformer { import ast.tpd._ + import Flatten._ + override def phaseName = "flatten" override def changesMembers = true // the phase removes inner classes @@ -27,29 +35,17 @@ class Flatten extends MiniPhaseTransform with SymTransformer { thisTransform => else ref } - private[this] var liftedDefs = new mutable.ListBuffer[Tree] - private[this] var liftedDefsQueue = List.empty[mutable.ListBuffer[Tree]] - - override def prepareForPackageDef(tree: PackageDef)(implicit ctx: Context) = { - liftedDefsQueue = liftedDefs :: liftedDefsQueue - liftedDefs = new mutable.ListBuffer[Tree] - this - } - - override def transformPackageDef(tree: PackageDef)(implicit ctx: Context, info: TransformerInfo) = { - liftedDefs = liftedDefsQueue.head - liftedDefsQueue = liftedDefsQueue.tail - tree - } + override def prepareForPackageDef(tree: PackageDef)(implicit ctx: Context) = + ctx.fresh.setProperty(LiftedDefs, new mutable.ListBuffer[Tree]) - private def liftIfNested(tree: Tree)(implicit ctx: Context, info: TransformerInfo) = + private def liftIfNested(tree: Tree)(implicit ctx: Context) = if (ctx.owner is Package) tree else { transformFollowing(tree).foreachInThicket(liftedDefs += _) EmptyTree } - override def transformStats(stats: List[Tree])(implicit ctx: Context, info: TransformerInfo) = + override def transformStats(stats: List[Tree])(implicit ctx: Context) = if (ctx.owner is Package) { val liftedStats = stats ++ liftedDefs liftedDefs.clear() @@ -57,6 +53,6 @@ class Flatten extends MiniPhaseTransform with SymTransformer { thisTransform => } else stats - override def transformTypeDef(tree: TypeDef)(implicit ctx: Context, info: TransformerInfo) = + override def transformTypeDef(tree: TypeDef)(implicit ctx: Context) = liftIfNested(tree) } diff --git a/compiler/src/dotty/tools/dotc/transform/FunctionXXLForwarders.scala b/compiler/src/dotty/tools/dotc/transform/FunctionXXLForwarders.scala index e67247fd8e32..49bfc56529d2 100644 --- a/compiler/src/dotty/tools/dotc/transform/FunctionXXLForwarders.scala +++ b/compiler/src/dotty/tools/dotc/transform/FunctionXXLForwarders.scala @@ -9,7 +9,7 @@ import Definitions._ import DenotTransformers._ import StdNames._ import Symbols._ -import TreeTransforms._ +import SuperPhase._ import Types._ @@ -22,12 +22,12 @@ import Types._ * `def apply(xs: Array[Object]): R = this.apply(xs(0).asInstanceOf[T1], ..., xs(n-1).asInstanceOf[Tn]).asInstanceOf[R]` * is generated. */ -class FunctionXXLForwarders extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform => +class FunctionXXLForwarders extends MiniPhase with IdentityDenotTransformer { import ast.tpd._ override def phaseName: String = "functionXXLForwarders" - override def transformTemplate(impl: Template)(implicit ctx: Context, info: TransformerInfo): Template = { + override def transformTemplate(impl: Template)(implicit ctx: Context): Template = { def forwarderRhs(receiver: Tree, xsTree: Tree): Tree = { val argsApply = ref(xsTree.symbol).select(nme.apply) diff --git a/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala b/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala index 8166e4f35675..83984690ae64 100644 --- a/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala +++ b/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import TreeTransforms._ +import SuperPhase._ import core.DenotTransformers._ import core.Symbols._ import core.Contexts._ @@ -21,7 +21,7 @@ import collection.mutable.{ LinkedHashMap, LinkedHashSet, TreeSet } /** * Rewires closures to implement more specific types of Functions. */ -class FunctionalInterfaces extends MiniPhaseTransform { +class FunctionalInterfaces extends MiniPhase { import tpd._ def phaseName: String = "functionalInterfaces" @@ -29,7 +29,7 @@ class FunctionalInterfaces extends MiniPhaseTransform { val functionName = "JFunction".toTermName val functionPackage = "scala.compat.java8.".toTermName - override def transformClosure(tree: Closure)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformClosure(tree: Closure)(implicit ctx: Context): Tree = { val cls = tree.tpe.widen.classSymbol.asClass val implType = tree.meth.tpe.widen diff --git a/compiler/src/dotty/tools/dotc/transform/GetClass.scala b/compiler/src/dotty/tools/dotc/transform/GetClass.scala index 6a9a5fda2019..bca809f91be0 100644 --- a/compiler/src/dotty/tools/dotc/transform/GetClass.scala +++ b/compiler/src/dotty/tools/dotc/transform/GetClass.scala @@ -6,7 +6,7 @@ import core.Contexts.Context import core.StdNames.nme import core.Phases.Phase import TypeUtils._ -import TreeTransforms.{MiniPhaseTransform, TransformerInfo} +import SuperPhase.MiniPhase /** Rewrite `getClass` calls as follow: * @@ -15,7 +15,7 @@ import TreeTransforms.{MiniPhaseTransform, TransformerInfo} * For every instance of non-primitive class D: * instanceD.getClass -> instanceD.getClass */ -class GetClass extends MiniPhaseTransform { +class GetClass extends MiniPhase { import tpd._ override def phaseName: String = "getClass" @@ -23,7 +23,7 @@ class GetClass extends MiniPhaseTransform { // getClass transformation should be applied to specialized methods override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[Erasure], classOf[FunctionalInterfaces]) - override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformApply(tree: Apply)(implicit ctx: Context): Tree = { import ast.Trees._ tree match { case Apply(Select(qual, nme.getClass_), Nil) if qual.tpe.widen.isPrimitiveValueType => diff --git a/compiler/src/dotty/tools/dotc/transform/Getters.scala b/compiler/src/dotty/tools/dotc/transform/Getters.scala index 31171dfabe5e..cbcd4321065a 100644 --- a/compiler/src/dotty/tools/dotc/transform/Getters.scala +++ b/compiler/src/dotty/tools/dotc/transform/Getters.scala @@ -9,7 +9,7 @@ import Types._ import Symbols._ import SymUtils._ import Constants._ -import TreeTransforms._ +import SuperPhase._ import Flags._ import Decorators._ import ValueClasses._ @@ -46,7 +46,7 @@ import ValueClasses._ * * No fields are generated yet. This is done later in phase Memoize. */ -class Getters extends MiniPhaseTransform with SymTransformer { thisTransform => +class Getters extends MiniPhase with SymTransformer { import ast.tpd._ override def phaseName = "getters" @@ -68,9 +68,9 @@ class Getters extends MiniPhaseTransform with SymTransformer { thisTransform => } private val NoGetterNeeded = Method | Param | JavaDefined | JavaStatic - override def transformValDef(tree: ValDef)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformValDef(tree: ValDef)(implicit ctx: Context): Tree = if (tree.symbol is Method) DefDef(tree.symbol.asTerm, tree.rhs).withPos(tree.pos) else tree - override def transformAssign(tree: Assign)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformAssign(tree: Assign)(implicit ctx: Context): Tree = if (tree.lhs.symbol is Method) tree.lhs.becomes(tree.rhs).withPos(tree.pos) else tree } diff --git a/compiler/src/dotty/tools/dotc/transform/HoistSuperArgs.scala b/compiler/src/dotty/tools/dotc/transform/HoistSuperArgs.scala index 9ef36a7caf56..eb6ff09d8b2e 100644 --- a/compiler/src/dotty/tools/dotc/transform/HoistSuperArgs.scala +++ b/compiler/src/dotty/tools/dotc/transform/HoistSuperArgs.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import TreeTransforms._ +import SuperPhase._ import core.DenotTransformers._ import core.Symbols._ import core.Contexts._ @@ -37,7 +37,7 @@ import SymUtils._ * as method parameters. The definition is installed in the scope enclosing the class, * or, if that is a package, it is made a static method of the class itself. */ -class HoistSuperArgs extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform => +class HoistSuperArgs extends MiniPhase with IdentityDenotTransformer { thisPhase => import ast.tpd._ def phaseName = "hoistSuperArgs" @@ -94,7 +94,7 @@ class HoistSuperArgs extends MiniPhaseTransform with IdentityDenotTransformer { flags = Synthetic | Private | Method | staticFlag, info = replaceResult(constr.info, argTypeWrtConstr), coord = constr.coord) - if (methOwner.isClass) meth.enteredAfter(thisTransform) else meth + if (methOwner.isClass) meth.enteredAfter(thisPhase) else meth } /** Type of a reference implies that it needs to be hoisted */ @@ -142,7 +142,7 @@ class HoistSuperArgs extends MiniPhaseTransform with IdentityDenotTransformer { case tree => tree }) - tmap(arg).changeOwnerAfter(constr, superMeth, thisTransform) + tmap(arg).changeOwnerAfter(constr, superMeth, thisPhase) }) superArgDefs += superArgDef def termParamRefs(tp: Type, params: List[Symbol]): List[List[Tree]] = tp match { @@ -189,7 +189,7 @@ class HoistSuperArgs extends MiniPhaseTransform with IdentityDenotTransformer { } } - override def transformTypeDef(tdef: TypeDef)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformTypeDef(tdef: TypeDef)(implicit ctx: Context): Tree = tdef.rhs match { case impl @ Template(cdef, superCall :: others, _, _) => val hoist = new Hoister(tdef.symbol) diff --git a/compiler/src/dotty/tools/dotc/transform/InterceptedMethods.scala b/compiler/src/dotty/tools/dotc/transform/InterceptedMethods.scala index b1f384586a0b..71536309b0b5 100644 --- a/compiler/src/dotty/tools/dotc/transform/InterceptedMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/InterceptedMethods.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import TreeTransforms._ +import SuperPhase._ import core.Denotations._ import core.SymDenotations._ import core.Contexts._ @@ -16,7 +16,6 @@ import Contexts._ import Symbols._ import Decorators._ import NameOps._ -import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, TreeTransformer, TreeTransform} import dotty.tools.dotc.ast.Trees._ import dotty.tools.dotc.ast.{untpd, tpd} import dotty.tools.dotc.core.Constants.Constant @@ -36,9 +35,7 @@ import Phases.Phase * using the most precise overload available * - `x.getClass` for getClass in primitives becomes `x.getClass` with getClass in class Object. */ -class InterceptedMethods extends MiniPhaseTransform { - thisTransform => - +class InterceptedMethods extends MiniPhase { import tpd._ override def phaseName: String = "intercepted" @@ -51,11 +48,11 @@ class InterceptedMethods extends MiniPhaseTransform { override def prepareForUnit(tree: Tree)(implicit ctx: Context) = { this.Any_## = defn.Any_## primitiveGetClassMethods = Set[Symbol]() ++ defn.ScalaValueClasses().map(x => x.requiredMethod(nme.getClass_)) - this + ctx } // this should be removed if we have guarantee that ## will get Apply node - override def transformSelect(tree: tpd.Select)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformSelect(tree: tpd.Select)(implicit ctx: Context): Tree = { if (tree.symbol.isTerm && (Any_## eq tree.symbol.asTerm)) { val rewrite = poundPoundValue(tree.qualifier) ctx.log(s"$phaseName rewrote $tree to $rewrite") @@ -78,7 +75,7 @@ class InterceptedMethods extends MiniPhaseTransform { else staticsCall(nme.anyHash) } - override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformApply(tree: Apply)(implicit ctx: Context): Tree = { def unknown = { assert(false, s"The symbol '${tree.fun.symbol.showLocated}' was intercepted but didn't match any cases, " + s"that means the intercepted methods set doesn't match the code") diff --git a/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala b/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala index 587ba1fbe398..7b2f8fc4fa7d 100644 --- a/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala +++ b/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import dotty.tools.dotc.util.Positions._ -import TreeTransforms.{MiniPhaseTransform, TransformerInfo} +import SuperPhase.MiniPhase import core._ import Contexts.Context, Types._, Constants._, Decorators._, Symbols._ import TypeUtils._, TypeErasure._, Flags._ @@ -29,7 +29,7 @@ import TypeUtils._, TypeErasure._, Flags._ * - leave as is (`happens`) * 2. Rewrite according to steps taken in 1 */ -class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer => +class IsInstanceOfEvaluator extends MiniPhase { import dotty.tools.dotc.ast.tpd._ @@ -38,7 +38,7 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer => /** Transforms a [TypeApply](dotty.tools.dotc.ast.Trees.TypeApply) in order to * evaluate an `isInstanceOf` check according to the rules defined above. */ - override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformTypeApply(tree: TypeApply)(implicit ctx: Context): Tree = { val defn = ctx.definitions /** Handles the four cases of statically known `isInstanceOf`s and gives diff --git a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala index f2645c5446cc..6a31266589e3 100644 --- a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala +++ b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import TreeTransforms._ +import SuperPhase._ import core.DenotTransformers._ import core.Symbols._ import core.Contexts._ @@ -16,68 +16,22 @@ import core.Phases._ import ast.Trees._ import SymUtils._ import ExplicitOuter.outer -import util.Attachment +import util.Property import util.Positions._ import collection.{ mutable, immutable } import collection.mutable.{ HashMap, HashSet, LinkedHashMap, LinkedHashSet, TreeSet } object LambdaLift { - private class NoPath extends Exception -} - -/** This phase performs the necessary rewritings to eliminate classes and methods - * nested in other methods. In detail: - * 1. It adds all free variables of local functions as additional parameters (proxies). - * 2. It rebinds references to free variables to the corresponding proxies, - * 3. It lifts all local functions and classes out as far as possible, but at least - * to the enclosing class. - * 4. It stores free variables of non-trait classes as additional fields of the class. - * The fields serve as proxies for methods in the class, which avoids the need - * of passing additional parameters to these methods. - * - * A particularly tricky case are local traits. These cannot store free variables - * as field proxies, because LambdaLift runs after Mixin, so the fields cannot be - * expanded anymore. Instead, methods of local traits get free variables of - * the trait as additional proxy parameters. The difference between local classes - * and local traits is illustrated by the two rewritings below. - * - * def f(x: Int) = { def f(x: Int) = new C(x).f2 - * class C { ==> class C(x$1: Int) { - * def f2 = x def f2 = x$1 - * } } - * new C().f2 - * } - * - * def f(x: Int) = { def f(x: Int) = new C().f2(x) - * trait T { ==> trait T - * def f2 = x def f2(x$1: Int) = x$1 - * } } - * class C extends T class C extends T - * new C().f2 - * } - */ -class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform => - import LambdaLift._ import ast.tpd._ + private class NoPath extends Exception - /** the following two members override abstract members in Transform */ - val phaseName: String = "lambdaLift" - val treeTransform = new LambdaLifter - - override def runsAfterGroupsOf: Set[Class[_ <: Phase]] = Set(classOf[Constructors], classOf[HoistSuperArgs]) - // Constructors has to happen before LambdaLift because the lambda lift logic - // becomes simpler if it can assume that parameter accessors have already been - // converted to parameters in super calls. Without this it is very hard to get - // lambda lift for super calls right. Witness the implementation restrictions to - // this effect in scalac. - - class LambdaLifter extends TreeTransform { - override def phase = thisTransform + /** The core lambda lift functionality. */ + class Lifter(thisPhase: MiniPhase with DenotTransformer)(implicit ctx: Context) { private type SymSet = TreeSet[Symbol] /** A map storing free variables of functions and classes */ - private val free = new LinkedHashMap[Symbol, SymSet] + val free = new LinkedHashMap[Symbol, SymSet] /** A map storing the free variable proxies of functions and classes. * For every function and class, this is a map from the free variables @@ -104,7 +58,7 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform private val outerParam = new HashMap[Symbol, Symbol] /** Buffers for lifted out classes and methods, indexed by owner */ - private val liftedDefs = new HashMap[Symbol, mutable.ListBuffer[Tree]] + val liftedDefs = new HashMap[Symbol, mutable.ListBuffer[Tree]] /** A flag to indicate whether new free variables have been found */ private[this] var changedFreeVars: Boolean = _ @@ -350,7 +304,7 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform for (fv <- freeValues.toList) yield { val proxyName = newName(fv) val proxy = ctx.newSymbol(owner, proxyName.asTermName, newFlags, fv.info, coord = fv.coord) - if (owner.isClass) proxy.enteredAfter(thisTransform) + if (owner.isClass) proxy.enteredAfter(thisPhase) (fv, proxy) } }.toMap @@ -389,28 +343,23 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform name = newName(local), initFlags = local.flags &~ Module &~ Final | Private | maybeStatic, // drop Module because class is no longer a singleton in the lifted context. - info = liftedInfo(local)).installAfter(thisTransform) + info = liftedInfo(local)).installAfter(thisPhase) } for (local <- free.keys) if (!liftedOwner.contains(local)) - local.copySymDenotation(info = liftedInfo(local)).installAfter(thisTransform) + local.copySymDenotation(info = liftedInfo(local)).installAfter(thisPhase) } - private def init(implicit ctx: Context) = { + // initialization + ctx.atPhase(thisPhase) { implicit ctx => (new CollectDependencies).traverse(ctx.compilationUnit.tpdTree) computeFreeVars() computeLiftedOwners() - generateProxies()(ctx.withPhase(thisTransform.next)) - liftLocals()(ctx.withPhase(thisTransform.next)) + generateProxies()(ctx.withPhase(thisPhase.next)) + liftLocals()(ctx.withPhase(thisPhase.next)) } - override def prepareForUnit(tree: Tree)(implicit ctx: Context) = { - val lifter = new LambdaLifter - lifter.init(ctx.withPhase(thisTransform)) - lifter - } - - private def currentEnclosure(implicit ctx: Context) = + def currentEnclosure(implicit ctx: Context) = ctx.owner.enclosingMethodOrClass private def inCurrentOwner(sym: Symbol)(implicit ctx: Context) = @@ -438,7 +387,7 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform if (inCurrentOwner(sym)) sym else searchIn(currentEnclosure) } - private def memberRef(sym: Symbol)(implicit ctx: Context, info: TransformerInfo): Tree = { + def memberRef(sym: Symbol)(implicit ctx: Context): Tree = { val clazz = sym.enclosingClass val qual = if (clazz.isStaticOwner || ctx.owner.enclosingClass == clazz) @@ -449,28 +398,28 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform case _ => outer.path(toCls = clazz) } else outer.path(toCls = clazz) - transformFollowingDeep(qual.select(sym)) + thisPhase.transformFollowingDeep(qual.select(sym)) } - private def proxyRef(sym: Symbol)(implicit ctx: Context, info: TransformerInfo): Tree = { - val psym = proxy(sym)(ctx.withPhase(thisTransform)) - transformFollowingDeep(if (psym.owner.isTerm) ref(psym) else memberRef(psym)) + def proxyRef(sym: Symbol)(implicit ctx: Context): Tree = { + val psym = proxy(sym)(ctx.withPhase(thisPhase)) + thisPhase.transformFollowingDeep(if (psym.owner.isTerm) ref(psym) else memberRef(psym)) } - private def addFreeArgs(sym: Symbol, args: List[Tree])(implicit ctx: Context, info: TransformerInfo) = + def addFreeArgs(sym: Symbol, args: List[Tree])(implicit ctx: Context) = free get sym match { case Some(fvs) => fvs.toList.map(proxyRef(_)) ++ args case _ => args } - private def addFreeParams(tree: Tree, proxies: List[Symbol])(implicit ctx: Context, info: TransformerInfo): Tree = proxies match { + def addFreeParams(tree: Tree, proxies: List[Symbol])(implicit ctx: Context): Tree = proxies match { case Nil => tree case proxies => val sym = tree.symbol val freeParamDefs = proxies.map(proxy => - transformFollowingDeep(ValDef(proxy.asTerm).withPos(tree.pos)).asInstanceOf[ValDef]) + thisPhase.transformFollowingDeep(ValDef(proxy.asTerm).withPos(tree.pos)).asInstanceOf[ValDef]) def proxyInit(field: Symbol, param: Symbol) = - transformFollowingDeep(memberRef(field).becomes(ref(param))) + thisPhase.transformFollowingDeep(memberRef(field).becomes(ref(param))) /** Initialize proxy fields from proxy parameters and map `rhs` from fields to parameters */ def copyParams(rhs: Tree) = { @@ -493,61 +442,116 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform } } - private def liftDef(tree: MemberDef)(implicit ctx: Context, info: TransformerInfo): Tree = { + def liftDef(tree: MemberDef)(implicit ctx: Context): Tree = { val buf = liftedDefs(tree.symbol.owner) - transformFollowing(rename(tree, tree.symbol.name)).foreachInThicket(buf += _) + thisPhase.transformFollowing(rename(tree, tree.symbol.name)).foreachInThicket(buf += _) EmptyTree } - private def needsLifting(sym: Symbol) = liftedOwner contains sym - - override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo) = { - val sym = tree.symbol - tree.tpe match { - case tpe @ TermRef(prefix, _) => - if (prefix eq NoPrefix) - if (sym.enclosure != currentEnclosure && !sym.isStatic) - (if (sym is Method) memberRef(sym) else proxyRef(sym)).withPos(tree.pos) - else if (sym.owner.isClass) // sym was lifted out - ref(sym).withPos(tree.pos) - else - tree - else if (!prefixIsElidable(tpe)) ref(tpe) - else tree - case _ => - tree - } - } + def needsLifting(sym: Symbol) = liftedOwner contains sym + } - override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo) = - cpy.Apply(tree)(tree.fun, addFreeArgs(tree.symbol, tree.args)).withPos(tree.pos) + val Lifter = new Property.Key[Lifter] + def lifter(implicit ctx: Context) = ctx.property(Lifter).get +} - override def transformClosure(tree: Closure)(implicit ctx: Context, info: TransformerInfo) = - cpy.Closure(tree)(env = addFreeArgs(tree.meth.symbol, tree.env)) +/** This phase performs the necessary rewritings to eliminate classes and methods + * nested in other methods. In detail: + * 1. It adds all free variables of local functions as additional parameters (proxies). + * 2. It rebinds references to free variables to the corresponding proxies, + * 3. It lifts all local functions and classes out as far as possible, but at least + * to the enclosing class. + * 4. It stores free variables of non-trait classes as additional fields of the class. + * The fields serve as proxies for methods in the class, which avoids the need + * of passing additional parameters to these methods. + * + * A particularly tricky case are local traits. These cannot store free variables + * as field proxies, because LambdaLift runs after Mixin, so the fields cannot be + * expanded anymore. Instead, methods of local traits get free variables of + * the trait as additional proxy parameters. The difference between local classes + * and local traits is illustrated by the two rewritings below. + * + * def f(x: Int) = { def f(x: Int) = new C(x).f2 + * class C { ==> class C(x$1: Int) { + * def f2 = x def f2 = x$1 + * } } + * new C().f2 + * } + * + * def f(x: Int) = { def f(x: Int) = new C().f2(x) + * trait T { ==> trait T + * def f2 = x def f2(x$1: Int) = x$1 + * } } + * class C extends T class C extends T + * new C().f2 + * } + */ +class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisPhase => + import LambdaLift._ + import ast.tpd._ - override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo) = { - val sym = tree.symbol - val paramsAdded = - if (free.contains(sym)) addFreeParams(tree, proxies(sym)).asInstanceOf[DefDef] - else tree - if (needsLifting(sym)) liftDef(paramsAdded) - else paramsAdded - } + /** the following two members override abstract members in Transform */ + val phaseName: String = "lambdaLift" + + override def runsAfterGroupsOf: Set[Class[_ <: Phase]] = Set(classOf[Constructors], classOf[HoistSuperArgs]) + // Constructors has to happen before LambdaLift because the lambda lift logic + // becomes simpler if it can assume that parameter accessors have already been + // converted to parameters in super calls. Without this it is very hard to get + // lambda lift for super calls right. Witness the implementation restrictions to + // this effect in scalac. - override def transformReturn(tree: Return)(implicit ctx: Context, info: TransformerInfo) = tree.expr match { - case Block(stats, value) => - Block(stats, Return(value, tree.from)).withPos(tree.pos) + override def prepareForUnit(tree: Tree)(implicit ctx: Context) = + ctx.fresh.setProperty(Lifter, new Lifter(thisPhase)) + + override def transformIdent(tree: Ident)(implicit ctx: Context) = { + val sym = tree.symbol + tree.tpe match { + case tpe @ TermRef(prefix, _) => + val lft = lifter + if (prefix eq NoPrefix) + if (sym.enclosure != lft.currentEnclosure && !sym.isStatic) + (if (sym is Method) lft.memberRef(sym) else lft.proxyRef(sym)).withPos(tree.pos) + else if (sym.owner.isClass) // sym was lifted out + ref(sym).withPos(tree.pos) + else + tree + else if (!prefixIsElidable(tpe)) ref(tpe) + else tree case _ => tree } + } - override def transformTemplate(tree: Template)(implicit ctx: Context, info: TransformerInfo) = { - val cls = ctx.owner - val impl = addFreeParams(tree, proxies(cls)).asInstanceOf[Template] - cpy.Template(impl)(body = impl.body ++ liftedDefs.remove(cls).get) - } + override def transformApply(tree: Apply)(implicit ctx: Context) = + cpy.Apply(tree)(tree.fun, lifter.addFreeArgs(tree.symbol, tree.args)).withPos(tree.pos) - override def transformTypeDef(tree: TypeDef)(implicit ctx: Context, info: TransformerInfo) = - if (needsLifting(tree.symbol)) liftDef(tree) else tree + override def transformClosure(tree: Closure)(implicit ctx: Context) = + cpy.Closure(tree)(env = lifter.addFreeArgs(tree.meth.symbol, tree.env)) + + override def transformDefDef(tree: DefDef)(implicit ctx: Context) = { + val sym = tree.symbol + val lft = lifter + val paramsAdded = + if (lft.free.contains(sym)) lft.addFreeParams(tree, lft.proxies(sym)).asInstanceOf[DefDef] + else tree + if (lft.needsLifting(sym)) lft.liftDef(paramsAdded) + else paramsAdded + } + + override def transformReturn(tree: Return)(implicit ctx: Context) = tree.expr match { + case Block(stats, value) => + Block(stats, Return(value, tree.from)).withPos(tree.pos) + case _ => + tree } + + override def transformTemplate(tree: Template)(implicit ctx: Context) = { + val cls = ctx.owner + val lft = lifter + val impl = lft.addFreeParams(tree, lft.proxies(cls)).asInstanceOf[Template] + cpy.Template(impl)(body = impl.body ++ lft.liftedDefs.remove(cls).get) + } + + override def transformTypeDef(tree: TypeDef)(implicit ctx: Context) = + if (lifter.needsLifting(tree.symbol)) lifter.liftDef(tree) else tree } diff --git a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala index 94b046d317df..d5be0c1b2d32 100644 --- a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala @@ -14,7 +14,7 @@ import NameKinds._ import StdNames.nme import rewrite.Rewrites.patch import util.Positions.Position -import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, TreeTransformer, MiniPhaseTransform} +import dotty.tools.dotc.transform.SuperPhase._ import dotty.tools.dotc.ast.Trees._ import dotty.tools.dotc.ast.{untpd, tpd} import dotty.tools.dotc.core.Constants.Constant @@ -27,7 +27,7 @@ import dotty.tools.dotc.core.SymDenotations.SymDenotation import dotty.tools.dotc.core.DenotTransformers.{SymTransformer, IdentityDenotTransformer, DenotTransformer} import Erasure.Boxing.adaptToType -class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer { +class LazyVals extends MiniPhase with IdentityDenotTransformer { import LazyVals._ import tpd._ @@ -51,15 +51,15 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer { val containerFlagsMask = Flags.Method | Flags.Lazy | Flags.Accessor | Flags.Module - override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = + override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context): tpd.Tree = transformLazyVal(tree) - override def transformValDef(tree: tpd.ValDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformValDef(tree: tpd.ValDef)(implicit ctx: Context): tpd.Tree = { transformLazyVal(tree) } - def transformLazyVal(tree: ValOrDefDef)(implicit ctx: Context, info: TransformerInfo): Tree = { + def transformLazyVal(tree: ValOrDefDef)(implicit ctx: Context): Tree = { val sym = tree.symbol if (!(sym is Flags.Lazy) || sym.owner.is(Flags.Trait) || (sym.isStatic && sym.is(Flags.Module))) tree else { @@ -85,7 +85,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer { /** Append offset fields to companion objects */ - override def transformTemplate(template: tpd.Template)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformTemplate(template: tpd.Template)(implicit ctx: Context): tpd.Tree = { val cls = ctx.owner.asClass appendOffsetDefs.get(cls) match { @@ -162,7 +162,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer { } - override def transformStats(trees: List[tpd.Tree])(implicit ctx: Context, info: TransformerInfo): List[tpd.Tree] = { + override def transformStats(trees: List[tpd.Tree])(implicit ctx: Context): List[tpd.Tree] = { // backend requires field usage to be after field definition // need to bring containers to start of method val (holders, stats) = diff --git a/compiler/src/dotty/tools/dotc/transform/LiftTry.scala b/compiler/src/dotty/tools/dotc/transform/LiftTry.scala index 278868131c20..649a5bdae85c 100644 --- a/compiler/src/dotty/tools/dotc/transform/LiftTry.scala +++ b/compiler/src/dotty/tools/dotc/transform/LiftTry.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import TreeTransforms._ +import SuperPhase._ import core.DenotTransformers._ import core.Symbols._ import core.Contexts._ @@ -10,6 +10,13 @@ import core.Flags._ import core.Decorators._ import core.NameKinds.LiftedTreeName import NonLocalReturns._ +import util.Property + +object LiftTry { + val NeedLift = new Property.Key[Boolean] + def needLift(implicit ctx: Context) = ctx.property(NeedLift).getOrElse(false) + def liftingCtx(p: Boolean)(implicit ctx: Context) = ctx.withProperty(NeedLift, Some(p)) +} /** Lifts try's that might be executed on non-empty expression stacks * to their own methods. I.e. @@ -20,48 +27,42 @@ import NonLocalReturns._ * * { def liftedTree$n() = try body catch handler; liftedTree$n() } */ -class LiftTry extends MiniPhase with IdentityDenotTransformer { thisTransform => +class LiftTry extends MiniPhase with IdentityDenotTransformer { thisPhase => import ast.tpd._ + import LiftTry._ /** the following two members override abstract members in Transform */ val phaseName: String = "liftTry" - val treeTransform = new Transform(needLift = false) - val liftingTransform = new Transform(needLift = true) - - class Transform(needLift: Boolean) extends TreeTransform { - def phase = thisTransform - - override def prepareForApply(tree: Apply)(implicit ctx: Context) = - if (tree.fun.symbol.is(Label)) this - else liftingTransform + override def prepareForApply(tree: Apply)(implicit ctx: Context) = + if (tree.fun.symbol.is(Label)) ctx + else liftingCtx(true) - override def prepareForValDef(tree: ValDef)(implicit ctx: Context) = - if (!tree.symbol.exists || - tree.symbol.isSelfSym || - tree.symbol.owner == ctx.owner.enclosingMethod) this - else liftingTransform + override def prepareForValDef(tree: ValDef)(implicit ctx: Context) = + if (!tree.symbol.exists || + tree.symbol.isSelfSym || + tree.symbol.owner == ctx.owner.enclosingMethod) ctx + else liftingCtx(true) - override def prepareForAssign(tree: Assign)(implicit ctx: Context) = - if (tree.lhs.symbol.maybeOwner == ctx.owner.enclosingMethod) this - else liftingTransform + override def prepareForAssign(tree: Assign)(implicit ctx: Context) = + if (tree.lhs.symbol.maybeOwner == ctx.owner.enclosingMethod) ctx + else liftingCtx(true) - override def prepareForReturn(tree: Return)(implicit ctx: Context) = - if (!isNonLocalReturn(tree)) this - else liftingTransform + override def prepareForReturn(tree: Return)(implicit ctx: Context) = + if (!isNonLocalReturn(tree)) ctx + else liftingCtx(true) - override def prepareForTemplate(tree: Template)(implicit ctx: Context) = - treeTransform + override def prepareForTemplate(tree: Template)(implicit ctx: Context) = + liftingCtx(false) - override def transformTry(tree: Try)(implicit ctx: Context, info: TransformerInfo): Tree = - if (needLift) { - ctx.debuglog(i"lifting tree at ${tree.pos}, current owner = ${ctx.owner}") - val fn = ctx.newSymbol( - ctx.owner, LiftedTreeName.fresh(), Synthetic | Method, - MethodType(Nil, tree.tpe.widenIfUnstable), coord = tree.pos) - tree.changeOwnerAfter(ctx.owner, fn, thisTransform) - Block(DefDef(fn, tree) :: Nil, ref(fn).appliedToNone) - } - else tree - } + override def transformTry(tree: Try)(implicit ctx: Context): Tree = + if (needLift) { + ctx.debuglog(i"lifting tree at ${tree.pos}, current owner = ${ctx.owner}") + val fn = ctx.newSymbol( + ctx.owner, LiftedTreeName.fresh(), Synthetic | Method, + MethodType(Nil, tree.tpe.widenIfUnstable), coord = tree.pos) + tree.changeOwnerAfter(ctx.owner, fn, thisPhase) + Block(DefDef(fn, tree) :: Nil, ref(fn).appliedToNone) + } + else tree } diff --git a/compiler/src/dotty/tools/dotc/transform/LinkScala2Impls.scala b/compiler/src/dotty/tools/dotc/transform/LinkScala2Impls.scala index 180e48e5f84b..23cfad817834 100644 --- a/compiler/src/dotty/tools/dotc/transform/LinkScala2Impls.scala +++ b/compiler/src/dotty/tools/dotc/transform/LinkScala2Impls.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import core._ -import TreeTransforms._ +import SuperPhase._ import Contexts.Context import Flags._ import SymUtils._ @@ -34,82 +34,77 @@ import collection.mutable * * where f is a static member of M. */ -class LinkScala2Impls extends MiniPhase with IdentityDenotTransformer { thisTransform => +class LinkScala2Impls extends MiniPhase with IdentityDenotTransformer { thisPhase => import ast.tpd._ override def phaseName: String = "linkScala2Impls" override def changesMembers = true - val treeTransform = new Transform override def runsAfterGroupsOf: Set[Class[_ <: Phase]] = Set(classOf[Mixin]) // Adds as a side effect static members to traits which can confuse Mixin, // that's why it is runsAfterGroupOf - class Transform extends TreeTransform { - def phase = thisTransform - - /** Copy definitions from implementation class to trait itself */ - private def augmentScala_2_12_Trait(mixin: ClassSymbol)(implicit ctx: Context): Unit = { - def info_2_12(sym: Symbol) = sym.info match { - case mt @ MethodType(paramNames @ nme.SELF :: _) => - // 2.12 seems to always assume the enclsing mixin class as self type parameter, - // whereas 2.11 used the self type of this class instead. - val selfType :: otherParamTypes = mt.paramInfos - MethodType(paramNames, mixin.typeRef :: otherParamTypes, mt.resType) - case info => info - } - def newImpl(sym: TermSymbol): Symbol = sym.copy( - owner = mixin, - name = if (sym.isConstructor) sym.name else ImplMethName(sym.name), - info = info_2_12(sym) - ) - for (sym <- mixin.implClass.info.decls) - newImpl(sym.asTerm).enteredAfter(thisTransform) - } - - override def prepareForTemplate(impl: Template)(implicit ctx: Context) = { - val cls = impl.symbol.owner.asClass - for (mixin <- cls.mixins) - if (mixin.is(Scala_2_12_Trait, butNot = Scala_2_12_Augmented)) { - augmentScala_2_12_Trait(mixin) - mixin.setFlag(Scala_2_12_Augmented) - } - this + /** Copy definitions from implementation class to trait itself */ + private def augmentScala_2_12_Trait(mixin: ClassSymbol)(implicit ctx: Context): Unit = { + def info_2_12(sym: Symbol) = sym.info match { + case mt @ MethodType(paramNames @ nme.SELF :: _) => + // 2.12 seems to always assume the enclsing mixin class as self type parameter, + // whereas 2.11 used the self type of this class instead. + val selfType :: otherParamTypes = mt.paramInfos + MethodType(paramNames, mixin.typeRef :: otherParamTypes, mt.resType) + case info => info } + def newImpl(sym: TermSymbol): Symbol = sym.copy( + owner = mixin, + name = if (sym.isConstructor) sym.name else ImplMethName(sym.name), + info = info_2_12(sym) + ) + for (sym <- mixin.implClass.info.decls) + newImpl(sym.asTerm).enteredAfter(thisPhase) + } - override def transformApply(app: Apply)(implicit ctx: Context, info: TransformerInfo) = { - def currentClass = ctx.owner.enclosingClass.asClass - app match { - case Apply(sel @ Select(Super(_, _), _), args) - if sel.symbol.owner.is(Scala2xTrait) && currentClass.mixins.contains(sel.symbol.owner) => - val impl = implMethod(sel.symbol) - if (impl.exists) Apply(ref(impl), This(currentClass) :: args).withPos(app.pos) - else app // could have been an abstract method in a trait linked to from a super constructor - case Apply(sel, args) - if sel.symbol.maybeOwner.is(ImplClass) && sel.symbol.owner.traitOfImplClass.is(Scala_2_12_Trait) => - val impl = implMethod(sel.symbol) - cpy.Apply(app)(ref(impl), args) - case _ => - app + override def prepareForTemplate(impl: Template)(implicit ctx: Context) = { + val cls = impl.symbol.owner.asClass + for (mixin <- cls.mixins) + if (mixin.is(Scala_2_12_Trait, butNot = Scala_2_12_Augmented)) { + augmentScala_2_12_Trait(mixin) + mixin.setFlag(Scala_2_12_Augmented) } - } + ctx + } - /** The 2.12 implementation method of a super call or implementation class target */ - private def implMethod(meth: Symbol)(implicit ctx: Context): Symbol = { - val implName = ImplMethName(meth.name.asTermName) - val cls = meth.owner - if (cls.is(ImplClass)) - cls.traitOfImplClass.info.decl(implName).atSignature(meth.signature).symbol - else if (cls.is(Scala_2_12_Trait)) - if (meth.isConstructor) - cls.info.decl(nme.TRAIT_CONSTRUCTOR).symbol - else - cls.info.decl(implName) - .suchThat(c => FullParameterization.memberSignature(c.info) == meth.signature) - .symbol - else throw new AssertionError(i"no impl method for $meth") + override def transformApply(app: Apply)(implicit ctx: Context) = { + def currentClass = ctx.owner.enclosingClass.asClass + app match { + case Apply(sel @ Select(Super(_, _), _), args) + if sel.symbol.owner.is(Scala2xTrait) && currentClass.mixins.contains(sel.symbol.owner) => + val impl = implMethod(sel.symbol) + if (impl.exists) Apply(ref(impl), This(currentClass) :: args).withPos(app.pos) + else app // could have been an abstract method in a trait linked to from a super constructor + case Apply(sel, args) + if sel.symbol.maybeOwner.is(ImplClass) && sel.symbol.owner.traitOfImplClass.is(Scala_2_12_Trait) => + val impl = implMethod(sel.symbol) + cpy.Apply(app)(ref(impl), args) + case _ => + app } } + /** The 2.12 implementation method of a super call or implementation class target */ + private def implMethod(meth: Symbol)(implicit ctx: Context): Symbol = { + val implName = ImplMethName(meth.name.asTermName) + val cls = meth.owner + if (cls.is(ImplClass)) + cls.traitOfImplClass.info.decl(implName).atSignature(meth.signature).symbol + else if (cls.is(Scala_2_12_Trait)) + if (meth.isConstructor) + cls.info.decl(nme.TRAIT_CONSTRUCTOR).symbol + else + cls.info.decl(implName) + .suchThat(c => FullParameterization.memberSignature(c.info) == meth.signature) + .symbol + else throw new AssertionError(i"no impl method for $meth") + } + private val Scala2xTrait = allOf(Scala2x, Trait) } diff --git a/compiler/src/dotty/tools/dotc/transform/Literalize.scala.disabled b/compiler/src/dotty/tools/dotc/transform/Literalize.scala.disabled index f33baa52b810..6ecdcef7065d 100644 --- a/compiler/src/dotty/tools/dotc/transform/Literalize.scala.disabled +++ b/compiler/src/dotty/tools/dotc/transform/Literalize.scala.disabled @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import TreeTransforms._ +import SuperPhase._ import core.DenotTransformers._ import core.Symbols._ import core.Contexts._ @@ -20,7 +20,7 @@ import dotty.tools.dotc.core.Constants._ * The phase also makes sure that the constant of a literal is the same as the constant * in the type of the literal. */ -class Literalize extends MiniPhaseTransform { thisTransform => +class Literalize extends MiniPhase { thisTransform => import ast.tpd._ override def phaseName: String = "literalize" @@ -60,19 +60,19 @@ class Literalize extends MiniPhaseTransform { thisTransform => recur(tree.tpe) } - override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformIdent(tree: Ident)(implicit ctx: Context): Tree = literalize(tree) - override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformSelect(tree: Select)(implicit ctx: Context): Tree = literalize(tree) - override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformApply(tree: Apply)(implicit ctx: Context): Tree = literalize(tree) - override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformTypeApply(tree: TypeApply)(implicit ctx: Context): Tree = literalize(tree) - override def transformLiteral(tree: Literal)(implicit ctx: Context, info: TransformerInfo): Tree = tree.tpe match { + override def transformLiteral(tree: Literal)(implicit ctx: Context): Tree = tree.tpe match { case ConstantType(const) if tree.const.value != const.value || (tree.const.tag != const.tag) => Literal(const) case _ => tree } diff --git a/compiler/src/dotty/tools/dotc/transform/Memoize.scala b/compiler/src/dotty/tools/dotc/transform/Memoize.scala index 44bb6bd73c88..a2d946a9b696 100644 --- a/compiler/src/dotty/tools/dotc/transform/Memoize.scala +++ b/compiler/src/dotty/tools/dotc/transform/Memoize.scala @@ -12,7 +12,7 @@ import Symbols._ import SymUtils._ import Constants._ import ast.Trees._ -import TreeTransforms._ +import SuperPhase._ import NameOps._ import Flags._ import Decorators._ @@ -32,7 +32,7 @@ import Decorators._ * def x_=(y: T): Unit = () * --> def x_=(y: T): Unit = x = y */ - class Memoize extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform => + class Memoize extends MiniPhase with IdentityDenotTransformer { thisPhase => import ast.tpd._ override def phaseName = "memoize" @@ -66,7 +66,7 @@ import Decorators._ */ override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[Mixin]) - override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformDefDef(tree: DefDef)(implicit ctx: Context): Tree = { val sym = tree.symbol def newField = { @@ -82,7 +82,7 @@ import Decorators._ info = fieldType, coord = tree.pos ).withAnnotationsCarrying(sym, defn.FieldMetaAnnot) - .enteredAfter(thisTransform) + .enteredAfter(thisPhase) } def addAnnotations(denot: Denotation): Unit = @@ -90,7 +90,7 @@ import Decorators._ case fieldDenot: SymDenotation if sym.annotations.nonEmpty => val cpy = fieldDenot.copySymDenotation() cpy.annotations = sym.annotations - cpy.installAfter(thisTransform) + cpy.installAfter(thisPhase) case _ => () } @@ -98,7 +98,7 @@ import Decorators._ if (sym.annotations.nonEmpty) { val cpy = sym.copySymDenotation() cpy.annotations = Nil - cpy.installAfter(thisTransform) + cpy.installAfter(thisPhase) } val NoFieldNeeded = Lazy | Deferred | JavaDefined | (if (ctx.settings.YnoInline.value) EmptyFlags else Inline) @@ -127,13 +127,13 @@ import Decorators._ } if (sym.isGetter) { - var rhs = tree.rhs.changeOwnerAfter(sym, field, thisTransform) + var rhs = tree.rhs.changeOwnerAfter(sym, field, thisPhase) if (isWildcardArg(rhs)) rhs = EmptyTree val fieldDef = transformFollowing(ValDef(field, adaptToField(rhs))) val rhsClass = tree.tpt.tpe.widenDealias.classSymbol val getterRhs = if (isErasableBottomField(rhsClass)) erasedBottomTree(rhsClass) - else transformFollowingDeep(ref(field))(ctx.withOwner(sym), info) + else transformFollowingDeep(ref(field))(ctx.withOwner(sym)) val getterDef = cpy.DefDef(tree)(rhs = getterRhs) addAnnotations(fieldDef.denot) removeAnnotations(sym) @@ -144,7 +144,7 @@ import Decorators._ if (isErasableBottomField(tree.vparamss.head.head.tpt.tpe.classSymbol)) tree else { val initializer = Assign(ref(field), adaptToField(ref(tree.vparamss.head.head.symbol))) - val setterDef = cpy.DefDef(tree)(rhs = transformFollowingDeep(initializer)(ctx.withOwner(sym), info)) + val setterDef = cpy.DefDef(tree)(rhs = transformFollowingDeep(initializer)(ctx.withOwner(sym))) removeAnnotations(sym) setterDef } diff --git a/compiler/src/dotty/tools/dotc/transform/Mixin.scala b/compiler/src/dotty/tools/dotc/transform/Mixin.scala index fc6cc67eba18..c9300274e2cd 100644 --- a/compiler/src/dotty/tools/dotc/transform/Mixin.scala +++ b/compiler/src/dotty/tools/dotc/transform/Mixin.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import core._ -import TreeTransforms._ +import SuperPhase._ import Contexts.Context import Flags._ import SymUtils._ @@ -91,7 +91,7 @@ import collection.mutable * into enclosing classes where they are not visible. This can only be done if all references * are symbolic. */ -class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform => +class Mixin extends MiniPhase with SymTransformer { thisPhase => import ast.tpd._ override def phaseName: String = "mixin" @@ -125,13 +125,13 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform => initName, Protected | Synthetic | Method, sym.info, - coord = sym.symbol.coord).enteredAfter(thisTransform)) + coord = sym.symbol.coord).enteredAfter(thisPhase)) } }.asTerm - override def transformTemplate(impl: Template)(implicit ctx: Context, info: TransformerInfo) = { + override def transformTemplate(impl: Template)(implicit ctx: Context) = { val cls = impl.symbol.owner.asClass - val ops = new MixinOps(cls, thisTransform) + val ops = new MixinOps(cls, thisPhase) import ops._ def traitDefs(stats: List[Tree]): List[Tree] = { @@ -143,8 +143,8 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform => val vsym = stat.symbol val isym = initializer(vsym) val rhs = Block( - initBuf.toList.map(_.changeOwnerAfter(impl.symbol, isym, thisTransform)), - stat.rhs.changeOwnerAfter(vsym, isym, thisTransform).wildcardToDefault) + initBuf.toList.map(_.changeOwnerAfter(impl.symbol, isym, thisPhase)), + stat.rhs.changeOwnerAfter(vsym, isym, thisPhase).wildcardToDefault) initBuf.clear() cpy.DefDef(stat)(rhs = EmptyTree) :: DefDef(isym, rhs) :: Nil case stat: DefDef if stat.symbol.isSetter => @@ -186,7 +186,7 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform => } def was(sym: Symbol, flags: FlagSet) = - ctx.atPhase(thisTransform) { implicit ctx => sym is flags } + ctx.atPhase(thisPhase) { implicit ctx => sym is flags } def traitInits(mixin: ClassSymbol): List[Tree] = { var argNum = 0 diff --git a/compiler/src/dotty/tools/dotc/transform/MixinOps.scala b/compiler/src/dotty/tools/dotc/transform/MixinOps.scala index b63833468660..d3e08d7f9b7e 100644 --- a/compiler/src/dotty/tools/dotc/transform/MixinOps.scala +++ b/compiler/src/dotty/tools/dotc/transform/MixinOps.scala @@ -8,7 +8,7 @@ import SymUtils._ import StdNames._, NameOps._ import Decorators._ -class MixinOps(cls: ClassSymbol, thisTransform: DenotTransformer)(implicit ctx: Context) { +class MixinOps(cls: ClassSymbol, thisPhase: DenotTransformer)(implicit ctx: Context) { import ast.tpd._ val superCls: Symbol = cls.superClass @@ -23,7 +23,7 @@ class MixinOps(cls: ClassSymbol, thisTransform: DenotTransformer)(implicit ctx: owner = cls, name = member.name.stripScala2LocalSuffix, flags = member.flags &~ Deferred, - info = cls.thisType.memberInfo(member)).enteredAfter(thisTransform).asTerm + info = cls.thisType.memberInfo(member)).enteredAfter(thisPhase).asTerm res.addAnnotations(member.annotations) res } @@ -40,10 +40,10 @@ class MixinOps(cls: ClassSymbol, thisTransform: DenotTransformer)(implicit ctx: } /** Is `sym` a member of implementing class `cls`? - * The test is performed at phase `thisTransform`. + * The test is performed at phase `thisPhase`. */ def isCurrent(sym: Symbol) = - ctx.atPhase(thisTransform) { implicit ctx => + ctx.atPhase(thisPhase) { implicit ctx => cls.info.member(sym.name).hasAltWith(_.symbol == sym) // this is a hot spot, where we spend several seconds while compiling stdlib // unfortunately it will discard and recompute all the member chaches, diff --git a/compiler/src/dotty/tools/dotc/transform/MoveStatics.scala b/compiler/src/dotty/tools/dotc/transform/MoveStatics.scala index 0942c0b4af11..f54e41415414 100644 --- a/compiler/src/dotty/tools/dotc/transform/MoveStatics.scala +++ b/compiler/src/dotty/tools/dotc/transform/MoveStatics.scala @@ -13,10 +13,10 @@ import dotty.tools.dotc.core.StdNames.nme import dotty.tools.dotc.core.Phases.Phase import dotty.tools.dotc.core.Symbols._ import dotty.tools.dotc.core.Types.MethodType -import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, TransformerInfo} +import dotty.tools.dotc.transform.SuperPhase.MiniPhase /** Move static methods from companion to the class itself */ -class MoveStatics extends MiniPhaseTransform with SymTransformer { thisTransformer => +class MoveStatics extends MiniPhase with SymTransformer { import tpd._ override def phaseName = "moveStatic" @@ -31,7 +31,7 @@ class MoveStatics extends MiniPhaseTransform with SymTransformer { thisTransform else sym } - override def transformStats(trees: List[Tree])(implicit ctx: Context, info: TransformerInfo): List[Tree] = { + override def transformStats(trees: List[Tree])(implicit ctx: Context): List[Tree] = { if (ctx.owner.is(Flags.Package)) { val (classes, others) = trees.partition(x => x.isInstanceOf[TypeDef] && x.symbol.isClass) val pairs = classes.groupBy(_.symbol.name.stripModuleClassSuffix).asInstanceOf[Map[Name, List[TypeDef]]] diff --git a/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala b/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala index fdee076b452f..b4540acbc749 100644 --- a/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala +++ b/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala @@ -3,7 +3,7 @@ package transform import core._ import Contexts._, Symbols._, Types._, Flags._, Decorators._, StdNames._, Constants._, Phases._ -import TreeTransforms._ +import SuperPhase._ import ast.Trees._ import NameKinds.NonLocalReturnKeyName import collection.mutable @@ -16,7 +16,7 @@ object NonLocalReturns { /** Implement non-local returns using NonLocalReturnControl exceptions. */ -class NonLocalReturns extends MiniPhaseTransform { thisTransformer => +class NonLocalReturns extends MiniPhase { override def phaseName = "nonLocalReturns" import NonLocalReturns._ @@ -81,13 +81,13 @@ class NonLocalReturns extends MiniPhaseTransform { thisTransformer => Block(keyDef :: Nil, tryCatch) } - override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformDefDef(tree: DefDef)(implicit ctx: Context): Tree = nonLocalReturnKeys.remove(tree.symbol) match { case Some(key) => cpy.DefDef(tree)(rhs = nonLocalReturnTry(tree.rhs, key, tree.symbol)) case _ => tree } - override def transformReturn(tree: Return)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformReturn(tree: Return)(implicit ctx: Context): Tree = if (isNonLocalReturn(tree)) nonLocalReturnThrow(tree.expr, tree.from.symbol).withPos(tree.pos) else tree } diff --git a/compiler/src/dotty/tools/dotc/transform/NormalizeFlags.scala b/compiler/src/dotty/tools/dotc/transform/NormalizeFlags.scala index 35a183c84a13..c6cdbe1cafc1 100644 --- a/compiler/src/dotty/tools/dotc/transform/NormalizeFlags.scala +++ b/compiler/src/dotty/tools/dotc/transform/NormalizeFlags.scala @@ -6,7 +6,7 @@ import DenotTransformers.SymTransformer import Phases.Phase import Contexts.Context import SymDenotations.SymDenotation -import TreeTransforms.{MiniPhaseTransform, TransformerInfo} +import SuperPhase.MiniPhase import Flags._, Symbols._ /** 1. Widens all private[this] and protected[this] qualifiers to just private/protected @@ -14,7 +14,7 @@ import Flags._, Symbols._ * do not have initialization code. A pure interface member is either an abstract * or alias type definition or a deferred val or def. */ -class NormalizeFlags extends MiniPhaseTransform with SymTransformer { thisTransformer => +class NormalizeFlags extends MiniPhase with SymTransformer { override def phaseName = "normalizeFlags" def transformSym(ref: SymDenotation)(implicit ctx: Context) = { diff --git a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala index 33b7852ac0a7..901b1a316211 100644 --- a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala +++ b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala @@ -21,7 +21,7 @@ import config.Printers.typr * Do the same also if there are intermediate inaccessible parameter accessor forwarders. * The aim of this transformation is to avoid redundant parameter accessor fields. */ -class ParamForwarding(thisTransformer: DenotTransformer) { +class ParamForwarding(thisPhase: DenotTransformer) { import ast.tpd._ def forwardParamAccessors(impl: Template)(implicit ctx: Context): Template = { @@ -66,7 +66,7 @@ class ParamForwarding(thisTransformer: DenotTransformer) { if (alias.exists) { def forwarder(implicit ctx: Context) = { sym.copySymDenotation(initFlags = sym.flags | Method | Stable, info = sym.info.ensureMethodic) - .installAfter(thisTransformer) + .installAfter(thisPhase) var superAcc = Super(This(currentClass), tpnme.EMPTY, inConstrCall = false).select(alias) if (alias.owner != currentClass.superClass) @@ -77,7 +77,7 @@ class ParamForwarding(thisTransformer: DenotTransformer) { typr.println(i"adding param forwarder $superAcc") DefDef(sym, superAcc.ensureConforms(sym.info.widen)) } - return forwarder(ctx.withPhase(thisTransformer.next)) + return forwarder(ctx.withPhase(thisPhase.next)) } } } @@ -88,7 +88,7 @@ class ParamForwarding(thisTransformer: DenotTransformer) { stats map forwardParamAccessor } - cpy.Template(impl)(body = fwd(impl.body)(ctx.withPhase(thisTransformer))) + cpy.Template(impl)(body = fwd(impl.body)(ctx.withPhase(thisPhase))) } def adaptRef[T <: RefTree](tree: T)(implicit ctx: Context): T = tree.tpe match { diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index 6e8f3141d39b..84b6c1e82792 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import core._ -import TreeTransforms._ +import SuperPhase._ import collection.mutable import SymDenotations._, Symbols._, Contexts._, Types._, Names._, StdNames._, NameOps._ import ast.Trees._ @@ -19,7 +19,7 @@ import config.Printers.patmatch * After this phase, the only Match nodes remaining in the code are simple switches * where every pattern is an integer constant */ -class PatternMatcher extends MiniPhaseTransform { +class PatternMatcher extends MiniPhase { import ast.tpd._ import PatternMatcher._ @@ -27,7 +27,7 @@ class PatternMatcher extends MiniPhaseTransform { override def runsAfter = Set(classOf[ElimRepeated]) override def runsAfterGroupsOf = Set(classOf[TailRec]) // tailrec is not capable of reversing the patmat tranformation made for tree - override def transformMatch(tree: Match)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformMatch(tree: Match)(implicit ctx: Context): Tree = { val translated = new Translator(tree.tpe, this).translateMatch(tree) // check exhaustivity and unreachability @@ -69,7 +69,7 @@ object PatternMatcher { * It's represented by its own data type. Plans are optimized by * inlining, hoisting, and the elimination of redundant tests and dead code. */ - class Translator(resultType: Type, trans: TreeTransform)(implicit ctx: Context, info: TransformerInfo) { + class Translator(resultType: Type, thisPhase: MiniPhase)(implicit ctx: Context) { // ------- Bindings for variables and labels --------------------- @@ -765,7 +765,7 @@ object PatternMatcher { } } - def outerTest: Tree = trans.transformFollowingDeep { + def outerTest: Tree = thisPhase.transformFollowingDeep { val expectedOuter = singleton(expectedTp.normalizedPrefix) val expectedClass = expectedTp.dealias.classSymbol.asClass ExplicitOuter.ensureOuterAccessors(expectedClass) diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcherOld.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcherOld.scala index 6375e4b86aad..733d647cf9d6 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcherOld.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcherOld.scala @@ -3,7 +3,7 @@ package transform import scala.language.postfixOps -import TreeTransforms._ +import SuperPhase._ import core.Denotations._ import core.SymDenotations._ import core.Contexts._ @@ -34,7 +34,7 @@ import dotty.tools.dotc.core.Flags /** This phase rewrites pattern matches. * FIXME: A more detailed explanation would be good. */ -class PatternMatcherOld extends MiniPhaseTransform with DenotTransformer { +class PatternMatcherOld extends MiniPhase with DenotTransformer { import dotty.tools.dotc.ast.tpd._ override def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = ref @@ -47,7 +47,7 @@ class PatternMatcherOld extends MiniPhaseTransform with DenotTransformer { private[this] var _id = 0 // left for debuging - override def transformMatch(tree: Match)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformMatch(tree: Match)(implicit ctx: Context): Tree = { val translated = new Translator()(ctx).translator.translateMatch(tree) // check exhaustivity and unreachability diff --git a/compiler/src/dotty/tools/dotc/transform/PhantomArgLift.scala b/compiler/src/dotty/tools/dotc/transform/PhantomArgLift.scala index 6b823a8ce56f..9ed9335fc7a1 100644 --- a/compiler/src/dotty/tools/dotc/transform/PhantomArgLift.scala +++ b/compiler/src/dotty/tools/dotc/transform/PhantomArgLift.scala @@ -4,7 +4,7 @@ import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Contexts._ import dotty.tools.dotc.core.NameKinds._ import dotty.tools.dotc.core.Types._ -import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, TransformerInfo} +import dotty.tools.dotc.transform.SuperPhase.MiniPhase import dotty.tools.dotc.typer.EtaExpansion import scala.collection.mutable.ListBuffer @@ -24,7 +24,7 @@ import scala.collection.mutable.ListBuffer * `ev$f(ev$x1,...)(ev$y1,...)...(...)` * */ -class PhantomArgLift extends MiniPhaseTransform { +class PhantomArgLift extends MiniPhase { import tpd._ override def phaseName: String = "phantomArgLift" @@ -40,7 +40,7 @@ class PhantomArgLift extends MiniPhaseTransform { /* Tree transform */ - override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = tree.tpe.widen match { + override def transformApply(tree: Apply)(implicit ctx: Context): Tree = tree.tpe.widen match { case _: MethodType => tree // Do the transformation higher in the tree if needed case _ => if (!hasImpurePhantomArgs(tree)) tree diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index 1d235a81ae04..07c6753892ab 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -1,7 +1,6 @@ package dotty.tools.dotc package transform -import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, TreeTransform, TreeTransformer} import dotty.tools.dotc.ast.{Trees, tpd, untpd} import scala.collection.{ mutable, immutable } import ValueClasses._ @@ -54,7 +53,7 @@ import reporting.diagnostic.messages.SuperCallsNotAllowedInline * mini-phase or subfunction of a macro phase equally well. But taken by themselves * they do not warrant their own group of miniphases before pickling. */ -class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTransformer => +class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase => import tpd._ /** the following two members override abstract members in Transform */ @@ -62,14 +61,14 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTrans override def changesMembers = true // the phase adds super accessors and synthetic methods - override def transformPhase(implicit ctx: Context) = thisTransformer.next + override def transformPhase(implicit ctx: Context) = thisPhase.next protected def newTransformer(implicit ctx: Context): Transformer = new PostTyperTransformer - val superAcc = new SuperAccessors(thisTransformer) - val paramFwd = new ParamForwarding(thisTransformer) - val synthMth = new SyntheticMethods(thisTransformer) + val superAcc = new SuperAccessors(thisPhase) + val paramFwd = new ParamForwarding(thisPhase) + val synthMth = new SyntheticMethods(thisPhase) private def newPart(tree: Tree): Option[New] = methPart(tree) match { case Select(nu: New, _) => Some(nu) diff --git a/compiler/src/dotty/tools/dotc/transform/PrimitiveForwarders.scala b/compiler/src/dotty/tools/dotc/transform/PrimitiveForwarders.scala index fec7bd741dab..cc09632063be 100644 --- a/compiler/src/dotty/tools/dotc/transform/PrimitiveForwarders.scala +++ b/compiler/src/dotty/tools/dotc/transform/PrimitiveForwarders.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import core._ -import TreeTransforms._ +import SuperPhase._ import Contexts.Context import Flags._ import SymUtils._ @@ -30,7 +30,7 @@ import ResolveSuper._ * IMPORTANT: When\If Valhalla happens, we'll need to move mixin before erasure and than this code will need to be rewritten * as it will instead change super-class. */ -class PrimitiveForwarders extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform => +class PrimitiveForwarders extends MiniPhase with IdentityDenotTransformer { thisPhase => import ast.tpd._ override def phaseName: String = "primitiveForwarders" @@ -39,9 +39,9 @@ class PrimitiveForwarders extends MiniPhaseTransform with IdentityDenotTransform override def changesMembers = true // the phase adds primitive forwarders - override def transformTemplate(impl: Template)(implicit ctx: Context, info: TransformerInfo) = { + override def transformTemplate(impl: Template)(implicit ctx: Context) = { val cls = impl.symbol.owner.asClass - val ops = new MixinOps(cls, thisTransform) + val ops = new MixinOps(cls, thisPhase) import ops._ def methodPrimitiveForwarders: List[Tree] = diff --git a/compiler/src/dotty/tools/dotc/transform/PrivateToStatic.scala.disabled b/compiler/src/dotty/tools/dotc/transform/PrivateToStatic.scala.disabled index 218839d010be..5e5c1e9b8433 100644 --- a/compiler/src/dotty/tools/dotc/transform/PrivateToStatic.scala.disabled +++ b/compiler/src/dotty/tools/dotc/transform/PrivateToStatic.scala.disabled @@ -11,10 +11,10 @@ import StdNames._ import SymDenotations._ import Types._ import collection.mutable -import TreeTransforms._ +import SuperPhase._ import Decorators._ import ast.Trees._ -import TreeTransforms.TransformerInfo +import SuperPhase.TransformerInfo /** Makes private methods static, provided they not deferred, accessors, or static, * by rewriting a method `m` in class `C` as follows: @@ -56,7 +56,7 @@ class PrivateToStatic extends MiniPhase with SymTransformer { thisTransform => } else this - override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo) = + override def transformDefDef(tree: DefDef)(implicit ctx: Context) = if (shouldBeStatic(tree.symbol)) { val thisParamDef = ValDef(thisParam.asTerm) val vparams :: Nil = tree.vparamss @@ -64,7 +64,7 @@ class PrivateToStatic extends MiniPhase with SymTransformer { thisTransform => } else tree - override def transformThis(tree: This)(implicit ctx: Context, info: TransformerInfo) = + override def transformThis(tree: This)(implicit ctx: Context) = if (shouldBeStatic(ctx.owner.enclosingMethod)) ref(thisParam).withPos(tree.pos) else tree @@ -72,7 +72,7 @@ class PrivateToStatic extends MiniPhase with SymTransformer { thisTransform => * * qual.m(args) --> m(qual, args) */ - override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo) = + override def transformApply(tree: Apply)(implicit ctx: Context) = tree.fun match { case fun @ Select(qual, name) if shouldBeStatic(fun.symbol) => ctx.debuglog(i"mapping $tree to ${cpy.Ident(fun)(name)} (${qual :: tree.args}%, %)") @@ -81,7 +81,7 @@ class PrivateToStatic extends MiniPhase with SymTransformer { thisTransform => tree } - override def transformClosure(tree: Closure)(implicit ctx: Context, info: TransformerInfo) = + override def transformClosure(tree: Closure)(implicit ctx: Context) = tree.meth match { case meth @ Select(qual, name) if shouldBeStatic(meth.symbol) => cpy.Closure(tree)( diff --git a/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala b/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala index 8a7b7665a9ec..2ec20c68fba3 100644 --- a/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala +++ b/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala @@ -9,10 +9,10 @@ import dotty.tools.dotc.core.Names._ import dotty.tools.dotc.core.Phases import dotty.tools.dotc.core.SymDenotations.SymDenotation import dotty.tools.dotc.core.Symbols._ -import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, TransformerInfo} +import dotty.tools.dotc.transform.SuperPhase.MiniPhase /** Renames lifted classes to local numbering scheme */ -class RenameLifted extends MiniPhaseTransform with SymTransformer { thisTransformer => +class RenameLifted extends MiniPhase with SymTransformer { override def phaseName = "renameLifted" diff --git a/compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala b/compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala index 03a8f9678085..fae222da2399 100644 --- a/compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala +++ b/compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import core._ -import TreeTransforms._ +import SuperPhase._ import Contexts.Context import Flags._ import SymUtils._ @@ -45,7 +45,7 @@ import ResolveSuper._ * This is the first part of what was the mixin phase. It is complemented by * Mixin, which runs after erasure. */ -class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform => +class ResolveSuper extends MiniPhase with IdentityDenotTransformer { thisPhase => import ast.tpd._ override def phaseName: String = "resolveSuper" @@ -55,9 +55,9 @@ class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { th override def changesMembers = true // the phase adds super accessors and method forwarders - override def transformTemplate(impl: Template)(implicit ctx: Context, info: TransformerInfo) = { + override def transformTemplate(impl: Template)(implicit ctx: Context) = { val cls = impl.symbol.owner.asClass - val ops = new MixinOps(cls, thisTransform) + val ops = new MixinOps(cls, thisPhase) import ops._ def superAccessors(mixin: ClassSymbol): List[Tree] = @@ -79,12 +79,12 @@ class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { th cpy.Template(impl)(body = overrides ::: impl.body) } - override def transformDefDef(ddef: DefDef)(implicit ctx: Context, info: TransformerInfo) = { + override def transformDefDef(ddef: DefDef)(implicit ctx: Context) = { val meth = ddef.symbol.asTerm if (meth.isSuperAccessor && !meth.is(Deferred)) { assert(ddef.rhs.isEmpty) val cls = meth.owner.asClass - val ops = new MixinOps(cls, thisTransform) + val ops = new MixinOps(cls, thisPhase) import ops._ polyDefDef(meth, forwarder(rebindSuper(cls, meth))) } diff --git a/compiler/src/dotty/tools/dotc/transform/RestoreScopes.scala b/compiler/src/dotty/tools/dotc/transform/RestoreScopes.scala index 8d2b8e25a61a..0004f49822dc 100644 --- a/compiler/src/dotty/tools/dotc/transform/RestoreScopes.scala +++ b/compiler/src/dotty/tools/dotc/transform/RestoreScopes.scala @@ -7,18 +7,17 @@ import Contexts.Context import Symbols._ import Scopes._ import collection.mutable -import TreeTransforms.MiniPhaseTransform +import SuperPhase.MiniPhase import SymDenotations._ import ast.Trees._ import NameOps._ -import TreeTransforms.TransformerInfo import StdNames._ /** The preceding lambda lift and flatten phases move symbols to different scopes * and rename them. This miniphase cleans up afterwards and makes sure that all * class scopes contain the symbols defined in them. */ -class RestoreScopes extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform => +class RestoreScopes extends MiniPhase with IdentityDenotTransformer { thisPhase => import ast.tpd._ override def phaseName = "restoreScopes" @@ -29,12 +28,12 @@ class RestoreScopes extends MiniPhaseTransform with IdentityDenotTransformer { t * enclosing package definitions. So by the time RestoreScopes gets to * see a typedef or template, it still might be changed by DropEmptyConstructors. */ - override def transformPackageDef(pdef: PackageDef)(implicit ctx: Context, info: TransformerInfo) = { + override def transformPackageDef(pdef: PackageDef)(implicit ctx: Context) = { pdef.stats.foreach(restoreScope) pdef } - private def restoreScope(tree: Tree)(implicit ctx: Context, info: TransformerInfo) = tree match { + private def restoreScope(tree: Tree)(implicit ctx: Context) = tree match { case TypeDef(_, impl: Template) => val restoredDecls = newScope for (stat <- impl.constr :: impl.body) @@ -61,7 +60,7 @@ class RestoreScopes extends MiniPhaseTransform with IdentityDenotTransformer { t val cinfo = cls.classInfo tree.symbol.copySymDenotation( info = cinfo.derivedClassInfo( // Dotty deviation: Cannot expand cinfo inline without a type error - decls = restoredDecls: Scope)).installAfter(thisTransform) + decls = restoredDecls: Scope)).installAfter(thisPhase) tree case tree => tree } diff --git a/compiler/src/dotty/tools/dotc/transform/SelectStatic.scala b/compiler/src/dotty/tools/dotc/transform/SelectStatic.scala index b90c6ed37620..99b0e1998d9f 100644 --- a/compiler/src/dotty/tools/dotc/transform/SelectStatic.scala +++ b/compiler/src/dotty/tools/dotc/transform/SelectStatic.scala @@ -8,19 +8,19 @@ import dotty.tools.dotc.core.DenotTransformers.IdentityDenotTransformer import dotty.tools.dotc.core.Flags._ import dotty.tools.dotc.core.Symbols._ import dotty.tools.dotc.core._ -import dotty.tools.dotc.transform.TreeTransforms._ +import dotty.tools.dotc.transform.SuperPhase._ /** Removes selects that would be compiled into GetStatic * otherwise backend needs to be aware that some qualifiers need to be dropped. * Similar transformation seems to be performed by flatten in nsc * @author Dmytro Petrashko */ -class SelectStatic extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform => +class SelectStatic extends MiniPhase with IdentityDenotTransformer { import ast.tpd._ override def phaseName: String = "selectStatic" - override def transformSelect(tree: tpd.Select)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformSelect(tree: tpd.Select)(implicit ctx: Context): tpd.Tree = { val sym = tree.symbol def isStaticMember = (sym is Flags.Module) && sym.initial.maybeOwner.initial.isStaticOwner || @@ -48,15 +48,15 @@ class SelectStatic extends MiniPhaseTransform with IdentityDenotTransformer { th case _ => t } - override def transformApply(tree: tpd.Apply)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformApply(tree: tpd.Apply)(implicit ctx: Context): tpd.Tree = { normalize(tree) } - override def transformTypeApply(tree: tpd.TypeApply)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformTypeApply(tree: tpd.TypeApply)(implicit ctx: Context): tpd.Tree = { normalize(tree) } - override def transformClosure(tree: tpd.Closure)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformClosure(tree: tpd.Closure)(implicit ctx: Context): tpd.Tree = { normalize(tree) } } diff --git a/compiler/src/dotty/tools/dotc/transform/SeqLiterals.scala b/compiler/src/dotty/tools/dotc/transform/SeqLiterals.scala index 49ea695300bb..fbce0be30b17 100644 --- a/compiler/src/dotty/tools/dotc/transform/SeqLiterals.scala +++ b/compiler/src/dotty/tools/dotc/transform/SeqLiterals.scala @@ -3,7 +3,7 @@ package transform import core._ import Types._ -import dotty.tools.dotc.transform.TreeTransforms._ +import dotty.tools.dotc.transform.SuperPhase._ import Contexts.Context import Symbols._ import Phases._ @@ -18,7 +18,7 @@ import Decorators._ * is called directly. The reason for this step is that JavaSeqLiterals, being arrays * keep a precise type after erasure, whereas SeqLiterals only get the erased type `Seq`, */ -class SeqLiterals extends MiniPhaseTransform { +class SeqLiterals extends MiniPhase { import ast.tpd._ override def phaseName = "seqLiterals" @@ -29,7 +29,7 @@ class SeqLiterals extends MiniPhaseTransform { case _ => } - override def transformSeqLiteral(tree: SeqLiteral)(implicit ctx: Context, info: TransformerInfo): Tree = tree match { + override def transformSeqLiteral(tree: SeqLiteral)(implicit ctx: Context): Tree = tree match { case tree: JavaSeqLiteral => tree case _ => val arr = JavaSeqLiteral(tree.elems, tree.elemtpt) diff --git a/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala b/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala index 91301c0cd86e..646de1ae3b92 100644 --- a/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala +++ b/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import TreeTransforms._ +import SuperPhase._ import core.DenotTransformers.IdentityDenotTransformer import core.Symbols._ import core.Contexts._ @@ -14,8 +14,19 @@ import core.NameOps._ import core.NameKinds.DirectMethodName import ast.Trees._ import ast.tpd +import util.Property import collection.mutable +object ShortcutImplicits { + private type DirectMeths = mutable.HashMap[Symbol, Symbol] + private val DirectMeth = new Property.Key[DirectMeths] + + /** A map to cache mapping local methods to their direct counterparts. + * A fresh map is created for each unit. + */ + private def directMeth(implicit ctx: Context) = ctx.property(DirectMeth).get +} + /** This phase optimizes code using implicit function types, by applying two rewrite rules. * Let IF be the implicit function type * @@ -44,15 +55,14 @@ import collection.mutable * `qual` refers to a method `m` is rewritten to a reference to `m$direct`, * keeping the same type and value arguments as they are found in `qual`. */ -class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisTransform => +class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisPhase => import tpd._ + import ShortcutImplicits._ override def phaseName: String = "shortcutImplicits" override def changesMembers = true // the phase adds "direct" methods - val treeTransform = new Transform - /** If this option is true, we don't specialize symbols that are known to be only * targets of monomorphic calls. * The reason for this option is that benchmarks show that on the JVM for monomorphic dispatch @@ -61,109 +71,101 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisTr */ final val specializeMonoTargets = true - class Transform extends TreeTransform { - def phase = thisTransform - - override def prepareForUnit(tree: Tree)(implicit ctx: Context) = new Transform - - /** A map to cache mapping local methods to their direct counterparts. - * A fresh map is created for each unit. - */ - private val directMeth = new mutable.HashMap[Symbol, Symbol] - - /** Should `sym` get a ..$direct companion? - * This is the case if (1) `sym` is a method with an implicit function type as final result type. - * However if `specializeMonoTargets` is false, we exclude symbols that are known - * to be only targets of monomorphic calls because they are effectively - * final and don't override anything. - */ - private def shouldBeSpecialized(sym: Symbol)(implicit ctx: Context) = - sym.is(Method, butNot = Accessor) && - defn.isImplicitFunctionType(sym.info.finalResultType) && - !sym.isAnonymousFunction && - (specializeMonoTargets || !sym.isEffectivelyFinal || sym.allOverriddenSymbols.nonEmpty) - - /** @pre The type's final result type is an implicit function type `implicit Ts => R`. - * @return The type of the `apply` member of `implicit Ts => R`. - */ - private def directInfo(info: Type)(implicit ctx: Context): Type = info match { - case info: PolyType => info.derivedLambdaType(resType = directInfo(info.resultType)) - case info: MethodType => info.derivedLambdaType(resType = directInfo(info.resultType)) - case info: ExprType => directInfo(info.resultType) - case info => info.member(nme.apply).info - } + override def prepareForUnit(tree: Tree)(implicit ctx: Context) = + ctx.fresh.setProperty(DirectMeth, new DirectMeths) + + /** Should `sym` get a ..$direct companion? + * This is the case if (1) `sym` is a method with an implicit function type as final result type. + * However if `specializeMonoTargets` is false, we exclude symbols that are known + * to be only targets of monomorphic calls because they are effectively + * final and don't override anything. + */ + private def shouldBeSpecialized(sym: Symbol)(implicit ctx: Context) = + sym.is(Method, butNot = Accessor) && + defn.isImplicitFunctionType(sym.info.finalResultType) && + !sym.isAnonymousFunction && + (specializeMonoTargets || !sym.isEffectivelyFinal || sym.allOverriddenSymbols.nonEmpty) + + /** @pre The type's final result type is an implicit function type `implicit Ts => R`. + * @return The type of the `apply` member of `implicit Ts => R`. + */ + private def directInfo(info: Type)(implicit ctx: Context): Type = info match { + case info: PolyType => info.derivedLambdaType(resType = directInfo(info.resultType)) + case info: MethodType => info.derivedLambdaType(resType = directInfo(info.resultType)) + case info: ExprType => directInfo(info.resultType) + case info => info.member(nme.apply).info + } - /** A new `m$direct` method to accompany the given method `m` */ - private def newDirectMethod(sym: Symbol)(implicit ctx: Context): Symbol = { - val direct = sym.copy( - name = DirectMethodName(sym.name.asTermName).asInstanceOf[sym.ThisName], - flags = sym.flags | Synthetic, - info = directInfo(sym.info)) - if (direct.allOverriddenSymbols.isEmpty) direct.resetFlag(Override) - direct - } + /** A new `m$direct` method to accompany the given method `m` */ + private def newDirectMethod(sym: Symbol)(implicit ctx: Context): Symbol = { + val direct = sym.copy( + name = DirectMethodName(sym.name.asTermName).asInstanceOf[sym.ThisName], + flags = sym.flags | Synthetic, + info = directInfo(sym.info)) + if (direct.allOverriddenSymbols.isEmpty) direct.resetFlag(Override) + direct + } - /** The direct method `m$direct` that accompanies the given method `m`. - * Create one if it does not exist already. - */ - private def directMethod(sym: Symbol)(implicit ctx: Context): Symbol = - if (sym.owner.isClass) { - val direct = sym.owner.info.member(DirectMethodName(sym.name.asTermName)) - .suchThat(_.info matches directInfo(sym.info)).symbol - if (direct.maybeOwner == sym.owner) direct - else newDirectMethod(sym).enteredAfter(thisTransform) + /** The direct method `m$direct` that accompanies the given method `m`. + * Create one if it does not exist already. + */ + private def directMethod(sym: Symbol)(implicit ctx: Context): Symbol = + if (sym.owner.isClass) { + val direct = sym.owner.info.member(DirectMethodName(sym.name.asTermName)) + .suchThat(_.info matches directInfo(sym.info)).symbol + if (direct.maybeOwner == sym.owner) direct + else newDirectMethod(sym).enteredAfter(thisPhase) + } + else directMeth.getOrElseUpdate(sym, newDirectMethod(sym)) + + /** Transform `qual.apply` occurrences according to rewrite rule (2) above */ + override def transformSelect(tree: Select)(implicit ctx: Context) = + if (tree.name == nme.apply && + defn.isImplicitFunctionType(tree.qualifier.tpe.widen) && + shouldBeSpecialized(tree.qualifier.symbol)) { + def directQual(tree: Tree): Tree = tree match { + case Apply(fn, args) => cpy.Apply(tree)(directQual(fn), args) + case TypeApply(fn, args) => cpy.TypeApply(tree)(directQual(fn), args) + case Block(stats, expr) => cpy.Block(tree)(stats, directQual(expr)) + case tree: RefTree => + cpy.Ref(tree)(DirectMethodName(tree.name.asTermName)) + .withType(directMethod(tree.symbol).termRef) } - else directMeth.getOrElseUpdate(sym, newDirectMethod(sym)) - - /** Transform `qual.apply` occurrences according to rewrite rule (2) above */ - override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) = - if (tree.name == nme.apply && - defn.isImplicitFunctionType(tree.qualifier.tpe.widen) && - shouldBeSpecialized(tree.qualifier.symbol)) { - def directQual(tree: Tree): Tree = tree match { - case Apply(fn, args) => cpy.Apply(tree)(directQual(fn), args) - case TypeApply(fn, args) => cpy.TypeApply(tree)(directQual(fn), args) - case Block(stats, expr) => cpy.Block(tree)(stats, directQual(expr)) - case tree: RefTree => - cpy.Ref(tree)(DirectMethodName(tree.name.asTermName)) - .withType(directMethod(tree.symbol).termRef) - } - directQual(tree.qualifier) - } else tree - - /** Transform methods with implicit function type result according to rewrite rule (1) above */ - override def transformDefDef(mdef: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = { - val original = mdef.symbol - if (shouldBeSpecialized(original)) { - val direct = directMethod(original) - - def splitClosure(tree: Tree): (List[Type] => List[List[Tree]] => Tree, Tree) = tree match { - case Block(Nil, expr) => splitClosure(expr) - case Block((meth @ DefDef(nme.ANON_FUN, Nil, clparams :: Nil, _, _)) :: Nil, cl: Closure) => - val tparamSyms = mdef.tparams.map(_.symbol) - val vparamSymss = mdef.vparamss.map(_.map(_.symbol)) - val clparamSyms = clparams.map(_.symbol) - val remappedCore = (ts: List[Type]) => (prefss: List[List[Tree]]) => - meth.rhs - .subst(tparamSyms ::: (vparamSymss.flatten ++ clparamSyms), - ts.map(_.typeSymbol) ::: prefss.flatten.map(_.symbol)) - .changeOwnerAfter(original, direct, thisTransform) - .changeOwnerAfter(meth.symbol, direct, thisTransform) - val forwarder = ref(direct) - .appliedToTypeTrees(tparamSyms.map(ref(_))) - .appliedToArgss(vparamSymss.map(_.map(ref(_))) :+ clparamSyms.map(ref(_))) - val fwdClosure = cpy.Block(tree)(cpy.DefDef(meth)(rhs = forwarder) :: Nil, cl) - (remappedCore, fwdClosure) - case EmptyTree => - (_ => _ => EmptyTree, EmptyTree) - } - - val (remappedCore, fwdClosure) = splitClosure(mdef.rhs) - val originalDef = cpy.DefDef(mdef)(rhs = fwdClosure) - val directDef = transformDefDef(polyDefDef(direct.asTerm, remappedCore)) - flatTree(List(originalDef, directDef)) + directQual(tree.qualifier) + } else tree + + /** Transform methods with implicit function type result according to rewrite rule (1) above */ + override def transformDefDef(mdef: DefDef)(implicit ctx: Context): Tree = { + val original = mdef.symbol + if (shouldBeSpecialized(original)) { + val direct = directMethod(original) + + def splitClosure(tree: Tree): (List[Type] => List[List[Tree]] => Tree, Tree) = tree match { + case Block(Nil, expr) => splitClosure(expr) + case Block((meth @ DefDef(nme.ANON_FUN, Nil, clparams :: Nil, _, _)) :: Nil, cl: Closure) => + val tparamSyms = mdef.tparams.map(_.symbol) + val vparamSymss = mdef.vparamss.map(_.map(_.symbol)) + val clparamSyms = clparams.map(_.symbol) + val remappedCore = (ts: List[Type]) => (prefss: List[List[Tree]]) => + meth.rhs + .subst(tparamSyms ::: (vparamSymss.flatten ++ clparamSyms), + ts.map(_.typeSymbol) ::: prefss.flatten.map(_.symbol)) + .changeOwnerAfter(original, direct, thisPhase) + .changeOwnerAfter(meth.symbol, direct, thisPhase) + val forwarder = ref(direct) + .appliedToTypeTrees(tparamSyms.map(ref(_))) + .appliedToArgss(vparamSymss.map(_.map(ref(_))) :+ clparamSyms.map(ref(_))) + val fwdClosure = cpy.Block(tree)(cpy.DefDef(meth)(rhs = forwarder) :: Nil, cl) + (remappedCore, fwdClosure) + case EmptyTree => + (_ => _ => EmptyTree, EmptyTree) } - else mdef + + val (remappedCore, fwdClosure) = splitClosure(mdef.rhs) + val originalDef = cpy.DefDef(mdef)(rhs = fwdClosure) + val directDef = transformDefDef(polyDefDef(direct.asTerm, remappedCore)) + flatTree(List(originalDef, directDef)) } + else mdef } } diff --git a/compiler/src/dotty/tools/dotc/transform/Splitter.scala b/compiler/src/dotty/tools/dotc/transform/Splitter.scala index 3b6af780c6b9..d8edf6d22293 100644 --- a/compiler/src/dotty/tools/dotc/transform/Splitter.scala +++ b/compiler/src/dotty/tools/dotc/transform/Splitter.scala @@ -1,14 +1,14 @@ package dotty.tools.dotc package transform -import TreeTransforms._ +import SuperPhase._ import ast.Trees._ import core._ import Contexts._, Types._, Decorators._, Denotations._, Symbols._, SymDenotations._, Names._ /** Distribute applications into Block and If nodes */ -class Splitter extends MiniPhaseTransform { thisTransform => +class Splitter extends MiniPhase { import ast.tpd._ override def phaseName: String = "splitter" @@ -23,10 +23,10 @@ class Splitter extends MiniPhaseTransform { thisTransform => recur(tree.fun) } - override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo) = + override def transformTypeApply(tree: TypeApply)(implicit ctx: Context) = distribute(tree, typeApply) - override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo) = + override def transformApply(tree: Apply)(implicit ctx: Context) = distribute(tree, apply) private val typeApply = (fn: Tree, args: List[Tree]) => (ctx: Context) => TypeApply(fn, args)(ctx) @@ -48,7 +48,7 @@ class Splitter extends MiniPhaseTransform { thisTransform => * if (ev$1.isInstanceOf[A]) ev$1.asInstanceOf[A].f(a) * else ev$1.asInstanceOf[B].f(a) */ - override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) = { + override def transformSelect(tree: Select)(implicit ctx: Context) = { val Select(qual, name) = tree def memberDenot(tp: Type): SingleDenotation = { diff --git a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala index e223bff6e992..879a7fc9ccad 100644 --- a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, TreeTransform, TreeTransformer} +import dotty.tools.dotc.transform.SuperPhase._ import dotty.tools.dotc.ast.{Trees, tpd} import scala.collection.{ mutable, immutable } import ValueClasses._ @@ -35,7 +35,7 @@ import Symbols._, TypeUtils._, SymUtils._ * * (4) Super calls do not go to synthetic field accessors */ -class SuperAccessors(thisTransformer: DenotTransformer) { +class SuperAccessors(thisPhase: DenotTransformer) { import tpd._ @@ -83,7 +83,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) { val deferredOrPrivate = if (clazz is Trait) Deferred else Private val acc = ctx.newSymbol( clazz, superName, Artifact | Method | deferredOrPrivate, - superInfo, coord = sym.coord).enteredAfter(thisTransformer) + superInfo, coord = sym.coord).enteredAfter(thisPhase) // Diagnostic for SI-7091 if (!accDefs.contains(clazz)) ctx.error(s"Internal error: unable to store accessor definition in ${clazz}. clazz.hasPackageFlag=${clazz is Package}. Accessor required for ${sel} (${sel.show})", sel.pos) @@ -130,7 +130,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) { } if (name.isTermName && mix.name.isEmpty && ((clazz is Trait) || clazz != ctx.owner.enclosingClass || !validCurrentClass)) - superAccessorCall(sel)(ctx.withPhase(thisTransformer.next)) + superAccessorCall(sel)(ctx.withPhase(thisPhase.next)) else sel } @@ -183,7 +183,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) { } val protectedAccessor = clazz.info.decl(accName).suchThat(_.signature == accType.signature).symbol orElse { val newAcc = ctx.newSymbol( - clazz, accName, Artifact | Method, accType, coord = sel.pos).enteredAfter(thisTransformer) + clazz, accName, Artifact | Method, accType, coord = sel.pos).enteredAfter(thisPhase) val code = polyDefDef(newAcc, trefs => vrefss => { val (receiver :: _) :: tail = vrefss val base = receiver.select(sym).appliedToTypes(trefs) @@ -235,7 +235,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) { val accType = accTypeOf(sym.info) val protectedAccessor = clazz.info.decl(accName).suchThat(_.signature == accType.signature).symbol orElse { val newAcc = ctx.newSymbol( - clazz, accName, Artifact, accType, coord = tree.pos).enteredAfter(thisTransformer) + clazz, accName, Artifact, accType, coord = tree.pos).enteredAfter(thisPhase) val code = polyDefDef(newAcc, trefs => vrefss => { val (receiver :: _) :: tail = vrefss val base = receiver.select(sym).appliedToTypes(trefs) @@ -267,7 +267,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) { val accType = MethodType(clazz.classInfo.selfType :: field.info :: Nil, defn.UnitType) val protectedAccessor = clazz.info.decl(accName).symbol orElse { val newAcc = ctx.newSymbol( - clazz, accName, Artifact, accType, coord = tree.pos).enteredAfter(thisTransformer) + clazz, accName, Artifact, accType, coord = tree.pos).enteredAfter(thisPhase) val code = DefDef(newAcc, vrefss => { val (receiver :: value :: Nil) :: Nil = vrefss Assign(receiver.select(field), value).withPos(tree.pos) diff --git a/compiler/src/dotty/tools/dotc/transform/SuperPhase.scala b/compiler/src/dotty/tools/dotc/transform/SuperPhase.scala index 052445ad766d..c1493fcacdad 100644 --- a/compiler/src/dotty/tools/dotc/transform/SuperPhase.scala +++ b/compiler/src/dotty/tools/dotc/transform/SuperPhase.scala @@ -121,7 +121,7 @@ object SuperPhase { def transformFollowing(tree: Tree)(implicit ctx: Context): Tree = superPhase.transformNode(tree, idxInGroup + 1) - protected def singletonGroup = new SuperPhase(phaseName, Array(this)) + protected def singletonGroup = new SuperPhase(Array(this)) override def run(implicit ctx: Context): Unit = singletonGroup.run @@ -135,9 +135,13 @@ object SuperPhase { } import SuperPhase._ -class SuperPhase(override val phaseName: String, val miniPhases: Array[MiniPhase]) extends Phase { +class SuperPhase(val miniPhases: Array[MiniPhase]) extends Phase { import ast.tpd._ + override val phaseName = + if (miniPhases.length == 1) miniPhases(0).phaseName + else miniPhases.map(_.phaseName).mkString("SuperPhase{", ", ", "}") + private val cpy: TypedTreeCopier = cpyBetweenPhases /** Transform node using all phases in this group that have idxInGroup >= start */ @@ -216,7 +220,7 @@ class SuperPhase(override val phaseName: String, val miniPhases: Array[MiniPhase trans(cpy.Match(tree1)(selector, cases)) case Tag.CaseDef => val tree1 = tree.asInstanceOf[CaseDef] - val pat = transformTree(tree1.pat, start) + val pat = transformTree(tree1.pat, start)(ctx.addMode(Mode.Pattern)) val guard = transformTree(tree1.guard, start) val body = transformTree(tree1.body, start) trans(cpy.CaseDef(tree1)(pat, guard, body)) @@ -258,45 +262,42 @@ class SuperPhase(override val phaseName: String, val miniPhases: Array[MiniPhase trans(cpy.UnApply(tree1)(fun, implicits, patterns)) case Tag.ValDef => val tree1 = tree.asInstanceOf[ValDef] - def transformValDef(implicit ctx: Context) = { + def mapValDef(implicit ctx: Context) = { val tpt = transformTree(tree1.tpt, start) val rhs = transformTree(tree1.rhs, start) - trans(cpy.ValDef(tree1)(tree1.name, tpt, rhs)) + cpy.ValDef(tree1)(tree1.name, tpt, rhs) } if (tree1.isEmpty) tree1 - else transformValDef(if (tree.symbol.exists) localContext else ctx) + else trans(mapValDef(if (tree.symbol.exists) localContext else ctx)) case Tag.DefDef => val tree1 = tree.asInstanceOf[DefDef] - def transformDefDef(implicit ctx: Context) = { + def mapDefDef(implicit ctx: Context) = { val tparams = transformSpecificTrees(tree1.tparams, start) val vparamss = tree1.vparamss.mapConserve(transformSpecificTrees(_, start)) val tpt = transformTree(tree1.tpt, start) val rhs = transformTree(tree1.rhs, start) - trans(cpy.DefDef(tree1)(tree1.name, tparams, vparamss, tpt, rhs)) + cpy.DefDef(tree1)(tree1.name, tparams, vparamss, tpt, rhs) } - transformDefDef(localContext) + trans(mapDefDef(localContext)) case Tag.TypeDef => val tree1 = tree.asInstanceOf[TypeDef] - def transformTypeDef(implicit ctx: Context) = { - val rhs = transformTree(tree1.rhs, start) - trans(cpy.TypeDef(tree1)(tree1.name, rhs)) - } - transformTypeDef(localContext) + val rhs = transformTree(tree1.rhs, start)(localContext) + trans(cpy.TypeDef(tree1)(tree1.name, rhs)) case Tag.Template => val tree1 = tree.asInstanceOf[Template] val constr = transformSpecificTree(tree1.constr, start) - val parents = transformTrees(tree1.parents, start) + val parents = transformTrees(tree1.parents, start)(ctx.superCallContext) val self = transformSpecificTree(tree1.self, start) val body = transformStats(tree1.body, tree1.symbol, start) trans(cpy.Template(tree1)(constr, parents, self, body)) case Tag.PackageDef => val tree1 = tree.asInstanceOf[PackageDef] - def transformPackage(implicit ctx: Context) = { + def mapPackage(implicit ctx: Context) = { val pid = transformSpecificTree(tree1.pid, start) val stats = transformStats(tree1.stats, tree.symbol, start) - trans(cpy.PackageDef(tree1)(pid, stats)) + cpy.PackageDef(tree1)(pid, stats) } - transformPackage(localContext) + trans(mapPackage(localContext)) case Tag.Thicket => val tree1 = tree.asInstanceOf[Thicket] cpy.Thicket(tree1)(transformTrees(tree1.trees, start)) @@ -333,7 +334,8 @@ class SuperPhase(override val phaseName: String, val miniPhases: Array[MiniPhase transformTrees(trees, start).asInstanceOf[List[T]] override def run(implicit ctx: Context): Unit = - ctx.compilationUnit.tpdTree = transformUnit(ctx.compilationUnit.tpdTree) + ctx.compilationUnit.tpdTree = + transformUnit(ctx.compilationUnit.tpdTree)(ctx.withPhase(miniPhases.last.next)) // The rest of this class is all made up by initialization code @@ -401,7 +403,8 @@ class SuperPhase(override val phaseName: String, val miniPhases: Array[MiniPhase private val nodeTransformer: Array[Array[Transformer[Tree, Tree]]] = Array.fill(Tag.NumTags)(otherNodeTransformer) - private def init(name: String, tag: TreeTag, ctf: IndexedTransformer[_, Context], ntf: IndexedTransformer[_, Tree]): Unit = { + // Dotty problem, replace T with _ in the line below, and you get an irreducible application errpr + private def init[T](name: String, tag: TreeTag, ctf: IndexedTransformer[T, Context], ntf: IndexedTransformer[T, Tree]): Unit = { if (miniPhases.exists(defines(_, "prepareFor" + name))) contextTransformer(tag) = newContextTransformerArray(name, ctf.asInstanceOf[IndexedTransformer[Tree, Context]]) if (miniPhases.exists(defines(_, "transform" + name))) diff --git a/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala b/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala index 74e3b6821a9d..e8a85a805c48 100644 --- a/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala @@ -5,7 +5,7 @@ import core._ import Symbols._, Types._, Contexts._, Names._, StdNames._, Constants._, SymUtils._ import scala.collection.{ mutable, immutable } import Flags._ -import TreeTransforms._ +import SuperPhase._ import DenotTransformers._ import ast.Trees._ import ast.untpd @@ -36,7 +36,7 @@ import scala.language.postfixOps * def equals(other: Any): Boolean * def hashCode(): Int */ -class SyntheticMethods(thisTransformer: DenotTransformer) { +class SyntheticMethods(thisPhase: DenotTransformer) { import ast.tpd._ private[this] var myValueSymbols: List[Symbol] = Nil @@ -80,7 +80,7 @@ class SyntheticMethods(thisTransformer: DenotTransformer) { val synthetic = sym.copy( owner = clazz, flags = sym.flags &~ Deferred | Synthetic | Override, - coord = clazz.coord).enteredAfter(thisTransformer).asTerm + coord = clazz.coord).enteredAfter(thisPhase).asTerm def forwardToRuntime(vrefss: List[List[Tree]]): Tree = ref(defn.runtimeMethodRef("_" + sym.name.toString)).appliedToArgs(This(clazz) :: vrefss.head) diff --git a/compiler/src/dotty/tools/dotc/transform/TailRec.scala b/compiler/src/dotty/tools/dotc/transform/TailRec.scala index f6660e813b9d..08c7ad5ca240 100644 --- a/compiler/src/dotty/tools/dotc/transform/TailRec.scala +++ b/compiler/src/dotty/tools/dotc/transform/TailRec.scala @@ -12,7 +12,7 @@ import Symbols._ import Types._ import NameKinds.TailLabelName import TreeTransforms.{MiniPhaseTransform, TransformerInfo} -import reporting.diagnostic.messages.TailrecNotApplicable +import SuperPhase.MiniPhase /** * A Tail Rec Transformer @@ -63,7 +63,7 @@ import reporting.diagnostic.messages.TailrecNotApplicable * self recursive functions, that's why it's renamed to tailrec *

*/ -class TailRec extends MiniPhaseTransform with FullParameterization { thisTransform => +class TailRec extends MiniPhase with FullParameterization { import TailRec._ import dotty.tools.dotc.ast.tpd._ @@ -75,12 +75,12 @@ class TailRec extends MiniPhaseTransform with FullParameterization { thisTransfo /** Symbols of methods that have @tailrec annotatios inside */ private val methodsWithInnerAnnots = new collection.mutable.HashSet[Symbol]() - override def transformUnit(tree: Tree)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformUnit(tree: Tree)(implicit ctx: Context): Tree = { methodsWithInnerAnnots.clear() tree } - override def transformTyped(tree: Typed)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformTyped(tree: Typed)(implicit ctx: Context): Tree = { if (tree.tpt.tpe.hasAnnotation(defn.TailrecAnnot)) methodsWithInnerAnnots += ctx.owner.enclosingMethod tree @@ -94,7 +94,7 @@ class TailRec extends MiniPhaseTransform with FullParameterization { thisTransfo else ctx.newSymbol(method, name.toTermName, labelFlags, method.info) } - override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context): tpd.Tree = { val sym = tree.symbol tree match { case dd@DefDef(name, tparams, vparamss0, tpt, _) diff --git a/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala b/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala index f500583d172a..8bce96d017c8 100644 --- a/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala +++ b/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import TreeTransforms._ +import SuperPhase._ import core._ import Symbols._ import SymDenotations._ @@ -17,12 +17,12 @@ import reporting.trace /** Abstract base class of ByNameClosures and ElimByName, factoring out the * common functionality to transform arguments of by-name parameters. */ -abstract class TransformByNameApply extends MiniPhaseTransform { thisTransformer: DenotTransformer => +abstract class TransformByNameApply extends MiniPhase { thisPhase: DenotTransformer => import ast.tpd._ /** The info of the tree's symbol before it is potentially transformed in this phase */ private def originalDenotation(tree: Tree)(implicit ctx: Context) = - tree.symbol.denot(ctx.withPhase(thisTransformer)) + tree.symbol.denot(ctx.withPhase(thisPhase)) /** If denotation had an ExprType before, it now gets a function type */ protected def exprBecomesFunction(symd: SymDenotation)(implicit ctx: Context) = @@ -35,7 +35,7 @@ abstract class TransformByNameApply extends MiniPhaseTransform { thisTransformer def mkByNameClosure(arg: Tree, argType: Type)(implicit ctx: Context): Tree = unsupported(i"mkClosure($arg)") - override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformApply(tree: Apply)(implicit ctx: Context): Tree = trace(s"transforming ${tree.show} at phase ${ctx.phase}", show = true) { def transformArg(arg: Tree, formal: Type): Tree = formal.dealias match { diff --git a/compiler/src/dotty/tools/dotc/transform/TransformWildcards.scala b/compiler/src/dotty/tools/dotc/transform/TransformWildcards.scala index 946722227af9..c3c7fdf96abe 100644 --- a/compiler/src/dotty/tools/dotc/transform/TransformWildcards.scala +++ b/compiler/src/dotty/tools/dotc/transform/TransformWildcards.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import TreeTransforms._ +import SuperPhase._ import core.DenotTransformers._ import core.Contexts._ import ast.tpd @@ -11,7 +11,7 @@ import ast.tpd * `val x : T = _` to `val x : T = ` * */ -class TransformWildcards extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform => +class TransformWildcards extends MiniPhase with IdentityDenotTransformer { import tpd._ override def phaseName = "transformWildcards" @@ -23,7 +23,7 @@ class TransformWildcards extends MiniPhaseTransform with IdentityDenotTransforme } } - override def transformValDef(tree: ValDef)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformValDef(tree: ValDef)(implicit ctx: Context): Tree = { if (ctx.owner.isClass) tree else cpy.ValDef(tree)(rhs = tree.rhs.wildcardToDefault) } diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index e2237c187a27..45fab5ad5821 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import TreeTransforms._ +import SuperPhase._ import core.Names.Name import core.DenotTransformers._ import core.Denotations._ @@ -106,7 +106,7 @@ class TreeChecker extends Phase with SymTransformer { } private def previousPhases(phases: List[Phase])(implicit ctx: Context): List[Phase] = phases match { - case (phase: TreeTransformer) :: phases1 => + case (phase: SuperPhase) :: phases1 => val subPhases = phase.miniPhases val previousSubPhases = previousPhases(subPhases.toList) if (previousSubPhases.length == subPhases.length) previousSubPhases ::: previousPhases(phases1) diff --git a/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala b/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala index 44d26e7dd3a4..5f86b1c9de2f 100644 --- a/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala +++ b/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala @@ -9,7 +9,7 @@ import core.NameKinds.ExceptionBinderName import dotty.tools.dotc.core.Decorators._ import dotty.tools.dotc.core.Flags import dotty.tools.dotc.core.Contexts.Context -import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, TransformerInfo} +import dotty.tools.dotc.transform.SuperPhase.MiniPhase import dotty.tools.dotc.util.Positions.Position /** Compiles the cases that can not be handled by primitive catch cases as a common pattern match. @@ -40,7 +40,7 @@ import dotty.tools.dotc.util.Positions.Position * - `case _: T =>` where `T` is not `Throwable` * */ -class TryCatchPatterns extends MiniPhaseTransform { +class TryCatchPatterns extends MiniPhase { import dotty.tools.dotc.ast.tpd._ def phaseName: String = "tryCatchPatterns" @@ -58,7 +58,7 @@ class TryCatchPatterns extends MiniPhaseTransform { case _ => } - override def transformTry(tree: Try)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformTry(tree: Try)(implicit ctx: Context): Tree = { val (tryCases, patternMatchCases) = tree.cases.span(isCatchCase) val fallbackCase = mkFallbackPatterMatchCase(patternMatchCases, tree.pos) cpy.Try(tree)(cases = tryCases ++ fallbackCase) @@ -81,7 +81,7 @@ class TryCatchPatterns extends MiniPhaseTransform { } private def mkFallbackPatterMatchCase(patternMatchCases: List[CaseDef], pos: Position)( - implicit ctx: Context, info: TransformerInfo): Option[CaseDef] = { + implicit ctx: Context): Option[CaseDef] = { if (patternMatchCases.isEmpty) None else { val exName = ExceptionBinderName.fresh() diff --git a/compiler/src/dotty/tools/dotc/transform/VCElideAllocations.scala b/compiler/src/dotty/tools/dotc/transform/VCElideAllocations.scala index 1582158acaaa..e08ab1994141 100644 --- a/compiler/src/dotty/tools/dotc/transform/VCElideAllocations.scala +++ b/compiler/src/dotty/tools/dotc/transform/VCElideAllocations.scala @@ -4,7 +4,7 @@ package transform import ast.{Trees, tpd} import core._, core.Decorators._ import Contexts._, Trees._, StdNames._, Symbols._ -import DenotTransformers._, TreeTransforms._, Phases.Phase +import DenotTransformers._, SuperPhase._, Phases.Phase import ExtensionMethods._, TreeExtractors._, ValueClasses._ /** This phase elides unnecessary value class allocations @@ -15,14 +15,14 @@ import ExtensionMethods._, TreeExtractors._, ValueClasses._ * new V(u1) == new V(u2) => u1 == u2 * (new V(u)).underlying() => u */ -class VCElideAllocations extends MiniPhaseTransform with IdentityDenotTransformer { +class VCElideAllocations extends MiniPhase with IdentityDenotTransformer { import tpd._ override def phaseName: String = "vcElideAllocations" override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[ElimErasedValueType]) - override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformApply(tree: Apply)(implicit ctx: Context): Tree = tree match { // new V(u1) == new V(u2) => u1 == u2 // (We don't handle != because it has been eliminated by InterceptedMethods) diff --git a/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala b/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala index 146d30697bae..6850a6dda387 100644 --- a/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala @@ -4,7 +4,7 @@ package transform import ast.{Trees, tpd} import core._, core.Decorators._ import Contexts._, Trees._, Types._ -import DenotTransformers._, TreeTransforms._, Phases.Phase +import DenotTransformers._, SuperPhase._, Phases.Phase import ExtensionMethods._, ValueClasses._ import collection.mutable.ListBuffer @@ -39,7 +39,7 @@ import collection.mutable.ListBuffer * methods (like [[TypeSpecializer]]), this way [[VCInlineMethods]] does not * need to have any knowledge of the name mangling done by other phases. */ -class VCInlineMethods extends MiniPhaseTransform with IdentityDenotTransformer { +class VCInlineMethods extends MiniPhase with IdentityDenotTransformer { import tpd._ override def phaseName: String = "vcInlineMethods" @@ -98,10 +98,10 @@ class VCInlineMethods extends MiniPhaseTransform with IdentityDenotTransformer { tree } - override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformSelect(tree: Select)(implicit ctx: Context): Tree = rewireIfNeeded(tree) - override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformTypeApply(tree: TypeApply)(implicit ctx: Context): Tree = rewireIfNeeded(tree) - override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = + override def transformApply(tree: Apply)(implicit ctx: Context): Tree = rewireIfNeeded(tree) } diff --git a/compiler/src/dotty/tools/dotc/transform/localopt/Simplify.scala b/compiler/src/dotty/tools/dotc/transform/localopt/Simplify.scala index c78536c3b4fc..e28c0e3f700e 100644 --- a/compiler/src/dotty/tools/dotc/transform/localopt/Simplify.scala +++ b/compiler/src/dotty/tools/dotc/transform/localopt/Simplify.scala @@ -8,7 +8,7 @@ import core.Types._ import core.Flags._ import core.Decorators._ import core.NameOps._ -import transform.TreeTransforms.{MiniPhaseTransform, TransformerInfo} +import transform.SuperPhase.MiniPhase import config.Printers.simplify import ast.tpd import dotty.tools.dotc.core.PhantomErasure @@ -27,7 +27,7 @@ import scala.annotation.tailrec * - running this phase late allows to eliminate inefficiencies created by previous phase * - different patters are easier to optimize at different moments of pipeline */ -class Simplify extends MiniPhaseTransform with IdentityDenotTransformer { +class Simplify extends MiniPhase with IdentityDenotTransformer { import tpd._ override def phaseName: String = "simplify" override val cpy = tpd.cpy @@ -93,11 +93,11 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer { if (p.isEmpty) o else o.filter(x => p.contains(x.name)) } - this + ctx } // The entry point of local optimisation: DefDefs - override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformDefDef(tree: DefDef)(implicit ctx: Context): Tree = { val ctx0 = ctx if (ctx.settings.optimise.value && !tree.symbol.is(Label)) { implicit val ctx: Context = ctx0.withOwner(tree.symbol(ctx0)) diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 204e9cf81e55..39de20ca6eaa 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -12,7 +12,8 @@ import util.Positions._ import scala.collection.{ mutable, immutable } import ast._ import Trees._ -import TreeTransforms._ +import SuperPhase._ +import util.Property import config.Printers.{checks, noPrinter} import util.DotClass import scala.util.{Try, Success, Failure} @@ -760,6 +761,11 @@ object RefChecks { } val NoLevelInfo = new OptLevelInfo() + + val LevelInfo = new Property.Key[OptLevelInfo] + + def currentLevel(implicit ctx: Context): OptLevelInfo = + ctx.property(LevelInfo).getOrElse(NoLevelInfo) } import RefChecks._ @@ -793,7 +799,7 @@ import RefChecks._ * todo: But RefChecks is not done yet. It's still a somewhat dirty port from the Scala 2 version. * todo: move untrivial logic to their own mini-phases */ -class RefChecks extends MiniPhase { thisTransformer => +class RefChecks extends MiniPhase { thisPhase => import tpd._ import reporting.diagnostic.messages.ForwardReferenceExtendsOverDefinition @@ -804,84 +810,75 @@ class RefChecks extends MiniPhase { thisTransformer => // Needs to run after ElimRepeated for override checks involving varargs methods override def runsAfter = Set(classOf[ElimRepeated]) - val treeTransform = new Transform(NoLevelInfo) - - class Transform(currentLevel: RefChecks.OptLevelInfo = RefChecks.NoLevelInfo) extends TreeTransform { - def phase = thisTransformer - - override def prepareForStats(trees: List[Tree])(implicit ctx: Context) = { - // println(i"preparing for $trees%; %, owner = ${ctx.owner}") - if (ctx.owner.isTerm) new Transform(new LevelInfo(currentLevel.levelAndIndex, trees)) - else this - } - - override def transformStats(trees: List[Tree])(implicit ctx: Context, info: TransformerInfo): List[Tree] = trees - - override def transformValDef(tree: ValDef)(implicit ctx: Context, info: TransformerInfo) = { - checkDeprecatedOvers(tree) - val sym = tree.symbol - if (sym.exists && sym.owner.isTerm) { - tree.rhs match { - case Ident(nme.WILDCARD) => ctx.error(UnboundPlaceholderParameter(), sym.pos) + override def prepareForStats(trees: List[Tree])(implicit ctx: Context) = + if (ctx.owner.isTerm) + ctx.fresh.setProperty(LevelInfo, new LevelInfo(currentLevel.levelAndIndex, trees)) + else ctx + + override def transformValDef(tree: ValDef)(implicit ctx: Context) = { + checkDeprecatedOvers(tree) + val sym = tree.symbol + if (sym.exists && sym.owner.isTerm) { + tree.rhs match { + case Ident(nme.WILDCARD) => ctx.error(UnboundPlaceholderParameter(), sym.pos) + case _ => + } + if (!sym.is(Lazy)) { + currentLevel.levelAndIndex.get(sym) match { + case Some((level, symIdx)) if symIdx <= level.maxIndex => + ctx.error(ForwardReferenceExtendsOverDefinition(sym, level.refSym), level.refPos) case _ => } - if (!sym.is(Lazy)) { - currentLevel.levelAndIndex.get(sym) match { - case Some((level, symIdx)) if symIdx <= level.maxIndex => - ctx.error(ForwardReferenceExtendsOverDefinition(sym, level.refSym), level.refPos) - case _ => - } - } } - tree } + tree + } - override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo) = { - checkDeprecatedOvers(tree) - if (tree.symbol is Macro) EmptyTree else tree - } + override def transformDefDef(tree: DefDef)(implicit ctx: Context) = { + checkDeprecatedOvers(tree) + if (tree.symbol is Macro) EmptyTree else tree + } - override def transformTemplate(tree: Template)(implicit ctx: Context, info: TransformerInfo) = try { - val cls = ctx.owner - checkOverloadedRestrictions(cls) - checkParents(cls) - checkCompanionNameClashes(cls) - checkAllOverrides(cls) + override def transformTemplate(tree: Template)(implicit ctx: Context) = try { + val cls = ctx.owner + checkOverloadedRestrictions(cls) + checkParents(cls) + checkCompanionNameClashes(cls) + checkAllOverrides(cls) + tree + } catch { + case ex: MergeError => + ctx.error(ex.getMessage, tree.pos) tree - } catch { - case ex: MergeError => - ctx.error(ex.getMessage, tree.pos) - tree - } + } - override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo) = { - checkUndesiredProperties(tree.symbol, tree.pos) - currentLevel.enterReference(tree.symbol, tree.pos) - tree - } + override def transformIdent(tree: Ident)(implicit ctx: Context) = { + checkUndesiredProperties(tree.symbol, tree.pos) + currentLevel.enterReference(tree.symbol, tree.pos) + tree + } - override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) = { - checkUndesiredProperties(tree.symbol, tree.pos) - tree - } + override def transformSelect(tree: Select)(implicit ctx: Context) = { + checkUndesiredProperties(tree.symbol, tree.pos) + tree + } - override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo) = { - if (isSelfConstrCall(tree)) { - assert(currentLevel.isInstanceOf[LevelInfo], ctx.owner + "/" + i"$tree") - val level = currentLevel.asInstanceOf[LevelInfo] - if (level.maxIndex > 0) { - // An implementation restriction to avoid VerifyErrors and lazyvals mishaps; see SI-4717 - ctx.debuglog("refsym = " + level.refSym) - ctx.error("forward reference not allowed from self constructor invocation", level.refPos) - } + override def transformApply(tree: Apply)(implicit ctx: Context) = { + if (isSelfConstrCall(tree)) { + assert(currentLevel.isInstanceOf[LevelInfo], ctx.owner + "/" + i"$tree") + val level = currentLevel.asInstanceOf[LevelInfo] + if (level.maxIndex > 0) { + // An implementation restriction to avoid VerifyErrors and lazyvals mishaps; see SI-4717 + ctx.debuglog("refsym = " + level.refSym) + ctx.error("forward reference not allowed from self constructor invocation", level.refPos) } - tree } + tree + } - override def transformNew(tree: New)(implicit ctx: Context, info: TransformerInfo) = { - currentLevel.enterReference(tree.tpe.typeSymbol, tree.pos) - tree - } + override def transformNew(tree: New)(implicit ctx: Context) = { + currentLevel.enterReference(tree.tpe.typeSymbol, tree.pos) + tree } } @@ -1379,7 +1376,7 @@ class RefChecks extends MiniPhase { thisTransformer => checkAllOverrides(ctx.owner) checkAnyValSubclass(ctx.owner) if (ctx.owner.isDerivedValueClass) - ctx.owner.primaryConstructor.makeNotPrivateAfter(NoSymbol, thisTransformer) // SI-6601, must be done *after* pickler! + ctx.owner.primaryConstructor.makeNotPrivateAfter(NoSymbol, thisPhase) // SI-6601, must be done *after* pickler! tree @@ -1408,7 +1405,7 @@ class RefChecks extends MiniPhase { thisTransformer => checkAllOverrides(ctx.owner) checkAnyValSubclass(ctx.owner) if (ctx.owner.isDerivedValueClass) - ctx.owner.primaryConstructor.makeNotPrivateAfter(NoSymbol, thisTransformer) // SI-6601, must be done *after* pickler! + ctx.owner.primaryConstructor.makeNotPrivateAfter(NoSymbol, thisPhase) // SI-6601, must be done *after* pickler! tree case tpt: TypeTree => diff --git a/compiler/test/dotty/tools/dotc/transform/CreateCompanionObjectsTest.scala b/compiler/test/dotty/tools/dotc/transform/CreateCompanionObjectsTest.scala index 18acb21057df..f0dfdbb14a69 100644 --- a/compiler/test/dotty/tools/dotc/transform/CreateCompanionObjectsTest.scala +++ b/compiler/test/dotty/tools/dotc/transform/CreateCompanionObjectsTest.scala @@ -13,7 +13,6 @@ import Symbols._ import Types._ import Decorators._ import Trees._ -import TreeTransforms.{TreeTransform, TreeTransformer} class CreateCompanionObjectsTest extends DottyTest { diff --git a/compiler/test/dotty/tools/dotc/transform/PostTyperTransformerTest.scala b/compiler/test/dotty/tools/dotc/transform/PostTyperTransformerTest.scala index 03d6d9b36e92..605f222c3cf5 100644 --- a/compiler/test/dotty/tools/dotc/transform/PostTyperTransformerTest.scala +++ b/compiler/test/dotty/tools/dotc/transform/PostTyperTransformerTest.scala @@ -13,7 +13,6 @@ import Symbols._ import Types._ import Decorators._ import Trees._ -import TreeTransforms.{TreeTransform, TreeTransformer} class PostTyperTransformerTest extends DottyTest { /* FIXME: re-enable after adapting to new scheme diff --git a/compiler/test/dotty/tools/dotc/transform/TreeTransformerTest.scala b/compiler/test/dotty/tools/dotc/transform/TreeTransformerTest.scala index 238ce3d51cbb..7670db20e480 100644 --- a/compiler/test/dotty/tools/dotc/transform/TreeTransformerTest.scala +++ b/compiler/test/dotty/tools/dotc/transform/TreeTransformerTest.scala @@ -3,7 +3,7 @@ package dotc package transform import org.junit.{Assert, Test} -import TreeTransforms.{TransformerInfo, TreeTransformer, MiniPhaseTransform} +import SuperPhase._ import ast.tpd import core.Constants.Constant import core.Contexts.Context @@ -14,16 +14,12 @@ class TreeTransformerTest extends DottyTest { def shouldReturnSameTreeIfUnchanged: Unit = checkCompile("frontend", "class A{ val d = 1}") { (tree, context) => implicit val ctx = context - class EmptyTransform extends MiniPhaseTransform { + class EmptyTransform extends MiniPhase { override def phaseName: String = "empty" init(ctx, ctx.period.firstPhaseId, ctx.period.lastPhaseId) } - val transformer = new TreeTransformer { - override def miniPhases = Array(new EmptyTransform) - - override def phaseName: String = "test" - } - val transformed = transformer.macroTransform(tree) + val transformer = new SuperPhase(Array(new EmptyTransform)) + val transformed = transformer.transformUnit(tree) Assert.assertTrue("returns same tree if unmodified", tree eq transformed @@ -34,18 +30,14 @@ class TreeTransformerTest extends DottyTest { def canReplaceConstant: Unit = checkCompile("frontend", "class A{ val d = 1}") { (tree, context) => implicit val ctx = context - class ConstantTransform extends MiniPhaseTransform { + class ConstantTransform extends MiniPhase { - override def transformLiteral(tree: tpd.Literal)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = tpd.Literal(Constant(2)) + override def transformLiteral(tree: tpd.Literal)(implicit ctx: Context): tpd.Tree = tpd.Literal(Constant(2)) override def phaseName: String = "canReplaceConstant" init(ctx, ctx.period.firstPhaseId, ctx.period.lastPhaseId) } - val transformer = new TreeTransformer { - override def miniPhases = Array(new ConstantTransform) - - override def phaseName: String = "test" - } - val transformed = transformer.macroTransform(tree) + val transformer = new SuperPhase(Array(new ConstantTransform)) + val transformed = transformer.transformUnit(tree) Assert.assertTrue("returns same tree if unmodified", transformed.toString.contains("List(ValDef(Modifiers(,,List()),d,TypeTree[TypeRef(ThisType(module class scala),Int)],Literal(Constant(2)))") @@ -56,12 +48,12 @@ class TreeTransformerTest extends DottyTest { def canOverwrite: Unit = checkCompile("frontend", "class A{ val d = 1}") { (tree, context) => implicit val ctx = context - class Transformation extends MiniPhaseTransform { + class Transformation extends MiniPhase { - override def transformLiteral(tree: tpd.Literal)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = tpd.Literal(Constant(-1)) + override def transformLiteral(tree: tpd.Literal)(implicit ctx: Context): tpd.Tree = tpd.Literal(Constant(-1)) override def phaseName: String = "canOverwrite" - override def transformValDef(tree: tpd.ValDef)(implicit ctx: Context, info: TransformerInfo): tpd.ValDef = { + override def transformValDef(tree: tpd.ValDef)(implicit ctx: Context): tpd.ValDef = { Assert.assertTrue("transformation of children succeeded", tree.rhs.toString == "Literal(Constant(-1))" ) @@ -70,13 +62,8 @@ class TreeTransformerTest extends DottyTest { init(ctx, ctx.period.firstPhaseId, ctx.period.lastPhaseId) } - val transformer = new TreeTransformer { - override def miniPhases = Array(new Transformation) - - override def phaseName: String = "test" - - } - val tr = transformer.macroTransform(tree).toString + val transformer = new SuperPhase(Array(new Transformation)) + val tr = transformer.transformUnit(tree).toString Assert.assertTrue("node can rewrite children", tr.contains("Literal(Constant(2))") && !tr.contains("Literal(Constant(-1))") @@ -87,17 +74,17 @@ class TreeTransformerTest extends DottyTest { def transformationOrder: Unit = checkCompile("frontend", "class A{ val d = 1}") { (tree, context) => implicit val ctx = context - class Transformation1 extends MiniPhaseTransform { + class Transformation1 extends MiniPhase { override def phaseName: String = "transformationOrder1" - override def transformLiteral(tree: tpd.Literal)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformLiteral(tree: tpd.Literal)(implicit ctx: Context): tpd.Tree = { Assert.assertTrue("correct constant", tree.const.toString == "Constant(1)" ) tpd.cpy.Literal(tree)(Constant(-1)) } - override def transformValDef(tree: tpd.ValDef)(implicit ctx: Context, info: TransformerInfo): tpd.ValDef = { + override def transformValDef(tree: tpd.ValDef)(implicit ctx: Context): tpd.ValDef = { Assert.assertTrue("transformation of children succeeded", tree.rhs.toString == "Literal(Constant(-1))" ) @@ -106,9 +93,9 @@ class TreeTransformerTest extends DottyTest { init(ctx, ctx.period.firstPhaseId, ctx.period.lastPhaseId) } - class Transformation2 extends MiniPhaseTransform { + class Transformation2 extends MiniPhase { override def phaseName: String = "transformationOrder2" - override def transformValDef(tree: tpd.ValDef)(implicit ctx: Context, info: TransformerInfo): tpd.ValDef = { + override def transformValDef(tree: tpd.ValDef)(implicit ctx: Context): tpd.ValDef = { Assert.assertTrue("transformation of children succeeded", tree.rhs.toString == "Literal(Constant(2))" ) @@ -117,12 +104,8 @@ class TreeTransformerTest extends DottyTest { init(ctx, ctx.period.firstPhaseId, ctx.period.lastPhaseId) } - val transformer = new TreeTransformer { - override def miniPhases = Array(new Transformation1, new Transformation2) - - override def phaseName: String = "test" - } - val tr = transformer.macroTransform(tree).toString + val transformer = new SuperPhase(Array(new Transformation1, new Transformation2)) + val tr = transformer.transformUnit(tree).toString Assert.assertTrue("node can rewrite children", tr.contains("Literal(Constant(3))") @@ -134,9 +117,9 @@ class TreeTransformerTest extends DottyTest { (tree, context) => implicit val ctx = context var transformed1 = 0 - class Transformation1 extends MiniPhaseTransform { + class Transformation1 extends MiniPhase { override def phaseName: String = "invocationCount1" - override def transformLiteral(tree: tpd.Literal)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformLiteral(tree: tpd.Literal)(implicit ctx: Context): tpd.Tree = { transformed1 += 1 Assert.assertTrue("correct constant", tree.const.toString == "Constant(1)" @@ -144,7 +127,7 @@ class TreeTransformerTest extends DottyTest { tpd.cpy.Literal(tree)(Constant(-1)) } - override def transformValDef(tree: tpd.ValDef)(implicit ctx: Context, info: TransformerInfo) = { + override def transformValDef(tree: tpd.ValDef)(implicit ctx: Context) = { transformed1 += 1 Assert.assertTrue("transformation of children succeeded", tree.rhs.toString == "Literal(Constant(-3))" @@ -155,10 +138,10 @@ class TreeTransformerTest extends DottyTest { init(ctx, ctx.period.firstPhaseId, ctx.period.lastPhaseId) } var transformed2 = 0 - class Transformation2 extends MiniPhaseTransform { + class Transformation2 extends MiniPhase { var constantsSeen = 0 override def phaseName: String = "invocationCount2" - override def transformLiteral(tree: tpd.Literal)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + override def transformLiteral(tree: tpd.Literal)(implicit ctx: Context): tpd.Tree = { transformed2 += 1 constantsSeen match { case 0 => @@ -175,7 +158,7 @@ class TreeTransformerTest extends DottyTest { tpd.cpy.Literal(tree)(Constant(-3)) } - override def transformValDef(tree: tpd.ValDef)(implicit ctx: Context, info: TransformerInfo) = { + override def transformValDef(tree: tpd.ValDef)(implicit ctx: Context) = { transformed2 += 1 Assert.assertTrue("transformation of children succeeded", tree.rhs.toString == "Literal(Constant(-3))" @@ -185,12 +168,8 @@ class TreeTransformerTest extends DottyTest { init(ctx, ctx.period.firstPhaseId, ctx.period.lastPhaseId) } - val transformer = new TreeTransformer { - override def miniPhases = Array(new Transformation1, new Transformation2) - - override def phaseName: String = "test" - } - val tr = transformer.macroTransform(tree).toString + val transformer = new SuperPhase(Array(new Transformation1, new Transformation2)) + val tr = transformer.transformUnit(tree).toString Assert.assertTrue("transformations aren't invoked multiple times", transformed1 == 2 && transformed2 == 3 ) diff --git a/doc-tool/src/dotty/tools/dottydoc/core/DocImplicitsPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/DocImplicitsPhase.scala index 6577f0cb784f..05b7bf4b4454 100644 --- a/doc-tool/src/dotty/tools/dottydoc/core/DocImplicitsPhase.scala +++ b/doc-tool/src/dotty/tools/dottydoc/core/DocImplicitsPhase.scala @@ -2,17 +2,17 @@ package dotty.tools package dottydoc package core -import dotty.tools.dotc.transform.TreeTransforms.{ MiniPhaseTransform, TransformerInfo } +import dotty.tools.dotc.transform.SuperPhase.MiniPhase import dotty.tools.dotc.core.Flags import dotc.core.Contexts.Context import util.syntax._ -class DocImplicitsPhase extends MiniPhaseTransform { thisTransformer => +class DocImplicitsPhase extends MiniPhase { import dotty.tools.dotc.ast.tpd._ def phaseName = "addImplicitsPhase" - override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = { + override def transformDefDef(tree: DefDef)(implicit ctx: Context): Tree = { if ( tree.symbol.is(Flags.Implicit) && // has to have an implicit flag tree.symbol.owner.isStaticOwner && // owner has to be static (e.g. top-level `object`) diff --git a/doc-tool/src/dotty/tools/dottydoc/core/transform.scala b/doc-tool/src/dotty/tools/dottydoc/core/transform.scala index cdf57bd02c5d..5eba48b289f6 100644 --- a/doc-tool/src/dotty/tools/dottydoc/core/transform.scala +++ b/doc-tool/src/dotty/tools/dottydoc/core/transform.scala @@ -14,7 +14,7 @@ import util.traversing._ object transform { /** * The idea behind DocMiniTransformations is to fuse transformations to the - * doc AST, much like `MiniPhaseTransform` in dotty core - but in a much more + * doc AST, much like `MiniPhase` in dotty core - but in a much more * simple implementation * * Usage From 568a8d3cae1f8eb24b9a1c6456044f7b7a1d51c2 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 22 Oct 2017 22:34:38 +0200 Subject: [PATCH 04/12] Fix test script --- compiler/test/dotc/tests.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/test/dotc/tests.scala b/compiler/test/dotc/tests.scala index 39ab4da8b9bd..eb52f44f5a42 100644 --- a/compiler/test/dotc/tests.scala +++ b/compiler/test/dotc/tests.scala @@ -348,7 +348,7 @@ class tests extends CompilerTest { "NormalizeFlags.scala", "OverridingPairs.scala", "ParamForwarding.scala", "Pickler.scala", "PostTyper.scala", "ResolveSuper.scala", "RestoreScopes.scala", "SeqLiterals.scala", "Splitter.scala", "SuperAccessors.scala", "SymUtils.scala", "SyntheticMethods.scala", "TailRec.scala", "TreeChecker.scala", "TreeExtractors.scala", - "TreeGen.scala", "TreeTransform.scala", "TypeTestsCasts.scala", "TypeUtils.scala", "ValueClasses.scala", + "TreeGen.scala", "SuperPhase.scala", "TypeTestsCasts.scala", "TypeUtils.scala", "ValueClasses.scala", "VCElideAllocations.scala", "VCInlineMethods.scala" ) map (s"${dotcDir}transform/" + _), testPickling) From 971c54f11a146350fdfa3ccac145a78d400f76a6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 23 Oct 2017 13:50:24 +0200 Subject: [PATCH 05/12] Add Store to Concept ... and provide a way to initialize contexts when phases are linked. --- compiler/src/dotty/tools/dotc/Run.scala | 37 +++++++++++-------- .../src/dotty/tools/dotc/core/Contexts.scala | 37 +++++++++---------- .../src/dotty/tools/dotc/core/Phases.scala | 2 + .../src/dotty/tools/dotc/util/Store.scala | 28 ++++++++++++++ 4 files changed, 70 insertions(+), 34 deletions(-) create mode 100644 compiler/src/dotty/tools/dotc/util/Store.scala diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala index d049c471de96..3ebd3a408781 100644 --- a/compiler/src/dotty/tools/dotc/Run.scala +++ b/compiler/src/dotty/tools/dotc/Run.scala @@ -115,23 +115,30 @@ class Run(comp: Compiler, ictx: Context) { val phases = ctx.squashPhases(ctx.phasePlan, ctx.settings.Yskip.value, ctx.settings.YstopBefore.value, stopAfter, ctx.settings.Ycheck.value) ctx.usePhases(phases) - var lastPrintedTree: PrintedTree = NoPrintedTree - for (phase <- ctx.allPhases) - if (phase.isRunnable) - Stats.trackTime(s"$phase ms ") { - val start = System.currentTimeMillis - units = phase.runOn(units) - if (ctx.settings.Xprint.value.containsPhase(phase)) { - for (unit <- units) { - lastPrintedTree = - printTree(lastPrintedTree)(ctx.fresh.setPhase(phase.next).setCompilationUnit(unit)) + + def runPhases(implicit ctx: Context) = { + var lastPrintedTree: PrintedTree = NoPrintedTree + for (phase <- ctx.allPhases) + if (phase.isRunnable) + Stats.trackTime(s"$phase ms ") { + val start = System.currentTimeMillis + units = phase.runOn(units) + if (ctx.settings.Xprint.value.containsPhase(phase)) { + for (unit <- units) { + lastPrintedTree = + printTree(lastPrintedTree)(ctx.fresh.setPhase(phase.next).setCompilationUnit(unit)) + } } + ctx.informTime(s"$phase ", start) + Stats.record(s"total trees at end of $phase", ast.Trees.ntrees) + for (unit <- units) + Stats.record(s"retained typed trees at end of $phase", unit.tpdTree.treeSize) } - ctx.informTime(s"$phase ", start) - Stats.record(s"total trees at end of $phase", ast.Trees.ntrees) - for (unit <- units) - Stats.record(s"retained typed trees at end of $phase", unit.tpdTree.treeSize) - } + } + + val runCtx = ctx.fresh + ctx.phases.foreach(_.initContext(runCtx)) + runPhases(runCtx) if (!ctx.reporter.hasErrors) Rewrites.writeBack() } diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 0fd08bf5649d..f4b1ba3e2aed 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -31,6 +31,7 @@ import config.{Settings, ScalaSettings, Platform, JavaPlatform} import language.implicitConversions import DenotTransformers.DenotTransformer import util.Property.Key +import util.Store import xsbti.AnalysisCallback object Contexts { @@ -157,13 +158,6 @@ object Contexts { protected def runInfo_=(runInfo: RunInfo) = _runInfo = runInfo def runInfo: RunInfo = _runInfo - /** An optional diagostics buffer than is used by some checking code - * to provide more information in the buffer if it exists. - */ - private[this] var _diagnostics: Option[StringBuilder] = _ - protected def diagnostics_=(diagnostics: Option[StringBuilder]) = _diagnostics = diagnostics - def diagnostics: Option[StringBuilder] = _diagnostics - /** The current bounds in force for type parameters appearing in a GADT */ private[this] var _gadt: GADTMap = _ protected def gadt_=(gadt: GADTMap) = _gadt = gadt @@ -174,6 +168,11 @@ object Contexts { protected def freshNames_=(freshNames: FreshNameCreator) = _freshNames = freshNames def freshNames: FreshNameCreator = _freshNames + /** A store that can be used by sub-components */ + private var _store: Store = _ + protected def store_=(store: Store) = _store = store + def store: Store = _store + /** A map in which more contextual properties can be stored */ private[this] var _moreProperties: Map[Key[Any], Any] = _ protected def moreProperties_=(moreProperties: Map[Key[Any], Any]) = _moreProperties = moreProperties @@ -300,13 +299,6 @@ object Contexts { def isNonEmptyScopeContext: Boolean = (this.scope ne outer.scope) && !this.scope.isEmpty - /** Leave message in diagnostics buffer if it exists */ - def diagnose(str: => String) = - for (sb <- diagnostics) { - sb.setLength(0) - sb.append(str) - } - /** The next outer context whose tree is a template or package definition * Note: Currently unused def enclTemplate: Context = { @@ -406,7 +398,6 @@ object Contexts { .withSettings(sstate) // tree is not preserved in condensed .withRunInfo(runInfo) - .withDiagnostics(diagnostics) .withMoreProperties(moreProperties) _condensed } @@ -474,12 +465,12 @@ object Contexts { def setImportInfo(importInfo: ImportInfo): this.type = { this.importInfo = importInfo; this } def setImplicits(implicits: ContextualImplicits): this.type = { this.implicitsCache = implicits; this } def setRunInfo(runInfo: RunInfo): this.type = { this.runInfo = runInfo; this } - def setDiagnostics(diagnostics: Option[StringBuilder]): this.type = { this.diagnostics = diagnostics; this } def setGadt(gadt: GADTMap): this.type = { this.gadt = gadt; this } def setFreshGADTBounds: this.type = setGadt(new GADTMap(gadt.bounds)) def setTypeComparerFn(tcfn: Context => TypeComparer): this.type = { this.typeComparer = tcfn(this); this } def setSearchHistory(searchHistory: SearchHistory): this.type = { this.searchHistory = searchHistory; this } def setFreshNames(freshNames: FreshNameCreator): this.type = { this.freshNames = freshNames; this } + def setStore(store: Store): this.type = { this.store = store; this } def setMoreProperties(moreProperties: Map[Key[Any], Any]): this.type = { this.moreProperties = moreProperties; this } def setProperty[T](key: Key[T], value: T): this.type = @@ -488,13 +479,21 @@ object Contexts { def dropProperty(key: Key[_]): this.type = setMoreProperties(moreProperties - key) + def addLocation[T](initial: T): Store.Location[T] = { + val (loc, store1) = store.newLocation(initial) + setStore(store1) + loc + } + + def updateStore[T](loc: Store.Location[T], value: T): this.type = + setStore(store.updated(loc, value)) + def setPhase(pid: PhaseId): this.type = setPeriod(Period(runId, pid)) def setPhase(phase: Phase): this.type = setPeriod(Period(runId, phase.start, phase.end)) def setSetting[T](setting: Setting[T], value: T): this.type = setSettings(setting.updateIn(sstate, value)) - def setDebug = setSetting(base.settings.debug, true) } @@ -527,9 +526,9 @@ object Contexts { tree = untpd.EmptyTree typeAssigner = TypeAssigner runInfo = new RunInfo(this) - diagnostics = None freshNames = new FreshNameCreator.Default moreProperties = Map.empty + store = Store.empty typeComparer = new TypeComparer(this) searchHistory = new SearchHistory(0, Map()) gadt = EmptyGADTMap @@ -643,7 +642,7 @@ object Contexts { private[core] var phasesPlan: List[List[Phase]] = _ /** Phases by id */ - private[core] var phases: Array[Phase] = _ + private[dotc] var phases: Array[Phase] = _ /** Phases with consecutive Transforms grouped into a single phase, Empty array if squashing is disabled */ private[core] var squashedPhases: Array[Phase] = Array.empty[Phase] diff --git a/compiler/src/dotty/tools/dotc/core/Phases.scala b/compiler/src/dotty/tools/dotc/core/Phases.scala index 757461ad526a..27812d203ddb 100644 --- a/compiler/src/dotty/tools/dotc/core/Phases.scala +++ b/compiler/src/dotty/tools/dotc/core/Phases.scala @@ -310,6 +310,8 @@ object Phases { def exists: Boolean = true + def initContext(ctx: FreshContext): Unit = () + private[this] var myPeriod: Period = Periods.InvalidPeriod private[this] var myBase: ContextBase = null private[this] var myErasedTypes = false diff --git a/compiler/src/dotty/tools/dotc/util/Store.scala b/compiler/src/dotty/tools/dotc/util/Store.scala new file mode 100644 index 000000000000..a95bab25e820 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/util/Store.scala @@ -0,0 +1,28 @@ +package dotty.tools.dotc.util + +object Store { + + class Location[T](private[Store] val idx: Int) extends AnyVal + + val empty: Store = new Store(Array()) +} + +class Store(private val elems: Array[AnyRef]) extends AnyVal { + import Store._ + + def newLocation[T](initial: T): (Location[T], Store) = { + val elems1 = new Array[AnyRef](elems.length + 1) + System.arraycopy(elems, 0, elems1, 0, elems.length) + elems1(elems.length) = initial.asInstanceOf[AnyRef] + (new Location(elems.length), new Store(elems1)) + } + + def updated[T](loc: Location[T], value: T): Store = { + val elems1 = elems.clone + elems1(loc.idx) = value.asInstanceOf[AnyRef] + new Store(elems1) + } + + def apply[T](loc: Location[T]): T = + elems(loc.idx).asInstanceOf[T] +} From c5b120102ee1b760dbe6162656c011b39a0d3309 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 23 Oct 2017 14:05:12 +0200 Subject: [PATCH 06/12] Use Store in MiniPhases Convert phases that created new TreeTransforms before to use the new Store concept instead of Properties. --- .../tools/dotc/transform/CapturedVars.scala | 16 ++++++++-------- .../dotty/tools/dotc/transform/Flatten.scala | 19 +++++++++---------- .../tools/dotc/transform/LambdaLift.scala | 13 ++++++++----- .../dotty/tools/dotc/transform/LiftTry.scala | 18 ++++++++++-------- 4 files changed, 35 insertions(+), 31 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala b/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala index aae00f0e51ce..c32ef8bb8f9b 100644 --- a/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala +++ b/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala @@ -15,25 +15,25 @@ import core.NameOps._ import core.NameKinds.TempResultName import ast.Trees._ import SymUtils._ -import util.Property +import util.Store import collection.{ mutable, immutable } import collection.mutable.{ LinkedHashMap, LinkedHashSet, TreeSet } -object CapturedVars { - val Captured = new Property.Key[collection.Set[Symbol]] - def captured(implicit ctx: Context) = ctx.property(Captured).getOrElse(Set.empty) -} - /** This phase translates variables that are captured in closures to * heap-allocated refs. */ class CapturedVars extends MiniPhase with IdentityDenotTransformer { thisPhase => - import CapturedVars._ import ast.tpd._ /** the following two members override abstract members in Transform */ val phaseName: String = "capturedVars" + private var Captured: Store.Location[collection.Set[Symbol]] = _ + private def captured(implicit ctx: Context) = ctx.store(Captured) + + override def initContext(ctx: FreshContext) = + Captured = ctx.addLocation(Set.empty) + private class RefInfo(implicit ctx: Context) { /** The classes for which a Ref type exists. */ val refClassKeys: collection.Set[Symbol] = @@ -79,7 +79,7 @@ class CapturedVars extends MiniPhase with IdentityDenotTransformer { thisPhase = override def prepareForUnit(tree: Tree)(implicit ctx: Context) = { val captured = (new CollectCaptured) .runOver(ctx.compilationUnit.tpdTree)(ctx.withPhase(thisPhase)) - ctx.fresh.setProperty(Captured, captured) + ctx.fresh.updateStore(Captured, captured) } /** The {Volatile|}{Int|Double|...|Object}Ref class corresponding to the class `cls`, diff --git a/compiler/src/dotty/tools/dotc/transform/Flatten.scala b/compiler/src/dotty/tools/dotc/transform/Flatten.scala index c518d8dc6db2..7ee24a2eb811 100644 --- a/compiler/src/dotty/tools/dotc/transform/Flatten.scala +++ b/compiler/src/dotty/tools/dotc/transform/Flatten.scala @@ -4,28 +4,27 @@ package transform import core._ import DenotTransformers.SymTransformer import Phases.Phase -import Contexts.Context +import Contexts.{Context, FreshContext} import Flags._ import SymDenotations.SymDenotation import collection.mutable import SuperPhase.MiniPhase -import util.Property - -object Flatten { - import ast.tpd._ - val LiftedDefs = new Property.Key[mutable.ListBuffer[Tree]] - def liftedDefs(implicit ctx: Context) = ctx.property(LiftedDefs).get -} +import util.Store /** Lift nested classes to toplevel */ class Flatten extends MiniPhase with SymTransformer { import ast.tpd._ - import Flatten._ override def phaseName = "flatten" override def changesMembers = true // the phase removes inner classes + private var LiftedDefs: Store.Location[mutable.ListBuffer[Tree]] = _ + private def liftedDefs(implicit ctx: Context) = ctx.store(LiftedDefs) + + override def initContext(ctx: FreshContext) = + LiftedDefs = ctx.addLocation[mutable.ListBuffer[Tree]](null) + def transformSym(ref: SymDenotation)(implicit ctx: Context) = { if (ref.isClass && !ref.is(Package) && !ref.owner.is(Package)) { ref.copySymDenotation( @@ -36,7 +35,7 @@ class Flatten extends MiniPhase with SymTransformer { } override def prepareForPackageDef(tree: PackageDef)(implicit ctx: Context) = - ctx.fresh.setProperty(LiftedDefs, new mutable.ListBuffer[Tree]) + ctx.fresh.updateStore(LiftedDefs, new mutable.ListBuffer[Tree]) private def liftIfNested(tree: Tree)(implicit ctx: Context) = if (ctx.owner is Package) tree diff --git a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala index 6a31266589e3..adba2f1a1331 100644 --- a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala +++ b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala @@ -16,7 +16,7 @@ import core.Phases._ import ast.Trees._ import SymUtils._ import ExplicitOuter.outer -import util.Property +import util.Store import util.Positions._ import collection.{ mutable, immutable } import collection.mutable.{ HashMap, HashSet, LinkedHashMap, LinkedHashSet, TreeSet } @@ -450,9 +450,6 @@ object LambdaLift { def needsLifting(sym: Symbol) = liftedOwner contains sym } - - val Lifter = new Property.Key[Lifter] - def lifter(implicit ctx: Context) = ctx.property(Lifter).get } /** This phase performs the necessary rewritings to eliminate classes and methods @@ -500,8 +497,14 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisPhase => // lambda lift for super calls right. Witness the implementation restrictions to // this effect in scalac. + private var Lifter: Store.Location[Lifter] = _ + private def lifter(implicit ctx: Context) = ctx.store(Lifter) + + override def initContext(ctx: FreshContext) = + Lifter = ctx.addLocation[Lifter](null) + override def prepareForUnit(tree: Tree)(implicit ctx: Context) = - ctx.fresh.setProperty(Lifter, new Lifter(thisPhase)) + ctx.fresh.updateStore(Lifter, new Lifter(thisPhase)) override def transformIdent(tree: Ident)(implicit ctx: Context) = { val sym = tree.symbol diff --git a/compiler/src/dotty/tools/dotc/transform/LiftTry.scala b/compiler/src/dotty/tools/dotc/transform/LiftTry.scala index 649a5bdae85c..a25363a746b0 100644 --- a/compiler/src/dotty/tools/dotc/transform/LiftTry.scala +++ b/compiler/src/dotty/tools/dotc/transform/LiftTry.scala @@ -10,13 +10,7 @@ import core.Flags._ import core.Decorators._ import core.NameKinds.LiftedTreeName import NonLocalReturns._ -import util.Property - -object LiftTry { - val NeedLift = new Property.Key[Boolean] - def needLift(implicit ctx: Context) = ctx.property(NeedLift).getOrElse(false) - def liftingCtx(p: Boolean)(implicit ctx: Context) = ctx.withProperty(NeedLift, Some(p)) -} +import util.Store /** Lifts try's that might be executed on non-empty expression stacks * to their own methods. I.e. @@ -29,11 +23,19 @@ object LiftTry { */ class LiftTry extends MiniPhase with IdentityDenotTransformer { thisPhase => import ast.tpd._ - import LiftTry._ /** the following two members override abstract members in Transform */ val phaseName: String = "liftTry" + private var NeedLift: Store.Location[Boolean] = _ + private def needLift(implicit ctx: Context): Boolean = ctx.store(NeedLift) + + override def initContext(ctx: FreshContext) = + NeedLift = ctx.addLocation(false) + + private def liftingCtx(p: Boolean)(implicit ctx: Context) = + if (needLift == p) ctx else ctx.fresh.updateStore(NeedLift, p) + override def prepareForApply(tree: Apply)(implicit ctx: Context) = if (tree.fun.symbol.is(Label)) ctx else liftingCtx(true) From 61a60e8747f70433cc9097dfc71318515ce3cae4 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 23 Oct 2017 15:02:22 +0200 Subject: [PATCH 07/12] Convert more phases to use stores --- .../src/dotty/tools/dotc/core/Contexts.scala | 6 +++++ .../tools/dotc/transform/LambdaLift.scala | 2 +- .../dotc/transform/ShortcutImplicits.scala | 24 +++++++++---------- .../dotty/tools/dotc/typer/RefChecks.scala | 15 ++++++------ .../src/dotty/tools/dotc/util/Store.scala | 9 +++++-- 5 files changed, 33 insertions(+), 23 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index f4b1ba3e2aed..9b04542b6a59 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -485,6 +485,12 @@ object Contexts { loc } + def addLocation[T](): Store.Location[T] = { + val (loc, store1) = store.newLocation[T]() + setStore(store1) + loc + } + def updateStore[T](loc: Store.Location[T], value: T): this.type = setStore(store.updated(loc, value)) diff --git a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala index adba2f1a1331..c275ce7350e1 100644 --- a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala +++ b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala @@ -501,7 +501,7 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisPhase => private def lifter(implicit ctx: Context) = ctx.store(Lifter) override def initContext(ctx: FreshContext) = - Lifter = ctx.addLocation[Lifter](null) + Lifter = ctx.addLocation[Lifter]() override def prepareForUnit(tree: Tree)(implicit ctx: Context) = ctx.fresh.updateStore(Lifter, new Lifter(thisPhase)) diff --git a/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala b/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala index 646de1ae3b92..506419f0ec9a 100644 --- a/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala +++ b/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala @@ -14,19 +14,9 @@ import core.NameOps._ import core.NameKinds.DirectMethodName import ast.Trees._ import ast.tpd -import util.Property +import util.Store import collection.mutable -object ShortcutImplicits { - private type DirectMeths = mutable.HashMap[Symbol, Symbol] - private val DirectMeth = new Property.Key[DirectMeths] - - /** A map to cache mapping local methods to their direct counterparts. - * A fresh map is created for each unit. - */ - private def directMeth(implicit ctx: Context) = ctx.property(DirectMeth).get -} - /** This phase optimizes code using implicit function types, by applying two rewrite rules. * Let IF be the implicit function type * @@ -57,12 +47,20 @@ object ShortcutImplicits { */ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisPhase => import tpd._ - import ShortcutImplicits._ override def phaseName: String = "shortcutImplicits" override def changesMembers = true // the phase adds "direct" methods + /** A map to cache mapping local methods to their direct counterparts. + * A fresh map is created for each unit. + */ + private var DirectMeth: Store.Location[mutable.HashMap[Symbol, Symbol]] = _ + private def directMeth(implicit ctx: Context) = ctx.store(DirectMeth) + + override def initContext(ctx: FreshContext) = + DirectMeth = ctx.addLocation[mutable.HashMap[Symbol, Symbol]]() + /** If this option is true, we don't specialize symbols that are known to be only * targets of monomorphic calls. * The reason for this option is that benchmarks show that on the JVM for monomorphic dispatch @@ -72,7 +70,7 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisPh final val specializeMonoTargets = true override def prepareForUnit(tree: Tree)(implicit ctx: Context) = - ctx.fresh.setProperty(DirectMeth, new DirectMeths) + ctx.fresh.updateStore(DirectMeth, new mutable.HashMap[Symbol, Symbol]) /** Should `sym` get a ..$direct companion? * This is the case if (1) `sym` is a method with an implicit function type as final result type. diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 39de20ca6eaa..d376cc698966 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -9,11 +9,11 @@ import StdNames._, Denotations._, Scopes._, Constants.Constant, SymUtils._ import NameKinds.DefaultGetterName import Annotations._ import util.Positions._ +import util.Store import scala.collection.{ mutable, immutable } import ast._ import Trees._ import SuperPhase._ -import util.Property import config.Printers.{checks, noPrinter} import util.DotClass import scala.util.{Try, Success, Failure} @@ -761,11 +761,6 @@ object RefChecks { } val NoLevelInfo = new OptLevelInfo() - - val LevelInfo = new Property.Key[OptLevelInfo] - - def currentLevel(implicit ctx: Context): OptLevelInfo = - ctx.property(LevelInfo).getOrElse(NoLevelInfo) } import RefChecks._ @@ -810,9 +805,15 @@ class RefChecks extends MiniPhase { thisPhase => // Needs to run after ElimRepeated for override checks involving varargs methods override def runsAfter = Set(classOf[ElimRepeated]) + private var LevelInfo: Store.Location[OptLevelInfo] = _ + private def currentLevel(implicit ctx: Context): OptLevelInfo = ctx.store(LevelInfo) + + override def initContext(ctx: FreshContext) = + LevelInfo = ctx.addLocation(NoLevelInfo) + override def prepareForStats(trees: List[Tree])(implicit ctx: Context) = if (ctx.owner.isTerm) - ctx.fresh.setProperty(LevelInfo, new LevelInfo(currentLevel.levelAndIndex, trees)) + ctx.fresh.updateStore(LevelInfo, new LevelInfo(currentLevel.levelAndIndex, trees)) else ctx override def transformValDef(tree: ValDef)(implicit ctx: Context) = { diff --git a/compiler/src/dotty/tools/dotc/util/Store.scala b/compiler/src/dotty/tools/dotc/util/Store.scala index a95bab25e820..72e6da0faa49 100644 --- a/compiler/src/dotty/tools/dotc/util/Store.scala +++ b/compiler/src/dotty/tools/dotc/util/Store.scala @@ -10,13 +10,18 @@ object Store { class Store(private val elems: Array[AnyRef]) extends AnyVal { import Store._ - def newLocation[T](initial: T): (Location[T], Store) = { + def newLocation[T](): (Location[T], Store) = { val elems1 = new Array[AnyRef](elems.length + 1) System.arraycopy(elems, 0, elems1, 0, elems.length) - elems1(elems.length) = initial.asInstanceOf[AnyRef] (new Location(elems.length), new Store(elems1)) } + def newLocation[T](initial: T): (Location[T], Store) = { + val (loc, store) = newLocation[T]() + store.elems(loc.idx) = initial.asInstanceOf[AnyRef] + (loc, store) + } + def updated[T](loc: Location[T], value: T): Store = { val elems1 = elems.clone elems1(loc.idx) = value.asInstanceOf[AnyRef] From cf93f4ab9f89fffa2d214cf59e408b135c02808c Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 24 Oct 2017 14:11:24 +0200 Subject: [PATCH 08/12] Rename SuperPhase -> MegaPhase and add @switch annotation to core match in it. --- .../backend/jvm/CollectEntryPoints.scala | 2 +- .../tools/backend/jvm/CollectSuperCalls.scala | 2 +- .../dotty/tools/backend/jvm/LabelDefs.scala | 2 +- .../dotty/tools/dotc/core/Decorators.scala | 4 ++-- .../src/dotty/tools/dotc/core/Phases.scala | 8 ++++---- .../dotc/transform/ArrayConstructors.scala | 2 +- .../dotc/transform/AugmentScala2Traits.scala | 2 +- .../tools/dotc/transform/CapturedVars.scala | 2 +- .../tools/dotc/transform/CheckReentrant.scala | 2 +- .../tools/dotc/transform/CheckStatic.scala | 2 +- .../dotty/tools/dotc/transform/ClassOf.scala | 2 +- .../dotc/transform/CollectEntryPoints.scala | 2 +- .../tools/dotc/transform/Constructors.scala | 2 +- .../tools/dotc/transform/CrossCastAnd.scala | 2 +- .../DropEmptyCompanions.scala.disabled | 4 ++-- .../tools/dotc/transform/DropInlined.scala | 2 +- .../tools/dotc/transform/ElimByName.scala | 2 +- .../dotc/transform/ElimErasedValueType.scala | 2 +- .../dotc/transform/ElimJavaPackages.scala | 2 +- .../dotc/transform/ElimOuterSelect.scala | 2 +- .../tools/dotc/transform/ElimRepeated.scala | 2 +- .../tools/dotc/transform/ElimStaticThis.scala | 2 +- .../tools/dotc/transform/ExpandPrivate.scala | 2 +- .../tools/dotc/transform/ExpandSAMs.scala | 2 +- .../tools/dotc/transform/ExplicitOuter.scala | 2 +- .../tools/dotc/transform/ExplicitSelf.scala | 2 +- .../dotc/transform/ExtensionMethods.scala | 2 +- .../tools/dotc/transform/FirstTransform.scala | 2 +- .../dotty/tools/dotc/transform/Flatten.scala | 2 +- .../transform/FunctionXXLForwarders.scala | 2 +- .../dotc/transform/FunctionalInterfaces.scala | 2 +- .../dotty/tools/dotc/transform/GetClass.scala | 2 +- .../dotty/tools/dotc/transform/Getters.scala | 2 +- .../tools/dotc/transform/HoistSuperArgs.scala | 2 +- .../dotc/transform/InterceptedMethods.scala | 2 +- .../transform/IsInstanceOfEvaluator.scala | 2 +- .../tools/dotc/transform/LambdaLift.scala | 2 +- .../dotty/tools/dotc/transform/LazyVals.scala | 2 +- .../dotty/tools/dotc/transform/LiftTry.scala | 2 +- .../dotc/transform/LinkScala2Impls.scala | 2 +- .../dotc/transform/Literalize.scala.disabled | 2 +- .../{SuperPhase.scala => MegaPhase.scala} | 19 ++++++++++--------- .../dotty/tools/dotc/transform/Memoize.scala | 2 +- .../dotty/tools/dotc/transform/Mixin.scala | 2 +- .../tools/dotc/transform/MoveStatics.scala | 2 +- .../dotc/transform/NonLocalReturns.scala | 2 +- .../tools/dotc/transform/NormalizeFlags.scala | 2 +- .../tools/dotc/transform/PatternMatcher.scala | 2 +- .../dotc/transform/PatternMatcherOld.scala | 2 +- .../tools/dotc/transform/PhantomArgLift.scala | 2 +- .../dotc/transform/PrimitiveForwarders.scala | 2 +- .../transform/PrivateToStatic.scala.disabled | 4 ++-- .../tools/dotc/transform/RenameLifted.scala | 2 +- .../tools/dotc/transform/ResolveSuper.scala | 2 +- .../tools/dotc/transform/RestoreScopes.scala | 2 +- .../tools/dotc/transform/SelectStatic.scala | 2 +- .../tools/dotc/transform/SeqLiterals.scala | 2 +- .../dotc/transform/ShortcutImplicits.scala | 2 +- .../dotty/tools/dotc/transform/Splitter.scala | 2 +- .../tools/dotc/transform/SuperAccessors.scala | 2 +- .../dotc/transform/SyntheticMethods.scala | 2 +- .../dotty/tools/dotc/transform/TailRec.scala | 3 +-- .../dotc/transform/TransformByNameApply.scala | 2 +- .../dotc/transform/TransformWildcards.scala | 2 +- .../tools/dotc/transform/TreeChecker.scala | 4 ++-- .../dotc/transform/TryCatchPatterns.scala | 2 +- .../dotc/transform/VCElideAllocations.scala | 2 +- .../dotc/transform/VCInlineMethods.scala | 2 +- .../dotc/transform/localopt/Simplify.scala | 2 +- .../dotty/tools/dotc/typer/RefChecks.scala | 2 +- compiler/test/dotc/tests.scala | 2 +- .../dotc/transform/TreeTransformerTest.scala | 12 ++++++------ .../dottydoc/core/DocImplicitsPhase.scala | 2 +- 73 files changed, 94 insertions(+), 94 deletions(-) rename compiler/src/dotty/tools/dotc/transform/{SuperPhase.scala => MegaPhase.scala} (98%) diff --git a/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala b/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala index 5a02abc6c3e0..41b7e549d2f5 100644 --- a/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala +++ b/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala @@ -3,7 +3,7 @@ package dotty.tools.backend.jvm import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Types -import dotty.tools.dotc.transform.SuperPhase._ +import dotty.tools.dotc.transform.MegaPhase._ import dotty.tools.dotc.ast.tpd import dotty.tools.dotc import dotty.tools.dotc.backend.jvm.DottyPrimitives diff --git a/compiler/src/dotty/tools/backend/jvm/CollectSuperCalls.scala b/compiler/src/dotty/tools/backend/jvm/CollectSuperCalls.scala index ef5ac908c4e0..cabc51c394bf 100644 --- a/compiler/src/dotty/tools/backend/jvm/CollectSuperCalls.scala +++ b/compiler/src/dotty/tools/backend/jvm/CollectSuperCalls.scala @@ -5,7 +5,7 @@ import dotty.tools.dotc.ast.Trees._ import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Symbols._ import dotty.tools.dotc.core.Flags.Trait -import dotty.tools.dotc.transform.SuperPhase.MiniPhase +import dotty.tools.dotc.transform.MegaPhase.MiniPhase /** Collect all super calls to trait members. * diff --git a/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala b/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala index 6be8d8e6ca4d..a70953ab478f 100644 --- a/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala +++ b/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala @@ -4,7 +4,7 @@ import dotty.tools.dotc.ast.Trees.Thicket import dotty.tools.dotc.ast.{Trees, tpd} import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Types -import dotty.tools.dotc.transform.SuperPhase._ +import dotty.tools.dotc.transform.MegaPhase._ import dotty.tools.dotc import dotty.tools.dotc.backend.jvm.DottyPrimitives import dotty.tools.dotc.core.Flags.FlagSet diff --git a/compiler/src/dotty/tools/dotc/core/Decorators.scala b/compiler/src/dotty/tools/dotc/core/Decorators.scala index b4dda6d4d880..53b2e19e5e12 100644 --- a/compiler/src/dotty/tools/dotc/core/Decorators.scala +++ b/compiler/src/dotty/tools/dotc/core/Decorators.scala @@ -6,7 +6,7 @@ import Symbols._ import Contexts._, Names._, Phases._, printing.Texts._, printing.Printer, printing.Showable import util.Positions.Position, util.SourcePosition import collection.mutable.ListBuffer -import dotty.tools.dotc.transform.SuperPhase +import dotty.tools.dotc.transform.MegaPhase import ast.tpd._ import scala.language.implicitConversions import printing.Formatting._ @@ -152,7 +152,7 @@ object Decorators { */ implicit class PhaseListDecorator(val names: List[String]) extends AnyVal { def containsPhase(phase: Phase): Boolean = phase match { - case phase: SuperPhase => phase.miniPhases.exists(containsPhase) + case phase: MegaPhase => phase.miniPhases.exists(containsPhase) case _ => names exists { name => name == "all" || { diff --git a/compiler/src/dotty/tools/dotc/core/Phases.scala b/compiler/src/dotty/tools/dotc/core/Phases.scala index 27812d203ddb..72fc85dda830 100644 --- a/compiler/src/dotty/tools/dotc/core/Phases.scala +++ b/compiler/src/dotty/tools/dotc/core/Phases.scala @@ -11,7 +11,7 @@ import Denotations._ import Decorators._ import config.Printers.config import scala.collection.mutable.{ListBuffer, ArrayBuffer} -import dotty.tools.dotc.transform.SuperPhase._ +import dotty.tools.dotc.transform.MegaPhase._ import dotty.tools.dotc.transform._ import Periods._ import typer.{FrontEnd, RefChecks} @@ -111,7 +111,7 @@ object Phases { assert(false, s"Only tree transforms can be squashed, ${phase.phaseName} can not be squashed") } } - val superPhase = new SuperPhase(filteredPhaseBlock.asInstanceOf[List[MiniPhase]].toArray) + val superPhase = new MegaPhase(filteredPhaseBlock.asInstanceOf[List[MiniPhase]].toArray) prevPhases ++= filteredPhaseBlock.map(_.getClazz) superPhase } else { // block of a single phase, no squashing @@ -141,7 +141,7 @@ object Phases { val flatPhases = collection.mutable.ListBuffer[Phase]() phasess.foreach(p => p match { - case p: SuperPhase => flatPhases ++= p.miniPhases + case p: MegaPhase => flatPhases ++= p.miniPhases case _ => flatPhases += p }) @@ -169,7 +169,7 @@ object Phases { while (i < phasess.length) { val phase = phasess(i) phase match { - case p: SuperPhase => + case p: MegaPhase => val miniPhases = p.miniPhases miniPhases.foreach{ phase => checkRequirements(phase) diff --git a/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala b/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala index 93248439dbfa..c7d02d53175b 100644 --- a/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala +++ b/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import core._ -import SuperPhase._ +import MegaPhase._ import Contexts.Context import Flags._ import SymUtils._ diff --git a/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala b/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala index 7ea8bf666cda..e208902d3589 100644 --- a/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala +++ b/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import core._ -import SuperPhase._ +import MegaPhase._ import Contexts.Context import Flags._ import SymUtils._ diff --git a/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala b/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala index c32ef8bb8f9b..55704e71ee3b 100644 --- a/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala +++ b/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import SuperPhase._ +import MegaPhase._ import core.DenotTransformers._ import core.Symbols._ import core.Contexts._ diff --git a/compiler/src/dotty/tools/dotc/transform/CheckReentrant.scala b/compiler/src/dotty/tools/dotc/transform/CheckReentrant.scala index 8727e94911b2..cdb72fd429d8 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckReentrant.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckReentrant.scala @@ -3,7 +3,7 @@ package transform import core._ import Names._ -import dotty.tools.dotc.transform.SuperPhase._ +import dotty.tools.dotc.transform.MegaPhase._ import ast.Trees._ import Flags._ import Types._ diff --git a/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala b/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala index 6bd73ea3ecb2..16efc0cfe52c 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala @@ -5,7 +5,7 @@ import core._ import Names._ import StdNames.nme import Types._ -import dotty.tools.dotc.transform.SuperPhase._ +import dotty.tools.dotc.transform.MegaPhase._ import ast.Trees._ import Flags._ import Contexts.Context diff --git a/compiler/src/dotty/tools/dotc/transform/ClassOf.scala b/compiler/src/dotty/tools/dotc/transform/ClassOf.scala index 766c9495f312..493ff8df638d 100644 --- a/compiler/src/dotty/tools/dotc/transform/ClassOf.scala +++ b/compiler/src/dotty/tools/dotc/transform/ClassOf.scala @@ -7,7 +7,7 @@ import core.Contexts.Context import core.StdNames.nme import core.Symbols.{defn,TermSymbol} import core.TypeErasure -import SuperPhase._ +import MegaPhase._ /** Rewrite `classOf` calls as follow: * diff --git a/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala index 2b835c0444d6..071b41444bfc 100644 --- a/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala +++ b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala @@ -8,7 +8,7 @@ import dotty.tools.dotc.core.Symbols.NoSymbol import scala.annotation.tailrec import dotty.tools.dotc.core._ import Symbols._ -import dotty.tools.dotc.transform.SuperPhase._ +import dotty.tools.dotc.transform.MegaPhase._ import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Contexts.Context import scala.collection.mutable diff --git a/compiler/src/dotty/tools/dotc/transform/Constructors.scala b/compiler/src/dotty/tools/dotc/transform/Constructors.scala index ad08bbf32646..4954c143590f 100644 --- a/compiler/src/dotty/tools/dotc/transform/Constructors.scala +++ b/compiler/src/dotty/tools/dotc/transform/Constructors.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import core._ -import SuperPhase._ +import MegaPhase._ import dotty.tools.dotc.ast.tpd._ import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.StdNames._ diff --git a/compiler/src/dotty/tools/dotc/transform/CrossCastAnd.scala b/compiler/src/dotty/tools/dotc/transform/CrossCastAnd.scala index 05d5bf3c940f..a50b8cb01e97 100644 --- a/compiler/src/dotty/tools/dotc/transform/CrossCastAnd.scala +++ b/compiler/src/dotty/tools/dotc/transform/CrossCastAnd.scala @@ -4,7 +4,7 @@ import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Flags import dotty.tools.dotc.core.Types.{NoType, Type, AndType} -import dotty.tools.dotc.transform.SuperPhase._ +import dotty.tools.dotc.transform.MegaPhase._ import tpd._ import scala.collection.mutable.ListBuffer diff --git a/compiler/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled b/compiler/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled index 68d777db1612..559ce68947a0 100644 --- a/compiler/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled +++ b/compiler/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled @@ -12,8 +12,8 @@ import ast.Trees._ import collection.mutable import Decorators._ import NameOps._ -import SuperPhase.MiniPhase -import dotty.tools.dotc.transform.SuperPhase.TransformerInfo +import MegaPhase.MiniPhase +import dotty.tools.dotc.transform.MegaPhase.TransformerInfo /** Remove companion objects that are empty * Lots of constraints here: diff --git a/compiler/src/dotty/tools/dotc/transform/DropInlined.scala b/compiler/src/dotty/tools/dotc/transform/DropInlined.scala index 4d9fbc92ca03..55dec8628a48 100644 --- a/compiler/src/dotty/tools/dotc/transform/DropInlined.scala +++ b/compiler/src/dotty/tools/dotc/transform/DropInlined.scala @@ -3,7 +3,7 @@ package transform import typer.Inliner import core.Contexts.Context -import SuperPhase.MiniPhase +import MegaPhase.MiniPhase /** Drop Inlined nodes */ class DropInlined extends MiniPhase { diff --git a/compiler/src/dotty/tools/dotc/transform/ElimByName.scala b/compiler/src/dotty/tools/dotc/transform/ElimByName.scala index c98b5fca0c30..36c22f2e2068 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimByName.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimByName.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import SuperPhase._ +import MegaPhase._ import core._ import DenotTransformers.InfoTransformer import Symbols._ diff --git a/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala b/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala index 4c434827fb2c..3de005fac34b 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala @@ -3,7 +3,7 @@ package transform import ast.{Trees, tpd} import core._, core.Decorators._ -import SuperPhase._, Phases.Phase +import MegaPhase._, Phases.Phase import Types._, Contexts._, Constants._, Names._, NameOps._, Flags._, DenotTransformers._ import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Scopes._, Denotations._ import TypeErasure.ErasedValueType, ValueClasses._ diff --git a/compiler/src/dotty/tools/dotc/transform/ElimJavaPackages.scala b/compiler/src/dotty/tools/dotc/transform/ElimJavaPackages.scala index a3339c7c8118..a823ce4d7ed7 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimJavaPackages.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimJavaPackages.scala @@ -4,7 +4,7 @@ import dotty.tools.dotc.ast.tpd._ import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Flags._ import dotty.tools.dotc.core.Types.{Type, TypeRef} -import dotty.tools.dotc.transform.SuperPhase.MiniPhase +import dotty.tools.dotc.transform.MegaPhase.MiniPhase /** * Eliminates syntactic references to Java packages, so that there's no chance diff --git a/compiler/src/dotty/tools/dotc/transform/ElimOuterSelect.scala b/compiler/src/dotty/tools/dotc/transform/ElimOuterSelect.scala index bc6cb1f3162f..cec86c88e651 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimOuterSelect.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimOuterSelect.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import core._ -import SuperPhase.MiniPhase +import MegaPhase.MiniPhase import Contexts.Context import Types._ import Decorators._ diff --git a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala index a33a88f7fa17..6ad1edfaa31e 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala @@ -5,7 +5,7 @@ import core._ import Names._ import StdNames.nme import Types._ -import dotty.tools.dotc.transform.SuperPhase._ +import dotty.tools.dotc.transform.MegaPhase._ import ast.Trees._ import Flags._ import Contexts.Context diff --git a/compiler/src/dotty/tools/dotc/transform/ElimStaticThis.scala b/compiler/src/dotty/tools/dotc/transform/ElimStaticThis.scala index 5fe2a2b654a4..662e5d5c55bd 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimStaticThis.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimStaticThis.scala @@ -7,7 +7,7 @@ import Flags._ import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.StdNames._ import dotty.tools.dotc.core.SymDenotations.SymDenotation -import SuperPhase.MiniPhase +import MegaPhase.MiniPhase import dotty.tools.dotc.core.Types.{ThisType, TermRef} /** Replace This references to module classes in static methods by global identifiers to the diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala index db107c809688..f49495c80d3f 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala @@ -15,7 +15,7 @@ import Types._ import collection.mutable import Decorators._ import ast.Trees._ -import SuperPhase._ +import MegaPhase._ import java.io.File.separatorChar import ValueClasses._ diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala index 38b1e0491570..ef1aca47af89 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala @@ -4,7 +4,7 @@ package transform import core._ import Contexts._, Symbols._, Types._, Flags._, Decorators._, StdNames._, Constants._ import SymDenotations.SymDenotation -import SuperPhase._ +import MegaPhase._ import SymUtils._ import ast.untpd import ast.Trees._ diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala index ba757f31d0e1..268123b0d3fe 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import SuperPhase._ +import MegaPhase._ import core.DenotTransformers._ import core.Symbols._ import core.Contexts._ diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitSelf.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitSelf.scala index 48d68a0d7aa7..307b8ea56854 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExplicitSelf.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExplicitSelf.scala @@ -4,7 +4,7 @@ package transform import core._ import Contexts.Context import Types._ -import SuperPhase._ +import MegaPhase._ import Decorators._ import ast.Trees._ import Flags._ diff --git a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala index fe620c1d42c6..6bb2b29ee522 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala @@ -5,7 +5,7 @@ package dotty.tools.dotc package transform -import dotty.tools.dotc.transform.SuperPhase._ +import dotty.tools.dotc.transform.MegaPhase._ import ValueClasses._ import dotty.tools.dotc.ast.{Trees, tpd} import scala.collection.{ mutable, immutable } diff --git a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala index 40d52eb0d985..e935da998cb1 100644 --- a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala +++ b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala @@ -5,7 +5,7 @@ import core._ import Names._ import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Phases.NeedsCompanions -import dotty.tools.dotc.transform.SuperPhase._ +import dotty.tools.dotc.transform.MegaPhase._ import ast.Trees._ import Flags._ import Types._ diff --git a/compiler/src/dotty/tools/dotc/transform/Flatten.scala b/compiler/src/dotty/tools/dotc/transform/Flatten.scala index 7ee24a2eb811..8633391ce175 100644 --- a/compiler/src/dotty/tools/dotc/transform/Flatten.scala +++ b/compiler/src/dotty/tools/dotc/transform/Flatten.scala @@ -8,7 +8,7 @@ import Contexts.{Context, FreshContext} import Flags._ import SymDenotations.SymDenotation import collection.mutable -import SuperPhase.MiniPhase +import MegaPhase.MiniPhase import util.Store /** Lift nested classes to toplevel */ diff --git a/compiler/src/dotty/tools/dotc/transform/FunctionXXLForwarders.scala b/compiler/src/dotty/tools/dotc/transform/FunctionXXLForwarders.scala index 49bfc56529d2..feacc647f917 100644 --- a/compiler/src/dotty/tools/dotc/transform/FunctionXXLForwarders.scala +++ b/compiler/src/dotty/tools/dotc/transform/FunctionXXLForwarders.scala @@ -9,7 +9,7 @@ import Definitions._ import DenotTransformers._ import StdNames._ import Symbols._ -import SuperPhase._ +import MegaPhase._ import Types._ diff --git a/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala b/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala index 83984690ae64..228e73e1d5fa 100644 --- a/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala +++ b/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import SuperPhase._ +import MegaPhase._ import core.DenotTransformers._ import core.Symbols._ import core.Contexts._ diff --git a/compiler/src/dotty/tools/dotc/transform/GetClass.scala b/compiler/src/dotty/tools/dotc/transform/GetClass.scala index bca809f91be0..e83363d3dea0 100644 --- a/compiler/src/dotty/tools/dotc/transform/GetClass.scala +++ b/compiler/src/dotty/tools/dotc/transform/GetClass.scala @@ -6,7 +6,7 @@ import core.Contexts.Context import core.StdNames.nme import core.Phases.Phase import TypeUtils._ -import SuperPhase.MiniPhase +import MegaPhase.MiniPhase /** Rewrite `getClass` calls as follow: * diff --git a/compiler/src/dotty/tools/dotc/transform/Getters.scala b/compiler/src/dotty/tools/dotc/transform/Getters.scala index cbcd4321065a..55e68d69ff11 100644 --- a/compiler/src/dotty/tools/dotc/transform/Getters.scala +++ b/compiler/src/dotty/tools/dotc/transform/Getters.scala @@ -9,7 +9,7 @@ import Types._ import Symbols._ import SymUtils._ import Constants._ -import SuperPhase._ +import MegaPhase._ import Flags._ import Decorators._ import ValueClasses._ diff --git a/compiler/src/dotty/tools/dotc/transform/HoistSuperArgs.scala b/compiler/src/dotty/tools/dotc/transform/HoistSuperArgs.scala index eb6ff09d8b2e..d0d55d735329 100644 --- a/compiler/src/dotty/tools/dotc/transform/HoistSuperArgs.scala +++ b/compiler/src/dotty/tools/dotc/transform/HoistSuperArgs.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import SuperPhase._ +import MegaPhase._ import core.DenotTransformers._ import core.Symbols._ import core.Contexts._ diff --git a/compiler/src/dotty/tools/dotc/transform/InterceptedMethods.scala b/compiler/src/dotty/tools/dotc/transform/InterceptedMethods.scala index 71536309b0b5..dc14acf50f03 100644 --- a/compiler/src/dotty/tools/dotc/transform/InterceptedMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/InterceptedMethods.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import SuperPhase._ +import MegaPhase._ import core.Denotations._ import core.SymDenotations._ import core.Contexts._ diff --git a/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala b/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala index 7b2f8fc4fa7d..4f6f8d3db3e4 100644 --- a/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala +++ b/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import dotty.tools.dotc.util.Positions._ -import SuperPhase.MiniPhase +import MegaPhase.MiniPhase import core._ import Contexts.Context, Types._, Constants._, Decorators._, Symbols._ import TypeUtils._, TypeErasure._, Flags._ diff --git a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala index c275ce7350e1..a7b4a37793a1 100644 --- a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala +++ b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import SuperPhase._ +import MegaPhase._ import core.DenotTransformers._ import core.Symbols._ import core.Contexts._ diff --git a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala index d5be0c1b2d32..0f930b353e36 100644 --- a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala @@ -14,7 +14,7 @@ import NameKinds._ import StdNames.nme import rewrite.Rewrites.patch import util.Positions.Position -import dotty.tools.dotc.transform.SuperPhase._ +import dotty.tools.dotc.transform.MegaPhase._ import dotty.tools.dotc.ast.Trees._ import dotty.tools.dotc.ast.{untpd, tpd} import dotty.tools.dotc.core.Constants.Constant diff --git a/compiler/src/dotty/tools/dotc/transform/LiftTry.scala b/compiler/src/dotty/tools/dotc/transform/LiftTry.scala index a25363a746b0..f42131b88153 100644 --- a/compiler/src/dotty/tools/dotc/transform/LiftTry.scala +++ b/compiler/src/dotty/tools/dotc/transform/LiftTry.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import SuperPhase._ +import MegaPhase._ import core.DenotTransformers._ import core.Symbols._ import core.Contexts._ diff --git a/compiler/src/dotty/tools/dotc/transform/LinkScala2Impls.scala b/compiler/src/dotty/tools/dotc/transform/LinkScala2Impls.scala index 23cfad817834..4b1b93ab63f4 100644 --- a/compiler/src/dotty/tools/dotc/transform/LinkScala2Impls.scala +++ b/compiler/src/dotty/tools/dotc/transform/LinkScala2Impls.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import core._ -import SuperPhase._ +import MegaPhase._ import Contexts.Context import Flags._ import SymUtils._ diff --git a/compiler/src/dotty/tools/dotc/transform/Literalize.scala.disabled b/compiler/src/dotty/tools/dotc/transform/Literalize.scala.disabled index 6ecdcef7065d..8d2b06e24462 100644 --- a/compiler/src/dotty/tools/dotc/transform/Literalize.scala.disabled +++ b/compiler/src/dotty/tools/dotc/transform/Literalize.scala.disabled @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import SuperPhase._ +import MegaPhase._ import core.DenotTransformers._ import core.Symbols._ import core.Contexts._ diff --git a/compiler/src/dotty/tools/dotc/transform/SuperPhase.scala b/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala similarity index 98% rename from compiler/src/dotty/tools/dotc/transform/SuperPhase.scala rename to compiler/src/dotty/tools/dotc/transform/MegaPhase.scala index c1493fcacdad..faf40bb5086e 100644 --- a/compiler/src/dotty/tools/dotc/transform/SuperPhase.scala +++ b/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala @@ -10,14 +10,15 @@ import scala.annotation.tailrec import config.Printers.transforms import scala.util.control.NonFatal import reporting.trace +import annotation.switch -/** A SuperPhase combines a number of mini-phases which are all executed in +/** A MegaPhase combines a number of mini-phases which are all executed in * a single tree traversal. * * This is an evolution of the previous "TreeTransformers.scala", which was written by @DarkDimius and * is described in his thesis. */ -object SuperPhase { +object MegaPhase { import ast.tpd._ /** The base class of tree transforms. For each kind of tree K, there are @@ -35,8 +36,8 @@ object SuperPhase { */ abstract class MiniPhase extends Phase { - private[SuperPhase] var superPhase: SuperPhase = _ - private[SuperPhase] var idxInGroup: Int = _ + private[MegaPhase] var superPhase: MegaPhase = _ + private[MegaPhase] var idxInGroup: Int = _ /** List of names of phases that should have finished their processing of all compilation units * before this phase starts @@ -121,7 +122,7 @@ object SuperPhase { def transformFollowing(tree: Tree)(implicit ctx: Context): Tree = superPhase.transformNode(tree, idxInGroup + 1) - protected def singletonGroup = new SuperPhase(Array(this)) + protected def singletonGroup = new MegaPhase(Array(this)) override def run(implicit ctx: Context): Unit = singletonGroup.run @@ -133,14 +134,14 @@ object SuperPhase { private val idNodeTransformer: Transformer[AnyRef, AnyRef] = (t, ctx) => t private val idContextTransformer: Transformer[AnyRef, Context] = (t, ctx) => ctx } -import SuperPhase._ +import MegaPhase._ -class SuperPhase(val miniPhases: Array[MiniPhase]) extends Phase { +class MegaPhase(val miniPhases: Array[MiniPhase]) extends Phase { import ast.tpd._ override val phaseName = if (miniPhases.length == 1) miniPhases(0).phaseName - else miniPhases.map(_.phaseName).mkString("SuperPhase{", ", ", "}") + else miniPhases.map(_.phaseName).mkString("MegaPhase{", ", ", "}") private val cpy: TypedTreeCopier = cpyBetweenPhases @@ -163,7 +164,7 @@ class SuperPhase(val miniPhases: Array[MiniPhase]) extends Phase { } { implicit val ctx = nestedCtx - tag match { + (tag: @switch) match { case Tag.Select => val tree1 = tree.asInstanceOf[Select] val qual = transformTree(tree1.qualifier, start) diff --git a/compiler/src/dotty/tools/dotc/transform/Memoize.scala b/compiler/src/dotty/tools/dotc/transform/Memoize.scala index a2d946a9b696..497a229c2748 100644 --- a/compiler/src/dotty/tools/dotc/transform/Memoize.scala +++ b/compiler/src/dotty/tools/dotc/transform/Memoize.scala @@ -12,7 +12,7 @@ import Symbols._ import SymUtils._ import Constants._ import ast.Trees._ -import SuperPhase._ +import MegaPhase._ import NameOps._ import Flags._ import Decorators._ diff --git a/compiler/src/dotty/tools/dotc/transform/Mixin.scala b/compiler/src/dotty/tools/dotc/transform/Mixin.scala index c9300274e2cd..ac25694eab7f 100644 --- a/compiler/src/dotty/tools/dotc/transform/Mixin.scala +++ b/compiler/src/dotty/tools/dotc/transform/Mixin.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import core._ -import SuperPhase._ +import MegaPhase._ import Contexts.Context import Flags._ import SymUtils._ diff --git a/compiler/src/dotty/tools/dotc/transform/MoveStatics.scala b/compiler/src/dotty/tools/dotc/transform/MoveStatics.scala index f54e41415414..484e538e0bf4 100644 --- a/compiler/src/dotty/tools/dotc/transform/MoveStatics.scala +++ b/compiler/src/dotty/tools/dotc/transform/MoveStatics.scala @@ -13,7 +13,7 @@ import dotty.tools.dotc.core.StdNames.nme import dotty.tools.dotc.core.Phases.Phase import dotty.tools.dotc.core.Symbols._ import dotty.tools.dotc.core.Types.MethodType -import dotty.tools.dotc.transform.SuperPhase.MiniPhase +import dotty.tools.dotc.transform.MegaPhase.MiniPhase /** Move static methods from companion to the class itself */ class MoveStatics extends MiniPhase with SymTransformer { diff --git a/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala b/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala index b4540acbc749..70ae9a77574a 100644 --- a/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala +++ b/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala @@ -3,7 +3,7 @@ package transform import core._ import Contexts._, Symbols._, Types._, Flags._, Decorators._, StdNames._, Constants._, Phases._ -import SuperPhase._ +import MegaPhase._ import ast.Trees._ import NameKinds.NonLocalReturnKeyName import collection.mutable diff --git a/compiler/src/dotty/tools/dotc/transform/NormalizeFlags.scala b/compiler/src/dotty/tools/dotc/transform/NormalizeFlags.scala index c6cdbe1cafc1..ced55ef697d4 100644 --- a/compiler/src/dotty/tools/dotc/transform/NormalizeFlags.scala +++ b/compiler/src/dotty/tools/dotc/transform/NormalizeFlags.scala @@ -6,7 +6,7 @@ import DenotTransformers.SymTransformer import Phases.Phase import Contexts.Context import SymDenotations.SymDenotation -import SuperPhase.MiniPhase +import MegaPhase.MiniPhase import Flags._, Symbols._ /** 1. Widens all private[this] and protected[this] qualifiers to just private/protected diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index 84b6c1e82792..512ee80472e0 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import core._ -import SuperPhase._ +import MegaPhase._ import collection.mutable import SymDenotations._, Symbols._, Contexts._, Types._, Names._, StdNames._, NameOps._ import ast.Trees._ diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcherOld.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcherOld.scala index 733d647cf9d6..154a788b4427 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcherOld.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcherOld.scala @@ -3,7 +3,7 @@ package transform import scala.language.postfixOps -import SuperPhase._ +import MegaPhase._ import core.Denotations._ import core.SymDenotations._ import core.Contexts._ diff --git a/compiler/src/dotty/tools/dotc/transform/PhantomArgLift.scala b/compiler/src/dotty/tools/dotc/transform/PhantomArgLift.scala index 9ed9335fc7a1..7df418e598d6 100644 --- a/compiler/src/dotty/tools/dotc/transform/PhantomArgLift.scala +++ b/compiler/src/dotty/tools/dotc/transform/PhantomArgLift.scala @@ -4,7 +4,7 @@ import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Contexts._ import dotty.tools.dotc.core.NameKinds._ import dotty.tools.dotc.core.Types._ -import dotty.tools.dotc.transform.SuperPhase.MiniPhase +import dotty.tools.dotc.transform.MegaPhase.MiniPhase import dotty.tools.dotc.typer.EtaExpansion import scala.collection.mutable.ListBuffer diff --git a/compiler/src/dotty/tools/dotc/transform/PrimitiveForwarders.scala b/compiler/src/dotty/tools/dotc/transform/PrimitiveForwarders.scala index cc09632063be..17535ac45cfe 100644 --- a/compiler/src/dotty/tools/dotc/transform/PrimitiveForwarders.scala +++ b/compiler/src/dotty/tools/dotc/transform/PrimitiveForwarders.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import core._ -import SuperPhase._ +import MegaPhase._ import Contexts.Context import Flags._ import SymUtils._ diff --git a/compiler/src/dotty/tools/dotc/transform/PrivateToStatic.scala.disabled b/compiler/src/dotty/tools/dotc/transform/PrivateToStatic.scala.disabled index 5e5c1e9b8433..51dc44d8b90a 100644 --- a/compiler/src/dotty/tools/dotc/transform/PrivateToStatic.scala.disabled +++ b/compiler/src/dotty/tools/dotc/transform/PrivateToStatic.scala.disabled @@ -11,10 +11,10 @@ import StdNames._ import SymDenotations._ import Types._ import collection.mutable -import SuperPhase._ +import MegaPhase._ import Decorators._ import ast.Trees._ -import SuperPhase.TransformerInfo +import MegaPhase.TransformerInfo /** Makes private methods static, provided they not deferred, accessors, or static, * by rewriting a method `m` in class `C` as follows: diff --git a/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala b/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala index 2ec20c68fba3..beef392a3eb2 100644 --- a/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala +++ b/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala @@ -9,7 +9,7 @@ import dotty.tools.dotc.core.Names._ import dotty.tools.dotc.core.Phases import dotty.tools.dotc.core.SymDenotations.SymDenotation import dotty.tools.dotc.core.Symbols._ -import dotty.tools.dotc.transform.SuperPhase.MiniPhase +import dotty.tools.dotc.transform.MegaPhase.MiniPhase /** Renames lifted classes to local numbering scheme */ class RenameLifted extends MiniPhase with SymTransformer { diff --git a/compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala b/compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala index fae222da2399..22a700bdb734 100644 --- a/compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala +++ b/compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package transform import core._ -import SuperPhase._ +import MegaPhase._ import Contexts.Context import Flags._ import SymUtils._ diff --git a/compiler/src/dotty/tools/dotc/transform/RestoreScopes.scala b/compiler/src/dotty/tools/dotc/transform/RestoreScopes.scala index 0004f49822dc..b88d46fdda6a 100644 --- a/compiler/src/dotty/tools/dotc/transform/RestoreScopes.scala +++ b/compiler/src/dotty/tools/dotc/transform/RestoreScopes.scala @@ -7,7 +7,7 @@ import Contexts.Context import Symbols._ import Scopes._ import collection.mutable -import SuperPhase.MiniPhase +import MegaPhase.MiniPhase import SymDenotations._ import ast.Trees._ import NameOps._ diff --git a/compiler/src/dotty/tools/dotc/transform/SelectStatic.scala b/compiler/src/dotty/tools/dotc/transform/SelectStatic.scala index 99b0e1998d9f..761d092da972 100644 --- a/compiler/src/dotty/tools/dotc/transform/SelectStatic.scala +++ b/compiler/src/dotty/tools/dotc/transform/SelectStatic.scala @@ -8,7 +8,7 @@ import dotty.tools.dotc.core.DenotTransformers.IdentityDenotTransformer import dotty.tools.dotc.core.Flags._ import dotty.tools.dotc.core.Symbols._ import dotty.tools.dotc.core._ -import dotty.tools.dotc.transform.SuperPhase._ +import dotty.tools.dotc.transform.MegaPhase._ /** Removes selects that would be compiled into GetStatic * otherwise backend needs to be aware that some qualifiers need to be dropped. diff --git a/compiler/src/dotty/tools/dotc/transform/SeqLiterals.scala b/compiler/src/dotty/tools/dotc/transform/SeqLiterals.scala index fbce0be30b17..139424bb111a 100644 --- a/compiler/src/dotty/tools/dotc/transform/SeqLiterals.scala +++ b/compiler/src/dotty/tools/dotc/transform/SeqLiterals.scala @@ -3,7 +3,7 @@ package transform import core._ import Types._ -import dotty.tools.dotc.transform.SuperPhase._ +import dotty.tools.dotc.transform.MegaPhase._ import Contexts.Context import Symbols._ import Phases._ diff --git a/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala b/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala index 506419f0ec9a..453bb7508d7b 100644 --- a/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala +++ b/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import SuperPhase._ +import MegaPhase._ import core.DenotTransformers.IdentityDenotTransformer import core.Symbols._ import core.Contexts._ diff --git a/compiler/src/dotty/tools/dotc/transform/Splitter.scala b/compiler/src/dotty/tools/dotc/transform/Splitter.scala index d8edf6d22293..65a8143cd267 100644 --- a/compiler/src/dotty/tools/dotc/transform/Splitter.scala +++ b/compiler/src/dotty/tools/dotc/transform/Splitter.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import SuperPhase._ +import MegaPhase._ import ast.Trees._ import core._ import Contexts._, Types._, Decorators._, Denotations._, Symbols._, SymDenotations._, Names._ diff --git a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala index 879a7fc9ccad..4f7e588a2548 100644 --- a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import dotty.tools.dotc.transform.SuperPhase._ +import dotty.tools.dotc.transform.MegaPhase._ import dotty.tools.dotc.ast.{Trees, tpd} import scala.collection.{ mutable, immutable } import ValueClasses._ diff --git a/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala b/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala index e8a85a805c48..ac87ffc91984 100644 --- a/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala @@ -5,7 +5,7 @@ import core._ import Symbols._, Types._, Contexts._, Names._, StdNames._, Constants._, SymUtils._ import scala.collection.{ mutable, immutable } import Flags._ -import SuperPhase._ +import MegaPhase._ import DenotTransformers._ import ast.Trees._ import ast.untpd diff --git a/compiler/src/dotty/tools/dotc/transform/TailRec.scala b/compiler/src/dotty/tools/dotc/transform/TailRec.scala index 08c7ad5ca240..9f413e026417 100644 --- a/compiler/src/dotty/tools/dotc/transform/TailRec.scala +++ b/compiler/src/dotty/tools/dotc/transform/TailRec.scala @@ -11,8 +11,7 @@ import Denotations.SingleDenotation import Symbols._ import Types._ import NameKinds.TailLabelName -import TreeTransforms.{MiniPhaseTransform, TransformerInfo} -import SuperPhase.MiniPhase +import MegaPhase.MiniPhase /** * A Tail Rec Transformer diff --git a/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala b/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala index 8bce96d017c8..c0825c7e8bea 100644 --- a/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala +++ b/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import SuperPhase._ +import MegaPhase._ import core._ import Symbols._ import SymDenotations._ diff --git a/compiler/src/dotty/tools/dotc/transform/TransformWildcards.scala b/compiler/src/dotty/tools/dotc/transform/TransformWildcards.scala index c3c7fdf96abe..be813dbeea90 100644 --- a/compiler/src/dotty/tools/dotc/transform/TransformWildcards.scala +++ b/compiler/src/dotty/tools/dotc/transform/TransformWildcards.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import SuperPhase._ +import MegaPhase._ import core.DenotTransformers._ import core.Contexts._ import ast.tpd diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index 45fab5ad5821..ddd3ccd827cf 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc package transform -import SuperPhase._ +import MegaPhase._ import core.Names.Name import core.DenotTransformers._ import core.Denotations._ @@ -106,7 +106,7 @@ class TreeChecker extends Phase with SymTransformer { } private def previousPhases(phases: List[Phase])(implicit ctx: Context): List[Phase] = phases match { - case (phase: SuperPhase) :: phases1 => + case (phase: MegaPhase) :: phases1 => val subPhases = phase.miniPhases val previousSubPhases = previousPhases(subPhases.toList) if (previousSubPhases.length == subPhases.length) previousSubPhases ::: previousPhases(phases1) diff --git a/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala b/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala index 5f86b1c9de2f..a669dcb79843 100644 --- a/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala +++ b/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala @@ -9,7 +9,7 @@ import core.NameKinds.ExceptionBinderName import dotty.tools.dotc.core.Decorators._ import dotty.tools.dotc.core.Flags import dotty.tools.dotc.core.Contexts.Context -import dotty.tools.dotc.transform.SuperPhase.MiniPhase +import dotty.tools.dotc.transform.MegaPhase.MiniPhase import dotty.tools.dotc.util.Positions.Position /** Compiles the cases that can not be handled by primitive catch cases as a common pattern match. diff --git a/compiler/src/dotty/tools/dotc/transform/VCElideAllocations.scala b/compiler/src/dotty/tools/dotc/transform/VCElideAllocations.scala index e08ab1994141..91076cbc3cc3 100644 --- a/compiler/src/dotty/tools/dotc/transform/VCElideAllocations.scala +++ b/compiler/src/dotty/tools/dotc/transform/VCElideAllocations.scala @@ -4,7 +4,7 @@ package transform import ast.{Trees, tpd} import core._, core.Decorators._ import Contexts._, Trees._, StdNames._, Symbols._ -import DenotTransformers._, SuperPhase._, Phases.Phase +import DenotTransformers._, MegaPhase._, Phases.Phase import ExtensionMethods._, TreeExtractors._, ValueClasses._ /** This phase elides unnecessary value class allocations diff --git a/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala b/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala index 6850a6dda387..7daa374855a6 100644 --- a/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala @@ -4,7 +4,7 @@ package transform import ast.{Trees, tpd} import core._, core.Decorators._ import Contexts._, Trees._, Types._ -import DenotTransformers._, SuperPhase._, Phases.Phase +import DenotTransformers._, MegaPhase._, Phases.Phase import ExtensionMethods._, ValueClasses._ import collection.mutable.ListBuffer diff --git a/compiler/src/dotty/tools/dotc/transform/localopt/Simplify.scala b/compiler/src/dotty/tools/dotc/transform/localopt/Simplify.scala index e28c0e3f700e..d336c944e9e6 100644 --- a/compiler/src/dotty/tools/dotc/transform/localopt/Simplify.scala +++ b/compiler/src/dotty/tools/dotc/transform/localopt/Simplify.scala @@ -8,7 +8,7 @@ import core.Types._ import core.Flags._ import core.Decorators._ import core.NameOps._ -import transform.SuperPhase.MiniPhase +import transform.MegaPhase.MiniPhase import config.Printers.simplify import ast.tpd import dotty.tools.dotc.core.PhantomErasure diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index d376cc698966..efecb89d5d68 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -13,7 +13,7 @@ import util.Store import scala.collection.{ mutable, immutable } import ast._ import Trees._ -import SuperPhase._ +import MegaPhase._ import config.Printers.{checks, noPrinter} import util.DotClass import scala.util.{Try, Success, Failure} diff --git a/compiler/test/dotc/tests.scala b/compiler/test/dotc/tests.scala index eb52f44f5a42..a81a8c12fce0 100644 --- a/compiler/test/dotc/tests.scala +++ b/compiler/test/dotc/tests.scala @@ -348,7 +348,7 @@ class tests extends CompilerTest { "NormalizeFlags.scala", "OverridingPairs.scala", "ParamForwarding.scala", "Pickler.scala", "PostTyper.scala", "ResolveSuper.scala", "RestoreScopes.scala", "SeqLiterals.scala", "Splitter.scala", "SuperAccessors.scala", "SymUtils.scala", "SyntheticMethods.scala", "TailRec.scala", "TreeChecker.scala", "TreeExtractors.scala", - "TreeGen.scala", "SuperPhase.scala", "TypeTestsCasts.scala", "TypeUtils.scala", "ValueClasses.scala", + "TreeGen.scala", "MegaPhase.scala", "TypeTestsCasts.scala", "TypeUtils.scala", "ValueClasses.scala", "VCElideAllocations.scala", "VCInlineMethods.scala" ) map (s"${dotcDir}transform/" + _), testPickling) diff --git a/compiler/test/dotty/tools/dotc/transform/TreeTransformerTest.scala b/compiler/test/dotty/tools/dotc/transform/TreeTransformerTest.scala index 7670db20e480..aace7b734d17 100644 --- a/compiler/test/dotty/tools/dotc/transform/TreeTransformerTest.scala +++ b/compiler/test/dotty/tools/dotc/transform/TreeTransformerTest.scala @@ -3,7 +3,7 @@ package dotc package transform import org.junit.{Assert, Test} -import SuperPhase._ +import MegaPhase._ import ast.tpd import core.Constants.Constant import core.Contexts.Context @@ -18,7 +18,7 @@ class TreeTransformerTest extends DottyTest { override def phaseName: String = "empty" init(ctx, ctx.period.firstPhaseId, ctx.period.lastPhaseId) } - val transformer = new SuperPhase(Array(new EmptyTransform)) + val transformer = new MegaPhase(Array(new EmptyTransform)) val transformed = transformer.transformUnit(tree) Assert.assertTrue("returns same tree if unmodified", @@ -36,7 +36,7 @@ class TreeTransformerTest extends DottyTest { override def phaseName: String = "canReplaceConstant" init(ctx, ctx.period.firstPhaseId, ctx.period.lastPhaseId) } - val transformer = new SuperPhase(Array(new ConstantTransform)) + val transformer = new MegaPhase(Array(new ConstantTransform)) val transformed = transformer.transformUnit(tree) Assert.assertTrue("returns same tree if unmodified", @@ -62,7 +62,7 @@ class TreeTransformerTest extends DottyTest { init(ctx, ctx.period.firstPhaseId, ctx.period.lastPhaseId) } - val transformer = new SuperPhase(Array(new Transformation)) + val transformer = new MegaPhase(Array(new Transformation)) val tr = transformer.transformUnit(tree).toString Assert.assertTrue("node can rewrite children", @@ -104,7 +104,7 @@ class TreeTransformerTest extends DottyTest { init(ctx, ctx.period.firstPhaseId, ctx.period.lastPhaseId) } - val transformer = new SuperPhase(Array(new Transformation1, new Transformation2)) + val transformer = new MegaPhase(Array(new Transformation1, new Transformation2)) val tr = transformer.transformUnit(tree).toString Assert.assertTrue("node can rewrite children", @@ -168,7 +168,7 @@ class TreeTransformerTest extends DottyTest { init(ctx, ctx.period.firstPhaseId, ctx.period.lastPhaseId) } - val transformer = new SuperPhase(Array(new Transformation1, new Transformation2)) + val transformer = new MegaPhase(Array(new Transformation1, new Transformation2)) val tr = transformer.transformUnit(tree).toString Assert.assertTrue("transformations aren't invoked multiple times", transformed1 == 2 && transformed2 == 3 diff --git a/doc-tool/src/dotty/tools/dottydoc/core/DocImplicitsPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/DocImplicitsPhase.scala index 05b7bf4b4454..00dcd83b37dc 100644 --- a/doc-tool/src/dotty/tools/dottydoc/core/DocImplicitsPhase.scala +++ b/doc-tool/src/dotty/tools/dottydoc/core/DocImplicitsPhase.scala @@ -2,7 +2,7 @@ package dotty.tools package dottydoc package core -import dotty.tools.dotc.transform.SuperPhase.MiniPhase +import dotty.tools.dotc.transform.MegaPhase.MiniPhase import dotty.tools.dotc.core.Flags import dotc.core.Contexts.Context import util.syntax._ From 19de54fca86ca5b5680ced49a05eeb2cabb64701 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 26 Oct 2017 11:25:20 +0200 Subject: [PATCH 09/12] Reorder TreeTags The switch on tags in transformTree was a lookup switch with the previous distribution of tags. By moving tags that get eliminated before pickling to the end we can turn it into a table switch. --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 41 ++++++++++--------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index c1ba5bc666c5..77fbd90cfb5c 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -43,25 +43,28 @@ object Trees { final val SeqLiteral = 18 final val Inlined = 19 final val TypeTree = 20 - final val SingletonTypeTree = 21 - final val AndTypeTree = 22 - final val OrTypeTree = 23 - final val RefinedTypeTree = 24 - final val AppliedTypeTree = 25 - final val LambdaTypeTree = 26 - final val ByNameTypeTree = 27 - final val TypeBoundsTree = 28 - final val Bind = 29 - final val Alternative = 30 - final val UnApply = 31 - final val ValDef = 32 - final val DefDef = 33 - final val TypeDef = 34 - final val Template = 35 - final val Import = 36 - final val PackageDef = 37 - final val Annotated = 38 - final val Thicket = 39 + final val Bind = 21 + final val Alternative = 22 + final val UnApply = 23 + final val ValDef = 24 + final val DefDef = 25 + final val TypeDef = 26 + final val Template = 27 + final val Import = 28 + final val PackageDef = 29 + final val Thicket = 30 + + final val NumPickledTreeTags = 31 + + final val Annotated = 31 + final val SingletonTypeTree = 32 + final val AndTypeTree = 33 + final val OrTypeTree = 34 + final val RefinedTypeTree = 35 + final val AppliedTypeTree = 36 + final val LambdaTypeTree = 37 + final val ByNameTypeTree = 38 + final val TypeBoundsTree = 39 final val NumTypedTreeTags = 40 From 0bd23f8b779323bb2929aa9850b7d7c89663cecc Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 26 Oct 2017 11:31:03 +0200 Subject: [PATCH 10/12] Fix rebase breakage --- compiler/src/dotty/tools/dotc/transform/TailRec.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/src/dotty/tools/dotc/transform/TailRec.scala b/compiler/src/dotty/tools/dotc/transform/TailRec.scala index 9f413e026417..184a7881b0ed 100644 --- a/compiler/src/dotty/tools/dotc/transform/TailRec.scala +++ b/compiler/src/dotty/tools/dotc/transform/TailRec.scala @@ -12,6 +12,7 @@ import Symbols._ import Types._ import NameKinds.TailLabelName import MegaPhase.MiniPhase +import reporting.diagnostic.messages.TailrecNotApplicable /** * A Tail Rec Transformer From 346f1f2d1cf09539f331871006e2638017dfd6db Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 26 Oct 2017 12:08:25 +0200 Subject: [PATCH 11/12] Bring back relaxedTyping --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 85 ++++++++++--------- compiler/src/dotty/tools/dotc/ast/untpd.scala | 40 ++++----- .../src/dotty/tools/dotc/core/Phases.scala | 6 +- .../tools/dotc/transform/LambdaLift.scala | 2 + .../tools/dotc/transform/MegaPhase.scala | 16 ++++ .../dotty/tools/dotc/typer/TypeAssigner.scala | 8 +- 6 files changed, 92 insertions(+), 65 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 77fbd90cfb5c..0453f65dabdb 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -54,8 +54,9 @@ object Trees { final val PackageDef = 29 final val Thicket = 30 + /** The highest tree tag that can appear in a picked tree + 1 */ final val NumPickledTreeTags = 31 - + final val Annotated = 31 final val SingletonTypeTree = 32 final val AndTypeTree = 33 @@ -66,6 +67,7 @@ object Trees { final val ByNameTypeTree = 38 final val TypeBoundsTree = 39 + /** The highest tree tag that can appear in a typed tree + 1 */ final val NumTypedTreeTags = 40 final val TypedSplice = 40 @@ -89,6 +91,7 @@ object Trees { final val ContextBounds = 48 final val PatDef = 49 + /** The highest tree tag + 1 */ final val NumTags = 50 } @@ -432,7 +435,7 @@ object Trees { case class Ident[-T >: Untyped] private[ast] (name: Name) extends RefTree[T] { type ThisTree[-T >: Untyped] = Ident[T] - def tag = Tag.Ident + final def tag = Tag.Ident def qualifier: Tree[T] = genericEmptyTree /** Is this a `BackquotedIdent` ? */ @@ -450,7 +453,7 @@ object Trees { case class Select[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name) extends RefTree[T] { type ThisTree[-T >: Untyped] = Select[T] - def tag = Tag.Select + final def tag = Tag.Select } class SelectWithSig[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name, val sig: Signature) @@ -462,7 +465,7 @@ object Trees { case class This[-T >: Untyped] private[ast] (qual: untpd.Ident) extends DenotingTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = This[T] - def tag = Tag.This + final def tag = Tag.This // Denotation of a This tree is always the underlying class; needs correction for modules. override def denot(implicit ctx: Context): Denotation = { typeOpt match { @@ -478,7 +481,7 @@ object Trees { case class Super[-T >: Untyped] private[ast] (qual: Tree[T], mix: untpd.Ident) extends ProxyTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = Super[T] - def tag = Tag.Super + final def tag = Tag.Super def forwardTo = qual } @@ -493,35 +496,35 @@ object Trees { case class Apply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]]) extends GenericApply[T] { type ThisTree[-T >: Untyped] = Apply[T] - def tag = Tag.Apply + final def tag = Tag.Apply } /** fun[args] */ case class TypeApply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]]) extends GenericApply[T] { type ThisTree[-T >: Untyped] = TypeApply[T] - def tag = Tag.TypeApply + final def tag = Tag.TypeApply } /** const */ case class Literal[-T >: Untyped] private[ast] (const: Constant) extends TermTree[T] { type ThisTree[-T >: Untyped] = Literal[T] - def tag = Tag.Literal + final def tag = Tag.Literal } /** new tpt, but no constructor call */ case class New[-T >: Untyped] private[ast] (tpt: Tree[T]) extends TermTree[T] { type ThisTree[-T >: Untyped] = New[T] - def tag = Tag.New + final def tag = Tag.New } /** expr : tpt */ case class Typed[-T >: Untyped] private[ast] (expr: Tree[T], tpt: Tree[T]) extends ProxyTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = Typed[T] - def tag = Tag.Typed + final def tag = Tag.Typed def forwardTo = expr } @@ -529,28 +532,28 @@ object Trees { case class NamedArg[-T >: Untyped] private[ast] (name: Name, arg: Tree[T]) extends Tree[T] { type ThisTree[-T >: Untyped] = NamedArg[T] - def tag = Tag.NamedArg + final def tag = Tag.NamedArg } /** name = arg, outside a parameter list */ case class Assign[-T >: Untyped] private[ast] (lhs: Tree[T], rhs: Tree[T]) extends TermTree[T] { type ThisTree[-T >: Untyped] = Assign[T] - def tag = Tag.Assign + final def tag = Tag.Assign } /** { stats; expr } */ case class Block[-T >: Untyped] private[ast] (stats: List[Tree[T]], expr: Tree[T]) extends TermTree[T] { type ThisTree[-T >: Untyped] = Block[T] - def tag = Tag.Block + final def tag = Tag.Block } /** if cond then thenp else elsep */ case class If[-T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T]) extends TermTree[T] { type ThisTree[-T >: Untyped] = If[T] - def tag = Tag.If + final def tag = Tag.If } /** A closure with an environment and a reference to a method. @@ -565,21 +568,21 @@ object Trees { case class Closure[-T >: Untyped] private[ast] (env: List[Tree[T]], meth: Tree[T], tpt: Tree[T]) extends TermTree[T] { type ThisTree[-T >: Untyped] = Closure[T] - def tag = Tag.Closure + final def tag = Tag.Closure } /** selector match { cases } */ case class Match[-T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]]) extends TermTree[T] { type ThisTree[-T >: Untyped] = Match[T] - def tag = Tag.Match + final def tag = Tag.Match } /** case pat if guard => body; only appears as child of a Match */ case class CaseDef[-T >: Untyped] private[ast] (pat: Tree[T], guard: Tree[T], body: Tree[T]) extends Tree[T] { type ThisTree[-T >: Untyped] = CaseDef[T] - def tag = Tag.CaseDef + final def tag = Tag.CaseDef } /** return expr @@ -590,7 +593,7 @@ object Trees { case class Return[-T >: Untyped] private[ast] (expr: Tree[T], from: Tree[T] = genericEmptyTree) extends TermTree[T] { type ThisTree[-T >: Untyped] = Return[T] - def tag = Tag.Return + final def tag = Tag.Return } /** try block catch handler finally finalizer @@ -615,7 +618,7 @@ object Trees { case class Try[-T >: Untyped] private[ast] (expr: Tree[T], cases: List[CaseDef[T]], finalizer: Tree[T]) extends TermTree[T] { type ThisTree[-T >: Untyped] = Try[T] - def tag = Tag.Try + final def tag = Tag.Try } /** Seq(elems) @@ -624,7 +627,7 @@ object Trees { case class SeqLiteral[-T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T]) extends Tree[T] { type ThisTree[-T >: Untyped] = SeqLiteral[T] - def tag = Tag.SeqLiteral + final def tag = Tag.SeqLiteral } /** Array(elems) */ @@ -652,14 +655,14 @@ object Trees { case class Inlined[-T >: Untyped] private[ast] (call: tpd.Tree, bindings: List[MemberDef[T]], expansion: Tree[T]) extends Tree[T] { type ThisTree[-T >: Untyped] = Inlined[T] - def tag = Tag.Inlined + final def tag = Tag.Inlined } /** A type tree that represents an existing or inferred type */ case class TypeTree[-T >: Untyped] () extends DenotingTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = TypeTree[T] - def tag = Tag.TypeTree + final def tag = Tag.TypeTree override def isEmpty = !hasType override def toString = s"TypeTree${if (hasType) s"[$typeOpt]" else ""}" @@ -669,28 +672,28 @@ object Trees { case class SingletonTypeTree[-T >: Untyped] private[ast] (ref: Tree[T]) extends DenotingTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = SingletonTypeTree[T] - def tag = Tag.SingletonTypeTree + final def tag = Tag.SingletonTypeTree } /** left & right */ case class AndTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T]) extends TypTree[T] { type ThisTree[-T >: Untyped] = AndTypeTree[T] - def tag = Tag.AndTypeTree + final def tag = Tag.AndTypeTree } /** left | right */ case class OrTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T]) extends TypTree[T] { type ThisTree[-T >: Untyped] = OrTypeTree[T] - def tag = Tag.OrTypeTree + final def tag = Tag.OrTypeTree } /** tpt { refinements } */ case class RefinedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], refinements: List[Tree[T]]) extends ProxyTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = RefinedTypeTree[T] - def tag = Tag.RefinedTypeTree + final def tag = Tag.RefinedTypeTree def forwardTo = tpt } @@ -698,7 +701,7 @@ object Trees { case class AppliedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], args: List[Tree[T]]) extends ProxyTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = AppliedTypeTree[T] - def tag = Tag.AppliedTypeTree + final def tag = Tag.AppliedTypeTree def forwardTo = tpt } @@ -706,28 +709,28 @@ object Trees { case class LambdaTypeTree[-T >: Untyped] private[ast] (tparams: List[TypeDef[T]], body: Tree[T]) extends TypTree[T] { type ThisTree[-T >: Untyped] = LambdaTypeTree[T] - def tag = Tag.LambdaTypeTree + final def tag = Tag.LambdaTypeTree } /** => T */ case class ByNameTypeTree[-T >: Untyped] private[ast] (result: Tree[T]) extends TypTree[T] { type ThisTree[-T >: Untyped] = ByNameTypeTree[T] - def tag = Tag.ByNameTypeTree + final def tag = Tag.ByNameTypeTree } /** >: lo <: hi */ case class TypeBoundsTree[-T >: Untyped] private[ast] (lo: Tree[T], hi: Tree[T]) extends TypTree[T] { type ThisTree[-T >: Untyped] = TypeBoundsTree[T] - def tag = Tag.TypeBoundsTree + final def tag = Tag.TypeBoundsTree } /** name @ body */ case class Bind[-T >: Untyped] private[ast] (name: Name, body: Tree[T]) extends NameTree[T] with DefTree[T] with PatternTree[T] { type ThisTree[-T >: Untyped] = Bind[T] - def tag = Tag.Bind + final def tag = Tag.Bind override def isType = name.isTypeName override def isTerm = name.isTermName } @@ -736,7 +739,7 @@ object Trees { case class Alternative[-T >: Untyped] private[ast] (trees: List[Tree[T]]) extends PatternTree[T] { type ThisTree[-T >: Untyped] = Alternative[T] - def tag = Tag.Alternative + final def tag = Tag.Alternative } /** The typed translation of `extractor(patterns)` in a pattern. The translation has the following @@ -756,14 +759,14 @@ object Trees { case class UnApply[-T >: Untyped] private[ast] (fun: Tree[T], implicits: List[Tree[T]], patterns: List[Tree[T]]) extends PatternTree[T] { type ThisTree[-T >: Untyped] = UnApply[T] - def tag = Tag.UnApply + final def tag = Tag.UnApply } /** mods val name: tpt = rhs */ case class ValDef[-T >: Untyped] private[ast] (name: TermName, tpt: Tree[T], private var preRhs: LazyTree) extends ValOrDefDef[T] { type ThisTree[-T >: Untyped] = ValDef[T] - def tag = Tag.ValDef + final def tag = Tag.ValDef assert(isEmpty || tpt != genericEmptyTree) def unforced = preRhs protected def force(x: AnyRef) = preRhs = x @@ -774,7 +777,7 @@ object Trees { vparamss: List[List[ValDef[T]]], tpt: Tree[T], private var preRhs: LazyTree) extends ValOrDefDef[T] { type ThisTree[-T >: Untyped] = DefDef[T] - def tag = Tag.DefDef + final def tag = Tag.DefDef assert(tpt != genericEmptyTree) def unforced = preRhs protected def force(x: AnyRef) = preRhs = x @@ -788,7 +791,7 @@ object Trees { case class TypeDef[-T >: Untyped] private[ast] (name: TypeName, rhs: Tree[T]) extends MemberDef[T] { type ThisTree[-T >: Untyped] = TypeDef[T] - def tag = Tag.TypeDef + final def tag = Tag.TypeDef /** Is this a definition of a class? */ def isClassDef = rhs.isInstanceOf[Template[_]] @@ -798,7 +801,7 @@ object Trees { case class Template[-T >: Untyped] private[ast] (constr: DefDef[T], parents: List[Tree[T]], self: ValDef[T], private var preBody: LazyTreeList) extends DefTree[T] with WithLazyField[List[Tree[T]]] { type ThisTree[-T >: Untyped] = Template[T] - def tag = Tag.Template + final def tag = Tag.Template def unforcedBody = unforced def unforced = preBody protected def force(x: AnyRef) = preBody = x @@ -812,14 +815,14 @@ object Trees { case class Import[-T >: Untyped] private[ast] (expr: Tree[T], selectors: List[Tree[Untyped]]) extends DenotingTree[T] { type ThisTree[-T >: Untyped] = Import[T] - def tag = Tag.Import + final def tag = Tag.Import } /** package pid { stats } */ case class PackageDef[-T >: Untyped] private[ast] (pid: RefTree[T], stats: List[Tree[T]]) extends ProxyTree[T] { type ThisTree[-T >: Untyped] = PackageDef[T] - def tag = Tag.PackageDef + final def tag = Tag.PackageDef def forwardTo = pid } @@ -827,7 +830,7 @@ object Trees { case class Annotated[-T >: Untyped] private[ast] (arg: Tree[T], annot: Tree[T]) extends ProxyTree[T] { type ThisTree[-T >: Untyped] = Annotated[T] - def tag = Tag.Annotated + final def tag = Tag.Annotated def forwardTo = arg } @@ -846,7 +849,7 @@ object Trees { case class Thicket[-T >: Untyped](trees: List[Tree[T]]) extends Tree[T] with WithoutTypeOrPos[T] { type ThisTree[-T >: Untyped] = Thicket[T] - def tag = Tag.Thicket + final def tag = Tag.Thicket override def isEmpty: Boolean = trees.isEmpty override def toList: List[Tree[T]] = flatten(trees) override def toString = if (isEmpty) "EmptyTree" else "Thicket(" + trees.mkString(", ") + ")" diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index 6de2c5744074..28ef978a5012 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -25,7 +25,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { * @param owner The current owner at the time the tree was defined */ abstract case class TypedSplice(tree: tpd.Tree)(val owner: Symbol) extends ProxyTree { - def tag = Tag.TypedSplice + final def tag = Tag.TypedSplice def forwardTo = tree } @@ -38,16 +38,16 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { case class ModuleDef(name: TermName, impl: Template) extends MemberDef { type ThisTree[-T >: Untyped] <: Trees.NameTree[T] with Trees.MemberDef[T] with ModuleDef - def tag = Tag.ModuleDef + final def tag = Tag.ModuleDef def withName(name: Name)(implicit ctx: Context) = cpy.ModuleDef(this)(name.toTermName, impl) } case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree) extends TermTree { - def tag = Tag.ParsedTry + final def tag = Tag.ParsedTry } case class SymbolLit(str: String) extends TermTree { - def tag = Tag.SymbolLit + final def tag = Tag.SymbolLit } /** An interpolated string @@ -55,11 +55,11 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { * possibly with a simple string literal as last element of the list */ case class InterpolatedString(id: TermName, segments: List[Tree]) extends TermTree { - def tag = Tag.InterpolatedString + final def tag = Tag.InterpolatedString } case class Function(args: List[Tree], body: Tree) extends Tree { - def tag = Tag.Function + final def tag = Tag.Function override def isTerm = body.isTerm override def isType = body.isType } @@ -77,49 +77,49 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { class WildcardFunction(placeholderParams: List[ValDef], body: Tree) extends Function(placeholderParams, body) case class InfixOp(left: Tree, op: Ident, right: Tree) extends OpTree { - def tag = Tag.InfixOp + final def tag = Tag.InfixOp } case class PostfixOp(od: Tree, op: Ident) extends OpTree { - def tag = Tag.PostfixOp + final def tag = Tag.PostfixOp } case class PrefixOp(op: Ident, od: Tree) extends OpTree { - def tag = Tag.PrefixOp + final def tag = Tag.PrefixOp } case class Parens(t: Tree) extends ProxyTree { - def tag = Tag.Parens + final def tag = Tag.Parens def forwardTo = t } case class Tuple(trees: List[Tree]) extends Tree { - def tag = Tag.Tuple + final def tag = Tag.Tuple override def isTerm = trees.isEmpty || trees.head.isTerm override def isType = !isTerm } case class Throw(expr: Tree) extends TermTree { - def tag = Tag.Throw + final def tag = Tag.Throw } case class WhileDo(cond: Tree, body: Tree) extends TermTree { - def tag = Tag.WhileDo + final def tag = Tag.WhileDo } case class DoWhile(body: Tree, cond: Tree) extends TermTree { - def tag = Tag.DoWhile + final def tag = Tag.DoWhile } case class ForYield(enums: List[Tree], expr: Tree) extends TermTree { - def tag = Tag.ForYield + final def tag = Tag.ForYield } case class ForDo(enums: List[Tree], body: Tree) extends TermTree { - def tag = Tag.ForDo + final def tag = Tag.ForDo } case class GenFrom(pat: Tree, expr: Tree) extends Tree { - def tag = Tag.GenFrom + final def tag = Tag.GenFrom } case class GenAlias(pat: Tree, expr: Tree) extends Tree { - def tag = Tag.GenAlias + final def tag = Tag.GenAlias } case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree]) extends TypTree { - def tag = Tag.ContextBounds + final def tag = Tag.ContextBounds } case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree) extends DefTree { - def tag = Tag.PatDef + final def tag = Tag.PatDef } @sharable object EmptyTypeIdent extends Ident(tpnme.EMPTY) with WithoutTypeOrPos[Untyped] { diff --git a/compiler/src/dotty/tools/dotc/core/Phases.scala b/compiler/src/dotty/tools/dotc/core/Phases.scala index 72fc85dda830..77f700454cad 100644 --- a/compiler/src/dotty/tools/dotc/core/Phases.scala +++ b/compiler/src/dotty/tools/dotc/core/Phases.scala @@ -272,7 +272,11 @@ object Phases { def isRunnable(implicit ctx: Context): Boolean = !ctx.reporter.hasErrors - /** List of names of phases that should precede this phase */ + /** If set, allow missing or superfluous arguments in applications + * and type applications. + */ + def relaxedTyping: Boolean = false + /** List of names of phases that should precede this phase */ def runsAfter: Set[Class[_ <: Phase]] = Set.empty /** @pre `isRunnable` returns true */ diff --git a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala index a7b4a37793a1..5573b8e080ec 100644 --- a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala +++ b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala @@ -490,6 +490,8 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisPhase => /** the following two members override abstract members in Transform */ val phaseName: String = "lambdaLift" + override def relaxedTypingInGroup = true + override def runsAfterGroupsOf: Set[Class[_ <: Phase]] = Set(classOf[Constructors], classOf[HoistSuperArgs]) // Constructors has to happen before LambdaLift because the lambda lift logic // becomes simpler if it can assume that parameter accessors have already been diff --git a/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala b/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala index faf40bb5086e..4c24eb0c6144 100644 --- a/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala +++ b/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala @@ -44,6 +44,11 @@ object MegaPhase { */ def runsAfterGroupsOf: Set[Class[_ <: Phase]] = Set.empty + final override def relaxedTyping = superPhase.relaxedTyping + + /** If set, use relaxed typing for all phases in group */ + def relaxedTypingInGroup = false + val cpy: TypedTreeCopier = cpyBetweenPhases def prepareForIdent(tree: Ident)(implicit ctx: Context): Context = ctx @@ -143,6 +148,17 @@ class MegaPhase(val miniPhases: Array[MiniPhase]) extends Phase { if (miniPhases.length == 1) miniPhases(0).phaseName else miniPhases.map(_.phaseName).mkString("MegaPhase{", ", ", "}") + private var relaxedTypingCache: Boolean = _ + private var relaxedTypingKnown = false + + override final def relaxedTyping = { + if (!relaxedTypingKnown) { + relaxedTypingCache = miniPhases.exists(_.relaxedTypingInGroup) + relaxedTypingKnown = true + } + relaxedTypingCache + } + private val cpy: TypedTreeCopier = cpyBetweenPhases /** Transform node using all phases in this group that have idxInGroup >= start */ diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 09d380eb06f9..8d8408fb21bb 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -349,9 +349,11 @@ trait TypeAssigner { def assignType(tree: untpd.Apply, fn: Tree, args: List[Tree])(implicit ctx: Context) = { val ownType = fn.tpe.widen match { case fntpe: MethodType => - if (fntpe.isDependent) safeSubstParams(fntpe.resultType, fntpe.paramRefs, args.tpes) - else fntpe.resultType - case t => + if (sameLength(fntpe.paramInfos, args) || ctx.phase.prev.relaxedTyping) + if (fntpe.isDependent) safeSubstParams(fntpe.resultType, fntpe.paramRefs, args.tpes) + else fntpe.resultType + else + errorType(i"wrong number of arguments for $fntpe: ${fn.tpe}, expected: ${fntpe.paramInfos.length}, found: ${args.length}", tree.pos) case t => errorType(err.takesNoParamsStr(fn, ""), tree.pos) } tree.withType(ownType) From 5a41b3e7b0a8f522c82a3686a0e22481afcfbeb9 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 26 Oct 2017 14:37:53 +0200 Subject: [PATCH 12/12] Make Mixin a relaxedTyping phase Mixin changes the number of parameters of trait initializers and therefore needs relaxed typing. This was not discovered before because TreeTransformers did not use a time travelling tree copier. --- compiler/src/dotty/tools/dotc/transform/Mixin.scala | 3 +++ compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/Mixin.scala b/compiler/src/dotty/tools/dotc/transform/Mixin.scala index ac25694eab7f..e17976984a07 100644 --- a/compiler/src/dotty/tools/dotc/transform/Mixin.scala +++ b/compiler/src/dotty/tools/dotc/transform/Mixin.scala @@ -96,6 +96,9 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase => override def phaseName: String = "mixin" + override def relaxedTypingInGroup = true + // Because it changes number of parameters in trait initializers + override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[Erasure]) override def changesMembers = true // the phase adds implementions of mixin accessors diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 8d8408fb21bb..45c8a422b855 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -349,11 +349,12 @@ trait TypeAssigner { def assignType(tree: untpd.Apply, fn: Tree, args: List[Tree])(implicit ctx: Context) = { val ownType = fn.tpe.widen match { case fntpe: MethodType => - if (sameLength(fntpe.paramInfos, args) || ctx.phase.prev.relaxedTyping) + if (sameLength(fntpe.paramInfos, args) || ctx.phase.prev.relaxedTyping || true) if (fntpe.isDependent) safeSubstParams(fntpe.resultType, fntpe.paramRefs, args.tpes) else fntpe.resultType else - errorType(i"wrong number of arguments for $fntpe: ${fn.tpe}, expected: ${fntpe.paramInfos.length}, found: ${args.length}", tree.pos) case t => + errorType(i"wrong number of arguments at ${ctx.phase.prev} for $fntpe: ${fn.tpe}, expected: ${fntpe.paramInfos.length}, found: ${args.length}", tree.pos) + case t => errorType(err.takesNoParamsStr(fn, ""), tree.pos) } tree.withType(ownType)