aboutsummaryrefslogtreecommitdiff
path: root/src/dotty
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-10-21 13:58:00 +0200
committerMartin Odersky <odersky@gmail.com>2016-10-31 14:44:59 +0100
commit59e83ce49fbb81f402be7d663f8f38bed0f556df (patch)
tree1fd3adae16570b5a42747b792f3dd651d5e2fddc /src/dotty
parent08658cb20fee008217966830c51a0ff56ee1ae72 (diff)
downloaddotty-59e83ce49fbb81f402be7d663f8f38bed0f556df.tar.gz
dotty-59e83ce49fbb81f402be7d663f8f38bed0f556df.tar.bz2
dotty-59e83ce49fbb81f402be7d663f8f38bed0f556df.zip
Don't convert to TypeTrees before pickling
If we want to pickle types with positions we should not converyt to TypeTrees before pickling. Instead, type trees are now converted to TypeTrees in FirstTransform.
Diffstat (limited to 'src/dotty')
-rw-r--r--src/dotty/tools/dotc/core/tasty/PositionPickler.scala1
-rw-r--r--src/dotty/tools/dotc/core/tasty/TreePickler.scala6
-rw-r--r--src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala11
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala5
-rw-r--r--src/dotty/tools/dotc/transform/FirstTransform.scala10
-rw-r--r--src/dotty/tools/dotc/transform/PostTyper.scala47
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala12
7 files changed, 56 insertions, 36 deletions
diff --git a/src/dotty/tools/dotc/core/tasty/PositionPickler.scala b/src/dotty/tools/dotc/core/tasty/PositionPickler.scala
index 24a6c998e..6eb798721 100644
--- a/src/dotty/tools/dotc/core/tasty/PositionPickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/PositionPickler.scala
@@ -61,6 +61,7 @@ class PositionPickler(pickler: TastyPickler, addrsOfTree: tpd.Tree => List[Addr]
def alwaysNeedsPos(x: Positioned) = x match {
case _: WithLazyField[_] // initialPos is inaccurate for trees with lazy field
| _: Trees.PackageDef[_] => true // package defs might be split into several Tasty files
+ case x: Trees.Tree[_] => x.isType // types are unpickled as TypeTrees, so child positions are not available
case _ => false
}
diff --git a/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/src/dotty/tools/dotc/core/tasty/TreePickler.scala
index 7f1895cc3..a1ac69e0d 100644
--- a/src/dotty/tools/dotc/core/tasty/TreePickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/TreePickler.scala
@@ -319,8 +319,8 @@ class TreePickler(pickler: TastyPickler) {
pickleName(sym)
pickleParams
tpt match {
- case tpt: TypeTree => pickleTpt(tpt)
case templ: Template => pickleTree(tpt)
+ case _ if tpt.isType => pickleTpt(tpt)
}
pickleTreeUnlessEmpty(rhs)
pickleModifiers(sym)
@@ -349,6 +349,8 @@ class TreePickler(pickler: TastyPickler) {
def pickleTree(tree: Tree)(implicit ctx: Context): Unit = try {
registerTreeAddr(tree)
tree match {
+ case tree if tree.isType =>
+ pickleTpt(tree)
case Ident(name) =>
tree.tpe match {
case tp: TermRef => pickleType(tp)
@@ -442,8 +444,6 @@ class TreePickler(pickler: TastyPickler) {
writeByte(INLINED)
bindings.foreach(preRegister)
withLength { pickleTree(call); pickleTree(expansion); bindings.foreach(pickleTree) }
- case TypeTree() =>
- pickleTpt(tree)
case Bind(name, body) =>
registerDef(tree.symbol)
writeByte(BIND)
diff --git a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
index 35613c08d..c2779ba88 100644
--- a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
@@ -383,12 +383,6 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
def readTypeRef(): Type =
typeAtAddr(readAddr())
- def readPath()(implicit ctx: Context): Type = {
- val tp = readType()
- assert(tp.isInstanceOf[SingletonType])
- tp
- }
-
def readTermRef()(implicit ctx: Context): TermRef =
readType().asInstanceOf[TermRef]
@@ -760,7 +754,6 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
val parentRefs = ctx.normalizeToClassRefs(parents.map(_.tpe), cls, cls.unforcedDecls)
val self =
if (nextByte == SELFDEF) {
- val selfStart = currentAddr
readByte()
untpd.ValDef(readName(), readTpt(), EmptyTree).withType(NoType)
}
@@ -869,7 +862,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
def readPathTerm(): Tree = {
goto(start)
- readPath() match {
+ readType() match {
case path: TermRef => ref(path)
case path: ThisType => This(path.cls)
case path: ConstantType => Literal(path.value)
@@ -948,7 +941,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
case BLOCK =>
readBlock(Block)
case INLINED =>
- val call = readTerm()
+ val call = setPos(currentAddr, TypeTree(readType()))
readBlock((defs, expr) => Inlined(call, defs.asInstanceOf[List[MemberDef]], expr))
case IF =>
If(readTerm(), readTerm(), readTerm())
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index 83b3da0b7..7aaf2e190 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -525,11 +525,14 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
if (tree.isType) txt = toText(tp)
else if (!tree.isDef) txt = ("<" ~ txt ~ ":" ~ toText(tp) ~ ">").close
}
+ else if (homogenizedView && tree.isType)
+ txt = toText(tree.typeOpt)
if (ctx.settings.Yprintpos.value && !tree.isInstanceOf[WithoutTypeOrPos[_]]) {
val pos =
if (homogenizedView && !tree.isInstanceOf[MemberDef]) tree.pos.toSynthetic
else tree.pos
- txt = (txt ~ "@" ~ pos.toString /*~ tree.getClass.toString*/).close
+ val clsStr = "" // DEBUG: if (tree.isType) tree.getClass.toString else ""
+ txt = (txt ~ "@" ~ pos.toString ~ clsStr).close
}
tree match {
case Block(_, _) | Template(_, _, _, _) => txt
diff --git a/src/dotty/tools/dotc/transform/FirstTransform.scala b/src/dotty/tools/dotc/transform/FirstTransform.scala
index 74dc9b9d6..adadf3e76 100644
--- a/src/dotty/tools/dotc/transform/FirstTransform.scala
+++ b/src/dotty/tools/dotc/transform/FirstTransform.scala
@@ -146,7 +146,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 +162,15 @@ 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 tree
+
+ override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) =
+ if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos) else tree
+
// invariants: all modules have companion objects
// all types are TypeTrees
// all this types are explicit
diff --git a/src/dotty/tools/dotc/transform/PostTyper.scala b/src/dotty/tools/dotc/transform/PostTyper.scala
index e4447509b..650bc4968 100644
--- a/src/dotty/tools/dotc/transform/PostTyper.scala
+++ b/src/dotty/tools/dotc/transform/PostTyper.scala
@@ -76,8 +76,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
// TODO fill in
}
- /** Check bounds of AppliedTypeTrees and TypeApplys.
- * Replace type trees with TypeTree nodes.
+ /** Check bounds of AppliedTypeTrees.
* Replace constant expressions with Literal nodes.
* Note: Demanding idempotency instead of purity in literalize is strictly speaking too loose.
* Example
@@ -105,18 +104,15 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
* 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
- }
- }
+ private def normalizeTree(tree: Tree)(implicit ctx: Context): Tree =
+ if (tree.isType) {
+ Checking.typeCheck(tree)
+ tree
+ }
+ 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
@@ -203,12 +199,12 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
override def transform(tree: Tree)(implicit ctx: Context): Tree =
try normalizeTree(tree) match {
- case tree: Ident =>
+ 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 =>
+ case tree: Select if !tree.isType =>
transformSelect(paramFwd.adaptRef(fixSignature(tree)), Nil)
case tree: Super =>
if (ctx.owner.enclosingMethod.isInlineMethod)
@@ -284,6 +280,25 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
super.transform(tree)
case tree @ Annotated(annotated, annot) =>
cpy.Annotated(tree)(transform(annotated), transformAnnot(annot))
+ case AppliedTypeTree(tycon, args) =>
+ // If `args` is a list of named arguments, return corresponding type parameters,
+ // otherwise return type parameters unchanged
+ val tparams = tycon.tpe.typeParams
+ def argNamed(tparam: TypeParamInfo) = args.find {
+ case NamedArg(name, _) => name == tparam.paramName
+ case _ => false
+ }.getOrElse(TypeTree(tparam.paramRef))
+ val orderedArgs = if (hasNamedArg(args)) tparams.map(argNamed) else args
+ val bounds = tparams.map(_.paramBoundsAsSeenFrom(tycon.tpe))
+ def instantiate(bound: Type, args: List[Type]) =
+ bound.LambdaAbstract(tparams).appliedTo(args)
+ Checking.checkBounds(orderedArgs, bounds, instantiate)
+
+ def checkValidIfHKApply(implicit ctx: Context): Unit =
+ Checking.checkWildcardHKApply(tycon.tpe.appliedTo(args.map(_.tpe)), tree.pos)
+ checkValidIfHKApply(ctx.addMode(Mode.AllowLambdaWildcardApply))
+ super.transform(tree)
+
case tree: TypeTree =>
tree.withType(
tree.tpe match {
diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala
index 7899174f5..b6c9e0047 100644
--- a/src/dotty/tools/dotc/typer/Checking.scala
+++ b/src/dotty/tools/dotc/typer/Checking.scala
@@ -79,7 +79,12 @@ object Checking {
*/
val typeChecker = new TreeTraverser {
def traverse(tree: Tree)(implicit ctx: Context) = {
- tree match {
+ typeCheck(tree)
+ traverseChildren(tree)
+ }
+ }
+
+ def typeCheck(tree: Tree)(implicit ctx: Context) = tree match {
case AppliedTypeTree(tycon, args) =>
// If `args` is a list of named arguments, return corresponding type parameters,
// otherwise return type parameters unchanged
@@ -103,10 +108,7 @@ object Checking {
checkRealizable(ref.tpe, ref.pos.focus)
case _ =>
}
- traverseChildren(tree)
- }
- }
-
+
/** Check that `tp` refers to a nonAbstract class
* and that the instance conforms to the self type of the created class.
*/