Skip to content

Commit 7bb2c25

Browse files
committed
Check macro expansion type
1 parent c3aa30f commit 7bb2c25

11 files changed

Lines changed: 59 additions & 6 deletions

File tree

compiler/src/dotty/tools/dotc/inlines/Inliner.scala

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -964,7 +964,25 @@ class Inliner(val call: tpd.Tree)(using Context):
964964
case tree1 @ Splice(expr) if level == 0 && !hasInliningErrors && !ctx.usedBestEffortTasty =>
965965
val expanded = expandMacro(expr, tree1.srcPos)
966966
transform.TreeChecker.checkMacroGeneratedTree(tree1, expanded)
967-
typedExpr(expanded) // Inline calls and constant fold code generated by the macro
967+
val res = typedExpr(expanded) // Inline calls and constant fold code generated by the macro
968+
969+
// We dealias opaque types because their aliases might not be visible
970+
// at the expansion site. See `tests/run-macros/opaque-inline`.
971+
val dealiasOpaques = new TypeMap:
972+
def apply(tp: Type): Type = tp match
973+
case tp: TypeRef if tp.typeSymbol.isOpaqueAlias =>
974+
val sym = tp.typeSymbol
975+
apply(sym.opaqueAlias.asSeenFrom(tp.prefix, sym.owner))
976+
case _ =>
977+
mapOver(tp)
978+
979+
val actualTp = dealiasOpaques(res.tpe)
980+
val expectedTp = dealiasOpaques(tree1.tpe)
981+
if actualTp frozen_<:< expectedTp then
982+
res
983+
else
984+
errorTree(tree1, em"""Macro expansion has type $actualTp, which does not conform to the expected type $expectedTp""")
985+
968986
case tree1 => tree1
969987

970988
override def typedMatch(tree: untpd.Match, pt: Type)(using Context): Tree =
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import scala.quoted.*
2+
3+
object Macro:
4+
inline def foo(): Int =
5+
${fooImpl()}
6+
7+
def fooImpl()(using Quotes): Expr[Int] =
8+
import quotes.reflect.*
9+
Expr("hello").asInstanceOf[Expr[Int]]
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@main def test =
2+
println(Macro.foo()) // error
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import scala.quoted.*
2+
3+
// Invariant type constructor
4+
final class Inv[A](val value: A)
5+
6+
object Inv:
7+
transparent inline def make: Inv[Tuple] =
8+
${ makeImpl }
9+
10+
def makeImpl(using Quotes): Expr[Inv[Tuple]] =
11+
val e: Expr[Inv[EmptyTuple]] = '{ new Inv[EmptyTuple](EmptyTuple) }
12+
e.asInstanceOf[Expr[Inv[Tuple]]]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
val inv: Inv[EmptyTuple] = Inv.make // error

tests/pos-macros/i25690/Macro_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ object Tracer:
1111

1212
def autoTraceImpl(using Quotes): Expr[Trace] =
1313
import quotes.reflect.*
14-
Literal(StringConstant("loc")).asExprOf[String].asInstanceOf[Expr[Trace]]
14+
'{ ${ Literal(StringConstant("loc")).asExprOf[String] }.asInstanceOf[Trace] }

tests/pos-macros/i25692/Macro_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ package internal.stacktracer:
2727

2828
object Macros:
2929
def autoTraceImpl(using Quotes): Expr[Tracer.instance.Type] =
30-
Expr("trace").asInstanceOf[Expr[Tracer.instance.Type]]
30+
'{ "trace".asInstanceOf[Tracer.instance.Type] }
3131

3232
package internal.macros:
3333
import zio.*
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import scala.quoted.*
2+
3+
// Invariant type constructor
4+
final class Inv[A](val value: A)
5+
6+
object Inv:
7+
transparent inline def make: Inv[? <: Tuple] =
8+
${ makeImpl }
9+
10+
def makeImpl(using Quotes): Expr[Inv[? <: Tuple]] =
11+
'{ new Inv[EmptyTuple](EmptyTuple) }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
val inv: Inv[EmptyTuple] = Inv.make

tests/run-macros/i7887/Macro_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
def myMacroImpl(a: quoted.Expr[_])(using qctx: quoted.Quotes) = {
1+
def myMacroImpl[S](a: quoted.Expr[S])(using qctx: quoted.Quotes): quoted.Expr[S] = {
22
import scala.quoted.quotes.reflect.*
33
def typed[A] = {
44
implicit val t: quoted.Type[A] = a.asTerm.tpe.widen.asType.asInstanceOf[quoted.Type[A]]

0 commit comments

Comments
 (0)