diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala | 14 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala | 15 |
2 files changed, 20 insertions, 9 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala index efa97b0d6f..a28d4b0083 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala @@ -1008,9 +1008,17 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { case concatenations => bc.genStartConcat(tree.pos) for (elem <- concatenations) { - val kind = tpeTK(elem) - genLoad(elem, kind) - bc.genStringConcat(kind, elem.pos) + val loadedElem = elem match { + case Apply(boxOp, value :: Nil) if currentRun.runDefinitions.isBox(boxOp.symbol) => + // Eliminate boxing of primitive values. Boxing is introduced by erasure because + // there's only a single synthetic `+` method "added" to the string class. + value + + case _ => elem + } + val elemType = tpeTK(loadedElem) + genLoad(loadedElem, elemType) + bc.genConcat(elemType, loadedElem.pos) } bc.genEndConcat(tree.pos) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala index 328a8187c8..0a95bc5e39 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala @@ -197,16 +197,19 @@ abstract class BCodeIdiomatic extends SubComponent { /* * can-multi-thread */ - final def genStringConcat(el: BType, pos: Position): Unit = { - val jtype = el match { + def genConcat(elemType: BType, pos: Position): Unit = { + val paramType = elemType match { case ct: ClassBType if ct.isSubtypeOf(StringRef).get => StringRef case ct: ClassBType if ct.isSubtypeOf(jlStringBufferRef).get => jlStringBufferRef case ct: ClassBType if ct.isSubtypeOf(jlCharSequenceRef).get => jlCharSequenceRef - case rt: RefBType => ObjectRef - case pt: PrimitiveBType => pt // Currently this ends up being boxed in erasure + // Don't match for `ArrayBType(CHAR)`, even though StringBuilder has such an overload: + // `"a" + Array('b')` should NOT be "ab", but "a[C@...". + case _: RefBType => ObjectRef + // jlStringBuilder does not have overloads for byte and short, but we can just use the int version + case BYTE | SHORT => INT + case pt: PrimitiveBType => pt } - - val bt = MethodBType(List(jtype), jlStringBuilderRef) + val bt = MethodBType(List(paramType), jlStringBuilderRef) invokevirtual(JavaStringBuilderClassName, "append", bt.descriptor, pos) } |