aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-03-26 19:15:40 +0100
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2014-03-29 09:29:05 +0100
commit37cf9efe509b0bac4fb6bda01b7126e7511e43f0 (patch)
treeee5fa94171acf87de4e5da5bf7ee704a18596163 /src/dotty/tools/dotc/typer
parent0a1e969cb09e953d6b3f3b64b63a050588aa3360 (diff)
downloaddotty-37cf9efe509b0bac4fb6bda01b7126e7511e43f0.tar.gz
dotty-37cf9efe509b0bac4fb6bda01b7126e7511e43f0.tar.bz2
dotty-37cf9efe509b0bac4fb6bda01b7126e7511e43f0.zip
Erasure phase PoC
Still missing: bridge method generation, signatures. Other changes - Turned around Checking and NoChecking. Checking is the default, NoChecking disables it. - Refactored Typer#typed to expose typedNamed, so that it can be overridden in erasure. - Made logging more forgiving wrt off-buy-one phase errors. Conflicts: src/dotty/tools/dotc/typer/Typer.scala
Diffstat (limited to 'src/dotty/tools/dotc/typer')
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala46
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala69
2 files changed, 60 insertions, 55 deletions
diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala
index 36822cb85..5818da180 100644
--- a/src/dotty/tools/dotc/typer/Checking.scala
+++ b/src/dotty/tools/dotc/typer/Checking.scala
@@ -18,26 +18,13 @@ import ErrorReporting.{errorType, InfoString}
import config.Printers._
import collection.mutable
-trait NoChecking {
- import tpd._
- def checkValue(tree: Tree, proto: Type)(implicit ctx: Context): tree.type = tree
- 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 checkLegalPrefix(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 {
+trait Checking {
import tpd._
/** Check that Java statics and packages can only be used in selections.
*/
- override def checkValue(tree: Tree, proto: Type)(implicit ctx: Context): tree.type = {
+ def checkValue(tree: Tree, proto: Type)(implicit ctx: Context): tree.type = {
if (!proto.isInstanceOf[SelectionProto]) {
val sym = tree.tpe.termSymbol
if ((sym is Package) || (sym is JavaModule)) ctx.error(i"$sym is not a value", tree.pos)
@@ -46,7 +33,7 @@ trait Checking extends NoChecking {
}
/** Check that type arguments `args` conform to corresponding bounds in `poly` */
- override def checkBounds(args: List[tpd.Tree], poly: PolyType, pos: Position)(implicit ctx: Context): Unit = {
+ def checkBounds(args: List[tpd.Tree], poly: PolyType, pos: Position)(implicit ctx: Context): Unit = {
val argTypes = args.tpes
def substituted(tp: Type) = tp.substParams(poly, argTypes)
for ((arg, bounds) <- args zip poly.paramBounds) {
@@ -58,20 +45,20 @@ trait Checking extends NoChecking {
}
/** Check that type `tp` is stable. */
- override def checkStable(tp: Type, pos: Position)(implicit ctx: Context): Unit =
+ def checkStable(tp: Type, pos: Position)(implicit ctx: Context): Unit =
if (!tp.isStable) ctx.error(i"$tp is not stable", pos)
/** Check that type `tp` is a legal prefix for '#'.
* @return The type itself
*/
- override def checkLegalPrefix(tp: Type, pos: Position)(implicit ctx: Context): Unit =
+ def checkLegalPrefix(tp: Type, pos: Position)(implicit ctx: Context): Unit =
if (!tp.isLegalPrefix) ctx.error(i"$tp is not a valid prefix for '#'", 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.
*/
- override def checkClassTypeWithStablePrefix(tp: Type, pos: Position, traitReq: Boolean)(implicit ctx: Context): Type =
+ def checkClassTypeWithStablePrefix(tp: Type, pos: Position, traitReq: Boolean)(implicit ctx: Context): Type =
tp.underlyingClassRef match {
case tref: TypeRef =>
checkStable(tref.prefix, pos)
@@ -83,7 +70,7 @@ trait Checking extends NoChecking {
}
/** Check that (return) type of implicit definition is not empty */
- override def checkImplicitTptNonEmpty(defTree: untpd.ValOrDefDef)(implicit ctx: Context): Unit = defTree.tpt match {
+ def checkImplicitTptNonEmpty(defTree: untpd.ValOrDefDef)(implicit ctx: Context): Unit = defTree.tpt match {
case tpt: untpd.DerivedTypeTree =>
case TypeTree(untpd.EmptyTree) =>
val resStr = if (defTree.isInstanceOf[untpd.DefDef]) "result " else ""
@@ -94,7 +81,7 @@ trait Checking extends NoChecking {
/** Check that a non-implicit parameter making up the first parameter section of an
* implicit conversion is not a singleton type.
*/
- override def checkImplicitParamsNotSingletons(vparamss: List[List[ValDef]])(implicit ctx: Context): Unit = vparamss match {
+ 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)
@@ -105,7 +92,7 @@ trait Checking extends NoChecking {
* their lower bound conforms to their upper cound. If a type argument is
* infeasible, issue and error and continue with upper bound.
*/
- override def checkFeasible(tp: Type, pos: Position, where: => String = "")(implicit ctx: Context): Type = tp match {
+ 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) =>
@@ -116,7 +103,7 @@ trait Checking extends NoChecking {
}
/** Check that class does not define */
- override def checkNoDoubleDefs(cls: Symbol)(implicit ctx: Context): Unit = {
+ def checkNoDoubleDefs(cls: Symbol)(implicit ctx: Context): Unit = {
val seen = new mutable.HashMap[Name, List[Symbol]] {
override def default(key: Name) = Nil
}
@@ -147,4 +134,17 @@ trait Checking extends NoChecking {
def checkInstantiatable(cls: ClassSymbol, pos: Position): Unit = {
??? // to be done in later phase: check that class `cls` is legal in a new.
}
+}
+
+trait NoChecking extends Checking {
+ import tpd._
+ override def checkValue(tree: Tree, proto: Type)(implicit ctx: Context): tree.type = tree
+ override def checkBounds(args: List[tpd.Tree], poly: PolyType, pos: Position)(implicit ctx: Context): Unit = ()
+ override def checkStable(tp: Type, pos: Position)(implicit ctx: Context): Unit = ()
+ override def checkLegalPrefix(tp: Type, pos: Position)(implicit ctx: Context): Unit = ()
+ override def checkClassTypeWithStablePrefix(tp: Type, pos: Position, traitReq: Boolean)(implicit ctx: Context): Type = tp
+ override def checkImplicitTptNonEmpty(defTree: untpd.ValOrDefDef)(implicit ctx: Context): Unit = ()
+ override def checkImplicitParamsNotSingletons(vparamss: List[List[ValDef]])(implicit ctx: Context): Unit = ()
+ override def checkFeasible(tp: Type, pos: Position, where: => String = "")(implicit ctx: Context): Type = tp
+ override def checkNoDoubleDefs(cls: Symbol)(implicit ctx: Context): Unit = ()
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 0ba53f8c0..87bc643a3 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -398,7 +398,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
* 2. If (1) fails, force all type variables so that the block's type is
* fully defined and try again.
*/
- private def ensureNoLocalRefs(block: Block, pt: Type, forcedDefined: Boolean = false)(implicit ctx: Context): Tree = {
+ protected def ensureNoLocalRefs(block: Block, pt: Type, forcedDefined: Boolean = false)(implicit ctx: Context): Tree = {
val Block(stats, expr) = block
val leaks = CheckTrees.escapingRefs(block)
if (leaks.isEmpty) block
@@ -858,41 +858,46 @@ 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
+ }
+
+ 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)
+ }
+ }
+
def typedUnadapted(initTree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = {
record("typedUnadapted")
val xtree = expanded(initTree)
xtree.removeAttachment(TypedAhead) match {
case Some(ttree) => ttree
case none =>
- 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
- }
-
- def typedNamed(tree: untpd.NameTree): Tree = 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)
- }
def typedUnnamed(tree: untpd.Tree): Tree = tree match {
case tree: untpd.Apply =>
@@ -924,7 +929,6 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
case tree: untpd.ByNameTypeTree => typedByNameTypeTree(tree)
case tree: untpd.TypeBoundsTree => typedTypeBoundsTree(tree)
case tree: untpd.Alternative => typedAlternative(tree, pt)
- case tree: untpd.Import => typedImport(tree, sym)
case tree: untpd.PackageDef => typedPackageDef(tree)
case tree: untpd.Annotated => typedAnnotated(tree, pt)
case tree: untpd.TypedSplice => tree.tree
@@ -934,7 +938,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
xtree match {
- case xtree: untpd.NameTree => typedNamed(xtree withName xtree.name.encode)
+ case xtree: untpd.NameTree => typedNamed(xtree, pt)
+ case xtree: untpd.Import => typedImport(xtree, xtree.removeAttachment(SymOfTree).get)
case xtree => typedUnnamed(xtree)
}
}