diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala index 9b262d1a41d3..d2bb51755f72 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala @@ -237,6 +237,18 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def Term_underlyingArgument(self: Term)(given Context): Term = self.underlyingArgument def Term_underlying(self: Term)(given Context): Term = self.underlying + def Term_etaExpand(term: Term): Term = term.tpe.widen match { + case mtpe: Types.MethodType if !mtpe.isParamDependent => + val closureResType = mtpe.resType match { + case t: Types.MethodType => t.toFunctionType() + case t => t + } + val closureTpe = Types.MethodType(mtpe.paramNames, mtpe.paramInfos, closureResType) + val closureMethod = ctx.newSymbol(ctx.owner, nme.ANON_FUN, Synthetic | Method, closureTpe) + tpd.Closure(closureMethod, tss => Term_etaExpand(new tpd.TreeOps(term).appliedToArgs(tss.head))) + case _ => term + } + type Ref = tpd.RefTree def matchRef(tree: Tree)(given Context): Option[Ref] = tree match { @@ -1591,19 +1603,9 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend PickledQuotes.quotedTypeToTree(self) /** Convert `Term` to an `quoted.Expr[Any]` */ - def QuotedExpr_seal(self: Term)(given ctx: Context): scala.quoted.Expr[Any] = { - def etaExpand(term: Term): Term = term.tpe.widen match { - case mtpe: Types.MethodType if !mtpe.isParamDependent => - val closureResType = mtpe.resType match { - case t: Types.MethodType => t.toFunctionType() - case t => t - } - val closureTpe = Types.MethodType(mtpe.paramNames, mtpe.paramInfos, closureResType) - val closureMethod = ctx.newSymbol(ctx.owner, nme.ANON_FUN, Synthetic | Method, closureTpe) - tpd.Closure(closureMethod, tss => etaExpand(new tpd.TreeOps(term).appliedToArgs(tss.head))) - case _ => term - } - new scala.internal.quoted.TastyTreeExpr(etaExpand(self), compilerId) + def QuotedExpr_seal(self: Term)(given ctx: Context): scala.quoted.Expr[Any] = self.tpe.widen match { + case _: Types.MethodType | _: Types.PolyType => throw new Exception("Cannot seal a partially applied Term. Try eta-expanding the term first.") + case _ => new scala.internal.quoted.TastyTreeExpr(self, compilerId) } /** Checked cast to a `quoted.Expr[U]` */ diff --git a/library/src/scala/tasty/reflect/CompilerInterface.scala b/library/src/scala/tasty/reflect/CompilerInterface.scala index b4007c4460ed..39f21f5b66b9 100644 --- a/library/src/scala/tasty/reflect/CompilerInterface.scala +++ b/library/src/scala/tasty/reflect/CompilerInterface.scala @@ -283,6 +283,7 @@ trait CompilerInterface { def Term_tpe(self: Term)(given ctx: Context): Type def Term_underlyingArgument(self: Term)(given ctx: Context): Term def Term_underlying(self: Term)(given ctx: Context): Term + def Term_etaExpand(term: Term): Term /** Tree representing a reference to definition */ type Ref <: Term diff --git a/library/src/scala/tasty/reflect/TreeOps.scala b/library/src/scala/tasty/reflect/TreeOps.scala index 8a7eeb22936c..5f0e91f35ec0 100644 --- a/library/src/scala/tasty/reflect/TreeOps.scala +++ b/library/src/scala/tasty/reflect/TreeOps.scala @@ -172,6 +172,7 @@ trait TreeOps extends Core { def tpe(given ctx: Context): Type = internal.Term_tpe(self) def underlyingArgument(given ctx: Context): Term = internal.Term_underlyingArgument(self) def underlying(given ctx: Context): Term = internal.Term_underlying(self) + def etaExpand(given ctx: Context): Term = internal.Term_etaExpand(self) /** A unary apply node with given argument: `tree(arg)` */ def appliedTo(arg: Term)(given ctx: Context): Term = diff --git a/tests/run-macros/tasty-seal-method/quoted_1.scala b/tests/run-macros/tasty-seal-method/quoted_1.scala index c8c000fdf21a..f20333392d3f 100644 --- a/tests/run-macros/tasty-seal-method/quoted_1.scala +++ b/tests/run-macros/tasty-seal-method/quoted_1.scala @@ -14,10 +14,10 @@ object Asserts { fn.tpe.widen match { case IsMethodType(_) => args.size match { - case 0 => Expr.betaReduce(fn.seal.cast[() => Int])() - case 1 => Expr.betaReduce(fn.seal.cast[Int => Int])('{0}) - case 2 => Expr.betaReduce(fn.seal.cast[(Int, Int) => Int])('{0}, '{0}) - case 3 => Expr.betaReduce(fn.seal.cast[(Int, Int, Int) => Int])('{0}, '{0}, '{0}) + case 0 => Expr.betaReduce(fn.etaExpand.seal.cast[() => Int])() + case 1 => Expr.betaReduce(fn.etaExpand.seal.cast[Int => Int])('{0}) + case 2 => Expr.betaReduce(fn.etaExpand.seal.cast[(Int, Int) => Int])('{0}, '{0}) + case 3 => Expr.betaReduce(fn.etaExpand.seal.cast[(Int, Int, Int) => Int])('{0}, '{0}, '{0}) } } case _ => x @@ -35,10 +35,10 @@ object Asserts { case Apply(fn, args) => val pre = rec(fn) args.size match { - case 0 => Expr.betaReduce(pre.seal.cast[() => Any])().unseal - case 1 => Expr.betaReduce(pre.seal.cast[Int => Any])('{0}).unseal - case 2 => Expr.betaReduce(pre.seal.cast[(Int, Int) => Any])('{0}, '{0}).unseal - case 3 => Expr.betaReduce(pre.seal.cast[(Int, Int, Int) => Any])('{0}, '{0}, '{0}).unseal + case 0 => Expr.betaReduce(pre.etaExpand.seal.cast[() => Any])().unseal + case 1 => Expr.betaReduce(pre.etaExpand.seal.cast[Int => Any])('{0}).unseal + case 2 => Expr.betaReduce(pre.etaExpand.seal.cast[(Int, Int) => Any])('{0}, '{0}).unseal + case 3 => Expr.betaReduce(pre.etaExpand.seal.cast[(Int, Int, Int) => Any])('{0}, '{0}, '{0}).unseal } case _ => term }