Skip to content

Commit 8235acc

Browse files
committed
Addressed comments
1 parent 2e82189 commit 8235acc

File tree

4 files changed

+42
-24
lines changed

4 files changed

+42
-24
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,9 @@ class Definitions {
568568
lazy val StringAdd_plusR = StringAddClass.requiredMethodRef(nme.raw.PLUS)
569569
def StringAdd_+(implicit ctx: Context) = StringAdd_plusR.symbol
570570

571+
lazy val StringContextType: TypeRef = ctx.requiredClassRef("scala.StringContext")
572+
def StringContextClass(implicit ctx: Context) = StringContextType.symbol.asClass
573+
571574
lazy val PartialFunctionType: TypeRef = ctx.requiredClassRef("scala.PartialFunction")
572575
def PartialFunctionClass(implicit ctx: Context) = PartialFunctionType.symbol.asClass
573576
lazy val AbstractPartialFunctionType: TypeRef = ctx.requiredClassRef("scala.runtime.AbstractPartialFunction")

compiler/src/dotty/tools/dotc/transform/localopt/StringInterpolatorOpt.scala

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,22 @@ class StringInterpolatorOpt extends MiniPhase {
1919
private object StringContextIntrinsic {
2020
def unapply(tree: Apply)(implicit ctx: Context): Option[(List[Tree], List[Tree])] = {
2121
tree match {
22-
case Apply(Select(Apply(Select(Ident(nme.StringContext), nme.apply),
23-
List(SeqLiteral(strs, _))), id), List(SeqLiteral(elems, _))) =>
24-
if (id == nme.raw_) Some(strs, elems)
25-
else if (id == nme.s) {
26-
try {
27-
val escapedStrs = strs.mapConserve { str =>
28-
val strValue = str.asInstanceOf[Literal].const.stringValue
29-
val escapedValue = StringContext.processEscapes(strValue)
30-
cpy.Literal(str)(Constant(escapedValue))
22+
case Apply(Select(Apply(Select(ident, nme.apply), List(SeqLiteral(strs, _))), fn),
23+
List(SeqLiteral(elems, _))) =>
24+
if (ident.symbol.eq(defn.StringContextClass) && strs.forall(_.isInstanceOf[Literal])) {
25+
if (fn == nme.raw_) Some(strs, elems)
26+
else if (fn == nme.s) {
27+
try {
28+
val escapedStrs = strs.mapConserve { str =>
29+
val strValue = str.asInstanceOf[Literal].const.stringValue
30+
val escapedValue = StringContext.processEscapes(strValue)
31+
cpy.Literal(str)(Constant(escapedValue))
32+
}
33+
Some(escapedStrs, elems)
34+
} catch {
35+
case _: StringContext.InvalidEscapeException => None
3136
}
32-
Some(escapedStrs, elems)
33-
} catch {
34-
case _: StringContext.InvalidEscapeException => None
35-
}
37+
} else None
3638
} else None
3739
case _ => None
3840
}
@@ -42,17 +44,18 @@ class StringInterpolatorOpt extends MiniPhase {
4244
override def transformApply(tree: Apply)(implicit ctx: Context): Tree = {
4345
tree match {
4446
case StringContextIntrinsic(strs: List[Tree], elems: List[Tree]) =>
45-
val numLits = strs.length
46-
strs.tail.foldLeft((0, strs.head)) { (acc: (Int, Tree), str: Tree) =>
47-
val (i, result) = acc
48-
val resultWithElem =
49-
if (i < numLits - 1) result.select(defn.String_+).appliedTo(elems(i))
50-
else result
51-
val resultWithStr =
52-
if (str.asInstanceOf[Literal].const.stringValue.isEmpty) resultWithElem
53-
else resultWithElem.select(defn.String_+).appliedTo(str)
54-
(i + 1, resultWithStr)
55-
}._2
47+
val stri = strs.iterator
48+
val elemi = elems.iterator
49+
var result = stri.next
50+
def concat(tree: Tree): Unit = {
51+
result = result.select(defn.String_+).appliedTo(tree)
52+
}
53+
while (elemi.hasNext) {
54+
concat(elemi.next)
55+
val str = stri.next
56+
if (!str.asInstanceOf[Literal].const.stringValue.isEmpty) concat(str)
57+
}
58+
result
5659
case _ => tree
5760
}
5861
}

tests/run/interpolation-opt.check

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@
33
is 3.0
44
a1two3.0b
55
a1two3.0b
6+
7+
8+
Hello World

tests/run/interpolation-opt.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,13 @@ object Test extends App {
1111
// Test empty strings between elements
1212
println(raw"a$one$two${three}b")
1313
println(s"a$one$two${three}b")
14+
15+
// Test empty string interpolators
16+
println(raw"")
17+
println(s"")
18+
19+
// Make sure that StringContext still works with idents
20+
val foo = "Hello"
21+
val bar = "World"
22+
println(StringContext(foo, bar).s(" "))
1423
}

0 commit comments

Comments
 (0)