Open goshacodes opened 6 days ago
@jchyb @Gedochao Hi, I've made a minimized example, it is not about Term.betaReduce, it is about using ?tupled? method arguments. Could you please help me with a workaround if possible?
inline def example: Int =
${ exampleMacro }
def exampleMacro(using quotes: Quotes): Expr[Int] =
import quotes.reflect.*
def tupled(args: List[Term]) =
args.foldRight[Term]('{ EmptyTuple }.asTerm) { (el, acc) =>
Select
.unique(acc, "*:")
.appliedToTypes(List(el.tpe, acc.tpe))
.appliedToArgs(List(el))
}
val sym = Symbol.newMethod(
parent = Symbol.spliceOwner,
name = "BANG",
tpe = MethodType(List("x", "y"))(_ => List(TypeRepr.of[Int], TypeRepr.of[Int]), _ => TypeRepr.of[Int]),
Flags.EmptyFlags,
Symbol.noSymbol
)
Block(
List(
DefDef(
sym,
params => Some(
'{
val tupledParams = ${tupled(params.flatten.collect { case t: Term => t }).asExprOf[(Int, Int)]}
1
}.asTerm
)
)
),
Apply(Ref(sym), List('{1}.asTerm, '{1}.asTerm))
).asExprOf[Int]
Found solution here. https://github.com/scala/scala3/issues/13599 Can we handle this exception somehow and show error message telling what to do? This is not very clear first time
@goshacodes I'm not sure if the example you posted is indeed the minimization of this... the code you provided seems to compile fine for me, no crashes 🤔 (although I had to add the missing import scala.quoted.*
)
🤔🤔🤔
@Gedochao It crashes for me, you are likely missing a file with macro call:
// main.scala
def main() = example
@goshacodes When you use -Xcheck-macro
option, you get an additional checking phase that checks the correctness of generated code. Since it has substantial performance footprint on compilation (that is unnecessary for macro library users), it's made optional, but highly recommended for macro development phase. This error here is indeed caught with -Xcheck-macro and ends compilation before the compiler crashes:
-- Error: main.scala:1:13 ------------------------------------------------------
1 |def main() = example
| ^^^^^^^
|Exception occurred while executing macro expansion.
|java.lang.AssertionError: assertion failed: Tree had an unexpected owner for val tupledParams
|Expected: method BANG (main$package$._$_$BANG)
|But was: val macro (main$package$._$macro)
|
|The code of the definition of val tupledParams is
|val tupledParams: scala.Tuple2[scala.Int, scala.Int] = scala.Tuple$package.EmptyTuple.*:[y.type, scala.Tuple$package.EmptyTuple.type](y).*:[x.type, scala.*:[y, scala.Tuple$package.EmptyTuple]](x)
|
|which was found in the code
|{
| val tupledParams: scala.Tuple2[scala.Int, scala.Int] = scala.Tuple$package.EmptyTuple.*:[y.type, scala.Tuple$package.EmptyTuple.type](y).*:[x.type, scala.*:[y, scala.Tuple$package.EmptyTuple]](x)
| 1
|}
|
|which has the AST representation
|Inlined(Some(TypeIdent("macro$package$")), Nil, Block(List(ValDef("tupledParams", Inferred(), Some(Inlined(None, Nil, Apply(TypeApply(Select(Apply(TypeApply(Select(Inlined(Some(TypeIdent("macro$package$")), Nil, Ident("EmptyTuple")), "*:"), List(Inferred(), Inferred())), List(Ident("y"))), "*:"), List(Inferred(), Inferred())), List(Ident("x"))))))), Literal(IntConstant(1))))
|
|
|
|Tip: The owner of a tree can be changed using method `Tree.changeOwner`.
|Tip: The default owner of definitions created in quotes can be changed using method `Symbol.asQuotes`.
|
| at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
| at scala.quoted.runtime.impl.QuotesImpl$$anon$10.traverse(QuotesImpl.scala:3154)
| at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.apply(Trees.scala:1801)
| at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.apply(Trees.scala:1801)
| at dotty.tools.dotc.ast.Trees$Instance$TreeAccumulator.fold$1(Trees.scala:1665)
| at dotty.tools.dotc.ast.Trees$Instance$TreeAccumulator.apply(Trees.scala:1667)
| at dotty.tools.dotc.ast.Trees$Instance$TreeAccumulator.foldOver(Trees.scala:1698)
| at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.traverseChildren(Trees.scala:1802)
| at scala.quoted.runtime.impl.QuotesImpl$$anon$10.traverse(QuotesImpl.scala:3162)
| at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.apply(Trees.scala:1801)
| at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.apply(Trees.scala:1801)
| at dotty.tools.dotc.ast.Trees$Instance$TreeAccumulator.foldOver(Trees.scala:1718)
| at dotty.tools.dotc.ast.Trees$Instance$TreeAccumulator.foldOver(Trees.scala:1671)
| at dotty.tools.dotc.ast.Trees$Instance$TreeTraverser.traverseChildren(Trees.scala:1802)
| at scala.quoted.runtime.impl.QuotesImpl$$anon$10.traverse(QuotesImpl.scala:3162)
| at scala.quoted.runtime.impl.QuotesImpl$reflect$.xCheckMacroOwners(QuotesImpl.scala:3163)
| at scala.quoted.runtime.impl.QuotesImpl$reflect$.scala$quoted$runtime$impl$QuotesImpl$reflect$$$xCheckedMacroOwners(QuotesImpl.scala:3116)
| at scala.quoted.runtime.impl.QuotesImpl$reflect$DefDef$.apply$$anonfun$3$$anonfun$1(QuotesImpl.scala:307)
| at dotty.tools.dotc.ast.tpd$.DefDef(tpd.scala:312)
| at scala.quoted.runtime.impl.QuotesImpl$reflect$DefDef$.apply$$anonfun$3(QuotesImpl.scala:308)
| at scala.quoted.runtime.impl.QuotesImpl$reflect$.scala$quoted$runtime$impl$QuotesImpl$reflect$$$withDefaultPos(QuotesImpl.scala:3107)
| at scala.quoted.runtime.impl.QuotesImpl$reflect$DefDef$.apply(QuotesImpl.scala:306)
| at scala.quoted.runtime.impl.QuotesImpl$reflect$DefDef$.apply(QuotesImpl.scala:303)
| at macro$package$.exampleMacro(macro.scala:29)
|
|-----------------------------------------------------------------------------
|Inline stack trace
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|This location contains code that was inlined from macro.scala:4
4 | ${ exampleMacro }
| ^^^^^^^^^^^^^^^^^
-----------------------------------------------------------------------------
Got it, thank you!
Compiler version
3.5.1 3.5.0 3.4.2
Problem
Hi! I'm trying to use tupled method arguments in method body and this leads to compiler crash.
Minimized
Output (click arrow to expand)