Skip to content

Commit 14bce62

Browse files
authored
Merge pull request #413 from scala/backport-lts-3.3-23064
Backport "Forbid `StringConstant(null)`" to 3.3 LTS
2 parents d6bc491 + e7aee4f commit 14bce62

File tree

5 files changed

+43
-2
lines changed

5 files changed

+43
-2
lines changed

compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala

+6-1
Original file line numberDiff line numberDiff line change
@@ -2419,7 +2419,12 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
24192419
end StringConstantTypeTest
24202420

24212421
object StringConstant extends StringConstantModule:
2422-
def apply(x: String): StringConstant = dotc.core.Constants.Constant(x)
2422+
def apply(x: String): StringConstant =
2423+
require(x != null, "value of StringConstant cannot be `null`")
2424+
// A `null` constant must be represented as a `NullConstant`, c.f. a
2425+
// constant with `tag == NullTag`, which is not a `StringConstant`.
2426+
// See issue 23008.
2427+
dotc.core.Constants.Constant(x)
24232428
def unapply(constant: StringConstant): Some[String] = Some(constant.stringValue)
24242429
end StringConstant
24252430

library/src/scala/quoted/Quotes.scala

+4-1
Original file line numberDiff line numberDiff line change
@@ -3556,7 +3556,10 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
35563556

35573557
/** Methods of the module object `val StringConstant` */
35583558
trait StringConstantModule { this: StringConstant.type =>
3559-
/** Create a constant String value */
3559+
/** Create a constant String value
3560+
*
3561+
* @throw `IllegalArgumentException` if the argument is `null`
3562+
*/
35603563
def apply(x: String): StringConstant
35613564
/** Match String value constant and extract its value */
35623565
def unapply(constant: StringConstant): Some[String]

tests/neg-macros/i23008.check

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
-- Error: tests/neg-macros/i23008/Test_2.scala:1:24 --------------------------------------------------------------------
3+
1 |@main def Test = Macros.buildString // error
4+
| ^^^^^^^^^^^^^^^^^^
5+
| Exception occurred while executing macro expansion.
6+
| java.lang.IllegalArgumentException: requirement failed: value of StringConstant cannot be `null`
7+
| at scala.Predef$.require(Predef.scala:337)
8+
| at scala.quoted.runtime.impl.QuotesImpl$reflect$StringConstant$.apply(QuotesImpl.scala:2533)
9+
| at scala.quoted.runtime.impl.QuotesImpl$reflect$StringConstant$.apply(QuotesImpl.scala:2532)
10+
| at scala.quoted.ToExpr$StringToExpr.apply(ToExpr.scala:80)
11+
| at scala.quoted.ToExpr$StringToExpr.apply(ToExpr.scala:78)
12+
| at scala.quoted.Expr$.apply(Expr.scala:70)
13+
| at Macros$.buildStringCode(Macro_1.scala:9)
14+
|
15+
|---------------------------------------------------------------------------------------------------------------------
16+
|Inline stack trace
17+
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
18+
|This location contains code that was inlined from Macro_1.scala:4
19+
4 | inline def buildString = ${buildStringCode}
20+
| ^^^^^^^^^^^^^^^^^^
21+
---------------------------------------------------------------------------------------------------------------------

tests/neg-macros/i23008/Macro_1.scala

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import scala.quoted.*
2+
3+
object Macros {
4+
inline def buildString = ${buildStringCode}
5+
6+
def buildStringCode(using Quotes): Expr[String] = {
7+
import quotes.reflect.*
8+
val str: String = null
9+
Expr(str)
10+
}
11+
}

tests/neg-macros/i23008/Test_2.scala

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@main def Test = Macros.buildString // error

0 commit comments

Comments
 (0)