From 2fffa023502cbaffe0e282495e18aefe2bff0d22 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 9 Aug 2013 17:53:20 +0200 Subject: Typing of SeqLiterals Also revised handling of SeqLiterals by replacing additional type member with split into SeqLiteral and JavaSeqLiteral. --- src/dotty/tools/dotc/ast/Desugar.scala | 1 - src/dotty/tools/dotc/ast/TreeInfo.scala | 7 ------- src/dotty/tools/dotc/ast/Trees.scala | 11 ++++++++++- src/dotty/tools/dotc/ast/TypedTrees.scala | 19 ++++++++++++++----- src/dotty/tools/dotc/ast/UntypedTrees.scala | 1 + src/dotty/tools/dotc/typer/Applications.scala | 4 ++-- src/dotty/tools/dotc/typer/Typer.scala | 6 ++++++ 7 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala index 0bd98fd2e..5c87517d2 100644 --- a/src/dotty/tools/dotc/ast/Desugar.scala +++ b/src/dotty/tools/dotc/ast/Desugar.scala @@ -557,7 +557,6 @@ object desugar { /** Traverse pattern and collect all variable names with their types in buffer. * Works for expanded as well as unexpanded patterns - * */ private object getVars extends UntypedTreeAccumulator[ListBuffer[VarInfo]] { override def apply(buf: ListBuffer[VarInfo], tree: Tree): ListBuffer[VarInfo] = { diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala index 9fcbeeea4..2c38d2c62 100644 --- a/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -239,13 +239,6 @@ trait TreeInfo[T >: Untyped] { self: Trees.Instance[T] => /** Is this case guarded? */ def isGuardedCase(cdef: CaseDef) = cdef.guard ne EmptyTree - /** Is this pattern node a sequence-valued pattern? */ - def isSequenceValued(tree: Tree): Boolean = unbind(tree) match { - case Alternative(ts) => ts exists isSequenceValued - case SeqLiteral(_) => true - case _ => false - } - /** The underlying pattern ignoring any bindings */ def unbind(x: Tree): Tree = x match { case Bind(_, y) => unbind(y) diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala index 5ae87d9ad..f31f7373c 100644 --- a/src/dotty/tools/dotc/ast/Trees.scala +++ b/src/dotty/tools/dotc/ast/Trees.scala @@ -501,12 +501,17 @@ object Trees { type ThisTree[-T >: Untyped] = Throw[T] } - /** Array[elemtpt](elems) */ + /** Seq(elems) */ case class SeqLiteral[-T >: Untyped] private[ast] (elems: List[Tree[T]]) extends Tree[T] { type ThisTree[-T >: Untyped] = SeqLiteral[T] } + /** Array(elems) */ + class JavaSeqLiteral[T >: Untyped] private[ast] (elems: List[Tree[T]]) + extends SeqLiteral(elems) { + } + /** A type tree that represents an existing or inferred type */ case class TypeTree[-T >: Untyped] private[ast] (original: Tree[T]) extends DenotingTree[T] with TypTree[T] { @@ -725,6 +730,7 @@ object Trees { type Try = Trees.Try[T] type Throw = Trees.Throw[T] type SeqLiteral = Trees.SeqLiteral[T] + type JavaSeqLiteral = Trees.JavaSeqLiteral[T] type TypeTree = Trees.TypeTree[T] type SingletonTypeTree = Trees.SingletonTypeTree[T] type SelectFromTypeTree = Trees.SelectFromTypeTree[T] @@ -910,6 +916,9 @@ object Trees { case _ => finalize(tree, untpd.Throw(expr)) } def SeqLiteral(tree: Tree, elems: List[Tree]): SeqLiteral = tree match { + case tree: JavaSeqLiteral => + if (elems eq tree.elems) tree + else finalize(tree, new JavaSeqLiteral(elems)) case tree: SeqLiteral if (elems eq tree.elems) => tree case _ => finalize(tree, untpd.SeqLiteral(elems)) } diff --git a/src/dotty/tools/dotc/ast/TypedTrees.scala b/src/dotty/tools/dotc/ast/TypedTrees.scala index 4f0f80255..3530accfc 100644 --- a/src/dotty/tools/dotc/ast/TypedTrees.scala +++ b/src/dotty/tools/dotc/ast/TypedTrees.scala @@ -147,12 +147,21 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { untpd.Throw(expr).withType(defn.NothingType).checked def SeqLiteral(elems: List[Tree])(implicit ctx: Context): SeqLiteral = - SeqLiteral(defn.SeqClass.typeConstructor.appliedTo( - ctx.lub(elems map (_.tpe)) :: Nil), elems) + untpd.SeqLiteral(elems) + .withType(defn.SeqClass.typeConstructor.appliedTo(ctx.lub(elems.tpes))) + .checked + + def SeqLiteral(tpe: Type, elems: List[Tree])(implicit ctx: Context): SeqLiteral = { + val untpdSeqLit = + if (tpe derivesFrom defn.SeqClass) untpd.SeqLiteral(elems) + else untpd.JavaSeqLiteral(elems) + untpdSeqLit.withType(tpe.elemType).checked + } - // TODO: Split into Java/Scala eq literals - def SeqLiteral(tpe: Type, elems: List[Tree])(implicit ctx: Context): SeqLiteral = - untpd.SeqLiteral(elems).withType(tpe).checked + def JavaSeqLiteral(elems: List[Tree])(implicit ctx: Context): SeqLiteral = + new untpd.JavaSeqLiteral(elems) + .withType(defn.ArrayClass.typeConstructor.appliedTo(ctx.lub(elems.tpes))) + .checked def TypeTree(original: Tree)(implicit ctx: Context): TypeTree = TypeTree(original.tpe, original) diff --git a/src/dotty/tools/dotc/ast/UntypedTrees.scala b/src/dotty/tools/dotc/ast/UntypedTrees.scala index 964d3a5a4..b3b05dc8b 100644 --- a/src/dotty/tools/dotc/ast/UntypedTrees.scala +++ b/src/dotty/tools/dotc/ast/UntypedTrees.scala @@ -70,6 +70,7 @@ object untpd extends Trees.Instance[Untyped] with TreeInfo[Untyped] { def Try(expr: Tree, handler: Tree, finalizer: Tree): Try = new Try(expr, handler, finalizer) def Throw(expr: Tree): Throw = new Throw(expr) def SeqLiteral(elems: List[Tree]): SeqLiteral = new SeqLiteral(elems) + def JavaSeqLiteral(elems: List[Tree]): JavaSeqLiteral = new JavaSeqLiteral(elems) def TypeTree(original: Tree): TypeTree = new TypeTree(original) def TypeTree() = new TypeTree(EmptyTree) def SingletonTypeTree(ref: Tree): SingletonTypeTree = new SingletonTypeTree(ref) diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala index 78817a261..7a6094078 100644 --- a/src/dotty/tools/dotc/typer/Applications.scala +++ b/src/dotty/tools/dotc/typer/Applications.scala @@ -410,8 +410,8 @@ trait Applications extends Compatibility { self: Typer => def makeVarArg(n: Int, elemFormal: Type): Unit = { val args = typedArgBuf.takeRight(n).toList typedArgBuf.trimEnd(n) - val seqType = if (methodType.isJava) defn.ArrayType else defn.SeqType - typedArgBuf += SeqLiteral(seqType.appliedTo(elemFormal :: Nil), args) + val seqLit = if (methodType.isJava) JavaSeqLiteral(args) else SeqLiteral(args) + typedArgBuf += seqLit } def fail(msg: => String, arg: Trees.Tree[T]) = { diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 5712dddcb..7995da312 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -533,6 +533,12 @@ class Typer extends Namer with Applications with Implicits { cpy.Throw(tree, expr1) withType defn.NothingType } + def typedSeqLiteral(tree: untpd.SeqLiteral, pt: Type)(implicit ctx: Context): SeqLiteral = { + val proto1 = pt.elemType orElse WildcardType + val elems1 = tree.elems map (typed(_, proto1)) + cpy.SeqLiteral(tree, elems1) withType ctx.lub(elems1.tpes) + } + def typedBind(tree: untpd.Bind, pt: Type)(implicit ctx: Context): Bind = { val body1 = typed(tree.body, pt) val sym = ctx.newSymbol(ctx.owner, tree.name.asTermName, EmptyFlags, pt, coord = tree.pos) -- cgit v1.2.3