Skip to content

Commit ad85da0

Browse files
authored
Backport "XcheckMacro types of Block expression and Apply/TypeApply function" to LTS (#19121)
Backports #18242 to the LTS branch. PR submitted by the release tooling. [skip ci]
2 parents f79a803 + 93cdd23 commit ad85da0

File tree

7 files changed

+117
-4
lines changed

7 files changed

+117
-4
lines changed

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

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -623,9 +623,11 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
623623

624624
object Apply extends ApplyModule:
625625
def apply(fun: Term, args: List[Term]): Apply =
626+
xCheckMacroAssert(fun.tpe.widen.isInstanceOf[dotc.core.Types.MethodType], "Expected `fun.tpe` to widen into a `MethodType`")
626627
xCheckMacroValidExprs(args)
627628
withDefaultPos(tpd.Apply(fun, args))
628629
def copy(original: Tree)(fun: Term, args: List[Term]): Apply =
630+
xCheckMacroAssert(fun.tpe.widen.isInstanceOf[dotc.core.Types.MethodType], "Expected `fun.tpe` to widen into a `MethodType`")
629631
xCheckMacroValidExprs(args)
630632
tpd.cpy.Apply(original)(fun, args)
631633
def unapply(x: Apply): (Term, List[Term]) =
@@ -664,8 +666,10 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
664666

665667
object TypeApply extends TypeApplyModule:
666668
def apply(fun: Term, args: List[TypeTree]): TypeApply =
669+
xCheckMacroAssert(fun.tpe.widen.isInstanceOf[dotc.core.Types.PolyType], "Expected `fun.tpe` to widen into a `PolyType`")
667670
withDefaultPos(tpd.TypeApply(fun, args))
668671
def copy(original: Tree)(fun: Term, args: List[TypeTree]): TypeApply =
672+
xCheckMacroAssert(fun.tpe.widen.isInstanceOf[dotc.core.Types.PolyType], "Expected `fun.tpe` to widen into a `PolyType`")
669673
tpd.cpy.TypeApply(original)(fun, args)
670674
def unapply(x: TypeApply): (Term, List[TypeTree]) =
671675
(x.fun, x.args)
@@ -789,7 +793,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
789793

790794
object Block extends BlockModule:
791795
def apply(stats: List[Statement], expr: Term): Block =
792-
xCheckMacroBlockOwners(withDefaultPos(tpd.Block(stats, expr)))
796+
xCheckMacroBlockOwners(withDefaultPos(tpd.Block(stats, xCheckMacroValidExpr(expr))))
793797
def copy(original: Tree)(stats: List[Statement], expr: Term): Block =
794798
xCheckMacroBlockOwners(tpd.cpy.Block(original)(stats, expr))
795799
def unapply(x: Block): (List[Statement], Term) =
@@ -3082,13 +3086,22 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
30823086
if xCheckMacro then termOpt.foreach(xCheckMacroValidExpr)
30833087
termOpt
30843088
private def xCheckMacroValidExpr(term: Term): term.type =
3085-
if xCheckMacro then
3086-
assert(!term.tpe.widenDealias.isInstanceOf[dotc.core.Types.MethodicType],
3089+
xCheckMacroAssert(!term.tpe.widenDealias.isInstanceOf[dotc.core.Types.MethodicType],
30873090
"Reference to a method must be eta-expanded before it is used as an expression: " + term.show)
30883091
term
30893092

30903093
private inline def xCheckMacroAssert(inline cond: Boolean, inline msg: String): Unit =
3091-
assert(!xCheckMacro || cond, msg)
3094+
if xCheckMacro && !cond then
3095+
xCheckMacroAssertFail(msg)
3096+
3097+
private def xCheckMacroAssertFail(msg: String): Unit =
3098+
val error = new AssertionError(msg)
3099+
if !yDebugMacro then
3100+
// start stack trace at the place where the user called the reflection method
3101+
error.setStackTrace(
3102+
error.getStackTrace
3103+
.dropWhile(_.getClassName().startsWith("scala.quoted.runtime.impl")))
3104+
throw error
30923105

30933106
object Printer extends PrinterModule:
30943107

tests/neg-macros/i18113.check

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
-- Error: tests/neg-macros/i18113/Test_2.scala:7:8 ---------------------------------------------------------------------
3+
7 | X.test(ref) // error
4+
| ^^^^^^^^^^^
5+
|Exception occurred while executing macro expansion.
6+
|java.lang.AssertionError: Reference to a method must be eta-expanded before it is used as an expression: x.Main.ref.plus
7+
| at x.X$.testImpl(Macro_1.scala:16)
8+
|
9+
|--------------------------------------------------------------------------------------------------------------------
10+
|Inline stack trace
11+
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
12+
|This location contains code that was inlined from Macro_1.scala:11
13+
11 | inline def test(ref:IntRef):Int = ${ testImpl('ref) }
14+
| ^^^^^^^^^^^^^^^^^^^
15+
--------------------------------------------------------------------------------------------------------------------

tests/neg-macros/i18113/Macro_1.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package x
2+
3+
import scala.quoted.*
4+
5+
class IntRef(var x: Int) {
6+
def plus(y:Int): Int = ???
7+
}
8+
9+
object X {
10+
11+
inline def test(ref:IntRef):Int = ${ testImpl('ref) }
12+
13+
def testImpl(ref:Expr[IntRef])(using Quotes):Expr[Int] = {
14+
import quotes.reflect.*
15+
val fun0 = Select.unique(ref.asTerm,"plus")
16+
val fun1 = Block(List(Assign(Select.unique(ref.asTerm,"x"),Literal(IntConstant(1)))),fun0)
17+
val r = Apply(fun1,List(Literal(IntConstant(2))))
18+
r.asExprOf[Int]
19+
}
20+
21+
}

tests/neg-macros/i18113/Test_2.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package x
2+
3+
object Main {
4+
5+
val ref = IntRef(0)
6+
7+
X.test(ref) // error
8+
9+
}

tests/neg-macros/i18113b.check

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
-- Error: tests/neg-macros/i18113b/Test_2.scala:7:8 --------------------------------------------------------------------
3+
7 | X.test(ref) // error
4+
| ^^^^^^^^^^^
5+
| Exception occurred while executing macro expansion.
6+
| java.lang.AssertionError: Expected `fun.tpe` to widen into a `MethodType`
7+
| at x.X$.testImpl(Macro_1.scala:27)
8+
|
9+
|--------------------------------------------------------------------------------------------------------------------
10+
|Inline stack trace
11+
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
12+
|This location contains code that was inlined from Macro_1.scala:12
13+
12 | inline def test(ref:IntRef):Int = ${ testImpl('ref) }
14+
| ^^^^^^^^^^^^^^^^^^^
15+
--------------------------------------------------------------------------------------------------------------------
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package x
2+
3+
import scala.quoted.*
4+
5+
class IntRef(var x: Int) {
6+
def plus(y:Int): Int = ???
7+
}
8+
9+
10+
object X {
11+
12+
inline def test(ref:IntRef):Int = ${ testImpl('ref) }
13+
14+
def testImpl(ref:Expr[IntRef])(using Quotes):Expr[Int] = {
15+
import quotes.reflect.*
16+
val fun0 = Select.unique(ref.asTerm,"plus")
17+
val mt = MethodType(List("p"))(
18+
_ => List(TypeRepr.of[Int]),
19+
_ => TypeRepr.of[Int]
20+
)
21+
val etaExpanded = Lambda(Symbol.spliceOwner, mt, (owner, params) => {
22+
Block(
23+
List(Assign(Select.unique(ref.asTerm,"x"),Literal(IntConstant(1)))),
24+
Apply(fun0,params.map(_.asInstanceOf[Term]))
25+
)
26+
})
27+
val r = Apply(etaExpanded,List(Literal(IntConstant(2))))
28+
r.asExprOf[Int]
29+
}
30+
31+
}

tests/neg-macros/i18113b/Test_2.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package x
2+
3+
object Main {
4+
5+
val ref = IntRef(0)
6+
7+
X.test(ref) // error
8+
9+
}

0 commit comments

Comments
 (0)