Skip to content

Commit 6563917

Browse files
committed
Add second field to SeqLiteral
The field keeps track of the element type. This is necessary because JavaSeqLiteral is nonvariant and the elements might be empty, so we cannot always compute the type from the element types.
1 parent 9a624b9 commit 6563917

17 files changed

+76
-57
lines changed

src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,7 @@ object desugar {
10001000
collect(expr)
10011001
case NamedArg(_, arg) =>
10021002
collect(arg)
1003-
case SeqLiteral(elems) =>
1003+
case SeqLiteral(elems, _) =>
10041004
elems foreach collect
10051005
case Alternative(trees) =>
10061006
for (tree <- trees; (vble, _) <- getVariables(tree))

src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -515,16 +515,18 @@ object Trees {
515515
type ThisTree[-T >: Untyped] = Try[T]
516516
}
517517

518-
/** Seq(elems) */
519-
case class SeqLiteral[-T >: Untyped] private[ast] (elems: List[Tree[T]])
518+
/** Seq(elems)
519+
* @param tpt The element type of the sequence.
520+
*/
521+
case class SeqLiteral[-T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T])
520522
extends Tree[T] {
521523
type ThisTree[-T >: Untyped] = SeqLiteral[T]
522524
}
523525

524526
/** Array(elems) */
525-
class JavaSeqLiteral[T >: Untyped] private[ast] (elems: List[Tree[T]])
526-
extends SeqLiteral(elems) {
527-
override def toString = s"JavaSeqLiteral($elems)"
527+
class JavaSeqLiteral[T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T])
528+
extends SeqLiteral(elems, elemtpt) {
529+
override def toString = s"JavaSeqLiteral($elems, $elemtpt)"
528530
}
529531

