Skip to content

Commit bea7430

Browse files
committed
Fix #4375: Properly erase SeqLiteral
Before this commit, the `SeqLiteral#elems` were typed based on the SeqLiteral prototype, which means that nothing ensured that the elems types conformed to the type of `SeqLiteral#elemtpt`. In i4375.scala this means that erasing `SeqLiteral([1, 2], Object)` did not box each element because the expected element type was `WildcardType`. To prevent this sort of issue, we now use the type of SeqLiteral#elemtpt if it exists as the expected type of each element in the sequence.
1 parent e77604d commit bea7430

File tree

2 files changed

+34
-10
lines changed

2 files changed

+34
-10
lines changed

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

+21-10
Original file line numberDiff line numberDiff line change
@@ -1126,20 +1126,31 @@ class Typer extends Namer
11261126
}
11271127

11281128
def typedSeqLiteral(tree: untpd.SeqLiteral, pt: Type)(implicit ctx: Context): SeqLiteral = track("typedSeqLiteral") {
1129-
val proto1 = pt.elemType match {
1129+
val elemProto = pt.elemType match {
11301130
case NoType => WildcardType
11311131
case bounds: TypeBounds => WildcardType(bounds)
11321132
case elemtp => elemtp
11331133
}
1134-
val elems1 = tree.elems mapconserve (typed(_, proto1))
1135-
val proto2 = // the computed type of the `elemtpt` field
1136-
if (!tree.elemtpt.isEmpty) WildcardType
1137-
else if (isFullyDefined(proto1, ForceDegree.none)) proto1
1138-
else if (tree.elems.isEmpty && tree.isInstanceOf[Trees.JavaSeqLiteral[_]])
1139-
defn.ObjectType // generic empty Java varargs are of type Object[]
1140-
else ctx.typeComparer.lub(elems1.tpes)
1141-
val elemtpt1 = typed(tree.elemtpt, proto2)
1142-
assignType(cpy.SeqLiteral(tree)(elems1, elemtpt1), elems1, elemtpt1)
1134+
1135+
def assign(elems1: List[Tree], elemtpt1: Tree) =
1136+
assignType(cpy.SeqLiteral(tree)(elems1, elemtpt1), elems1, elemtpt1)
1137+
1138+
if (!tree.elemtpt.isEmpty) {
1139+
val elemtpt1 = typed(tree.elemtpt, elemProto)
1140+
val elems1 = tree.elems.mapconserve(typed(_, elemtpt1.tpe))
1141+
assign(elems1, elemtpt1)
1142+
} else {
1143+
val elems1 = tree.elems.mapconserve(typed(_, elemProto))
1144+
val elemtptType =
1145+
if (isFullyDefined(elemProto, ForceDegree.none))
1146+
elemProto
1147+
else if (tree.elems.isEmpty && tree.isInstanceOf[Trees.JavaSeqLiteral[_]])
1148+
defn.ObjectType // generic empty Java varargs are of type Object[]
1149+
else
1150+
ctx.typeComparer.lub(elems1.tpes)
1151+
val elemtpt1 = typed(tree.elemtpt, elemtptType)
1152+
assign(elems1, elemtpt1)
1153+
}
11431154
}
11441155

11451156
def typedInlined(tree: untpd.Inlined, pt: Type)(implicit ctx: Context): Inlined = {

tests/pos/i4375.scala

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
object Test {
2+
type Id[A] >: A
3+
def test: Unit = {
4+
val a: Array[_ >: Id[Int]] = Array(1, 2)
5+
val b = a(0)
6+
}
7+
8+
class VC(i: String) extends AnyVal
9+
def test2: Unit = {
10+
val c: Array[_ >: Id[VC]] = Array(new VC(""))
11+
val d = c(0)
12+
}
13+
}

0 commit comments

Comments
 (0)