diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index 709f4b2db299..1e8f13578a86 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -20,8 +20,8 @@ class Compiler { def phases: List[List[Phase]] = List( List(new FrontEnd), - List(new LazyValsCreateCompanionObjects), //force separataion between lazyVals and LVCreateCO - List(new LazyValTranformContext().transformer, new TypeTestsCasts), + List(new LazyValsCreateCompanionObjects, new PatternMatcher), //force separataion between lazyVals and LVCreateCO + List(new LazyValTranformContext().transformer, new Splitter, new TypeTestsCasts), List(new Erasure), List(new UncurryTreeTransform) ) diff --git a/src/dotty/tools/dotc/Run.scala b/src/dotty/tools/dotc/Run.scala index 3f15bd4c3597..264373baff93 100644 --- a/src/dotty/tools/dotc/Run.scala +++ b/src/dotty/tools/dotc/Run.scala @@ -6,6 +6,7 @@ import Contexts._, Periods._, Symbols._, Phases._, Decorators._ import io.PlainFile import util.{SourceFile, NoSource, Stats, SimpleMap} import reporting.Reporter +import transform.TreeChecker import java.io.{BufferedWriter, OutputStreamWriter} import scala.reflect.io.VirtualFile @@ -39,18 +40,19 @@ class Run(comp: Compiler)(implicit ctx: Context) { for (phase <- phasesToRun) { if (!ctx.reporter.hasErrors) { phase.runOn(units) - if (ctx.settings.Xprint.value.containsPhase(phase)) - for (unit <- units) - printTree(ctx.fresh.setPhase(phase).setCompilationUnit(unit)) + def foreachUnit(op: Context => Unit)(implicit ctx: Context): Unit = + for (unit <- units) op(ctx.fresh.setPhase(phase.next).setCompilationUnit(unit)) + if (ctx.settings.Xprint.value.containsPhase(phase)) foreachUnit(printTree) + if (ctx.settings.Ycheck.value.containsPhase(phase)) foreachUnit(TreeChecker.check) } } } } - private def printTree(implicit ctx: Context) = { + private def printTree(ctx: Context) = { val unit = ctx.compilationUnit println(s"result of $unit after ${ctx.phase}:") - println(unit.tpdTree.show) + println(unit.tpdTree.show(ctx)) } def compile(sourceCode: String): Unit = { diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala index 173f8189401b..3f29fc72f6f7 100644 --- a/src/dotty/tools/dotc/ast/tpd.scala +++ b/src/dotty/tools/dotc/ast/tpd.scala @@ -7,6 +7,7 @@ import util.Positions._, Types._, Contexts._, Constants._, Names._, Flags._ import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._ import CheckTrees._, Denotations._, Decorators._ import config.Printers._ +import typer.ErrorReporting._ /** Some creators for typed trees */ object tpd extends Trees.Instance[Type] with TypedTreeInfo { @@ -400,11 +401,17 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } // convert a numeric with a toXXX method - def numericConversion(tree: Tree, numericCls: Symbol)(implicit ctx: Context): Tree = { + def primitiveConversion(tree: Tree, numericCls: Symbol)(implicit ctx: Context): Tree = { val mname = ("to" + numericCls.name).toTermName val conversion = tree.tpe member mname - assert(conversion.symbol.exists, s"$tree => $numericCls") - ensureApplied(Select(tree, conversion.symbol.termRef)) + if (conversion.symbol.exists) + ensureApplied(Select(tree, conversion.symbol.termRef)) + else if (tree.tpe.widen isRef numericCls) + tree + else { + ctx.warning(i"conversion from ${tree.tpe.widen} to ${numericCls.typeRef} will always fail at runtime.") + Throw(New(defn.ClassCastExceptionClass.typeRef, Nil)) withPos tree.pos + } } def evalOnce(tree: Tree)(within: Tree => Tree)(implicit ctx: Context) = { diff --git a/src/dotty/tools/dotc/config/ScalaSettings.scala b/src/dotty/tools/dotc/config/ScalaSettings.scala index 8ed725e36789..144e146c155c 100644 --- a/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -97,7 +97,7 @@ class ScalaSettings extends Settings.SettingGroup { val overrideVars = BooleanSetting("-Yoverride-vars", "Allow vars to be overridden.") val Yhelp = BooleanSetting("-Y", "Print a synopsis of private options.") val browse = PhasesSetting("-Ybrowse", "Browse the abstract syntax tree after") - val check = PhasesSetting("-Ycheck", "Check the tree at the end of") + val Ycheck = PhasesSetting("-Ycheck", "Check the tree at the end of") val YcheckTypedTrees = BooleanSetting("-YcheckTypedTrees", "Check all constructured typed trees for type correctness") val Yshow = PhasesSetting("-Yshow", "(Requires -Xshow-class or -Xshow-object) Show after") val Xcloselim = BooleanSetting("-Yclosure-elim", "Perform closure elimination.") diff --git a/src/dotty/tools/dotc/config/Settings.scala b/src/dotty/tools/dotc/config/Settings.scala index b3bf2f1348be..17d4d67125e8 100644 --- a/src/dotty/tools/dotc/config/Settings.scala +++ b/src/dotty/tools/dotc/config/Settings.scala @@ -223,7 +223,6 @@ object Settings { setting } - def BooleanSetting(name: String, descr: String): Setting[Boolean] = publish(Setting(name, descr, false)) diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index 8d083b29cdd0..b0214a631e8b 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -181,6 +181,30 @@ object Contexts { protected def searchHistory_= (searchHistory: SearchHistory) = _searchHistory = searchHistory def searchHistory: SearchHistory = _searchHistory + private var phasedCtx: Context = _ + private var phasedCtxs: Array[Context] = _ + + + /** This context at given phase. + * This method will always return a phase period equal to phaseId, thus will never return squashed phases + */ + final def withPhase(phaseId: PhaseId): Context = { + if (this.phaseId == phaseId) this + else if (phasedCtx.phaseId == phaseId) phasedCtx + else if (phasedCtxs != null && phasedCtxs(phaseId) != null) phasedCtxs(phaseId) + else { + val ctx1 = fresh.setPhase(phaseId) + if (phasedCtx eq this) phasedCtx = ctx1 + else { + if (phasedCtxs == null) phasedCtxs = new Array[Context](base.phases.length) + phasedCtxs(phaseId) = ctx1 + } + ctx1 + } + } + + final def withPhase(phase: Phase): Context = + withPhase(phase.id) /** If -Ydebug is on, the top of the stack trace where this context * was created, otherwise `null`. */ @@ -266,29 +290,23 @@ object Contexts { } */ - /** A fresh clone of this context. */ - def fresh: FreshContext = { - val newctx: Context = super.clone.asInstanceOf[FreshContext] - newctx.outer = this - newctx.implicitsCache = null - newctx.setCreationTrace() - // Dotty deviation: Scala2x allows access to private members implicitCache and setCreationTrace - // even from a subclass prefix. Dotty (and Java) do not. It's confirmed as a bug in Scala2x. - newctx.asInstanceOf[FreshContext] + protected def init(outer: Context): this.type = { + this.outer = outer + this.implicitsCache = null + this.phasedCtx = this + this.phasedCtxs = null + setCreationTrace() + this } + /** A fresh clone of this context. */ + def fresh: FreshContext = clone.asInstanceOf[FreshContext].init(this) + + final def withOwner(owner: Symbol): Context = + if (owner ne this.owner) fresh.setOwner(owner) else this final def withMode(mode: Mode): Context = if (mode != this.mode) fresh.setMode(mode) else this - /** - * This method will always return a phase period equal to phaseId, thus will never return squashed phases - */ - final def withPhase(phaseId: PhaseId): Context = - if (this.phaseId == phaseId) this else fresh.setPhase(phaseId) - final def withPhase(phase: Phase): Context = - if (this.period == phase.period) this else fresh.setPhase(phase) - - final def addMode(mode: Mode): Context = withMode(this.mode | mode) final def maskMode(mode: Mode): Context = withMode(this.mode & mode) final def retractMode(mode: Mode): Context = withMode(this.mode &~ mode) @@ -313,7 +331,7 @@ object Contexts { def setPeriod(period: Period): this.type = { this.period = period; this } def setMode(mode: Mode): this.type = { this.mode = mode; this } def setTyperState(typerState: TyperState): this.type = { this.typerState = typerState; this } - def clearTyperState: this.type = setTyperState(typerState.fresh(isCommittable = true)) + def setNewTyperState: this.type = setTyperState(typerState.fresh(isCommittable = true)) def setExploreTyperState: this.type = setTyperState(typerState.fresh(isCommittable = false)) def setPrinterFn(printer: Context => Printer): this.type = { this.printerFn = printer; this } def setOwner(owner: Symbol): this.type = { assert(owner != NoSymbol); this.owner = owner; this } @@ -321,7 +339,7 @@ object Contexts { def setCompilationUnit(compilationUnit: CompilationUnit): this.type = { this.compilationUnit = compilationUnit; this } def setTree(tree: Tree[_ >: Untyped]): this.type = { this.tree = tree; this } def setScope(scope: Scope): this.type = { this.scope = scope; this } - def clearScope: this.type = { this.scope = newScope; this } + def setNewScope: this.type = { this.scope = newScope; this } def setTypeAssigner(typeAssigner: TypeAssigner): this.type = { this.typeAssigner = typeAssigner; this } def setTyper(typer: Typer): this.type = { this.scope = typer.scope; setTypeAssigner(typer) } def setImportInfo(importInfo: ImportInfo): this.type = { this.importInfo = importInfo; this } diff --git a/src/dotty/tools/dotc/core/Decorators.scala b/src/dotty/tools/dotc/core/Decorators.scala index cd9680e64d94..21f914d9903f 100644 --- a/src/dotty/tools/dotc/core/Decorators.scala +++ b/src/dotty/tools/dotc/core/Decorators.scala @@ -6,6 +6,7 @@ import Symbols._ import Contexts._, Names._, Phases._, printing.Texts._, printing.Printer import util.Positions.Position, util.SourcePosition import collection.mutable.ListBuffer +import dotty.tools.dotc.transform.TreeTransforms._ import scala.language.implicitConversions /** This object provides useful implicit decorators for types defined elsewhere */ @@ -127,8 +128,10 @@ object Decorators { * one of the names in the list of strings. */ implicit class PhaseListDecorator(val names: List[String]) extends AnyVal { - def containsPhase(phase: Phase) = - names exists (phase.name.startsWith) + def containsPhase(phase: Phase): Boolean = phase match { + case phase: TreeTransformer => phase.transformations.exists(containsPhase) + case _ => names exists (phase.name.startsWith) + } } implicit def sourcePos(pos: Position)(implicit ctx: Context): SourcePosition = diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index 3ae74b467419..46878d3cabe1 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -103,8 +103,8 @@ class Definitions { lazy val Object_!= = newMethod(ObjectClass, nme.NE, methOfAny(BooleanType), Final) lazy val Object_eq = newMethod(ObjectClass, nme.eq, methOfAnyRef(BooleanType), Final) lazy val Object_ne = newMethod(ObjectClass, nme.ne, methOfAnyRef(BooleanType), Final) - lazy val Object_isInstanceOf = newT1EmptyParamsMethod(ObjectClass, nme.isInstanceOf_Ob, _ => BooleanType, Final | Synthetic) - lazy val Object_asInstanceOf = newT1EmptyParamsMethod(ObjectClass, nme.asInstanceOf_Ob, PolyParam(_, 0), Final | Synthetic) + lazy val Object_isInstanceOf = newT1ParameterlessMethod(ObjectClass, nme.isInstanceOf_Ob, _ => BooleanType, Final | Synthetic) + lazy val Object_asInstanceOf = newT1ParameterlessMethod(ObjectClass, nme.asInstanceOf_Ob, PolyParam(_, 0), Final | Synthetic) lazy val Object_synchronized = newPolyMethod(ObjectClass, nme.synchronized_, 1, pt => MethodType(List(PolyParam(pt, 0)), PolyParam(pt, 0)), Final) @@ -218,6 +218,7 @@ class Definitions { lazy val OptionClass = ctx.requiredClass("scala.Option") lazy val BoxedNumberClass = ctx.requiredClass("java.lang.Number") lazy val ThrowableClass = ctx.requiredClass("java.lang.Throwable") + lazy val ClassCastExceptionClass = ctx.requiredClass("java.lang.ClassCastException") lazy val JavaSerializableClass = ctx.requiredClass("java.lang.Serializable") lazy val ComparableClass = ctx.requiredClass("java.lang.Comparable") lazy val ProductClass = ctx.requiredClass("scala.Product") diff --git a/src/dotty/tools/dotc/core/Phases.scala b/src/dotty/tools/dotc/core/Phases.scala index 87242c9b5b37..8b5606da245b 100644 --- a/src/dotty/tools/dotc/core/Phases.scala +++ b/src/dotty/tools/dotc/core/Phases.scala @@ -107,11 +107,11 @@ object Phases { postTyperEmmited = true new PostTyperTransformer { override def name: String = transformations.map(_.name).mkString("TreeTransform:{", ", ", "}") - override protected def transformations: Array[TreeTransform] = transforms.toArray + override def transformations: Array[TreeTransform] = transforms.toArray } } else new TreeTransformer { override def name: String = transformations.map(_.name).mkString("TreeTransform:{", ", ", "}") - override protected def transformations: Array[TreeTransform] = transforms.toArray + override def transformations: Array[TreeTransform] = transforms.toArray } squashedPhases += block block.init(this, phasess(i).head.id, phasess(i).last.id) diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index f07eaa2bebdc..e96f08855a9c 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -147,7 +147,7 @@ object SymDenotations { myFlags |= Touched // completions.println(s"completing ${this.debugString}") - try completer.complete(this) + try completer.complete(this)(ctx.withPhase(validFor.firstPhaseId)) catch { case ex: CyclicReference => completions.println(s"error while completing ${this.debugString}") diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index 9cd635cd9f38..4b251f1839e2 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -39,6 +39,8 @@ import TypeApplications._ /** A decorator that provides methods for modeling type application */ class TypeApplications(val self: Type) extends AnyVal { + def canHaveTypeParams(implicit ctx: Context) = !ctx.erasedTypes || self.isRef(defn.ArrayClass) + /** The type parameters of this type are: * For a ClassInfo type, the type parameters of its class. * For a typeref referring to a class, the type parameters of the class. @@ -128,7 +130,7 @@ class TypeApplications(val self: Type) extends AnyVal { defn.hkTrait(args map alwaysZero).typeParams } - if (args.isEmpty) self + if (args.isEmpty || !canHaveTypeParams) self else self match { case tp: TypeRef => val tsym = tp.symbol @@ -228,8 +230,11 @@ class TypeApplications(val self: Type) extends AnyVal { * `from` and `to` must be static classes, both with one type parameter, and the same variance. */ def translateParameterized(from: ClassSymbol, to: ClassSymbol)(implicit ctx: Context): Type = - if (self derivesFrom from) - RefinedType(to.typeRef, to.typeParams.head.name, self.member(from.typeParams.head.name).info) + if (self.derivesFrom(from)) + if (canHaveTypeParams) + RefinedType(to.typeRef, to.typeParams.head.name, self.member(from.typeParams.head.name).info) + else + to.typeRef else self /** If this is an encoding of a (partially) applied type, return its arguments, diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index a7a33ce8e20e..8799f9fd0474 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -1039,6 +1039,7 @@ object Types { } lastDenotation = d lastSymbol = d.symbol + checkedPeriod = ctx.period d } diff --git a/src/dotty/tools/dotc/core/transform/Erasure.scala b/src/dotty/tools/dotc/core/transform/Erasure.scala index d59bdf1a917b..842e2f81f7f4 100644 --- a/src/dotty/tools/dotc/core/transform/Erasure.scala +++ b/src/dotty/tools/dotc/core/transform/Erasure.scala @@ -61,16 +61,11 @@ object Erasure { */ def transformInfo(sym: Symbol, tp: Type)(implicit ctx: Context): Type = { val erase = erasureFn(sym is JavaDefined, isSemi = true, sym.isConstructor, wildcardOK = false) - if ((sym eq defn.Object_asInstanceOf) || sym.isType && (sym.owner eq defn.ArrayClass)) - sym.info - else if ((sym eq defn.Object_isInstanceOf) || (sym eq defn.ArrayClass.primaryConstructor)) { - val tp @ PolyType(pnames) = sym.info - tp.derivedPolyType(pnames, TypeBounds.empty :: Nil, erase(tp.resultType)) - } - else if (sym.isAbstractType) - TypeAlias(WildcardType) - else - erase(tp) + if ((sym eq defn.Object_asInstanceOf) || + (sym eq defn.Object_isInstanceOf) || + (sym.owner eq defn.ArrayClass) && (sym.isType || sym.isConstructor)) sym.info + else if (sym.isAbstractType) TypeAlias(WildcardType) + else erase(tp) } def isUnboundedGeneric(tp: Type)(implicit ctx: Context) = !( @@ -120,7 +115,7 @@ class Erasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wildcard case tp: TypeRef => val sym = tp.symbol if (!sym.isClass) - if (sym.owner eq defn.ArrayClass) tp else this(tp.info) + if (sym.exists && (sym.owner eq defn.ArrayClass)) tp else this(tp.info) //!!!! else if (sym.isDerivedValueClass) eraseDerivedValueClassRef(tp) else eraseNormalClassRef(tp) case tp: RefinedType => diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala index f9b602f54cc9..d4156e1d7645 100644 --- a/src/dotty/tools/dotc/transform/Erasure.scala +++ b/src/dotty/tools/dotc/transform/Erasure.scala @@ -130,7 +130,7 @@ object Erasure { // See SI-2386 for one example of when this might be necessary. cast(runtimeCall(nme.toObjectArray, tree :: Nil), pt) case _ => - println(s"casting from ${tree.showSummary}: ${tree.tpe.show} to ${pt.show}") + ctx.log(s"casting from ${tree.showSummary}: ${tree.tpe.show} to ${pt.show}") TypeApply(Select(tree, defn.Object_asInstanceOf), TypeTree(pt) :: Nil) } @@ -158,25 +158,18 @@ object Erasure { cast(tree, pt) } - class Typer extends typer.Typer with NoChecking { + class Typer extends typer.ReTyper with NoChecking { import Boxing._ - def erasedType(tree: untpd.Tree)(implicit ctx: Context): Type = - erasure(tree.tpe.asInstanceOf[Type]) + def erasedType(tree: untpd.Tree)(implicit ctx: Context): Type = erasure(tree.typeOpt) - private def promote(tree: untpd.Tree)(implicit ctx: Context): tree.ThisTree[Type] = { + override def promote(tree: untpd.Tree)(implicit ctx: Context): tree.ThisTree[Type] = { assert(tree.hasType) val erased = erasedType(tree)(ctx.withPhase(ctx.erasurePhase)) ctx.log(s"promoting ${tree.show}: ${erased.showWithUnderlying()}") tree.withType(erased) } - override def typedIdent(tree: untpd.Ident, pt: Type)(implicit ctx: Context): Tree = { - val tree1 = promote(tree) - println(i"typed ident ${tree.name}: ${tree1.tpe} at phase ${ctx.phase}, history = ${tree1.symbol.history}") - tree1 - } - /** Type check select nodes, applying the following rewritings exhaustively * on selections `e.m`. * @@ -226,8 +219,16 @@ object Erasure { recur(typed(tree.qualifier, AnySelectionProto)) } - override def typedTypeApply(tree: untpd.TypeApply, pt: Type)(implicit ctx: Context) = - typedExpr(tree.fun, pt) + override def typedTypeApply(tree: untpd.TypeApply, pt: Type)(implicit ctx: Context) = { + val TypeApply(fun, args) = tree + val fun1 = typedExpr(fun, pt) + fun1.tpe.widen match { + case funTpe: PolyType => + val args1 = args.mapconserve(typedType(_)) + untpd.cpy.TypeApply(tree, fun1, args1).withType(funTpe.instantiate(args1.tpes)) + case _ => fun1 + } + } override def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = { val Apply(fun, args) = tree @@ -253,12 +254,8 @@ object Erasure { super.typedDefDef(ddef1, sym) } - override def typedClassDef(cdef: untpd.TypeDef, sym: ClassSymbol)(implicit ctx: Context) = { - val TypeDef(mods, name, impl @ Template(constr, parents, self, body)) = cdef - val cdef1 = untpd.cpy.TypeDef(cdef, mods, name, - untpd.cpy.Template(impl, constr, parents, untpd.EmptyValDef, body)) - super.typedClassDef(cdef1, sym) - } + override def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(implicit ctx: Context) = + EmptyTree /* override def transformStats(stats: List[Tree], exprOwner: Symbol)(implicit ctx: Context) = { @@ -266,22 +263,6 @@ object Erasure { if (ctx.owner.isClass) addBridges(stats1) else stats1 } */ - override def typedNamed(tree: untpd.NameTree, pt: Type)(implicit ctx: Context): Tree = { - if (tree eq untpd.EmptyValDef) return tpd.EmptyValDef - assert(tree.hasType, tree) - val sym = tree.symbol - assert(sym.exists, tree) - def localContext = ctx.fresh.setTree(tree).setOwner(sym) - tree match { - case tree: untpd.Ident => typedIdent(tree, pt) - case tree: untpd.Select => typedSelect(tree, pt) - case tree: untpd.ValDef => typedValDef(tree, sym)(localContext) - case tree: untpd.DefDef => typedDefDef(tree, sym)(localContext) - case tree: untpd.TypeDef => - if (tree.isClassDef) typedClassDef(tree, sym.asClass)(localContext) - else EmptyTree - } - } override def adapt(tree: Tree, pt: Type)(implicit ctx: Context): Tree = ctx.traceIndented(i"adapting ${tree.showSummary}: ${tree.tpe} to $pt", show = true) { diff --git a/src/dotty/tools/dotc/transform/PatternMatcher.scala b/src/dotty/tools/dotc/transform/PatternMatcher.scala new file mode 100644 index 000000000000..ff25a94de85f --- /dev/null +++ b/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -0,0 +1,27 @@ +package dotty.tools.dotc +package transform + +import TreeTransforms._ +import core.DenotTransformers._ +import core.Denotations._ +import core.SymDenotations._ +import core.Contexts._ +import core.Symbols._ +import core.Types._ +import core.Constants._ +import core.StdNames._ +import core.transform.Erasure.isUnboundedGeneric +import typer.ErrorReporting._ +import ast.Trees._ + +/** This transform eliminates patterns. Right now it's a dummy. + * Awaiting the real pattern matcher. + */ +class PatternMatcher extends TreeTransform { + import ast.tpd._ + + override def name: String = "patternMatcher" + + override def transformCaseDef(tree: CaseDef)(implicit ctx: Context, info: TransformerInfo): Tree = + cpy.CaseDef(tree, Literal(Constant("")), tree.guard, tree.body) +} \ No newline at end of file diff --git a/src/dotty/tools/dotc/transform/PostTyperTransformers.scala b/src/dotty/tools/dotc/transform/PostTyperTransformers.scala index 14e2cf35d175..25f122cf58c4 100644 --- a/src/dotty/tools/dotc/transform/PostTyperTransformers.scala +++ b/src/dotty/tools/dotc/transform/PostTyperTransformers.scala @@ -48,8 +48,8 @@ object PostTyperTransformers { reorder0(stats) } - override def transformStats(trees: List[tpd.Tree], info: TransformerInfo, current: Int)(implicit ctx: Context): List[tpd.Tree] = - super.transformStats(reorder(trees)(ctx, info), info, current) + override def transformStats(trees: List[tpd.Tree], exprOwner: Symbol, info: TransformerInfo, current: Int)(implicit ctx: Context): List[tpd.Tree] = + super.transformStats(reorder(trees)(ctx, info), exprOwner, info, current) override def transform(tree: tpd.Tree, info: TransformerInfo, cur: Int)(implicit ctx: Context): tpd.Tree = tree match { case tree: Import => EmptyTree diff --git a/src/dotty/tools/dotc/transform/Splitter.scala b/src/dotty/tools/dotc/transform/Splitter.scala new file mode 100644 index 000000000000..9c01574aae45 --- /dev/null +++ b/src/dotty/tools/dotc/transform/Splitter.scala @@ -0,0 +1,27 @@ +package dotty.tools.dotc +package transform + +import TreeTransforms._ +import ast.Trees._ +import core.Contexts._ +import core.Types._ + +/** This transform makes usre every identifier and select node + * carries a symbol. To do this, certain qualifiers with a union type + * have to be "splitted" with a type test. + * + * For now, only self references are treated. + */ +class Splitter extends TreeTransform { + import ast.tpd._ + + override def name: String = "splitter" + + /** Replace self referencing idents with ThisTypes. */ + override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo) = tree.tpe match { + case ThisType(cls) => + println(s"owner = ${ctx.owner}, context = ${ctx}") + This(cls) withPos tree.pos + case _ => tree + } +} \ No newline at end of file diff --git a/src/dotty/tools/dotc/transform/TreeChecker.scala b/src/dotty/tools/dotc/transform/TreeChecker.scala new file mode 100644 index 000000000000..ea3afc67905f --- /dev/null +++ b/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -0,0 +1,37 @@ +package dotty.tools.dotc +package transform + +import TreeTransforms._ +import core.DenotTransformers._ +import core.Denotations._ +import core.SymDenotations._ +import core.Contexts._ +import core.Symbols._ +import core.Types._ +import core.Constants._ +import core.StdNames._ +import core.transform.Erasure.isUnboundedGeneric +import typer.ErrorReporting._ +import ast.Trees._ + +/** This transform eliminates patterns. Right now it's a dummy. + * Awaiting the real pattern matcher. + */ +class TreeChecker { + import ast.tpd._ + + def check(ctx: Context) = { + println(s"checking ${ctx.compilationUnit} after phase ${ctx.phase.prev}") + Checker.transform(ctx.compilationUnit.tpdTree)(ctx) + } + + object Checker extends TreeMap { + override def transform(tree: Tree)(implicit ctx: Context) = { + println(i"checking $tree") + assert(tree.isEmpty || tree.hasType, tree.show) + super.transform(tree) + } + } +} + +object TreeChecker extends TreeChecker \ No newline at end of file diff --git a/src/dotty/tools/dotc/transform/TreeTransform.scala b/src/dotty/tools/dotc/transform/TreeTransform.scala index 10857da5afc9..425410ae7ed6 100644 --- a/src/dotty/tools/dotc/transform/TreeTransform.scala +++ b/src/dotty/tools/dotc/transform/TreeTransform.scala @@ -3,7 +3,9 @@ package dotty.tools.dotc.transform import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Phases.Phase +import dotty.tools.dotc.core.Symbols.Symbol import dotty.tools.dotc.ast.Trees._ +import dotty.tools.dotc.core.Decorators._ import scala.annotation.tailrec object TreeTransforms { @@ -129,7 +131,7 @@ object TreeTransforms { protected def mkTreeTransformer = new TreeTransformer { override def name: String = TreeTransform.this.name - override protected def transformations = Array(TreeTransform.this) + override def transformations = Array(TreeTransform.this) } override def run(implicit ctx: Context): Unit = { @@ -149,9 +151,7 @@ object TreeTransforms { type Mutator[T] = (TreeTransform, T, Context) => TreeTransform - class TransformerInfo(val transformers: Array[TreeTransform], val nx: NXTransformations, val group:TreeTransformer, val contexts:Array[Context]) { - assert(transformers.size == contexts.size) - } + class TransformerInfo(val transformers: Array[TreeTransform], val nx: NXTransformations, val group:TreeTransformer) /** * This class maintains track of which methods are redefined in MiniPhases and creates execution plans for transformXXX and prepareXXX @@ -414,7 +414,7 @@ object TreeTransforms { /** A group of tree transforms that are applied in sequence during the same phase */ abstract class TreeTransformer extends Phase { - protected def transformations: Array[TreeTransform] + def transformations: Array[TreeTransform] override def run(implicit ctx: Context): Unit = { val curTree = ctx.compilationUnit.tpdTree @@ -431,15 +431,15 @@ object TreeTransforms { val l = result.length var allDone = i < l while (i < l) { - val oldT = result(i) - val newT = mutator(oldT, tree, info.contexts(i)) - allDone = allDone && (newT eq NoTransform) - if (!(oldT eq newT)) { + val oldTransform = result(i) + val newTransform = mutator(oldTransform, tree, ctx.withPhase(oldTransform)) + allDone = allDone && (newTransform eq NoTransform) + if (!(oldTransform eq newTransform)) { if (!transformersCopied) result = result.clone() transformersCopied = true - result(i) = newT - if (!(newT.getClass == oldT.getClass)) { - resultNX = new NXTransformations(resultNX, newT, i, nxCopied) + result(i) = newTransform + if (!(newTransform.getClass == oldTransform.getClass)) { + resultNX = new NXTransformations(resultNX, newTransform, i, nxCopied) nxCopied = true } } @@ -447,7 +447,7 @@ object TreeTransforms { } if (allDone) null else if (!transformersCopied) info - else new TransformerInfo(result, resultNX, info.group, info.contexts) + else new TransformerInfo(result, resultNX, info.group) } val prepForIdent: Mutator[Ident] = (trans, tree, ctx) => trans.prepareForIdent(tree)(ctx) @@ -484,8 +484,7 @@ object TreeTransforms { def transform(t: Tree)(implicit ctx: Context): Tree = { val initialTransformations = transformations - val contexts = initialTransformations.map(tr => ctx.withPhase(tr).ctx) - val info = new TransformerInfo(initialTransformations, new NXTransformations(initialTransformations), this, contexts) + val info = new TransformerInfo(initialTransformations, new NXTransformations(initialTransformations), this) initialTransformations.zipWithIndex.foreach{ case (transform, id) => transform.idx = id @@ -498,8 +497,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)(info.contexts(cur), info) match { + trans.transformIdent(tree)(ctx.withPhase(trans), info) match { case t: Ident => goIdent(t, info.nx.nxTransIdent(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -510,7 +508,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)(info.contexts(cur), info) match { + trans.transformSelect(tree)(ctx.withPhase(trans), info) match { case t: Select => goSelect(t, info.nx.nxTransSelect(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -521,7 +519,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)(info.contexts(cur), info) match { + trans.transformThis(tree)(ctx.withPhase(trans), info) match { case t: This => goThis(t, info.nx.nxTransThis(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -532,7 +530,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)(info.contexts(cur), info) match { + trans.transformSuper(tree)(ctx.withPhase(trans), info) match { case t: Super => goSuper(t, info.nx.nxTransSuper(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -543,7 +541,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)(info.contexts(cur), info) match { + trans.transformApply(tree)(ctx.withPhase(trans), info) match { case t: Apply => goApply(t, info.nx.nxTransApply(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -554,7 +552,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)(info.contexts(cur), info) match { + trans.transformTypeApply(tree)(ctx.withPhase(trans), info) match { case t: TypeApply => goTypeApply(t, info.nx.nxTransTypeApply(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -565,7 +563,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)(info.contexts(cur), info) match { + trans.transformNew(tree)(ctx.withPhase(trans), info) match { case t: New => goNew(t, info.nx.nxTransNew(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -576,7 +574,7 @@ object TreeTransforms { final private[TreeTransforms] def goPair(tree: Pair, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformPair(tree)(info.contexts(cur), info) match { + trans.transformPair(tree)(ctx.withPhase(trans), info) match { case t: Pair => goPair(t, info.nx.nxTransPair(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -587,7 +585,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)(info.contexts(cur), info) match { + trans.transformTyped(tree)(ctx.withPhase(trans), info) match { case t: Typed => goTyped(t, info.nx.nxTransTyped(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -598,7 +596,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)(info.contexts(cur), info) match { + trans.transformAssign(tree)(ctx.withPhase(trans), info) match { case t: Assign => goAssign(t, info.nx.nxTransAssign(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -609,7 +607,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)(info.contexts(cur), info) match { + trans.transformLiteral(tree)(ctx.withPhase(trans), info) match { case t: Literal => goLiteral(t, info.nx.nxTransLiteral(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -620,7 +618,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)(info.contexts(cur), info) match { + trans.transformBlock(tree)(ctx.withPhase(trans), info) match { case t: Block => goBlock(t, info.nx.nxTransBlock(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -631,7 +629,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)(info.contexts(cur), info) match { + trans.transformIf(tree)(ctx.withPhase(trans), info) match { case t: If => goIf(t, info.nx.nxTransIf(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -642,7 +640,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)(info.contexts(cur), info) match { + trans.transformClosure(tree)(ctx.withPhase(trans), info) match { case t: Closure => goClosure(t, info.nx.nxTransClosure(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -653,7 +651,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)(info.contexts(cur), info) match { + trans.transformMatch(tree)(ctx.withPhase(trans), info) match { case t: Match => goMatch(t, info.nx.nxTransMatch(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -664,7 +662,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)(info.contexts(cur), info) match { + trans.transformCaseDef(tree)(ctx.withPhase(trans), info) match { case t: CaseDef => goCaseDef(t, info.nx.nxTransCaseDef(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -675,7 +673,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)(info.contexts(cur), info) match { + trans.transformReturn(tree)(ctx.withPhase(trans), info) match { case t: Return => goReturn(t, info.nx.nxTransReturn(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -686,7 +684,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)(info.contexts(cur), info) match { + trans.transformTry(tree)(ctx.withPhase(trans), info) match { case t: Try => goTry(t, info.nx.nxTransTry(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -697,7 +695,7 @@ object TreeTransforms { final private[TreeTransforms] def goThrow(tree: Throw, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformThrow(tree)(info.contexts(cur), info) match { + trans.transformThrow(tree)(ctx.withPhase(trans), info) match { case t: Throw => goThrow(t, info.nx.nxTransThrow(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -708,7 +706,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)(info.contexts(cur), info) match { + trans.transformSeqLiteral(tree)(ctx.withPhase(trans), info) match { case t: SeqLiteral => goSeqLiteral(t, info.nx.nxTransSeqLiteral(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -719,7 +717,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)(info.contexts(cur), info) match { + trans.transformTypeTree(tree)(ctx.withPhase(trans), info) match { case t: TypeTree => goTypeTree(t, info.nx.nxTransTypeTree(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -730,7 +728,7 @@ object TreeTransforms { final private[TreeTransforms] def goSelectFromTypeTree(tree: SelectFromTypeTree, cur: Int)(implicit ctx: Context, info: TransformerInfo): Tree = { if (cur < info.transformers.length) { val trans = info.transformers(cur) - trans.transformSelectFromTypeTree(tree)(info.contexts(cur), info) match { + trans.transformSelectFromTypeTree(tree)(ctx.withPhase(trans), info) match { case t: SelectFromTypeTree => goSelectFromTypeTree(t, info.nx.nxTransSelectFromTypeTree(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -741,7 +739,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)(info.contexts(cur), info) match { + trans.transformBind(tree)(ctx.withPhase(trans), info) match { case t: Bind => goBind(t, info.nx.nxTransBind(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -752,7 +750,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)(info.contexts(cur), info) match { + trans.transformAlternative(tree)(ctx.withPhase(trans), info) match { case t: Alternative => goAlternative(t, info.nx.nxTransAlternative(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -763,7 +761,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)(info.contexts(cur), info) match { + trans.transformValDef(tree)(ctx.withPhase(trans), info) match { case t: ValDef => goValDef(t, info.nx.nxTransValDef(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -774,7 +772,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)(info.contexts(cur), info) match { + trans.transformDefDef(tree)(ctx.withPhase(trans), info) match { case t: DefDef => goDefDef(t, info.nx.nxTransDefDef(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -785,7 +783,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)(info.contexts(cur), info) match { + trans.transformUnApply(tree)(ctx.withPhase(trans), info) match { case t: UnApply => goUnApply(t, info.nx.nxTransUnApply(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -796,7 +794,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)(info.contexts(cur), info) match { + trans.transformTypeDef(tree)(ctx.withPhase(trans), info) match { case t: TypeDef => goTypeDef(t, info.nx.nxTransTypeDef(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -807,7 +805,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)(info.contexts(cur), info) match { + trans.transformTemplate(tree)(ctx.withPhase(trans), info) match { case t: Template => goTemplate(t, info.nx.nxTransTemplate(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -818,7 +816,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)(info.contexts(cur), info) match { + trans.transformPackageDef(tree)(ctx.withPhase(trans), info) match { case t: PackageDef => goPackageDef(t, info.nx.nxTransPackageDef(cur + 1)) case t => transformSingle(t, cur + 1) } @@ -863,9 +861,7 @@ object TreeTransforms { case tree: UnApply => goUnApply(tree, info.nx.nxTransUnApply(cur)) case tree: Template => goTemplate(tree, info.nx.nxTransTemplate(cur)) case tree: PackageDef => goPackageDef(tree, info.nx.nxTransPackageDef(cur)) - case Thicket(trees) if trees != Nil => - val trees1 = transformL(trees.asInstanceOf[List[tpd.Tree]], info, cur) - if (trees1 eq trees) tree else Thicket(trees1) + case Thicket(trees) => cpy.Thicket(tree, transformTrees(trees, info, cur)) case tree => tree } @@ -876,7 +872,9 @@ object TreeTransforms { case tree => goUnamed(tree, cur) } - final private[TreeTransforms] def transformNameTree(tree: NameTree, info: TransformerInfo, cur: Int)(implicit ctx: Context): Tree = + def localContext(owner: Symbol)(implicit ctx: Context) = ctx.fresh.setOwner(owner) + + final private[TreeTransforms] def transformNamed(tree: NameTree, info: TransformerInfo, cur: Int)(implicit ctx: Context): Tree = tree match { case tree: Ident => implicit val mutatedInfo = mutateTransformers(info, prepForIdent, info.nx.nxPrepIdent, tree, cur) @@ -907,25 +905,27 @@ object TreeTransforms { implicit val mutatedInfo = mutateTransformers(info, prepForValDef, info.nx.nxPrepValDef, tree, cur) if (mutatedInfo eq null) tree else { - val tpt = transform(tree.tpt, mutatedInfo, cur) - val rhs = transform(tree.rhs, mutatedInfo, cur) + val nestedCtx = if (tree.symbol.exists) localContext(tree.symbol) else ctx + val tpt = transform(tree.tpt, mutatedInfo, cur)(nestedCtx) + val rhs = transform(tree.rhs, mutatedInfo, cur)(nestedCtx) goValDef(cpy.ValDef(tree, tree.mods, tree.name, tpt, rhs), mutatedInfo.nx.nxTransValDef(cur)) } case tree: DefDef => implicit val mutatedInfo = mutateTransformers(info, prepForDefDef, info.nx.nxPrepDefDef, tree, cur) if (mutatedInfo eq null) tree else { - val tparams = transformSubL(tree.tparams, mutatedInfo, cur) - val vparams = tree.vparamss.mapConserve(x => transformSubL(x, mutatedInfo, cur)) - val tpt = transform(tree.tpt, mutatedInfo, cur) - val rhs = transform(tree.rhs, mutatedInfo, cur) + val nestedCtx = localContext(tree.symbol) + val tparams = transformSubTrees(tree.tparams, mutatedInfo, cur)(nestedCtx) + val vparams = tree.vparamss.mapConserve(x => transformSubTrees(x, mutatedInfo, cur)(nestedCtx)) + val tpt = transform(tree.tpt, mutatedInfo, cur)(nestedCtx) + val rhs = transform(tree.rhs, mutatedInfo, cur)(nestedCtx) goDefDef(cpy.DefDef(tree, tree.mods, tree.name, tparams, vparams, tpt, rhs), mutatedInfo.nx.nxTransDefDef(cur)) } case tree: TypeDef => implicit val mutatedInfo = mutateTransformers(info, prepForTypeDef, info.nx.nxPrepTypeDef, tree, cur) if (mutatedInfo eq null) tree else { - val rhs = transform(tree.rhs, mutatedInfo, cur) + val rhs = transform(tree.rhs, mutatedInfo, cur)(localContext(tree.symbol)) goTypeDef(cpy.TypeDef(tree, tree.mods, tree.name, rhs, tree.tparams), mutatedInfo.nx.nxTransTypeDef(cur)) } case _ => @@ -950,7 +950,7 @@ object TreeTransforms { if (mutatedInfo eq null) tree else { val fun = transform(tree.fun, mutatedInfo, cur) - val args = transformSubL(tree.args, mutatedInfo, cur) + val args = transformSubTrees(tree.args, mutatedInfo, cur) goApply(cpy.Apply(tree, fun, args), mutatedInfo.nx.nxTransApply(cur)) } case tree: TypeApply => @@ -958,7 +958,7 @@ object TreeTransforms { if (mutatedInfo eq null) tree else { val fun = transform(tree.fun, mutatedInfo, cur) - val args = transformL(tree.args, mutatedInfo, cur) + val args = transformTrees(tree.args, mutatedInfo, cur) goTypeApply(cpy.TypeApply(tree, fun, args), mutatedInfo.nx.nxTransTypeApply(cur)) } case tree: Literal => @@ -1000,7 +1000,7 @@ object TreeTransforms { implicit val mutatedInfo = mutateTransformers(info, prepForBlock, info.nx.nxPrepBlock, tree, cur) if (mutatedInfo eq null) tree else { - val stats = transformStats(tree.stats, mutatedInfo, cur) + val stats = transformStats(tree.stats, ctx.owner, mutatedInfo, cur) val expr = transform(tree.expr, mutatedInfo, cur) goBlock(cpy.Block(tree, stats, expr), mutatedInfo.nx.nxTransBlock(cur)) } @@ -1017,7 +1017,7 @@ object TreeTransforms { implicit val mutatedInfo = mutateTransformers(info, prepForClosure, info.nx.nxPrepClosure, tree, cur) if (mutatedInfo eq null) tree else { - val env = transformL(tree.env, mutatedInfo, cur) + val env = transformTrees(tree.env, mutatedInfo, cur) val meth = transform(tree.meth, mutatedInfo, cur) val tpt = transform(tree.tpt, mutatedInfo, cur) goClosure(cpy.Closure(tree, env, meth, tpt), mutatedInfo.nx.nxTransClosure(cur)) @@ -1027,7 +1027,7 @@ object TreeTransforms { if (mutatedInfo eq null) tree else { val selector = transform(tree.selector, mutatedInfo, cur) - val cases = transformSubL(tree.cases, mutatedInfo, cur) + val cases = transformSubTrees(tree.cases, mutatedInfo, cur) goMatch(cpy.Match(tree, selector, cases), mutatedInfo.nx.nxTransMatch(cur)) } case tree: CaseDef => @@ -1067,7 +1067,7 @@ object TreeTransforms { implicit val mutatedInfo = mutateTransformers(info, prepForSeqLiteral, info.nx.nxPrepSeqLiteral, tree, cur) if (mutatedInfo eq null) tree else { - val elems = transformL(tree.elems, mutatedInfo, cur) + val elems = transformTrees(tree.elems, mutatedInfo, cur) goSeqLiteral(cpy.SeqLiteral(tree, elems), mutatedInfo.nx.nxTransLiteral(cur)) } case tree: TypeTree => @@ -1081,7 +1081,7 @@ object TreeTransforms { implicit val mutatedInfo = mutateTransformers(info, prepForAlternative, info.nx.nxPrepAlternative, tree, cur) if (mutatedInfo eq null) tree else { - val trees = transformL(tree.trees, mutatedInfo, cur) + val trees = transformTrees(tree.trees, mutatedInfo, cur) goAlternative(cpy.Alternative(tree, trees), mutatedInfo.nx.nxTransAlternative(cur)) } case tree: UnApply => @@ -1089,8 +1089,8 @@ object TreeTransforms { if (mutatedInfo eq null) tree else { val fun = transform(tree.fun, mutatedInfo, cur) - val implicits = transformL(tree.implicits, mutatedInfo, cur) - val patterns = transformL(tree.patterns, mutatedInfo, cur) + val implicits = transformTrees(tree.implicits, mutatedInfo, cur) + val patterns = transformTrees(tree.patterns, mutatedInfo, cur) goUnApply(cpy.UnApply(tree, fun, implicits, patterns), mutatedInfo.nx.nxTransUnApply(cur)) } case tree: Template => @@ -1098,29 +1098,28 @@ object TreeTransforms { if (mutatedInfo eq null) tree else { val constr = transformSub(tree.constr, mutatedInfo, cur) - val parents = transformL(tree.parents, mutatedInfo, cur) + val parents = transformTrees(tree.parents, mutatedInfo, cur) val self = transformSub(tree.self, mutatedInfo, cur) - val body = transformStats(tree.body, mutatedInfo, cur) + val body = transformStats(tree.body, tree.symbol, mutatedInfo, cur) goTemplate(cpy.Template(tree, constr, parents, self, body), mutatedInfo.nx.nxTransTemplate(cur)) } case tree: PackageDef => implicit val mutatedInfo = mutateTransformers(info, prepForPackageDef, info.nx.nxPrepPackageDef, tree, cur) if (mutatedInfo eq null) tree else { + val nestedCtx = localContext(tree.symbol) val pid = transformSub(tree.pid, mutatedInfo, cur) - val stats = transformStats(tree.stats, mutatedInfo, cur) + val stats = transformStats(tree.stats, tree.symbol, mutatedInfo, cur)(nestedCtx) goPackageDef(cpy.PackageDef(tree, pid, stats), mutatedInfo.nx.nxTransPackageDef(cur)) } - case Thicket(trees) if trees != Nil => - val trees1 = transformL(trees.asInstanceOf[List[tpd.Tree]], info, cur) - if (trees1 eq trees) tree else Thicket(trees1) + case Thicket(trees) => cpy.Thicket(tree, transformTrees(trees, info, cur)) case tree => tree } def transform(tree: Tree, info: TransformerInfo, cur: Int)(implicit ctx: Context): Tree = { tree match { //split one big match into 2 smaller ones - case tree: NameTree => transformNameTree(tree, info, cur) + case tree: NameTree => transformNamed(tree, info, cur) case tree => transformUnnamed(tree, info, cur) } } @@ -1134,20 +1133,26 @@ object TreeTransforms { } else trees } - def transformStats(trees: List[Tree], info: TransformerInfo, current: Int)(implicit ctx: Context): List[Tree] = { + def transformStats(trees: List[Tree], exprOwner: Symbol, info: TransformerInfo, current: Int)(implicit ctx: Context): List[Tree] = { val newInfo = mutateTransformers(info, prepForStats, info.nx.nxPrepStats, trees, current) - val newTrees = transformL(trees, newInfo, current)(ctx) - flatten(goStats(newTrees, newInfo.nx.nxTransStats(current))(ctx, newInfo)) + val exprCtx = ctx.withOwner(exprOwner) + def transformStat(stat: Tree): Tree = stat match { + case _: Import | _: DefTree => transform(stat, info, current) + case Thicket(stats) => cpy.Thicket(stat, stats mapConserve transformStat) + case _ => transform(stat, info, current)(exprCtx) + } + val newTrees = flatten(trees.mapconserve(transformStat)) + goStats(newTrees, newInfo.nx.nxTransStats(current))(ctx, newInfo) } - def transformL(trees: List[Tree], info: TransformerInfo, current: Int)(implicit ctx: Context): List[Tree] = + def transformTrees(trees: List[Tree], info: TransformerInfo, current: Int)(implicit ctx: Context): List[Tree] = flatten(trees mapConserve (x => transform(x, info, current))) def transformSub[Tr <: Tree](tree: Tr, info: TransformerInfo, current: Int)(implicit ctx: Context): Tr = transform(tree, info, current).asInstanceOf[Tr] - def transformSubL[Tr <: Tree](trees: List[Tr], info: TransformerInfo, current: Int)(implicit ctx: Context): List[Tr] = - transformL(trees, info, current)(ctx).asInstanceOf[List[Tr]] + def transformSubTrees[Tr <: Tree](trees: List[Tr], info: TransformerInfo, current: Int)(implicit ctx: Context): List[Tr] = + transformTrees(trees, info, current)(ctx).asInstanceOf[List[Tr]] } } diff --git a/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index 1c453750ea56..54f72c20c9cd 100644 --- a/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -13,6 +13,7 @@ import core.StdNames._ import core.transform.Erasure.isUnboundedGeneric import typer.ErrorReporting._ import ast.Trees._ +import Erasure.Boxing.box /** This transform normalizes type tests and type casts. * Any remaining type tests @@ -23,8 +24,6 @@ import ast.Trees._ class TypeTestsCasts extends TreeTransform { import ast.tpd._ - def box(tree: Tree): Tree = ??? - override def name: String = "typeTestsCasts" override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree = ctx.traceIndented(s"transforming ${tree.show}", show = true) { @@ -81,7 +80,7 @@ class TypeTestsCasts extends TreeTransform { Typed(qual, tree.args.head) else if (qualCls.isPrimitiveValueClass) { val argCls = argType.classSymbol - if (argCls.isPrimitiveValueClass) numericConversion(qual, argCls) + if (argCls.isPrimitiveValueClass) primitiveConversion(qual, argCls) else derivedTree(box(qual), defn.Object_asInstanceOf) } else diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala index 8990d21a24d0..db549b2d4d48 100644 --- a/src/dotty/tools/dotc/typer/Implicits.scala +++ b/src/dotty/tools/dotc/typer/Implicits.scala @@ -457,7 +457,7 @@ trait Implicits { self: Typer => pt) val generated1 = adapt(generated, pt) lazy val shadowing = - typed(untpd.Ident(ref.name) withPos pos.toSynthetic, funProto)(nestedContext.clearTyperState) + typed(untpd.Ident(ref.name) withPos pos.toSynthetic, funProto)(nestedContext.setNewTyperState) def refMatches(shadowing: Tree): Boolean = ref.symbol == closureBody(shadowing).symbol || { shadowing match { @@ -485,7 +485,7 @@ trait Implicits { self: Typer => val history = ctx.searchHistory nest wildProto val result = if (history eq ctx.searchHistory) divergingImplicit(ref) - else typedImplicit(ref)(nestedContext.clearTyperState.setSearchHistory(history)) + else typedImplicit(ref)(nestedContext.setNewTyperState.setSearchHistory(history)) result match { case fail: SearchFailure => rankImplicits(pending1, acc) diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala index 9c4ce232e344..173ac3aeba82 100644 --- a/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/src/dotty/tools/dotc/typer/Inferencing.scala @@ -30,7 +30,7 @@ trait Inferencing { this: Checking => * Variables that are successfully minimized do not count as uninstantiated. */ def isFullyDefined(tp: Type, force: ForceDegree.Value)(implicit ctx: Context): Boolean = { - val nestedCtx = ctx.fresh.clearTyperState + val nestedCtx = ctx.fresh.setNewTyperState val result = new IsFullyDefinedAccumulator(force)(nestedCtx).process(tp) if (result) nestedCtx.typerState.commit() result diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index e81949f05e4e..d0e78185f85a 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -292,7 +292,7 @@ class Namer { typer: Typer => /** A new context for the interior of a class */ def inClassContext(selfInfo: DotClass /* Should be Type | Symbol*/)(implicit ctx: Context): Context = { - val localCtx: Context = ctx.fresh.clearScope + val localCtx: Context = ctx.fresh.setNewScope selfInfo match { case sym: Symbol if sym.exists && sym.name != nme.WILDCARD => localCtx.scope.asInstanceOf[MutableScope].enter(sym) @@ -385,14 +385,14 @@ class Namer { typer: Typer => private def typeSig(sym: Symbol): Type = original match { case original: ValDef => if (sym is Module) moduleValSig(sym) - else valOrDefDefSig(original, sym, Nil, identity)(localContext(sym).clearScope) + else valOrDefDefSig(original, sym, Nil, identity)(localContext(sym).setNewScope) case original: DefDef => val typer1 = new Typer nestedTyper(sym) = typer1 typer1.defDefSig(original, sym)(localContext(sym).setTyper(typer1)) case original: TypeDef => assert(!original.isClassDef) - typeDefSig(original, sym)(localContext(sym).clearScope) + typeDefSig(original, sym)(localContext(sym).setNewScope) case imp: Import => try { val expr1 = typedAheadExpr(imp.expr, AnySelectionProto) diff --git a/src/dotty/tools/dotc/typer/ReTyper.scala b/src/dotty/tools/dotc/typer/ReTyper.scala new file mode 100644 index 000000000000..896dbba7dc2f --- /dev/null +++ b/src/dotty/tools/dotc/typer/ReTyper.scala @@ -0,0 +1,56 @@ +package dotty.tools.dotc +package typer + +import core.Contexts._ +import core.Types._ +import core.Symbols.Symbol +import typer.ProtoTypes._ +import ast.{tpd, untpd} +import ast.Trees._ + +/** A version of Typer that keeps all symbols defined and referenced in a + * previously typed tree. + * + * All definition nodes keep their symbols. All leaf nodes for idents, selects, + * and TypeTrees keep their types. Indexing is a no-op. + * + * Otherwise, everything is as in Typer. + */ +class ReTyper extends Typer { + import tpd._ + + protected def promote(tree: untpd.Tree)(implicit ctx: Context): tree.ThisTree[Type] = { + assert(tree.hasType) + tree.withType(tree.typeOpt) + } + + override def typedIdent(tree: untpd.Ident, pt: Type)(implicit ctx: Context): Tree = + promote(tree) + + override def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = { + assert(tree.hasType) + val qual1 = typed(tree.qualifier, AnySelectionProto) + untpd.cpy.Select(tree, qual1, tree.name).withType(tree.typeOpt) + } + + override def typedSelectFromTypeTree(tree: untpd.SelectFromTypeTree, pt: Type)(implicit ctx: Context): SelectFromTypeTree = { + assert(tree.hasType) + val qual1 = typed(tree.qualifier, AnySelectionProto) + untpd.cpy.SelectFromTypeTree(tree, qual1, tree.name).withType(tree.typeOpt) + } + + override def typedTypeTree(tree: untpd.TypeTree, pt: Type)(implicit ctx: Context): TypeTree = + promote(tree) + + override def typedBind(tree: untpd.Bind, pt: Type)(implicit ctx: Context): Bind = { + assert(tree.hasType) + val body1 = typed(tree.body, pt) + untpd.cpy.Bind(tree, tree.name, body1).withType(tree.typeOpt) + } + + override def retrieveSym(tree: untpd.Tree)(implicit ctx: Context): Symbol = tree.symbol + + override def localTyper(sym: Symbol) = this + + override def index(trees: List[untpd.Tree])(implicit ctx: Context) = ctx +} \ No newline at end of file diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala index 8be73ac82d01..5345b73965e1 100644 --- a/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -228,7 +228,7 @@ trait TypeAssigner { val ownType = fn.tpe.widen match { case pt: PolyType => val argTypes = args.tpes - if (sameLength(argTypes, pt.paramNames)) pt.instantiate(args.tpes) + if (sameLength(argTypes, pt.paramNames)) pt.instantiate(argTypes) else errorType(i"wrong number of type parameters for ${fn.tpe}; expected: ${pt.paramNames.length}", tree.pos) case _ => errorType(s"${err.exprStr(fn)} does not take type parameters", tree.pos) @@ -274,8 +274,12 @@ trait TypeAssigner { def assignType(tree: untpd.Throw)(implicit ctx: Context) = tree.withType(defn.NothingType) - def assignType(tree: untpd.SeqLiteral, elems: List[Tree])(implicit ctx: Context) = - tree.withType(defn.SeqType.appliedTo(ctx.typeComparer.lub(elems.tpes))) + def assignType(tree: untpd.SeqLiteral, elems: List[Tree])(implicit ctx: Context) = { + val ownType = + if (ctx.erasedTypes) defn.SeqType + else defn.SeqType.appliedTo(ctx.typeComparer.lub(elems.tpes)) + tree.withType(ownType) + } def assignType(tree: untpd.SingletonTypeTree, ref: Tree)(implicit ctx: Context) = tree.withType(ref.tpe) diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 87bc643a3c31..c2488f68cfdb 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -587,7 +587,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit assignType(cpy.CaseDef(tree, pat, guard1, body1), body1) } val doCase: () => CaseDef = - () => caseRest(typedPattern(tree.pat, selType))(ctx.fresh.clearScope) + () => caseRest(typedPattern(tree.pat, selType))(ctx.fresh.setNewScope) (doCase /: gadtSyms)((op, tsym) => tsym.withGADTFlexType(op))() } @@ -775,7 +775,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit //todo: make sure dependent method types do not depend on implicits or by-name params } - def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(implicit ctx: Context): TypeDef = track("typedTypeDef") { + def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(implicit ctx: Context): Tree = track("typedTypeDef") { val TypeDef(mods, name, rhs) = tdef val mods1 = typedModifiers(mods) val _ = typedType(rhs) // unused, typecheck only to remove from typedTree @@ -858,40 +858,26 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def typedAsFunction(tree: untpd.Tree, pt: Type)(implicit ctx: Context): Tree = typed(tree, if (defn.isFunctionType(pt)) pt else AnyFunctionProto) - def typedNamed(xtree: untpd.NameTree, pt: Type)(implicit ctx: Context): Tree = { - val tree = xtree withName xtree.name.encode - val sym = xtree.removeAttachment(SymOfTree) match { - case Some(sym) => - sym.ensureCompleted() - sym - case none => - NoSymbol - } - - def localContext = { - val freshCtx = ctx.fresh.setTree(xtree) - if (sym.exists) freshCtx.setOwner(sym) - else freshCtx // can happen for self defs - } + /** Retrieve symbol attached to given tree */ + protected def retrieveSym(tree: untpd.Tree)(implicit ctx: Context) = tree.removeAttachment(SymOfTree) match { + case Some(sym) => + sym.ensureCompleted() + sym + case none => + NoSymbol + } - tree match { - case tree: untpd.Ident => typedIdent(tree, pt) - case tree: untpd.Select => typedSelect(tree, pt) - case tree: untpd.SelectFromTypeTree => typedSelectFromTypeTree(tree, pt) - case tree: untpd.Bind => typedBind(tree, pt) - case tree: untpd.ValDef => - if (tree.isEmpty) tpd.EmptyValDef - else typedValDef(tree, sym)(localContext.clearScope) - case tree: untpd.DefDef => - val typer1 = nestedTyper.remove(sym).get - typer1.typedDefDef(tree, sym)(localContext.setTyper(typer1)) - case tree: untpd.TypeDef => - if (tree.isClassDef) typedClassDef(tree, sym.asClass)(localContext) - else typedTypeDef(tree, sym)(localContext.clearScope) - case _ => typedUnadapted(desugar(tree), pt) - } + /** A fresh local context with given tree and owner. + * Owner might not exist (can happen for self valdefs), in which case + * no owner is set in result context + */ + protected def localContext(tree: untpd.Tree, owner: Symbol)(implicit ctx: Context): FreshContext = { + val freshCtx = ctx.fresh.setTree(tree) + if (owner.exists) freshCtx.setOwner(owner) else freshCtx } + protected def localTyper(sym: Symbol): Typer = nestedTyper.remove(sym).get + def typedUnadapted(initTree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = { record("typedUnadapted") val xtree = expanded(initTree) @@ -899,6 +885,26 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit case Some(ttree) => ttree case none => + def typedNamed(tree: untpd.NameTree, pt: Type)(implicit ctx: Context): Tree = { + val sym = retrieveSym(xtree) + tree match { + case tree: untpd.Ident => typedIdent(tree, pt) + case tree: untpd.Select => typedSelect(tree, pt) + case tree: untpd.SelectFromTypeTree => typedSelectFromTypeTree(tree, pt) + case tree: untpd.Bind => typedBind(tree, pt) + case tree: untpd.ValDef => + if (tree.isEmpty) tpd.EmptyValDef + else typedValDef(tree, sym)(localContext(tree, sym).setNewScope) + case tree: untpd.DefDef => + val typer1 = localTyper(sym) + typer1.typedDefDef(tree, sym)(localContext(tree, sym).setTyper(typer1)) + case tree: untpd.TypeDef => + if (tree.isClassDef) typedClassDef(tree, sym.asClass)(localContext(tree, sym)) + else typedTypeDef(tree, sym)(localContext(tree, sym).setNewScope) + case _ => typedUnadapted(desugar(tree), pt) + } + } + def typedUnnamed(tree: untpd.Tree): Tree = tree match { case tree: untpd.Apply => if (ctx.mode is Mode.Pattern) typedUnApply(tree, pt) else typedApply(tree, pt) @@ -909,7 +915,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit case tree: untpd.Typed => typedTyped(tree, pt) case tree: untpd.NamedArg => typedNamedArg(tree, pt) case tree: untpd.Assign => typedAssign(tree, pt) - case tree: untpd.Block => typedBlock(desugar.block(tree), pt)(ctx.fresh.clearScope) + case tree: untpd.Block => typedBlock(desugar.block(tree), pt)(ctx.fresh.setNewScope) case tree: untpd.If => typedIf(tree, pt) case tree: untpd.Function => typedFunction(tree, pt) case tree: untpd.Closure => typedClosure(tree, pt) @@ -938,8 +944,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } xtree match { - case xtree: untpd.NameTree => typedNamed(xtree, pt) - case xtree: untpd.Import => typedImport(xtree, xtree.removeAttachment(SymOfTree).get) + case xtree: untpd.NameTree => typedNamed(xtree withName xtree.name.encode, pt) + case xtree: untpd.Import => typedImport(xtree, retrieveSym(xtree)) case xtree => typedUnnamed(xtree) } } @@ -992,7 +998,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit typed(tree, pt)(ctx addMode Mode.Pattern) def tryEither[T](op: Context => T)(fallBack: (T, TyperState) => T)(implicit ctx: Context) = { - val nestedCtx = ctx.fresh.clearTyperState + val nestedCtx = ctx.fresh.setNewTyperState val result = op(nestedCtx) if (nestedCtx.reporter.hasErrors) fallBack(result, nestedCtx.typerState) diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index ed6f3b5d9166..dcd5c67c8649 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -15,37 +15,39 @@ class tests extends CompilerTest { "-pagewidth", "160" ) val twice = List("#runs", "2") + val doErase = List("-Ystop-before:terminal") val posDir = "./tests/pos/" val negDir = "./tests/neg/" val newDir = "./tests/new/" val dotcDir = "./src/dotty/" -/* - @Test def pos_Coder() = compileFile(posDir, "Coder", twice) - @Test def pos_blockescapes() = compileFile(posDir, "blockescapes", twice) - @Test def pos_collections() = compileFile(posDir, "collections", twice) - @Test def pos_functions1() = compileFile(posDir, "functions1", twice) - @Test def pos_implicits1() = compileFile(posDir, "implicits1", twice) - @Test def pos_inferred() = compileFile(posDir, "inferred", twice) - @Test def pos_Patterns() = compileFile(posDir, "Patterns", twice) - @Test def pos_selftypes() = compileFile(posDir, "selftypes", twice) - @Test def pos_varargs() = compileFile(posDir, "varargs", twice) - @Test def pos_opassign() = compileFile(posDir, "opassign", twice) - @Test def pos_typedapply() = compileFile(posDir, "typedapply", twice) - @Test def pos_nameddefaults() = compileFile(posDir, "nameddefaults", twice) - @Test def pos_desugar() = compileFile(posDir, "desugar", twice) - @Test def pos_sigs() = compileFile(posDir, "sigs", twice) - @Test def pos_typers() = compileFile(posDir, "typers", twice) - @Test def pos_typedidents() = compileFile(posDir, "typedIdents", twice) - @Test def pos_assignments() = compileFile(posDir, "assignments", twice) - @Test def pos_packageobject() = compileFile(posDir, "packageobject", twice) - @Test def pos_overloaded() = compileFile(posDir, "overloaded", twice) - @Test def pos_templateParents() = compileFile(posDir, "templateParents", twice) - @Test def pos_structural() = compileFile(posDir, "structural", twice) - @Test def pos_i39 = compileFile(posDir, "i39", twice) - @Test def pos_overloadedAccess = compileFile(posDir, "overloadedAccess", twice) - @Test def pos_approximateUnion = compileFile(posDir, "approximateUnion", twice) -*/ + + @Test def pos_erasure = compileFile(posDir, "erasure", doErase) + @Test def pos_Coder() = compileFile(posDir, "Coder", doErase) + @Test def pos_blockescapes() = compileFile(posDir, "blockescapes", doErase) + @Test def pos_collections() = compileFile(posDir, "collections", doErase) + @Test def pos_functions1() = compileFile(posDir, "functions1", doErase) + @Test def pos_implicits1() = compileFile(posDir, "implicits1", doErase) + @Test def pos_inferred() = compileFile(posDir, "inferred", doErase) + @Test def pos_Patterns() = compileFile(posDir, "Patterns", doErase) + @Test def pos_selftypes() = compileFile(posDir, "selftypes", doErase) + @Test def pos_varargs() = compileFile(posDir, "varargs", doErase) + @Test def pos_opassign() = compileFile(posDir, "opassign", doErase) + @Test def pos_typedapply() = compileFile(posDir, "typedapply", doErase) + @Test def pos_nameddefaults() = compileFile(posDir, "nameddefaults", doErase) + @Test def pos_desugar() = compileFile(posDir, "desugar", doErase) + @Test def pos_sigs() = compileFile(posDir, "sigs", doErase) + @Test def pos_typers() = compileFile(posDir, "typers", doErase) + @Test def pos_typedidents() = compileFile(posDir, "typedIdents", doErase) + @Test def pos_assignments() = compileFile(posDir, "assignments", doErase) + @Test def pos_packageobject() = compileFile(posDir, "packageobject", doErase) + @Test def pos_overloaded() = compileFile(posDir, "overloaded", doErase) + @Test def pos_templateParents() = compileFile(posDir, "templateParents", doErase) + @Test def pos_structural() = compileFile(posDir, "structural", doErase) + @Test def pos_i39 = compileFile(posDir, "i39", doErase) + @Test def pos_overloadedAccess = compileFile(posDir, "overloadedAccess", doErase) + @Test def pos_approximateUnion = compileFile(posDir, "approximateUnion", doErase) + @Test def pos_all = compileFiles(posDir, twice) @Test def new_all = compileFiles(newDir, twice) diff --git a/tests/pos/unions.scala b/tests/pos/unions.scala new file mode 100644 index 000000000000..779d1847e97a --- /dev/null +++ b/tests/pos/unions.scala @@ -0,0 +1,14 @@ +object unions { + + class A { + def f: String = "abc" + } + + class B { + def f: String = "bcd" + } + + val x: A | B = if (true) new A else new B + println(x.f) + +}