aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Petrashko <dark@d-d.me>2014-03-31 21:31:16 +0200
committerDmitry Petrashko <dark@d-d.me>2014-03-31 21:31:16 +0200
commite448049027f1aafbe4ae72c859a3368a61592c91 (patch)
tree0fc7c111b557370fe053085771b4a21bd7c48a57
parent3335cd072babda7125cd6ed4782503011b15482a (diff)
parentfb9a9e65c941a7b840baaa32641818d32b45b5b7 (diff)
downloaddotty-e448049027f1aafbe4ae72c859a3368a61592c91.tar.gz
dotty-e448049027f1aafbe4ae72c859a3368a61592c91.tar.bz2
dotty-e448049027f1aafbe4ae72c859a3368a61592c91.zip
Merge pull request #102 from dotty-staging/transform/erasure
Transform/erasure
-rw-r--r--src/dotty/tools/dotc/Compiler.scala4
-rw-r--r--src/dotty/tools/dotc/Run.scala12
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala13
-rw-r--r--src/dotty/tools/dotc/config/ScalaSettings.scala2
-rw-r--r--src/dotty/tools/dotc/config/Settings.scala1
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala58
-rw-r--r--src/dotty/tools/dotc/core/Decorators.scala7
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala5
-rw-r--r--src/dotty/tools/dotc/core/Phases.scala4
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala2
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala11
-rw-r--r--src/dotty/tools/dotc/core/Types.scala1
-rw-r--r--src/dotty/tools/dotc/core/transform/Erasure.scala17
-rw-r--r--src/dotty/tools/dotc/transform/Erasure.scala51
-rw-r--r--src/dotty/tools/dotc/transform/PatternMatcher.scala27
-rw-r--r--src/dotty/tools/dotc/transform/PostTyperTransformers.scala4
-rw-r--r--src/dotty/tools/dotc/transform/Splitter.scala27
-rw-r--r--src/dotty/tools/dotc/transform/TreeChecker.scala37
-rw-r--r--src/dotty/tools/dotc/transform/TreeTransform.scala163
-rw-r--r--src/dotty/tools/dotc/transform/TypeTestsCasts.scala5
-rw-r--r--src/dotty/tools/dotc/typer/Implicits.scala4
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala6
-rw-r--r--src/dotty/tools/dotc/typer/ReTyper.scala56
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala10
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala80
-rw-r--r--test/dotc/tests.scala54
-rw-r--r--tests/pos/unions.scala14
28 files changed, 433 insertions, 244 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala
index 709f4b2db..1e8f13578 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 3f15bd4c3..264373baf 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 b549080e4..3664263e6 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 8ed725e36..144e146c1 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 b3bf2f134..17d4d6712 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 8d083b29c..b0214a631 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 cd9680e64..21f914d99 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 3ae74b467..46878d3ca 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 87242c9b5..8b5606da2 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 f07eaa2be..e96f08855 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 9cd635cd9..4b251f183 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 a7a33ce8e..8799f9fd0 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 d59bdf1a9..842e2f81f 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 f9b602f54..d4156e1d7 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 000000000..ff25a94de
--- /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("<eliminated pattern>")), 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 14e2cf35d..25f122cf5 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 000000000..9c01574aa
--- /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 000000000..ea3afc679
--- /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 10857da5a..425410ae7 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 1c453750e..54f72c20c 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 8990d21a2..db549b2d4 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 9c4ce232e..173ac3aeb 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 e81949f05..d0e78185f 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 000000000..896dbba7d
--- /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 8be73ac82..5345b7396 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 87bc643a3..c2488f68c 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 ed6f3b5d9..dcd5c67c8 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 000000000..779d1847e
--- /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)
+
+}