530532
/** A type tree that represents an existing or inferred type */
@@ -974,12 +976,12 @@ object Trees {
974976
case tree: Try if (expr eq tree.expr) && (cases eq tree.cases) && (finalizer eq tree.finalizer) => tree
975977
case _ => finalize(tree, untpd.Try(expr, cases, finalizer))
976978
}
977-
def SeqLiteral(tree: Tree)(elems: List[Tree])(implicit ctx: Context): SeqLiteral = tree match {
979+
def SeqLiteral(tree: Tree)(elems: List[Tree], elemtpt: Tree)(implicit ctx: Context): SeqLiteral = tree match {
978980
case tree: JavaSeqLiteral =>
979-
if (elems eq tree.elems) tree
980-
else finalize(tree, new JavaSeqLiteral(elems))
981-
case tree: SeqLiteral if elems eq tree.elems => tree
982-
case _ => finalize(tree, untpd.SeqLiteral(elems))
981+
if ((elems eq tree.elems) && (elemtpt eq tree.elemtpt)) tree
982+
else finalize(tree, new JavaSeqLiteral(elems, elemtpt))
983+
case tree: SeqLiteral if (elems eq tree.elems) && (elemtpt eq tree.elemtpt) => tree
984+
case _ => finalize(tree, untpd.SeqLiteral(elems, elemtpt))
983985
}
984986
def TypeTree(tree: Tree)(original: Tree): TypeTree = tree match {
985987
case tree: TypeTree if original eq tree.original => tree
@@ -1125,8 +1127,8 @@ object Trees {
11251127
cpy.Return(tree)(transform(expr), transformSub(from))
11261128
case Try(block, cases, finalizer) =>
11271129
cpy.Try(tree)(transform(block), transformSub(cases), transform(finalizer))
1128-
case SeqLiteral(elems) =>
1129-
cpy.SeqLiteral(tree)(transform(elems))
1130+
case SeqLiteral(elems, elemtpt) =>
1131+
cpy.SeqLiteral(tree)(transform(elems), transform(elemtpt))
11301132
case TypeTree(original) =>
11311133
tree
11321134
case SingletonTypeTree(ref) =>
@@ -1229,8 +1231,8 @@ object Trees {
12291231
this(this(x, expr), from)
12301232
case Try(block, handler, finalizer) =>
12311233
this(this(this(x, block), handler), finalizer)
1232-
case SeqLiteral(elems) =>
1233-
this(x, elems)
1234+
case SeqLiteral(elems, elemtpt) =>
1235+
this(this(x, elems), elemtpt)
12341236
case TypeTree(original) =>
12351237
x
12361238
case SingletonTypeTree(ref) =>

src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -123,14 +123,11 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
123123
def Try(block: Tree, cases: List[CaseDef], finalizer: Tree)(implicit ctx: Context): Try =
124124
ta.assignType(untpd.Try(block, cases, finalizer), block, cases)
125125

126-
def SeqLiteral(elems: List[Tree])(implicit ctx: Context): SeqLiteral =
127-
ta.assignType(untpd.SeqLiteral(elems), elems)
126+
def SeqLiteral(elems: List[Tree], elemtpt: Tree)(implicit ctx: Context): SeqLiteral =
127+
ta.assignType(untpd.SeqLiteral(elems, elemtpt), elems, elemtpt)
128128

129-
def SeqLiteral(tpe: Type, elems: List[Tree])(implicit ctx: Context): SeqLiteral =
130-
if (tpe derivesFrom defn.SeqClass) SeqLiteral(elems) else JavaSeqLiteral(elems)
131-
132-
def JavaSeqLiteral(elems: List[Tree])(implicit ctx: Context): SeqLiteral =
133-
ta.assignType(new untpd.JavaSeqLiteral(elems), elems)
129+
def JavaSeqLiteral(elems: List[Tree], elemtpt: Tree)(implicit ctx: Context): SeqLiteral =
130+
ta.assignType(new untpd.JavaSeqLiteral(elems, elemtpt), elems, elemtpt)
134131

135132
def TypeTree(original: Tree)(implicit ctx: Context): TypeTree =
136133
TypeTree(original.tpe, original)
@@ -564,11 +561,14 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
564561
}
565562
}
566563

567-
override def SeqLiteral(tree: Tree)(elems: List[Tree])(implicit ctx: Context): SeqLiteral = {
568-
val tree1 = untpd.cpy.SeqLiteral(tree)(elems)
564+
override def SeqLiteral(tree: Tree)(elems: List[Tree], elemtpt: Tree)(implicit ctx: Context): SeqLiteral = {
565+
val tree1 = untpd.cpy.SeqLiteral(tree)(elems, elemtpt)
569566
tree match {
570-
case tree: SeqLiteral if sameTypes(elems, tree.elems) => tree1.withTypeUnchecked(tree.tpe)
571-
case _ => ta.assignType(tree1, elems)
567+
case tree: SeqLiteral
568+
if sameTypes(elems, tree.elems) && (elemtpt.tpe eq tree.elemtpt.tpe) =>
569+
tree1.withTypeUnchecked(tree.tpe)
570+
case _ =>
571+
ta.assignType(tree1, elems, elemtpt)
572572
}
573573
}
574574

src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
127127
def CaseDef(pat: Tree, guard: Tree, body: Tree): CaseDef = new CaseDef(pat, guard, body)
128128
def Return(expr: Tree, from: Tree): Return = new Return(expr, from)
129129
def Try(expr: Tree, cases: List[CaseDef], finalizer: Tree): Try = new Try(expr, cases, finalizer)
130-
def SeqLiteral(elems: List[Tree]): SeqLiteral = new SeqLiteral(elems)
131-
def JavaSeqLiteral(elems: List[Tree]): JavaSeqLiteral = new JavaSeqLiteral(elems)
130+
def SeqLiteral(elems: List[Tree], elemtpt: Tree): SeqLiteral = new SeqLiteral(elems, elemtpt)
131+
def JavaSeqLiteral(elems: List[Tree], elemtpt: Tree): JavaSeqLiteral = new JavaSeqLiteral(elems, elemtpt)
132132
def TypeTree(original: Tree): TypeTree = new TypeTree(original)
133133
def TypeTree() = new TypeTree(EmptyTree)
134134
def SingletonTypeTree(ref: Tree): SingletonTypeTree = new SingletonTypeTree(ref)

src/dotty/tools/dotc/core/classfile/ClassfileParser.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,14 @@ class ClassfileParser(
438438
case None => hasError = true
439439
}
440440
if (hasError) None
441-
else if (skip) None else Some(JavaSeqLiteral(arr.toList))
441+
else if (skip) None
442+
else {
443+
val elems = arr.toList
444+
val elemType =
445+
if (elems.isEmpty) defn.ObjectType
446+
else ctx.typeComparer.lub(elems.tpes).widen
447+
Some(JavaSeqLiteral(elems, TypeTree(elemType)))
448+
}
442449
case ANNOTATION_TAG =>
443450
parseAnnotation(index, skip) map (_.tree)
444451
}

src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,9 +407,9 @@ class TreePickler(pickler: TastyPickler) {
407407
case Try(block, cases, finalizer) =>
408408
writeByte(TRY)
409409
withLength { pickleTree(block); cases.foreach(pickleTree); pickleTreeUnlessEmpty(finalizer) }
410-
case SeqLiteral(elems) =>
410+
case SeqLiteral(elems, elemtpt) =>
411411
writeByte(REPEATED)
412-
withLength { elems.foreach(pickleTree) }
412+
withLength { pickleTree(elemtpt); elems.foreach(pickleTree) }
413413
case TypeTree(original) =>
414414
pickleTpt(tree)
415415
case Bind(name, body) =>

src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
801801
val fn = readTerm()
802802
val isJava = fn.tpe.isInstanceOf[JavaMethodType]
803803
def readArg() = readTerm() match {
804-
case SeqLiteral(elems) if isJava => JavaSeqLiteral(elems)
804+
case SeqLiteral(elems, elemtpt) if isJava => JavaSeqLiteral(elems, elemtpt)
805805
case arg => arg
806806
}
807807
tpd.Apply(fn, until(end)(readArg()))
@@ -837,7 +837,8 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
837837
case TRY =>
838838
Try(readTerm(), readCases(end), ifBefore(end)(readTerm(), EmptyTree))
839839
case REPEATED =>
840-
SeqLiteral(until(end)(readTerm()))
840+
val elemtpt = readTpt()
841+
SeqLiteral(until(end)(readTerm()), elemtpt)
841842
case BIND =>
842843
val name = readName()
843844
val info = readType()

src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -850,8 +850,8 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
850850
val end = readNat() + readIndex
851851
// array elements are trees representing instances of scala.annotation.Annotation
852852
SeqLiteral(
853-
defn.SeqType.appliedTo(defn.AnnotationType :: Nil),
854-
until(end, () => readClassfileAnnotArg(readNat())))
853+
until(end, () => readClassfileAnnotArg(readNat())),
854+
TypeTree(defn.AnnotationType))
855855
}
856856

857857
private def readAnnotInfoArg()(implicit ctx: Context): Tree = {
@@ -1063,7 +1063,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
10631063
case ARRAYVALUEtree =>
10641064
val elemtpt = readTreeRef()
10651065
val trees = until(end, readTreeRef)
1066-
SeqLiteral(defn.SeqType.appliedTo(elemtpt.tpe :: Nil), trees)
1066+
SeqLiteral(trees, elemtpt)
10671067
// note can't deal with trees passed to Java methods as arrays here
10681068

10691069
case FUNCTIONtree =>

src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,8 +380,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
380380
changePrec(GlobalPrec) {
381381
"throw " ~ toText(expr)
382382
}
383-
case SeqLiteral(elems) =>
384-
"[" ~ toTextGlobal(elems, ",") ~ "]"
383+
case SeqLiteral(elems, elemtpt) =>
384+
"[" ~ toTextGlobal(elems, ",") ~ " : " ~ toText(elemtpt) ~ "]"
385385
case tpt: untpd.DerivedTypeTree =>
386386
"<derived typetree watching " ~ summarized(toText(tpt.watched)) ~ ">"
387387
case TypeTree(orig) =>

src/dotty/tools/dotc/transform/ElimRepeated.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati
7171

7272
/** Convert sequence argument to Java array */
7373
private def seqToArray(tree: Tree)(implicit ctx: Context): Tree = tree match {
74-
case SeqLiteral(elems) =>
75-
JavaSeqLiteral(elems)
74+
case SeqLiteral(elems, elemtpt) =>
75+
JavaSeqLiteral(elems, elemtpt)
7676
case _ =>
7777
val elemType = tree.tpe.firstBaseArgInfo(defn.SeqClass)
7878
var elemClass = elemType.classSymbol

src/dotty/tools/dotc/transform/SeqLiterals.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ class SeqLiterals extends MiniPhaseTransform {
3232
override def transformSeqLiteral(tree: SeqLiteral)(implicit ctx: Context, info: TransformerInfo): Tree = tree match {
3333
case tree: JavaSeqLiteral => tree
3434
case _ =>
35-
val arr = JavaSeqLiteral(tree.elems)
35+
val arr = JavaSeqLiteral(tree.elems, tree.elemtpt)
3636
//println(i"trans seq $tree, arr = $arr: ${arr.tpe} ${arr.tpe.elemType}")
37-
val elemtp = arr.tpe.elemType.bounds.hi
37+
val elemtp = tree.elemtpt.tpe
3838
val elemCls = elemtp.classSymbol
3939
val (wrapMethStr, targs) =
4040
if (elemCls.isPrimitiveValueClass) (s"wrap${elemCls.name}Array", Nil)

src/dotty/tools/dotc/transform/TreeTransform.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1148,7 +1148,8 @@ object TreeTransforms {
11481148
if (mutatedInfo eq null) tree
11491149
else {
11501150
val elems = transformTrees(tree.elems, mutatedInfo, cur)
1151-
goSeqLiteral(cpy.SeqLiteral(tree)(elems), mutatedInfo.nx.nxTransSeqLiteral(cur))
1151+
val elemtpt = transform(tree.elemtpt, mutatedInfo, cur)
1152+
goSeqLiteral(cpy.SeqLiteral(tree)(elems, elemtpt), mutatedInfo.nx.nxTransSeqLiteral(cur))
11521153
}
11531154
case tree: TypeTree =>
11541155
implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForTypeTree, info.nx.nxPrepTypeTree, tree, cur)

src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,10 @@ trait Applications extends Compatibility { self: Typer =>
442442
def makeVarArg(n: Int, elemFormal: Type): Unit = {
443443
val args = typedArgBuf.takeRight(n).toList
444444
typedArgBuf.trimEnd(n)
445-
val seqLit = if (methodType.isJava) JavaSeqLiteral(args) else SeqLiteral(args)
445+
val elemtpt = TypeTree(elemFormal)
446+
val seqLit =
447+
if (methodType.isJava) JavaSeqLiteral(args, elemtpt)
448+
else SeqLiteral(args, elemtpt)
446449
typedArgBuf += seqToRepeated(seqLit)
447450
}
448451

@@ -771,7 +774,7 @@ trait Applications extends Compatibility { self: Typer =>
771774
for (argType <- argTypes) assert(!argType.isInstanceOf[TypeBounds], unapplyApp.tpe.show)
772775
val bunchedArgs = argTypes match {
773776
case argType :: Nil =>
774-
if (argType.isRepeatedParam) untpd.SeqLiteral(args) :: Nil
777+
if (argType.isRepeatedParam) untpd.SeqLiteral(args, untpd.TypeTree()) :: Nil
775778
else if (args.lengthCompare(1) > 0 && ctx.canAutoTuple) untpd.Tuple(args) :: Nil
776779
else args
777780
case _ => args

src/dotty/tools/dotc/typer/ReTyper.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ class ReTyper extends Typer {
9292
try super.typedUnadapted(tree, pt)
9393
catch {
9494
case NonFatal(ex) =>
95-
Printers.transforms.println(i"exception while typing $tree of class ${tree.getClass} # ${tree.uniqueId}")
95+
println(i"exception while typing $tree of class ${tree.getClass} # ${tree.uniqueId}")
9696
throw ex
9797
}
9898

src/dotty/tools/dotc/typer/TypeAssigner.scala

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -392,14 +392,12 @@ trait TypeAssigner {
392392
if (cases.isEmpty) tree.withType(expr.tpe)
393393
else tree.withType(ctx.typeComparer.lub(expr.tpe :: cases.tpes))
394394

395-
def assignType(tree: untpd.SeqLiteral, elems: List[Tree])(implicit ctx: Context) = tree match {
396-
case tree: JavaSeqLiteral =>
397-
tree.withType(defn.ArrayOf(ctx.typeComparer.lub(elems.tpes).widen))
398-
case _ =>
399-
val ownType =
400-
if (ctx.erasedTypes) defn.SeqType
401-
else defn.SeqType.appliedTo(ctx.typeComparer.lub(elems.tpes).widen)
402-
tree.withType(ownType)
395+
def assignType(tree: untpd.SeqLiteral, elems: List[Tree], elemtpt: Tree)(implicit ctx: Context) = {
396+
val ownType = tree match {
397+
case tree: JavaSeqLiteral => defn.ArrayOf(elemtpt.tpe)
398+
case _ => if (ctx.erasedTypes) defn.SeqType else defn.SeqType.appliedTo(elemtpt.tpe)
399+
}
400+
tree.withType(ownType)
403401
}
404402

405403
def assignType(tree: untpd.SingletonTypeTree, ref: Tree)(implicit ctx: Context) =

src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,14 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
836836
def typedSeqLiteral(tree: untpd.SeqLiteral, pt: Type)(implicit ctx: Context): SeqLiteral = track("typedSeqLiteral") {
837837
val proto1 = pt.elemType orElse WildcardType
838838
val elems1 = tree.elems mapconserve (typed(_, proto1))
839-
assignType(cpy.SeqLiteral(tree)(elems1), elems1)
839+
val proto2 = // the computed type of the `elemtpt` field
840+
if (!tree.elemtpt.isEmpty) WildcardType
841+
else if (isFullyDefined(proto1, ForceDegree.none)) proto1
842+
else if (tree.elems.isEmpty && tree.isInstanceOf[Trees.JavaSeqLiteral[_]])
843+
defn.ObjectType // generic empty Java varargs are of type Object[]
844+
else ctx.typeComparer.lub(elems1.tpes)
845+
val elemtpt1 = typed(tree.elemtpt, proto2)
846+
assignType(cpy.SeqLiteral(tree)(elems1, elemtpt1), elems1, elemtpt1)
840847
}
841848

842849
def typedTypeTree(tree: untpd.TypeTree, pt: Type)(implicit ctx: Context): TypeTree = track("typedTypeTree") {

test/test/DeSugarTest.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ class DeSugarTest extends ParserTest {
5353
cpy.Typed(tree1)(transform(expr), transform(tpt, Type))
5454
case CaseDef(pat, guard, body) =>
5555
cpy.CaseDef(tree1)(transform(pat, Pattern), transform(guard), transform(body))
56-
case SeqLiteral(elems) =>
57-
cpy.SeqLiteral(tree1)(transform(elems))
56+
case SeqLiteral(elems, elemtpt) =>
57+
cpy.SeqLiteral(tree1)(transform(elems), transform(elemtpt))
5858
case UnApply(fun, implicits, patterns) =>
5959
cpy.UnApply(tree1)(transform(fun, Expr), transform(implicits), transform(patterns))
6060
case tree1 @ ValDef(name, tpt, _) =>

0 commit comments

Comments
 (0)