aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/transform
diff options
context:
space:
mode:
authorGuillaume Martres <smarter@ubuntu.com>2016-11-04 00:48:36 +0100
committerGitHub <noreply@github.com>2016-11-04 00:48:36 +0100
commit6ba6ea542d7915a48b426fea1f75f9cb8c2db424 (patch)
treef728f6c54fe8c2e57ae136ef08d6fb20eaca534b /src/dotty/tools/dotc/transform
parent98a92c6f4ec743edb9465071dcfd43f17dbf054b (diff)
parentd694f15a028cf14ea0cf210d3113c7b1d6af54e7 (diff)
downloaddotty-6ba6ea542d7915a48b426fea1f75f9cb8c2db424.tar.gz
dotty-6ba6ea542d7915a48b426fea1f75f9cb8c2db424.tar.bz2
dotty-6ba6ea542d7915a48b426fea1f75f9cb8c2db424.zip
Merge pull request #1587 from dotty-staging/change-tasty-pos
Fix Tasty positions
Diffstat (limited to 'src/dotty/tools/dotc/transform')
-rw-r--r--src/dotty/tools/dotc/transform/FirstTransform.scala28
-rw-r--r--src/dotty/tools/dotc/transform/Pickler.scala11
-rw-r--r--src/dotty/tools/dotc/transform/PostTyper.scala116
-rw-r--r--src/dotty/tools/dotc/transform/TailRec.scala2
-rw-r--r--src/dotty/tools/dotc/transform/TreeTransform.scala5
5 files changed, 85 insertions, 77 deletions
diff --git a/src/dotty/tools/dotc/transform/FirstTransform.scala b/src/dotty/tools/dotc/transform/FirstTransform.scala
index 74dc9b9d6..597146514 100644
--- a/src/dotty/tools/dotc/transform/FirstTransform.scala
+++ b/src/dotty/tools/dotc/transform/FirstTransform.scala
@@ -28,7 +28,9 @@ import StdNames._
* - ensures there are companion objects for all classes except module classes
* - eliminates some kinds of trees: Imports, NamedArgs
* - stubs out native methods
- * - eliminate self tree in Template and self symbol in ClassInfo
+ * - eliminates self tree in Template and self symbol in ClassInfo
+ * - collapsess all type trees to trees of class TypeTree
+ * - converts idempotent expressions with constant types
*/
class FirstTransform extends MiniPhaseTransform with InfoTransformer with AnnotationTransformer { thisTransformer =>
import ast.tpd._
@@ -146,7 +148,7 @@ class FirstTransform extends MiniPhaseTransform with InfoTransformer with Annota
override def transformTemplate(impl: Template)(implicit ctx: Context, info: TransformerInfo): Tree = {
cpy.Template(impl)(self = EmptyValDef)
}
-
+
override def transformDefDef(ddef: DefDef)(implicit ctx: Context, info: TransformerInfo) = {
if (ddef.symbol.hasAnnotation(defn.NativeAnnot)) {
ddef.symbol.resetFlag(Deferred)
@@ -162,9 +164,29 @@ class FirstTransform extends MiniPhaseTransform with InfoTransformer with Annota
override def transformOther(tree: Tree)(implicit ctx: Context, info: TransformerInfo) = tree match {
case tree: Import => EmptyTree
case tree: NamedArg => transform(tree.arg)
- case tree => tree
+ case tree => if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos) else tree
}
+ override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo) =
+ if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos)
+ else constToLiteral(tree)
+
+ override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) =
+ if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos)
+ else constToLiteral(tree)
+
+ override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo) =
+ constToLiteral(tree)
+
+ override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo) =
+ constToLiteral(tree)
+
+ override def transformTyped(tree: Typed)(implicit ctx: Context, info: TransformerInfo) =
+ constToLiteral(tree)
+
+ override def transformBlock(tree: Block)(implicit ctx: Context, info: TransformerInfo) =
+ constToLiteral(tree)
+
// invariants: all modules have companion objects
// all types are TypeTrees
// all this types are explicit
diff --git a/src/dotty/tools/dotc/transform/Pickler.scala b/src/dotty/tools/dotc/transform/Pickler.scala
index 90e62b65c..fc70ac4f2 100644
--- a/src/dotty/tools/dotc/transform/Pickler.scala
+++ b/src/dotty/tools/dotc/transform/Pickler.scala
@@ -46,10 +46,10 @@ class Pickler extends Phase {
val treePkl = pickler.treePkl
treePkl.pickle(tree :: Nil)
treePkl.compactify()
- pickler.addrOfTree = treePkl.buf.addrOfTree
+ pickler.addrsOfTree = treePkl.buf.addrsOfTree
pickler.addrOfSym = treePkl.addrOfSym
if (tree.pos.exists)
- new PositionPickler(pickler, treePkl.buf.addrOfTree).picklePositions(tree :: Nil)
+ new PositionPickler(pickler, treePkl.buf.addrsOfTree).picklePositions(tree :: Nil)
def rawBytes = // not needed right now, but useful to print raw format.
pickler.assembleParts().iterator.grouped(10).toList.zipWithIndex.map {
@@ -66,7 +66,10 @@ class Pickler extends Phase {
override def runOn(units: List[CompilationUnit])(implicit ctx: Context): List[CompilationUnit] = {
val result = super.runOn(units)
if (ctx.settings.YtestPickler.value)
- testUnpickler(units)(ctx.fresh.setPeriod(Period(ctx.runId + 1, FirstPhaseId)))
+ testUnpickler(units)(
+ ctx.fresh
+ .setPeriod(Period(ctx.runId + 1, FirstPhaseId))
+ .addMode(Mode.ReadPositions))
result
}
@@ -81,7 +84,7 @@ class Pickler extends Phase {
}
pickling.println("************* entered toplevel ***********")
for ((cls, unpickler) <- unpicklers) {
- val unpickled = unpickler.body(ctx.addMode(Mode.ReadPositions))
+ val unpickled = unpickler.body
testSame(i"$unpickled%\n%", beforePickling(cls), cls)
}
}
diff --git a/src/dotty/tools/dotc/transform/PostTyper.scala b/src/dotty/tools/dotc/transform/PostTyper.scala
index 12d48d98e..7e51635e5 100644
--- a/src/dotty/tools/dotc/transform/PostTyper.scala
+++ b/src/dotty/tools/dotc/transform/PostTyper.scala
@@ -41,6 +41,9 @@ import Symbols._, TypeUtils._
*
* (10) Adds Child annotations to all sealed classes
*
+ * (11) Minimizes `call` fields of `Inline` nodes to just point to the toplevel
+ * class from which code was inlined.
+ *
* 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
@@ -73,48 +76,6 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
// TODO fill in
}
- /** Check bounds of AppliedTypeTrees and TypeApplys.
- * Replace type trees with TypeTree nodes.
- * Replace constant expressions with Literal nodes.
- * Note: Demanding idempotency instead of purity in literalize is strictly speaking too loose.
- * Example
- *
- * object O { final val x = 42; println("43") }
- * O.x
- *
- * Strictly speaking we can't replace `O.x` with `42`. But this would make
- * most expressions non-constant. Maybe we can change the spec to accept this
- * kind of eliding behavior. Or else enforce true purity in the compiler.
- * The choice will be affected by what we will do with `inline` and with
- * Singleton type bounds (see SIP 23). Presumably
- *
- * object O1 { val x: Singleton = 42; println("43") }
- * object O2 { inline val x = 42; println("43") }
- *
- * should behave differently.
- *
- * O1.x should have the same effect as { println("43"); 42 }
- *
- * whereas
- *
- * O2.x = 42
- *
- * Revisit this issue once we have implemented `inline`. Then we can demand
- * purity of the prefix unless the selection goes to an inline val.
- */
- private def normalizeTree(tree: Tree)(implicit ctx: Context): Tree = tree match {
- case _: TypeTree | _: TypeApply => tree
- case _ =>
- if (tree.isType) {
- Checking.typeChecker.traverse(tree)
- TypeTree(tree.tpe).withPos(tree.pos)
- }
- else tree.tpe.widenTermRefExpr match {
- case ConstantType(value) if isIdempotentExpr(tree) => Literal(value)
- case _ => tree
- }
- }
-
/** If the type of `tree` is a TermRefWithSignature with an underdefined
* signature, narrow the type by re-computing the signature (which should
* be fully-defined by now).
@@ -159,7 +120,11 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
case pkg: PackageClassDenotation if !tree.symbol.maybeOwner.is(Package) =>
transformSelect(cpy.Select(tree)(qual select pkg.packageObj.symbol, tree.name), targs)
case _ =>
- superAcc.transformSelect(super.transform(tree), targs)
+ val tree1 = super.transform(tree)
+ constToLiteral(tree1) match {
+ case _: Literal => tree1
+ case _ => superAcc.transformSelect(tree1, targs)
+ }
}
}
@@ -199,14 +164,19 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
}
override def transform(tree: Tree)(implicit ctx: Context): Tree =
- try normalizeTree(tree) match {
- case tree: Ident =>
+ try tree match {
+ case tree: Ident if !tree.isType =>
tree.tpe match {
case tpe: ThisType => This(tpe.cls).withPos(tree.pos)
case _ => paramFwd.adaptRef(fixSignature(tree))
}
- case tree: Select =>
- transformSelect(paramFwd.adaptRef(fixSignature(tree)), Nil)
+ case tree @ Select(qual, name) =>
+ if (name.isTypeName) {
+ Checking.checkRealizable(qual.tpe, qual.pos.focus)
+ super.transform(tree)
+ }
+ else
+ transformSelect(paramFwd.adaptRef(fixSignature(tree)), Nil)
case tree: Super =>
if (ctx.owner.enclosingMethod.isInlineMethod)
ctx.error(em"super not allowed in inline ${ctx.owner}", tree.pos)
@@ -224,6 +194,19 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
}
case tree @ Assign(sel: Select, _) =>
superAcc.transformAssign(super.transform(tree))
+ case Inlined(call, bindings, expansion) =>
+ // Leave only a call trace consisting of
+ // - a reference to the top-level class from which the call was inlined,
+ // - the call's position
+ // in the call field of an Inlined node.
+ // The trace has enough info to completely reconstruct positions.
+ // The minimization is done for two reasons:
+ // 1. To save space (calls might contain large inline arguments, which would otherwise
+ // be duplicated
+ // 2. To enable correct pickling (calls can share symbols with the inlined code, which
+ // would trigger an assertion when pickling).
+ val callTrace = Ident(call.symbol.topLevelClass.typeRef).withPos(call.pos)
+ cpy.Inlined(tree)(callTrace, transformSub(bindings), transform(expansion))
case tree: Template =>
val saved = parentNews
parentNews ++= tree.parents.flatMap(newPart)
@@ -240,26 +223,23 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
case tree: TypeDef =>
transformMemberDef(tree)
val sym = tree.symbol
- val tree1 =
- if (sym.isClass) {
- if (sym.owner.is(Package) &&
- ctx.compilationUnit.source.exists &&
- sym != defn.SourceFileAnnot)
- sym.addAnnotation(Annotation.makeSourceFile(ctx.compilationUnit.source.file.path))
+ if (sym.isClass) {
+ // Add SourceFile annotation to top-level classes
+ if (sym.owner.is(Package) &&
+ ctx.compilationUnit.source.exists &&
+ sym != defn.SourceFileAnnot)
+ sym.addAnnotation(Annotation.makeSourceFile(ctx.compilationUnit.source.file.path))
- if (!sym.isAnonymousClass) // ignore anonymous class
- for (parent <- sym.asClass.classInfo.classParents) {
- val pclazz = parent.classSymbol
- if (pclazz.is(Sealed)) pclazz.addAnnotation(Annotation.makeChild(sym))
- }
+ // Add Child annotation to sealed parents unless current class is anonymous
+ if (!sym.isAnonymousClass) // ignore anonymous class
+ for (parent <- sym.asClass.classInfo.classParents) {
+ val pclazz = parent.classSymbol
+ if (pclazz.is(Sealed)) pclazz.addAnnotation(Annotation.makeChild(sym))
+ }
- tree
- }
- else {
- Checking.typeChecker.traverse(tree.rhs)
- cpy.TypeDef(tree)(rhs = TypeTree(tree.symbol.info))
- }
- super.transform(tree1)
+ tree
+ }
+ super.transform(tree)
case tree: MemberDef =>
transformMemberDef(tree)
super.transform(tree)
@@ -268,6 +248,12 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
super.transform(tree)
case tree @ Annotated(annotated, annot) =>
cpy.Annotated(tree)(transform(annotated), transformAnnot(annot))
+ case tree: AppliedTypeTree =>
+ Checking.checkAppliedType(tree)
+ super.transform(tree)
+ case SingletonTypeTree(ref) =>
+ Checking.checkRealizable(ref.tpe, ref.pos.focus)
+ super.transform(tree)
case tree: TypeTree =>
tree.withType(
tree.tpe match {
diff --git a/src/dotty/tools/dotc/transform/TailRec.scala b/src/dotty/tools/dotc/transform/TailRec.scala
index fde4db811..dc4454439 100644
--- a/src/dotty/tools/dotc/transform/TailRec.scala
+++ b/src/dotty/tools/dotc/transform/TailRec.scala
@@ -354,7 +354,7 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete
t // todo: could improve to handle DefDef's with a label flag calls to which are in tail position
case ValDef(_, _, _) | EmptyTree | Super(_, _) | This(_) |
- Literal(_) | TypeTree(_) | TypeDef(_, _) =>
+ Literal(_) | TypeTree() | TypeDef(_, _) =>
tree
case Return(expr, from) =>
diff --git a/src/dotty/tools/dotc/transform/TreeTransform.scala b/src/dotty/tools/dotc/transform/TreeTransform.scala
index 45fa3d607..a1ccf0e63 100644
--- a/src/dotty/tools/dotc/transform/TreeTransform.scala
+++ b/src/dotty/tools/dotc/transform/TreeTransform.scala
@@ -1122,10 +1122,7 @@ object TreeTransforms {
case tree: TypeTree =>
implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForTypeTree, info.nx.nxPrepTypeTree, tree, cur)
if (mutatedInfo eq null) tree
- else {
- val original = transform(tree.original, mutatedInfo, cur)
- goTypeTree(cpy.TypeTree(tree)(original), mutatedInfo.nx.nxTransTypeTree(cur))
- }
+ else goTypeTree(tree, mutatedInfo.nx.nxTransTypeTree(cur))
case tree: Alternative =>
implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForAlternative, info.nx.nxPrepAlternative, tree, cur)
if (mutatedInfo eq null) tree