diff --git a/compiler/src/dotty/tools/dotc/Compiler.scala b/compiler/src/dotty/tools/dotc/Compiler.scala index 4e6eeef20dd5..f80e01a00d91 100644 --- a/compiler/src/dotty/tools/dotc/Compiler.scala +++ b/compiler/src/dotty/tools/dotc/Compiler.scala @@ -53,7 +53,6 @@ class Compiler { new ElimJavaPackages), // Eliminate syntactic references to Java packages List(new CheckStatic, // Check restrictions that apply to @static members new ElimRepeated, // Rewrite vararg parameters and arguments - new RefChecks, // Various checks mostly related to abstract members and overriding new NormalizeFlags, // Rewrite some definition flags new ExtensionMethods, // Expand methods of value classes with extension methods new ExpandSAMs, // Expand single abstract method closures to anonymous classes @@ -61,7 +60,8 @@ class Compiler { new ByNameClosures, // Expand arguments to by-name parameters to closures new LiftTry, // Put try expressions that might execute on non-empty stacks into their own methods new HoistSuperArgs, // Hoist complex arguments of supercalls to enclosing scope - new ClassOf), // Expand `Predef.classOf` calls. + new ClassOf, // Expand `Predef.classOf` calls. + new RefChecks), // Various checks mostly related to abstract members and overriding List(new TryCatchPatterns, // Compile cases in try/catch new PatternMatcher, // Compile pattern matches new ExplicitOuter, // Add accessors to outer classes from nested ones. @@ -98,10 +98,10 @@ class Compiler { List(new LinkScala2Impls, // Redirect calls to trait methods defined by Scala 2.x, so that they now go to their implementations new LambdaLift, // Lifts out nested functions to class scope, storing free variables in environments // Note: in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here - new ElimStaticThis, // Replace `this` references to static objects by global identifiers - new Flatten, // Lift all inner classes to package scope - new RestoreScopes), // Repair scopes rendered invalid by moving definitions in prior phases of the group - List(new RenameLifted, // Renames lifted classes to local numbering scheme + new ElimStaticThis), // Replace `this` references to static objects by global identifiers + List(new Flatten, // Lift all inner classes to package scope + new RestoreScopes, // Repair scopes rendered invalid by moving definitions in prior phases of the group + new RenameLifted, // Renames lifted classes to local numbering scheme new TransformWildcards, // Replace wildcards with default values new MoveStatics, // Move static methods to companion classes new ExpandPrivate, // Widen private definitions accessed from nested classes diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 8e23819aa77d..df03eda317cc 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -656,26 +656,27 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { /** After phase `trans`, set the owner of every definition in this tree that was formerly * owner by `from` to `to`. */ - def changeOwnerAfter(from: Symbol, to: Symbol, trans: DenotTransformer)(implicit ctx: Context): ThisTree = { - assert(ctx.phase == trans.next) - val traverser = new TreeTraverser { - def traverse(tree: Tree)(implicit ctx: Context) = tree match { - case tree: DefTree => - val sym = tree.symbol - val prevDenot = sym.denot(ctx.withPhase(trans)) - if (prevDenot.effectiveOwner == from.skipWeakOwner) { - val d = sym.copySymDenotation(owner = to) - d.installAfter(trans) - d.transformAfter(trans, d => if (d.owner eq from) d.copySymDenotation(owner = to) else d) - } - if (sym.isWeakOwner) traverseChildren(tree) - case _ => - traverseChildren(tree) + def changeOwnerAfter(from: Symbol, to: Symbol, trans: DenotTransformer)(implicit ctx: Context): ThisTree = + if (ctx.phase == trans.next) { + val traverser = new TreeTraverser { + def traverse(tree: Tree)(implicit ctx: Context) = tree match { + case tree: DefTree => + val sym = tree.symbol + val prevDenot = sym.denot(ctx.withPhase(trans)) + if (prevDenot.effectiveOwner == from.skipWeakOwner) { + val d = sym.copySymDenotation(owner = to) + d.installAfter(trans) + d.transformAfter(trans, d => if (d.owner eq from) d.copySymDenotation(owner = to) else d) + } + if (sym.isWeakOwner) traverseChildren(tree) + case _ => + traverseChildren(tree) + } } + traverser.traverse(tree) + tree } - traverser.traverse(tree) - tree - } + else changeOwnerAfter(from, to, trans)(ctx.withPhase(trans.next)) /** A select node with the given selector name and a computed type */ def select(name: Name)(implicit ctx: Context): Select = diff --git a/compiler/src/dotty/tools/dotc/core/Phases.scala b/compiler/src/dotty/tools/dotc/core/Phases.scala index 92ed5d75a831..10c7b7416325 100644 --- a/compiler/src/dotty/tools/dotc/core/Phases.scala +++ b/compiler/src/dotty/tools/dotc/core/Phases.scala @@ -298,11 +298,6 @@ object Phases { */ def checkPostCondition(tree: tpd.Tree)(implicit ctx: Context): Unit = () - /** If set, allow missing or superfluous arguments in applications - * and type applications. - */ - def relaxedTyping: Boolean = false - /** Is this phase the standard typerphase? True for FrontEnd, but * not for other first phases (such as FromTasty). The predicate * is tested in some places that perform checks and corrections. It's diff --git a/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala b/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala index 07cbceb7b2e4..f0e69330adab 100644 --- a/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala +++ b/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala @@ -91,7 +91,7 @@ class CapturedVars extends MiniPhase with IdentityDenotTransformer { thisTransfo } override def prepareForValDef(vdef: ValDef)(implicit ctx: Context) = { - val sym = vdef.symbol + 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, @@ -119,7 +119,7 @@ class CapturedVars extends MiniPhase with IdentityDenotTransformer { thisTransfo 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) + id.select(nme.elem).ensureConforms(vble.denot(ctx.withPhase(thisTransform)).info) else id } diff --git a/compiler/src/dotty/tools/dotc/transform/ElimByName.scala b/compiler/src/dotty/tools/dotc/transform/ElimByName.scala index 9b3008f9147f..4202b9f91bb4 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimByName.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimByName.scala @@ -47,7 +47,8 @@ class ElimByName extends TransformByNameApply with InfoTransformer { thisTransfo /** Map `tree` to `tree.apply()` is `ftree` was of ExprType and becomes now a function */ private def applyIfFunction(tree: Tree, ftree: Tree)(implicit ctx: Context) = - if (isByNameRef(ftree)) tree.select(defn.Function0_apply).appliedToNone + if (isByNameRef(ftree)) + ctx.atPhase(next) { implicit ctx => tree.select(defn.Function0_apply).appliedToNone } else tree override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo): Tree = @@ -65,9 +66,11 @@ class ElimByName extends TransformByNameApply with InfoTransformer { thisTransfo } override def transformValDef(tree: ValDef)(implicit ctx: Context, info: TransformerInfo): Tree = - if (exprBecomesFunction(tree.symbol)) - cpy.ValDef(tree)(tpt = tree.tpt.withType(tree.symbol.info)) - else tree + ctx.atPhase(next) { implicit ctx => + if (exprBecomesFunction(tree.symbol)) + cpy.ValDef(tree)(tpt = tree.tpt.withType(tree.symbol.info)) + else tree + } def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = tp match { case ExprType(rt) if exprBecomesFunction(sym) => defn.FunctionOf(Nil, rt) diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala index 5f89923159f0..04b574d6fbbd 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala @@ -25,7 +25,7 @@ import dotty.tools.dotc.core.Phases.Phase /** Make private term members that are accessed from another class * non-private by resetting the Private flag and expanding their name. * - * Make private accessor in value class not-private. Ihis is necessary to unbox + * Make private accessor in value class not-private. This is necessary to unbox * the value class when accessing it from separate compilation units * * Also, make non-private any private parameter forwarders that forward to an inherited diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala index f17bec6f13fb..54e474888654 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -132,15 +132,11 @@ object ExplicitOuter { import ast.tpd._ /** Ensure that class `cls` has outer accessors */ - def ensureOuterAccessors(cls: ClassSymbol)(implicit ctx: Context): Unit = { - //todo: implementing #165 would simplify this logic - val prevPhase = ctx.phase.prev - assert(prevPhase.id <= ctx.explicitOuterPhase.id, "can add $outer symbols only before ExplicitOuter") - assert(prevPhase.isInstanceOf[DenotTransformer], "adding outerAccessors requires being DenotTransformer") - if (!hasOuter(cls)) { - newOuterAccessors(cls).foreach(_.enteredAfter(prevPhase.asInstanceOf[DenotTransformer])) + def ensureOuterAccessors(cls: ClassSymbol)(implicit ctx: Context): Unit = + ctx.atPhase(ctx.explicitOuterPhase.next) { implicit ctx => + if (!hasOuter(cls)) + newOuterAccessors(cls).foreach(_.enteredAfter(ctx.explicitOuterPhase.asInstanceOf[DenotTransformer])) } - } /** The outer accessor and potentially outer param accessor needed for class `cls` */ private def newOuterAccessors(cls: ClassSymbol)(implicit ctx: Context) = diff --git a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala index f05afe82da48..d1ff4b72c938 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala @@ -131,7 +131,7 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful private def createExtensionMethod(imeth: Symbol, staticClass: Symbol)(implicit ctx: Context): TermSymbol = { val extensionName = extensionNames(imeth).head.toTermName val extensionMeth = ctx.newSymbol(staticClass, extensionName, - imeth.flags | Final &~ (Override | Protected | AbsOverride), + (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)) @@ -175,8 +175,8 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful extensionDefs(staticClass) = newC newC } - store += atGroupEnd(fullyParameterizedDef(extensionMeth, tree)(_)) - cpy.DefDef(tree)(rhs = atGroupEnd(forwarder(extensionMeth, tree)(_))) + store += fullyParameterizedDef(extensionMeth, tree) + cpy.DefDef(tree)(rhs = forwarder(extensionMeth, tree)) } else tree } } diff --git a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala index 23d58c035577..f2645c5446cc 100644 --- a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala +++ b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala @@ -64,8 +64,6 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform val phaseName: String = "lambdaLift" val treeTransform = new LambdaLifter - override def relaxedTyping = 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/LazyVals.scala b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala index 9afb3051478c..94b046d317df 100644 --- a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala @@ -166,12 +166,10 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer { // backend requires field usage to be after field definition // need to bring containers to start of method val (holders, stats) = - atGroupEnd { implicit ctx: Context => - trees.partition { - _.symbol.flags.&~(Flags.Touched) == containerFlags - // Filtering out Flags.Touched is not required currently, as there are no LazyTypes involved here - // but just to be more safe - } + trees.partition { + _.symbol.flags.&~(Flags.Touched) == containerFlags + // Filtering out Flags.Touched is not required currently, as there are no LazyTypes involved here + // but just to be more safe } holders:::stats } diff --git a/compiler/src/dotty/tools/dotc/transform/NormalizeFlags.scala b/compiler/src/dotty/tools/dotc/transform/NormalizeFlags.scala index 75584690409c..35a183c84a13 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 +import TreeTransforms.{MiniPhaseTransform, TransformerInfo} 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 0d3ec5ac55d5..6e8f3141d39b 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -768,7 +768,7 @@ object PatternMatcher { def outerTest: Tree = trans.transformFollowingDeep { val expectedOuter = singleton(expectedTp.normalizedPrefix) val expectedClass = expectedTp.dealias.classSymbol.asClass - ExplicitOuter.ensureOuterAccessors(expectedClass)(ctx.withPhase(ctx.explicitOuterPhase.next)) + ExplicitOuter.ensureOuterAccessors(expectedClass) scrutinee.ensureConforms(expectedTp) .outerSelect(1, expectedOuter.tpe.widen) .select(defn.Object_eq) diff --git a/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala b/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala index fca24d71b8cf..8a7b7665a9ec 100644 --- a/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala +++ b/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala @@ -9,14 +9,15 @@ 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 +import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, TransformerInfo} /** Renames lifted classes to local numbering scheme */ class RenameLifted extends MiniPhaseTransform with SymTransformer { thisTransformer => override def phaseName = "renameLifted" - override def runsAfterGroupsOf: Set[Class[_ <: Phases.Phase]] = Set(classOf[RestoreScopes]) + // Not clear why this should run after restoreScopes + // override def runsAfterGroupsOf: Set[Class[_ <: Phases.Phase]] = Set(classOf[RestoreScopes]) def transformSym(ref: SymDenotation)(implicit ctx: Context): SymDenotation = if (needsRefresh(ref.symbol)) ref.copySymDenotation(name = refreshedName(ref.symbol)) diff --git a/compiler/src/dotty/tools/dotc/transform/TailRec.scala b/compiler/src/dotty/tools/dotc/transform/TailRec.scala index 4f6d5dace29b..8ab4e94c93d8 100644 --- a/compiler/src/dotty/tools/dotc/transform/TailRec.scala +++ b/compiler/src/dotty/tools/dotc/transform/TailRec.scala @@ -6,7 +6,7 @@ import ast.{TreeTypeMap, tpd} import core._ import Contexts.Context import Decorators._ -import DenotTransformers.DenotTransformer +import DenotTransformers.IdentityDenotTransformer import Denotations.SingleDenotation import Symbols._ import Types._ @@ -62,13 +62,11 @@ import TreeTransforms.{MiniPhaseTransform, TransformerInfo} * self recursive functions, that's why it's renamed to tailrec *

