diff options
author | Martin Odersky <odersky@gmail.com> | 2016-10-21 13:58:00 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-10-31 14:44:59 +0100 |
commit | 59e83ce49fbb81f402be7d663f8f38bed0f556df (patch) | |
tree | 1fd3adae16570b5a42747b792f3dd651d5e2fddc /src/dotty | |
parent | 08658cb20fee008217966830c51a0ff56ee1ae72 (diff) | |
download | dotty-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.scala | 1 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/tasty/TreePickler.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 11 | ||||
-rw-r--r-- | src/dotty/tools/dotc/printing/RefinedPrinter.scala | 5 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/FirstTransform.scala | 10 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/PostTyper.scala | 47 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Checking.scala | 12 |
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. */ |