diff options
author | Martin Odersky <odersky@gmail.com> | 2015-04-22 14:52:34 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2015-04-22 17:19:35 +0200 |
commit | 79958518b4f95b3dd8e34d543757034d181e4514 (patch) | |
tree | 1633ef8d9764fe9a1233c661288ecf5ccf1c6620 | |
parent | 1d4e4a6d4784edfe1d2490de7ceff9d3c82d4d27 (diff) | |
download | dotty-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.
-rw-r--r-- | src/dotty/tools/dotc/transform/FirstTransform.scala | 44 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/PostTyper.scala | 90 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Checking.scala | 17 |
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. */ |