aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-03-06 11:25:57 +0100
committerMartin Odersky <odersky@gmail.com>2014-03-07 11:12:34 +0100
commitdbd5a4d22b6164b708a87b508d9b9f135b44a3ee (patch)
treef260c0ac27d161aa7eced5edf0906e354256770b /src
parent2669fac03190a4b52b120e07896cf5cd3de208c6 (diff)
downloaddotty-dbd5a4d22b6164b708a87b508d9b9f135b44a3ee.tar.gz
dotty-dbd5a4d22b6164b708a87b508d9b9f135b44a3ee.tar.bz2
dotty-dbd5a4d22b6164b708a87b508d9b9f135b44a3ee.zip
Scond step to typer reorg: Introduce TypeAssigners.
TypeAssigners assign a toplevel type to a node. They are mixed into Typer, and can be accessed from tpd using ctx.typeAssigner.
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala20
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala13
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala27
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala18
-rw-r--r--src/dotty/tools/dotc/typer/ProtoTypes.scala2
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala27
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala6
7 files changed, 72 insertions, 41 deletions
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index 3a0790c9c..32a36bbd1 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -11,6 +11,8 @@ import config.Printers._
/** Some creators for typed trees */
object tpd extends Trees.Instance[Type] with TypedTreeInfo {
+ private def ta(implicit ctx: Context) = ctx.typeAssigner
+
def Modifiers(sym: Symbol)(implicit ctx: Context): Modifiers = Modifiers(
sym.flags & ModifierFlags,
if (sym.privateWithin.exists) sym.privateWithin.asType.name else tpnme.EMPTY,
@@ -68,27 +70,13 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}
def Literal(const: Constant)(implicit ctx: Context): Literal =
- typedLiteral(untpd.Literal(const))
-
- def typedLiteral(tree: untpd.Literal)(implicit ctx: Context) =
- tree.withType {
- tree.const.tag match {
- case UnitTag => defn.UnitType
- case NullTag => defn.NullType
- case _ => ConstantType(tree.const)
- }
- }
+ ta.assignType(untpd.Literal(const))
def unitLiteral(implicit ctx: Context): Literal =
Literal(Constant(()))
def New(tpt: Tree)(implicit ctx: Context): New =
- untpd.New(tpt).withType(tpt.tpe).checked
-
- def typedNew(tree: untpd.New)(implicit ctx: Context) = {
- ctx.typer.checkClassTypeWithStablePrefix(tree.tpt.tpe, tree.tpt.pos, traitReq = false)
- tree.withType(tree.tpt.tpe)
- }
+ ta.assignType(untpd.New(tpt))
def New(tp: Type)(implicit ctx: Context): New = New(TypeTree(tp))
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala
index dd96023d7..9be2e2f43 100644
--- a/src/dotty/tools/dotc/core/Contexts.scala
+++ b/src/dotty/tools/dotc/core/Contexts.scala
@@ -119,10 +119,11 @@ object Contexts {
protected def scope_=(scope: Scope) = _scope = scope
def scope: Scope = _scope
- /** The current typer */
- private[this] var _typer: Typer = _
- protected def typer_=(typer: Typer) = _typer = typer
- def typer: Typer = _typer
+ /** The current type assigner ot typer */
+ private[this] var _typeAssigner: TypeAssigner = _
+ protected def typeAssigner_=(typeAssigner: TypeAssigner) = _typeAssigner = typeAssigner
+ def typeAssigner: TypeAssigner = _typeAssigner
+ def typer: Typer = _typeAssigner.asInstanceOf[Typer]
/** The currently active import info */
private[this] var _importInfo: ImportInfo = _
@@ -312,7 +313,8 @@ object Contexts {
def withTree(tree: Tree[_ >: Untyped]): this.type = { this.tree = tree; this }
def withScope(scope: Scope): this.type = { this.scope = scope; this }
def withNewScope: this.type = { this.scope = newScope; this }
- def withTyper(typer: Typer): this.type = { this.typer = typer; this.scope = typer.scope; this }
+ def withTypeAssigner(typeAssigner: TypeAssigner): this.type = { this.typeAssigner = typeAssigner; this }
+ def withTyper(typer: Typer): this.type = { this.scope = typer.scope; withTypeAssigner(typer) }
def withImportInfo(importInfo: ImportInfo): this.type = { this.importInfo = importInfo; this }
def withRunInfo(runInfo: RunInfo): this.type = { this.runInfo = runInfo; this }
def withDiagnostics(diagnostics: Option[StringBuilder]): this.type = { this.diagnostics = diagnostics; this }
@@ -342,6 +344,7 @@ object Contexts {
owner = NoSymbol
sstate = settings.defaultState
tree = untpd.EmptyTree
+ typeAssigner = TypeAssigner
runInfo = new RunInfo(this)
diagnostics = None
moreProperties = Map.empty
diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala
index 2fa0d5519..5c21584bd 100644
--- a/src/dotty/tools/dotc/typer/Checking.scala
+++ b/src/dotty/tools/dotc/typer/Checking.scala
@@ -18,12 +18,23 @@ import ErrorReporting.{errorType, InfoString}
import config.Printers._
import collection.mutable
-trait Checking {
+trait NoChecking {
+ import tpd._
+ def checkBounds(args: List[tpd.Tree], poly: PolyType, pos: Position)(implicit ctx: Context): Unit = ()
+ def checkStable(tp: Type, pos: Position)(implicit ctx: Context): Unit = ()
+ def checkClassTypeWithStablePrefix(tp: Type, pos: Position, traitReq: Boolean)(implicit ctx: Context): Type = tp
+ def checkImplicitTptNonEmpty(defTree: untpd.ValOrDefDef)(implicit ctx: Context): Unit = ()
+ def checkImplicitParamsNotSingletons(vparamss: List[List[ValDef]])(implicit ctx: Context): Unit = ()
+ def checkFeasible(tp: Type, pos: Position, where: => String = "")(implicit ctx: Context): Type = tp
+ def checkNoDoubleDefs(cls: Symbol)(implicit ctx: Context): Unit = ()
+}
+
+trait Checking extends NoChecking {
import tpd._
/** Check that type arguments `args` conform to corresponding bounds in `poly` */
- def checkBounds(args: List[tpd.Tree], poly: PolyType, pos: Position)(implicit ctx: Context): Unit =
+ override def checkBounds(args: List[tpd.Tree], poly: PolyType, pos: Position)(implicit ctx: Context): Unit =
for ((arg, bounds) <- args zip poly.paramBounds) {
def notConforms(which: String, bound: Type) =
ctx.error(i"Type argument ${arg.tpe} does not conform to $which bound $bound", arg.pos)
@@ -34,14 +45,14 @@ trait Checking {
/** Check that type `tp` is stable.
* @return The type itself
*/
- def checkStable(tp: Type, pos: Position)(implicit ctx: Context): Unit =
+ override def checkStable(tp: Type, pos: Position)(implicit ctx: Context): Unit =
if (!tp.isStable) ctx.error(i"Prefix of type ${tp.widenIfUnstable} is not stable", pos)
/** Check that `tp` is a class type with a stable prefix. Also, if `isFirst` is
* false check that `tp` is a trait.
* @return `tp` itself if it is a class or trait ref, ObjectClass.typeRef if not.
*/
- def checkClassTypeWithStablePrefix(tp: Type, pos: Position, traitReq: Boolean)(implicit ctx: Context): Type =
+ override def checkClassTypeWithStablePrefix(tp: Type, pos: Position, traitReq: Boolean)(implicit ctx: Context): Type =
tp.underlyingClassRef match {
case tref: TypeRef =>
checkStable(tref.prefix, pos)
@@ -53,7 +64,7 @@ trait Checking {
}
/** Check that (return) type of implicit definition is not empty */
- def checkImplicitTptNonEmpty(defTree: untpd.ValOrDefDef)(implicit ctx: Context): Unit = defTree.tpt match {
+ override def checkImplicitTptNonEmpty(defTree: untpd.ValOrDefDef)(implicit ctx: Context): Unit = defTree.tpt match {
case TypeTree(original) if original.isEmpty =>
val resStr = if (defTree.isInstanceOf[untpd.DefDef]) "result " else ""
ctx.error(i"${resStr}type of implicit definition needs to be given explicitly", defTree.pos)
@@ -63,7 +74,7 @@ trait Checking {
/** Check that a non-implicit parameter making up the first parameter section of an
* implicit conversion is not a singleton type.
*/
- def checkImplicitParamsNotSingletons(vparamss: List[List[ValDef]])(implicit ctx: Context): Unit = vparamss match {
+ override def checkImplicitParamsNotSingletons(vparamss: List[List[ValDef]])(implicit ctx: Context): Unit = vparamss match {
case (vparam :: Nil) :: _ if !(vparam.symbol is Implicit) =>
if (vparam.tpt.tpe.isInstanceOf[SingletonType])
ctx.error(s"implicit conversion may not have a parameter of singleton type", vparam.tpt.pos)
@@ -74,7 +85,7 @@ trait Checking {
* their lower bound conforms to their upper cound. If a type argument is
* infeasible, issue and error and continue with upper bound.
*/
- def checkFeasible(tp: Type, pos: Position, where: => String = "")(implicit ctx: Context): Type = tp match {
+ override def checkFeasible(tp: Type, pos: Position, where: => String = "")(implicit ctx: Context): Type = tp match {
case tp: RefinedType =>
tp.derivedRefinedType(tp.parent, tp.refinedName, checkFeasible(tp.refinedInfo, pos, where))
case tp @ TypeBounds(lo, hi) if !(lo <:< hi) =>
@@ -85,7 +96,7 @@ trait Checking {
}
/** Check that class does not define */
- def checkNoDoubleDefs(cls: Symbol)(implicit ctx: Context): Unit = {
+ override def checkNoDoubleDefs(cls: Symbol)(implicit ctx: Context): Unit = {
val seen = new mutable.HashMap[Name, List[Symbol]] {
override def default(key: Name) = Nil
}
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 7d1e0629e..6e91e4754 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -58,14 +58,16 @@ trait NamerContextOps { this: Context =>
/** The symbol (stored in some typer's symTree) of an enclosing context definition */
def symOfContextTree(tree: untpd.Tree) = {
def go(ctx: Context): Symbol = {
- val typer = ctx.typer
- if (typer == null) NoSymbol
- else tree.getAttachment(typer.SymOfTree) match {
- case Some(sym) => sym
- case None =>
- var cx = ctx.outer
- while (cx.typer eq typer) cx = cx.outer
- go(cx)
+ ctx.typeAssigner match {
+ case typer: Typer =>
+ tree.getAttachment(typer.SymOfTree) match {
+ case Some(sym) => sym
+ case None =>
+ var cx = ctx.outer
+ while (cx.typeAssigner eq typer) cx = cx.outer
+ go(cx)
+ }
+ case _ => NoSymbol
}
}
go(this)
diff --git a/src/dotty/tools/dotc/typer/ProtoTypes.scala b/src/dotty/tools/dotc/typer/ProtoTypes.scala
index 87c556fdc..b4068408b 100644
--- a/src/dotty/tools/dotc/typer/ProtoTypes.scala
+++ b/src/dotty/tools/dotc/typer/ProtoTypes.scala
@@ -103,7 +103,7 @@ object ProtoTypes {
def map(tm: TypeMap)(implicit ctx: Context) = derivedSelectionProto(name, tm(memberProto), compat)
def fold[T](x: T, ta: TypeAccumulator[T])(implicit ctx: Context) = ta(x, memberProto)
- override def computeHash = addDelta(doHash(name, memberProto), if (compat == NoViewsAllowed) 1 else 0)
+ override def computeHash = addDelta(doHash(name, memberProto), if (compat eq NoViewsAllowed) 1 else 0)
}
class CachedSelectionProto(name: Name, memberProto: Type, compat: Compatibility) extends SelectionProto(name, memberProto, compat)
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala
new file mode 100644
index 000000000..e711ee949
--- /dev/null
+++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -0,0 +1,27 @@
+package dotty.tools
+package dotc
+package typer
+
+import core._
+import ast._
+import Scopes._, Contexts._, Constants._, Types._, Symbols._
+
+trait TypeAssigner extends NoChecking {
+
+ def assignType(tree: untpd.New)(implicit ctx: Context) = {
+ checkClassTypeWithStablePrefix(tree.tpt.tpe, tree.tpt.pos, traitReq = false)
+ tree.withType(tree.tpt.tpe)
+ }
+
+ def assignType(tree: untpd.Literal)(implicit ctx: Context) =
+ tree.withType {
+ tree.const.tag match {
+ case UnitTag => defn.UnitType
+ case NullTag => defn.NullType
+ case _ => ConstantType(tree.const)
+ }
+ }
+}
+
+object TypeAssigner extends TypeAssigner
+
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 12d349ce4..c545641a0 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -48,7 +48,7 @@ object Typer {
}
}
-class Typer extends Namer with Applications with Implicits with Inferencing with Checking {
+class Typer extends Namer with TypeAssigner with Applications with Implicits with Inferencing with Checking {
import Typer._
import tpd.{cpy => _, _}
@@ -413,7 +413,7 @@ class Typer extends Namer with Applications with Implicits with Inferencing with
}
def typedLiteral(tree: untpd.Literal)(implicit ctx: Context) = track("typedLiteral") {
- tpd.typedLiteral(tree)
+ assignType(tree)
}
def typedNew(tree: untpd.New, pt: Type)(implicit ctx: Context) = track("typedNew") {
@@ -425,7 +425,7 @@ class Typer extends Namer with Applications with Implicits with Inferencing with
typed(cpy.Block(tree, clsDef :: Nil, New(Ident(x), Nil)), pt)
case _ =>
val tpt1 = typedType(tree.tpt)
- tpd.typedNew(cpy.New(tree, tpt1))
+ assignType(cpy.New(tree, tpt1))
// todo in a later phase: checkInstantiatable(cls, tpt1.pos)
}
}