*/ -class TailRec extends MiniPhaseTransform with DenotTransformer with FullParameterization { thisTransform => +class TailRec extends MiniPhaseTransform with FullParameterization { thisTransform => import TailRec._ import dotty.tools.dotc.ast.tpd._ - override def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = ref - override def phaseName: String = "tailrec" final val labelFlags = Flags.Synthetic | Flags.Label @@ -101,65 +99,62 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete case dd@DefDef(name, tparams, vparamss0, tpt, _) if (sym.isEffectivelyFinal) && !((sym is Flags.Accessor) || (dd.rhs eq EmptyTree) || (sym is Flags.Label)) => val mandatory = sym.hasAnnotation(defn.TailrecAnnot) - atGroupEnd { implicit ctx: Context => - - cpy.DefDef(dd)(rhs = { - - val defIsTopLevel = sym.owner.isClass - val origMeth = sym - val label = mkLabel(sym, abstractOverClass = defIsTopLevel) - val owner = ctx.owner.enclosingClass.asClass - val thisTpe = owner.thisType.widen - - var rewrote = false - - // Note: this can be split in two separate transforms(in different groups), - // than first one will collect info about which transformations and rewritings should be applied - // and second one will actually apply, - // now this speculatively transforms tree and throws away result in many cases - val rhsSemiTransformed = { - val transformer = new TailRecElimination(origMeth, dd.tparams, owner, thisTpe, mandatory, label, abstractOverClass = defIsTopLevel) - val rhs = atGroupEnd(implicit ctx => transformer.transform(dd.rhs)) - rewrote = transformer.rewrote - rhs - } + cpy.DefDef(dd)(rhs = { + + val defIsTopLevel = sym.owner.isClass + val origMeth = sym + val label = mkLabel(sym, abstractOverClass = defIsTopLevel) + val owner = ctx.owner.enclosingClass.asClass + val thisTpe = owner.thisType.widen + + var rewrote = false + + // Note: this can be split in two separate transforms(in different groups), + // than first one will collect info about which transformations and rewritings should be applied + // and second one will actually apply, + // now this speculatively transforms tree and throws away result in many cases + val rhsSemiTransformed = { + val transformer = new TailRecElimination(origMeth, dd.tparams, owner, thisTpe, mandatory, label, abstractOverClass = defIsTopLevel) + val rhs = transformer.transform(dd.rhs) + rewrote = transformer.rewrote + rhs + } - if (rewrote) { - val dummyDefDef = cpy.DefDef(tree)(rhs = rhsSemiTransformed) - if (tree.symbol.owner.isClass) { - val labelDef = fullyParameterizedDef(label, dummyDefDef, abstractOverClass = defIsTopLevel) - val call = forwarder(label, dd, abstractOverClass = defIsTopLevel, liftThisType = true) - Block(List(labelDef), call) - } else { // inner method. Tail recursion does not change `this` - val labelDef = polyDefDef(label, trefs => vrefss => { - val origMeth = tree.symbol - val origTParams = tree.tparams.map(_.symbol) - val origVParams = tree.vparamss.flatten map (_.symbol) - new TreeTypeMap( - typeMap = identity(_) - .substDealias(origTParams, trefs) - .subst(origVParams, vrefss.flatten.map(_.tpe)), - oldOwners = origMeth :: Nil, - newOwners = label :: Nil - ).transform(rhsSemiTransformed) - }) - val callIntoLabel = ( - if (dd.tparams.isEmpty) ref(label) - else ref(label).appliedToTypes(dd.tparams.map(_.tpe)) - ).appliedToArgss(vparamss0.map(_.map(x=> ref(x.symbol)))) - Block(List(labelDef), callIntoLabel) - }} else { - if (mandatory) ctx.error( - "TailRec optimisation not applicable, method not tail recursive", - // FIXME: want to report this error on `dd.namePos`, but - // because of extension method getting a weird pos, it is - // better to report on symbol so there's no overlap - sym.pos - ) - dd.rhs - } - }) - } + if (rewrote) { + val dummyDefDef = cpy.DefDef(tree)(rhs = rhsSemiTransformed) + if (tree.symbol.owner.isClass) { + val labelDef = fullyParameterizedDef(label, dummyDefDef, abstractOverClass = defIsTopLevel) + val call = forwarder(label, dd, abstractOverClass = defIsTopLevel, liftThisType = true) + Block(List(labelDef), call) + } else { // inner method. Tail recursion does not change `this` + val labelDef = polyDefDef(label, trefs => vrefss => { + val origMeth = tree.symbol + val origTParams = tree.tparams.map(_.symbol) + val origVParams = tree.vparamss.flatten map (_.symbol) + new TreeTypeMap( + typeMap = identity(_) + .substDealias(origTParams, trefs) + .subst(origVParams, vrefss.flatten.map(_.tpe)), + oldOwners = origMeth :: Nil, + newOwners = label :: Nil + ).transform(rhsSemiTransformed) + }) + val callIntoLabel = ( + if (dd.tparams.isEmpty) ref(label) + else ref(label).appliedToTypes(dd.tparams.map(_.tpe)) + ).appliedToArgss(vparamss0.map(_.map(x=> ref(x.symbol)))) + Block(List(labelDef), callIntoLabel) + }} else { + if (mandatory) ctx.error( + "TailRec optimisation not applicable, method not tail recursive", + // FIXME: want to report this error on `dd.namePos`, but + // because of extension method getting a weird pos, it is + // better to report on symbol so there's no overlap + sym.pos + ) + dd.rhs + } + }) case d: DefDef if d.symbol.hasAnnotation(defn.TailrecAnnot) || methodsWithInnerAnnots.contains(d.symbol) => ctx.error("TailRec optimisation not applicable, method is neither private nor final so can be overridden", sym.pos) d @@ -239,8 +234,6 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete continue } - - if (isRecursiveCall) { if (ctx.tailPos) { val receiverIsSame = enclosingClass.appliedRef.widenDealias =:= recvWiden diff --git a/compiler/src/dotty/tools/dotc/transform/TreeTransform.scala b/compiler/src/dotty/tools/dotc/transform/TreeTransform.scala index b2a1ccd699d5..d3fd77f1403c 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeTransform.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeTransform.scala @@ -7,6 +7,7 @@ import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.DenotTransformers.{InfoTransformer, DenotTransformer} import dotty.tools.dotc.core.Denotations.SingleDenotation import dotty.tools.dotc.core.Phases.Phase +import dotty.tools.dotc.core.Periods._ import dotty.tools.dotc.core.SymDenotations.SymDenotation import dotty.tools.dotc.core.Symbols.Symbol import dotty.tools.dotc.core.Flags.PackageVal @@ -61,9 +62,6 @@ object TreeTransforms { def phase: MiniPhase - /** The phase at which the tree is transformed */ - final def treeTransformPhase: Phase = phase.next - val cpy: TypedTreeCopier = cpyBetweenPhases def prepareForIdent(tree: Ident)(implicit ctx: Context) = this @@ -139,11 +137,6 @@ object TreeTransforms { /** Transform single node using all transforms following the current one in this group */ def transformFollowing(tree: Tree)(implicit ctx: Context, info: TransformerInfo): Tree = info.group.transformSingle(tree, phase.idx + 1) - - def atGroupEnd[T](action : Context => T)(implicit ctx: Context, info: TransformerInfo) = { - val last = info.transformers(info.transformers.length - 1) - action(ctx.withPhase(last.phase.next)) - } } /** A phase that defines a TreeTransform to be used in a group */ @@ -471,6 +464,15 @@ object TreeTransforms { def miniPhases: Array[MiniPhase] + private var myGroupEndId: PhaseId = NoPhaseId + + def groupEndId: PhaseId = { + if (myGroupEndId == NoPhaseId) myGroupEndId = miniPhases.last.id + 1 + myGroupEndId + } + + val cpy: TypedTreeCopier = cpyBetweenPhases + override def run(implicit ctx: Context): Unit = { val curTree = ctx.compilationUnit.tpdTree val newTree = macroTransform(curTree) @@ -494,7 +496,7 @@ object TreeTransforms { var allDone = i < l while (i < l) { val oldTransform = result(i) - val newTransform = mutator(oldTransform, tree, ctx.withPhase(oldTransform.treeTransformPhase)) + val newTransform = mutator(oldTransform, tree, ctx.withPhase(groupEndId)) allDone = allDone && (newTransform eq NoTransform) if (!(oldTransform eq newTransform)) { if (!transformersCopied) result = result.clone() @@ -562,7 +564,7 @@ object TreeTransforms { final private[TreeTransforms] def goIdent(tree: Ident, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformIdent(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformIdent(tree)(ctx.withPhase(groupEndId), info) match { case t: Ident => goIdent(t, info.nx.nxTransIdent(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -573,7 +575,7 @@ object TreeTransforms { final private[TreeTransforms] def goSelect(tree: Select, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformSelect(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformSelect(tree)(ctx.withPhase(groupEndId), info) match { case t: Select => goSelect(t, info.nx.nxTransSelect(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -584,7 +586,7 @@ object TreeTransforms { final private[TreeTransforms] def goThis(tree: This, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformThis(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformThis(tree)(ctx.withPhase(groupEndId), info) match { case t: This => goThis(t, info.nx.nxTransThis(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -595,7 +597,7 @@ object TreeTransforms { final private[TreeTransforms] def goSuper(tree: Super, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformSuper(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformSuper(tree)(ctx.withPhase(groupEndId), info) match { case t: Super => goSuper(t, info.nx.nxTransSuper(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -606,7 +608,7 @@ object TreeTransforms { final private[TreeTransforms] def goApply(tree: Apply, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformApply(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformApply(tree)(ctx.withPhase(groupEndId), info) match { case t: Apply => goApply(t, info.nx.nxTransApply(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -617,7 +619,7 @@ object TreeTransforms { final private[TreeTransforms] def goTypeApply(tree: TypeApply, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformTypeApply(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformTypeApply(tree)(ctx.withPhase(groupEndId), info) match { case t: TypeApply => goTypeApply(t, info.nx.nxTransTypeApply(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -628,7 +630,7 @@ object TreeTransforms { final private[TreeTransforms] def goNew(tree: New, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformNew(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformNew(tree)(ctx.withPhase(groupEndId), info) match { case t: New => goNew(t, info.nx.nxTransNew(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -639,7 +641,7 @@ object TreeTransforms { final private[TreeTransforms] def goTyped(tree: Typed, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformTyped(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformTyped(tree)(ctx.withPhase(groupEndId), info) match { case t: Typed => goTyped(t, info.nx.nxTransTyped(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -650,7 +652,7 @@ object TreeTransforms { final private[TreeTransforms] def goAssign(tree: Assign, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformAssign(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformAssign(tree)(ctx.withPhase(groupEndId), info) match { case t: Assign => goAssign(t, info.nx.nxTransAssign(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -661,7 +663,7 @@ object TreeTransforms { final private[TreeTransforms] def goLiteral(tree: Literal, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformLiteral(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformLiteral(tree)(ctx.withPhase(groupEndId), info) match { case t: Literal => goLiteral(t, info.nx.nxTransLiteral(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -672,7 +674,7 @@ object TreeTransforms { final private[TreeTransforms] def goBlock(tree: Block, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformBlock(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformBlock(tree)(ctx.withPhase(groupEndId), info) match { case t: Block => goBlock(t, info.nx.nxTransBlock(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -683,7 +685,7 @@ object TreeTransforms { final private[TreeTransforms] def goIf(tree: If, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformIf(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformIf(tree)(ctx.withPhase(groupEndId), info) match { case t: If => goIf(t, info.nx.nxTransIf(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -694,7 +696,7 @@ object TreeTransforms { final private[TreeTransforms] def goClosure(tree: Closure, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformClosure(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformClosure(tree)(ctx.withPhase(groupEndId), info) match { case t: Closure => goClosure(t, info.nx.nxTransClosure(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -705,7 +707,7 @@ object TreeTransforms { final private[TreeTransforms] def goMatch(tree: Match, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformMatch(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformMatch(tree)(ctx.withPhase(groupEndId), info) match { case t: Match => goMatch(t, info.nx.nxTransMatch(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -716,7 +718,7 @@ object TreeTransforms { final private[TreeTransforms] def goCaseDef(tree: CaseDef, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformCaseDef(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformCaseDef(tree)(ctx.withPhase(groupEndId), info) match { case t: CaseDef => goCaseDef(t, info.nx.nxTransCaseDef(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -727,7 +729,7 @@ object TreeTransforms { final private[TreeTransforms] def goReturn(tree: Return, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformReturn(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformReturn(tree)(ctx.withPhase(groupEndId), info) match { case t: Return => goReturn(t, info.nx.nxTransReturn(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -738,7 +740,7 @@ object TreeTransforms { final private[TreeTransforms] def goTry(tree: Try, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformTry(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformTry(tree)(ctx.withPhase(groupEndId), info) match { case t: Try => goTry(t, info.nx.nxTransTry(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -749,7 +751,7 @@ object TreeTransforms { final private[TreeTransforms] def goSeqLiteral(tree: SeqLiteral, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformSeqLiteral(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformSeqLiteral(tree)(ctx.withPhase(groupEndId), info) match { case t: SeqLiteral => goSeqLiteral(t, info.nx.nxTransSeqLiteral(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -760,7 +762,7 @@ object TreeTransforms { final private[TreeTransforms] def goInlined(tree: Inlined, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformInlined(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformInlined(tree)(ctx.withPhase(groupEndId), info) match { case t: Inlined => goInlined(t, info.nx.nxTransInlined(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -771,7 +773,7 @@ object TreeTransforms { final private[TreeTransforms] def goTypeTree(tree: TypeTree, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformTypeTree(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformTypeTree(tree)(ctx.withPhase(groupEndId), info) match { case t: TypeTree => goTypeTree(t, info.nx.nxTransTypeTree(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -782,7 +784,7 @@ object TreeTransforms { final private[TreeTransforms] def goBind(tree: Bind, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformBind(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformBind(tree)(ctx.withPhase(groupEndId), info) match { case t: Bind => goBind(t, info.nx.nxTransBind(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -793,7 +795,7 @@ object TreeTransforms { final private[TreeTransforms] def goAlternative(tree: Alternative, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformAlternative(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformAlternative(tree)(ctx.withPhase(groupEndId), info) match { case t: Alternative => goAlternative(t, info.nx.nxTransAlternative(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -804,7 +806,7 @@ object TreeTransforms { final private[TreeTransforms] def goValDef(tree: ValDef, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformValDef(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformValDef(tree)(ctx.withPhase(groupEndId), info) match { case t: ValDef => goValDef(t, info.nx.nxTransValDef(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -815,7 +817,7 @@ object TreeTransforms { final private[TreeTransforms] def goDefDef(tree: DefDef, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformDefDef(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformDefDef(tree)(ctx.withPhase(groupEndId), info) match { case t: DefDef => goDefDef(t, info.nx.nxTransDefDef(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -826,7 +828,7 @@ object TreeTransforms { final private[TreeTransforms] def goUnApply(tree: UnApply, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformUnApply(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformUnApply(tree)(ctx.withPhase(groupEndId), info) match { case t: UnApply => goUnApply(t, info.nx.nxTransUnApply(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -837,7 +839,7 @@ object TreeTransforms { final private[TreeTransforms] def goTypeDef(tree: TypeDef, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformTypeDef(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformTypeDef(tree)(ctx.withPhase(groupEndId), info) match { case t: TypeDef => goTypeDef(t, info.nx.nxTransTypeDef(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -848,7 +850,7 @@ object TreeTransforms { final private[TreeTransforms] def goTemplate(tree: Template, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformTemplate(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformTemplate(tree)(ctx.withPhase(groupEndId), info) match { case t: Template => goTemplate(t, info.nx.nxTransTemplate(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -859,7 +861,7 @@ object TreeTransforms { final private[TreeTransforms] def goPackageDef(tree: PackageDef, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformPackageDef(tree)(ctx.withPhase(trans.treeTransformPhase), info) match { + trans.transformPackageDef(tree)(ctx.withPhase(groupEndId), info) match { case t: PackageDef => goPackageDef(t, info.nx.nxTransPackageDef(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -870,7 +872,7 @@ object TreeTransforms { final private[TreeTransforms] def goUnit(tree: Tree, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - val t = trans.transformUnit(tree)(ctx.withPhase(trans.treeTransformPhase), info) + val t = trans.transformUnit(tree)(ctx.withPhase(groupEndId), info) goUnit(t, info.nx.nxTransUnit(cur + 1)) } else tree } @@ -878,7 +880,7 @@ object TreeTransforms { final private[TreeTransforms] def goOther(tree: Tree, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - val t = trans.transformOther(tree)(ctx.withPhase(trans.treeTransformPhase), info) + val t = trans.transformOther(tree)(ctx.withPhase(groupEndId), info) transformSingle(t, cur + 1) } else tree } @@ -1180,7 +1182,7 @@ object TreeTransforms { util.Stats.record("TreeTransform.transform") // if cur > 0 then some of the symbols can be created by already performed transformations // this means that their denotations could not exists in previous period - val pctx = ctx.withPhase(info.transformers(cur).treeTransformPhase) + val pctx = ctx.withPhase(groupEndId) tree match { //split one big match into 2 smaller ones case tree: NameTree => transformNamed(tree, info, cur)(pctx) @@ -1201,7 +1203,7 @@ object TreeTransforms { final private[TreeTransforms] def goStats(trees: List[Tree], cur: Int)(implicit ctx: Context, info: TransformerInfo): List[Tree] = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - val stats = trans.transformStats(trees)(ctx.withPhase(trans.treeTransformPhase), info) + val stats = trans.transformStats(trees)(ctx.withPhase(groupEndId), info) goStats(stats, info.nx.nxTransStats(cur + 1)) } else trees } diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 93cb4093f68c..09d380eb06f9 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -334,21 +334,23 @@ trait TypeAssigner { else tp.substParam(pref, SkolemType(argType.widen)) } + /** Substitute types of all arguments `args` for corresponding `params` in `tp`. + * The number of parameters `params` may exceed the number of arguments. + * In this case, only the common prefix is substituted. + */ + def safeSubstParams(tp: Type, params: List[ParamRef], argTypes: List[Type])(implicit ctx: Context): Type = argTypes match { + case argType :: argTypes1 => + val tp1 = safeSubstParam(tp, params.head, argType) + safeSubstParams(tp1, params.tail, argTypes1) + case Nil => + tp + } + def assignType(tree: untpd.Apply, fn: Tree, args: List[Tree])(implicit ctx: Context) = { val ownType = fn.tpe.widen match { case fntpe: MethodType => - def safeSubstParams(tp: Type, params: List[ParamRef], args: List[Tree]): Type = params match { - case param :: params1 => - val tp1 = safeSubstParam(tp, param, args.head.tpe) - safeSubstParams(tp1, params1, args.tail) - case Nil => - tp - } - if (sameLength(fntpe.paramInfos, args) || ctx.phase.prev.relaxedTyping) - if (fntpe.isDependent) safeSubstParams(fntpe.resultType, fntpe.paramRefs, args) - else fntpe.resultType - else - errorType(i"wrong number of arguments for $fntpe: ${fn.tpe}, expected: ${fntpe.paramInfos.length}, found: ${args.length}", tree.pos) + if (fntpe.isDependent) safeSubstParams(fntpe.resultType, fntpe.paramRefs, args.tpes) + else fntpe.resultType case t => errorType(err.takesNoParamsStr(fn, ""), tree.pos) } @@ -404,7 +406,7 @@ trait TypeAssigner { } else { val argTypes = preCheckKinds(args, pt.paramInfos).tpes - if (sameLength(argTypes, paramNames) || ctx.phase.prev.relaxedTyping) pt.instantiate(argTypes) + if (sameLength(argTypes, paramNames)) pt.instantiate(argTypes) else wrongNumberOfTypeArgs(fn.tpe, pt.typeParams, args, tree.pos) } case _ => diff --git a/compiler/test/dotc/tests.scala b/compiler/test/dotc/tests.scala index a21496ed0e8f..39ab4da8b9bd 100644 --- a/compiler/test/dotc/tests.scala +++ b/compiler/test/dotc/tests.scala @@ -69,8 +69,8 @@ class tests extends CompilerTest { } implicit val defaultOptions: List[String] = noCheckOptions ++ { - if (dotty.Properties.isRunByDrone) List("-Ycheck:tailrec,resolveSuper,erasure,mixin,getClass,restoreScopes,labelDef") // should be Ycheck:all, but #725 - else List("-Ycheck:tailrec,resolveSuper,mixin,restoreScopes,labelDef,simplify") + if (dotty.Properties.isRunByDrone) List("-Ycheck:tailrec,resolveSuper,erasure,mixin,getClass,elimStaticThis,labelDef") // should be Ycheck:all, but #725 + else List("-Ycheck:tailrec,resolveSuper,mixin,elimStaticThis,labelDef,simplify") } ++ checkOptions ++ classPath val testPickling = List("-Xprint-types", "-Ytest-pickler", "-Ystop-after:pickler", "-Yprintpos") diff --git a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala index b0a31e6e1ce8..7c25cc56ea9f 100644 --- a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala +++ b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala @@ -42,7 +42,7 @@ object TestConfiguration { } mkString(":") } - val yCheckOptions = Array("-Ycheck:tailrec,resolveSuper,erasure,mixin,getClass,restoreScopes,labelDef") + val yCheckOptions = Array("-Ycheck:tailrec,resolveSuper,erasure,mixin,getClass,elimStaticThis,labelDef") val basicDefaultOptions = checkOptions ++ noCheckOptions ++ yCheckOptions val defaultUnoptimised = TestFlags(classPath, basicDefaultOptions)