aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-04-22 14:52:34 +0200
committerMartin Odersky <odersky@gmail.com>2015-04-22 17:19:35 +0200
commit79958518b4f95b3dd8e34d543757034d181e4514 (patch)
tree1633ef8d9764fe9a1233c661288ecf5ccf1c6620 /src/dotty/tools/dotc
parent1d4e4a6d4784edfe1d2490de7ceff9d3c82d4d27 (diff)
downloaddotty-79958518b4f95b3dd8e34d543757034d181e4514.tar.gz
dotty-79958518b4f95b3dd8e34d543757034d181e4514.tar.bz2
dotty-79958518b4f95b3dd8e34d543757034d181e4514.zip
Roll some of FirstTransform functionaility into PostTyper
Everything that needs to be done before pickling moves to PostTyper. The idea is that we want to make Pickler come before FirstTransform.
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r--src/dotty/tools/dotc/transform/FirstTransform.scala44
-rw-r--r--src/dotty/tools/dotc/transform/PostTyper.scala90
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala17
3 files changed, 76 insertions, 75 deletions
diff --git a/src/dotty/tools/dotc/transform/FirstTransform.scala b/src/dotty/tools/dotc/transform/FirstTransform.scala
index da0ec68d3..aecc1b86f 100644
--- a/src/dotty/tools/dotc/transform/FirstTransform.scala
+++ b/src/dotty/tools/dotc/transform/FirstTransform.scala
@@ -24,10 +24,7 @@ import StdNames._
/** The first tree transform
* - ensures there are companion objects for all classes except module classes
- * - eliminates some kinds of trees: Imports, NamedArgs, all TypTrees other than TypeTree
- * - converts Select/Ident/SelectFromTypeTree nodes that refer to types to TypeTrees.
- * - inserts `.package` for selections of package object members
- * - checks the bounds of AppliedTypeTrees
+ * - eliminates some kinds of trees: Imports, NamedArgs
* - stubs out native methods
*/
class FirstTransform extends MiniPhaseTransform with IdentityDenotTransformer with AnnotationTransformer { thisTransformer =>
@@ -111,47 +108,10 @@ class FirstTransform extends MiniPhaseTransform with IdentityDenotTransformer wi
override def transformStats(trees: List[Tree])(implicit ctx: Context, info: TransformerInfo): List[Tree] =
ast.Trees.flatten(reorderAndComplete(trees)(ctx.withPhase(thisTransformer.next)))
- private def normalizeType(tree: Tree)(implicit ctx: Context) =
- if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos) else tree
-
- override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo) = tree.tpe match {
- case tpe: ThisType =>
- /*
- A this reference hide in a self ident, and be subsequently missed
- when deciding on whether outer accessors are needed and computing outer paths.
- We do this normalization directly after Typer, because during typer the
- ident should rest available for hyperlinking.*/
- This(tpe.cls).withPos(tree.pos)
- case _ => normalizeType(tree)
- }
-
-
-
- override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) =
- normalizeType {
- val qual = tree.qualifier
- qual.symbol.moduleClass.denot match {
- case pkg: PackageClassDenotation if !tree.symbol.maybeOwner.is(Package) =>
- cpy.Select(tree)(qual select pkg.packageObj.symbol, tree.name)
- case _ =>
- tree
- }
- }
-
- override def transformSelectFromTypeTree(tree: SelectFromTypeTree)(implicit ctx: Context, info: TransformerInfo) =
- normalizeType(tree)
-
override def transformOther(tree: Tree)(implicit ctx: Context, info: TransformerInfo) = tree match {
case tree: Import => EmptyTree
case tree: NamedArg => transform(tree.arg)
- case AppliedTypeTree(tycon, args) =>
- val tparams = tycon.tpe.typeSymbol.typeParams
- val bounds = tparams.map(tparam =>
- tparam.info.asSeenFrom(tycon.tpe.normalizedPrefix, tparam.owner.owner).bounds)
- Checking.checkBounds(args, bounds, _.substDealias(tparams, _))
- normalizeType(tree)
- case tree =>
- normalizeType(tree)
+ case tree => tree
}
// invariants: all modules have companion objects
diff --git a/src/dotty/tools/dotc/transform/PostTyper.scala b/src/dotty/tools/dotc/transform/PostTyper.scala
index 1b42a2501..c6031b31e 100644
--- a/src/dotty/tools/dotc/transform/PostTyper.scala
+++ b/src/dotty/tools/dotc/transform/PostTyper.scala
@@ -8,6 +8,7 @@ import ValueClasses._
import scala.annotation.tailrec
import core._
import typer.ErrorReporting._
+import typer.Checking
import Types._, Contexts._, Constants._, Names._, NameOps._, Flags._, DenotTransformers._
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Scopes._, Denotations._
import util.Positions._
@@ -27,6 +28,14 @@ import Symbols._, TypeUtils._
*
* (4) Check that `New` nodes can be instantiated, and that annotations are valid
*
+ * (5) Convert all trees representing types to TypeTrees.
+ *
+ * (6) Check the bounds of AppliedTypeTrees
+ *
+ * (7) Insert `.package` for selections of package object members
+ *
+ * (8) Replaces self references by name with `this`
+ *
* The reason for making this a macro transform is that some functions (in particular
* super and protected accessors and instantiation checks) are naturally top-down and
* don't lend themselves to the bottom-up approach of a mini phase. The other two functions
@@ -49,24 +58,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
val superAcc = new SuperAccessors(thisTransformer)
val paramFwd = new ParamForwarding(thisTransformer)
val synthMth = new SyntheticMethods(thisTransformer)
-
- /** Check that `tp` refers to a nonAbstract class
- * and that the instance conforms to the self type of the created class.
- */
- private def checkInstantiable(tp: Type, pos: Position)(implicit ctx: Context): Unit =
- tp.underlyingClassRef(refinementOK = false) match {
- case tref: TypeRef =>
- val cls = tref.symbol
- if (cls.is(AbstractOrTrait))
- ctx.error(d"$cls is abstract; cannot be instantiated", pos)
- if (!cls.is(Module)) {
- val selfType = tp.givenSelfType.asSeenFrom(tref.prefix, cls.owner)
- if (selfType.exists && !(tp <:< selfType))
- ctx.error(d"$tp does not conform to its self type $selfType; cannot be instantiated")
- }
- case _ =>
- }
-
+
private def newPart(tree: Tree): Option[New] = methPart(tree) match {
case Select(nu: New, _) => Some(nu)
case _ => None
@@ -76,6 +68,22 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
// TODO fill in
}
+ private def normalizeTypeTree(tree: Tree)(implicit ctx: Context) = {
+ def norm(tree: Tree) = if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos) else tree
+ tree match {
+ case tree: TypeTree =>
+ tree
+ case AppliedTypeTree(tycon, args) =>
+ val tparams = tycon.tpe.typeSymbol.typeParams
+ val bounds = tparams.map(tparam =>
+ tparam.info.asSeenFrom(tycon.tpe.normalizedPrefix, tparam.owner.owner).bounds)
+ Checking.checkBounds(args, bounds, _.substDealias(tparams, _))
+ norm(tree)
+ case _ =>
+ norm(tree)
+ }
+ }
+
class PostTyperTransformer extends Transformer {
private var inJavaAnnot: Boolean = false
@@ -96,25 +104,41 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
private def transformAnnots(tree: MemberDef)(implicit ctx: Context): Unit =
tree.symbol.transformAnnotations(transformAnnot)
+ private def transformSelect(tree: Select, targs: List[Tree])(implicit ctx: Context) = {
+ val qual = tree.qualifier
+ qual.symbol.moduleClass.denot match {
+ case pkg: PackageClassDenotation if !tree.symbol.maybeOwner.is(Package) =>
+ assert(targs.isEmpty)
+ cpy.Select(tree)(qual select pkg.packageObj.symbol, tree.name)
+ case _ =>
+ superAcc.transformSelect(super.transform(tree), targs)
+ }
+ }
+
override def transform(tree: Tree)(implicit ctx: Context): Tree =
- try tree match {
- case impl: Template =>
+ try normalizeTypeTree(tree) match {
+ case tree: Ident =>
+ tree.tpe match {
+ case tpe: ThisType => This(tpe.cls).withPos(tree.pos)
+ case _ => tree
+ }
+ case tree: Select =>
+ transformSelect(tree, Nil)
+ case tree @ TypeApply(sel: Select, args) =>
+ val args1 = transform(args)
+ val sel1 = transformSelect(sel, args1)
+ if (superAcc.isProtectedAccessor(sel1)) sel1 else cpy.TypeApply(tree)(sel1, args1)
+ case tree @ Assign(sel: Select, _) =>
+ superAcc.transformAssign(super.transform(tree))
+ case tree: Template =>
val saved = parentNews
- parentNews ++= impl.parents.flatMap(newPart)
+ parentNews ++= tree.parents.flatMap(newPart)
try
synthMth.addSyntheticMethods(
paramFwd.forwardParamAccessors(
- superAcc.wrapTemplate(impl)(
+ superAcc.wrapTemplate(tree)(
super.transform(_).asInstanceOf[Template])))
finally parentNews = saved
- case tree @ TypeApply(sel: Select, args) =>
- val args1 = transform(args)
- val sel1 = superAcc.transformSelect(super.transform(sel), args1)
- if (superAcc.isProtectedAccessor(sel1)) sel1 else cpy.TypeApply(tree)(sel1, args1)
- case sel: Select =>
- superAcc.transformSelect(super.transform(sel), Nil)
- case tree @ Assign(sel: Select, _) =>
- superAcc.transformAssign(super.transform(tree))
case tree: DefDef =>
transformAnnots(tree)
superAcc.wrapDefDef(tree)(super.transform(tree).asInstanceOf[DefDef])
@@ -122,9 +146,9 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
transformAnnots(tree)
super.transform(tree)
case tree: New if !inJavaAnnot && !parentNews.contains(tree) =>
- checkInstantiable(tree.tpe, tree.pos)
+ Checking.checkInstantiable(tree.tpe, tree.pos)
super.transform(tree)
- case Annotated(annot, annotated) =>
+ case tree @ Annotated(annot, annotated) =>
cpy.Annotated(tree)(transformAnnot(annot), transform(annotated))
case tree: TypeTree =>
tree.withType(
@@ -133,7 +157,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
case tpe => tpe
}
)
- case _ =>
+ case tree =>
super.transform(tree)
}
catch {
diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala
index b28afa6f2..148e31885 100644
--- a/src/dotty/tools/dotc/typer/Checking.scala
+++ b/src/dotty/tools/dotc/typer/Checking.scala
@@ -39,6 +39,23 @@ object Checking {
d"Type argument ${arg.tpe} does not conform to $which bound $bound ${err.whyNoMatchStr(arg.tpe, bound)}",
arg.pos)
+ /** Check that `tp` refers to a nonAbstract class
+ * and that the instance conforms to the self type of the created class.
+ */
+ def checkInstantiable(tp: Type, pos: Position)(implicit ctx: Context): Unit =
+ tp.underlyingClassRef(refinementOK = false) match {
+ case tref: TypeRef =>
+ val cls = tref.symbol
+ if (cls.is(AbstractOrTrait))
+ ctx.error(d"$cls is abstract; cannot be instantiated", pos)
+ if (!cls.is(Module)) {
+ val selfType = tp.givenSelfType.asSeenFrom(tref.prefix, cls.owner)
+ if (selfType.exists && !(tp <:< selfType))
+ ctx.error(d"$tp does not conform to its self type $selfType; cannot be instantiated")
+ }
+ case _ =>
+ }
+
/** A type map which checks that the only cycles in a type are F-bounds
* and that protects all F-bounded references by LazyRefs.
*/