Skip to content

Commit

Permalink
Fix scala#13518: Fix primitive + string when the string is a TermRef.
Browse files Browse the repository at this point in the history
Sometimes, the argument string's `tpe` can be `TermRef`, in which
case it is not directly a ref to `StringClass`. That was triggering
the assertion.

The assertions and the calls to `makePrimitiveBox` have actually
not been needed for a long time. The IR supports the arguments to a
`String_+` operator to be of any type. So we fix the issue by
removing all of that and directly emitting the `String_+`.
  • Loading branch information
sjrd committed Sep 15, 2021
1 parent ea871c2 commit 6c6b087
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 21 deletions.
22 changes: 1 addition & 21 deletions compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2790,27 +2790,7 @@ class JSCodeGen()(using genCtx: Context) {
args: List[Tree]): js.Tree = {
implicit val pos = tree.span

val arg = args.head

/* Primitive number types such as scala.Int have a
* def +(s: String): String
* method, which is why we have to box the lhs sometimes.
* Otherwise, both lhs and rhs are already reference types (Any or String)
* so boxing is not necessary (in particular, rhs is never a primitive).
*/
assert(!isPrimitiveValueType(receiver.tpe) || arg.tpe.isRef(defn.StringClass))
assert(!isPrimitiveValueType(arg.tpe))

val genLhs = {
val genLhs0 = genExpr(receiver)
// Box the receiver if it is a primitive value
if (!isPrimitiveValueType(receiver.tpe)) genLhs0
else makePrimitiveBox(genLhs0, receiver.tpe)
}

val genRhs = genExpr(arg)

js.BinaryOp(js.BinaryOp.String_+, genLhs, genRhs)
js.BinaryOp(js.BinaryOp.String_+, genExpr(receiver), genExpr(args.head))
}

/** Gen JS code for a call to Any.## */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ class RegressionTestScala3 {
assertEquals(1, X_Issue13221.I.i)
assertEquals(1, X_Issue13221.blah)
}

@Test def primitivePlusStringThatIsATermRefIssue13518(): Unit = {
def charPlusString(x: String): String = 'a' + x
assertEquals("abc", charPlusString("bc"))

def intPlusString(x: String): String = 5 + x
assertEquals("5bc", intPlusString("bc"))
}
}

object RegressionTestScala3 {
Expand Down

0 comments on commit 6c6b087

Please sign in to comment.