Skip to content

Commit 03b1cd9

Browse files
committed
Inlined non-eta-expanded trees message
Closes #11483
1 parent 12f34c2 commit 03b1cd9

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed

compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,9 @@ object EtaExpansion extends LiftImpure {
223223
*/
224224
def etaExpand(tree: Tree, mt: MethodType, xarity: Int)(using Context): untpd.Tree = {
225225
import untpd._
226+
if ctx.phase == Phases.inliningPhase then
227+
report.error(em"Cannot automaticaly eta-expand calls in macros: $tree", tree.srcPos)
228+
return EmptyTree
226229
assert(!ctx.isAfterTyper)
227230
val defs = new mutable.ListBuffer[tpd.Tree]
228231
val lifted: Tree = TypedSplice(liftApp(defs, tree))

tests/neg-macros/i11483/Macro_1.scala

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package x
2+
3+
import scala.annotation._
4+
import scala.quoted._
5+
import scala.compiletime._
6+
7+
8+
trait CpsMonad[F[_]]:
9+
10+
def pure[T](x:T):F[T]
11+
12+
def impure[T](x:F[T]):T
13+
14+
def map[A,B](x:F[A])(f: A=>B):F[B]
15+
16+
17+
@compileTimeOnly("await should be inside async block")
18+
def await[F[_],T](f:F[T])(using am:CpsMonad[F]):T = ???
19+
20+
inline given conversion[F[_],T](using CpsMonad[F]): Conversion[F[T],T] =
21+
x => await(x)
22+
23+
24+
object X {
25+
26+
inline def process[F[_], T](inline t:T)(using m: CpsMonad[F]):F[T] =
27+
${ processImpl[F,T]('t, 'm) }
28+
29+
30+
def processImpl[F[_]:Type, T:Type](t:Expr[T], m:Expr[CpsMonad[F]])(using Quotes):Expr[F[T]] =
31+
import quotes.reflect._
32+
val r = processTree[F,T](t.asTerm, m.asTerm)
33+
r.asExprOf[F[T]]
34+
35+
36+
def processTree[F[_]:Type, T:Type](using Quotes)(t: quotes.reflect.Term, m: quotes.reflect.Term):quotes.reflect.Term =
37+
import quotes.reflect._
38+
val r: Term = t match
39+
case Inlined(_,List(),body) => processTree[F,T](body, m)
40+
case Inlined(d,bindings,body) =>
41+
Inlined(d,bindings,processTree[F,T](body, m))
42+
case Block(stats,expr) => Block(stats,processTree(expr, m))
43+
case Apply(Apply(TypeApply(Ident("await"),targs),List(body)),List(m)) => body
44+
case Apply(f,List(arg)) =>
45+
val nArg = processTree[F,String](arg, m)
46+
Apply(Apply(TypeApply(Select.unique(m,"map"),
47+
List(Inferred(arg.tpe.widen),Inferred(t.tpe.widen))
48+
),
49+
List(nArg)),
50+
List(f)
51+
)
52+
case Apply(f,List()) =>
53+
Apply(TypeApply(Select.unique(m,"pure"),List(Inferred(t.tpe.widen))),List(t))
54+
case Typed(x,tp) => Typed(processTree(x,m), Inferred(TypeRepr.of[F].appliedTo(tp.tpe)) )
55+
case _ => throw new RuntimeException(s"tree not recoginized: $t")
56+
r
57+
58+
59+
}

tests/neg-macros/i11483/Test_2.scala

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package x
2+
3+
import scala.language.implicitConversions
4+
import scala.concurrent.Future
5+
6+
given FutureAsyncMonad: CpsMonad[Future] with
7+
def pure[T](t:T): Future[T] = ???
8+
def impure[T](t:Future[T]): T = ???
9+
def map[A,B](x:Future[A])(f: A=>B): Future[B] = ???
10+
11+
12+
object Api:
13+
14+
def doSomething():Future[String] =
15+
Future.successful("doSomething")
16+
17+
def println(x:String):Unit =
18+
Console.println(x)
19+
20+
21+
object Main:
22+
23+
def main(args: Array[String]): Unit =
24+
X.process[Future,Unit]{
25+
Api.println( // error
26+
Api.doSomething() // error
27+
)
28+
}

0 commit comments

Comments
 (0)