@@ -34,6 +34,7 @@ import Denotations.SingleDenotation
3434import annotation .threadUnsafe
3535
3636import scala .util .control .NonFatal
37+ import dotty .tools .dotc .inlines .Inlines
3738
3839object Applications {
3940 import tpd .*
@@ -1408,6 +1409,50 @@ trait Applications extends Compatibility {
14081409 }
14091410 }
14101411
1412+ /** Inlines the unapply function before the dummy argument
1413+ *
1414+ * A call `P.unapply[...](using l1, ..)(`dummy`)(using t1, ..)` becomes
1415+ * ```
1416+ * {
1417+ * class $anon {
1418+ * def unapply(s: S)(using t1: T1, ..): R =
1419+ * ... // inlined code for: P.unapply[...](using l1, ..)(s)(using t1, ..)
1420+ * }
1421+ * new $anon
1422+ * }.unapply(`dummy`)(using t1, ..)
1423+ * ```
1424+ */
1425+ def inlinedUnapplyFnAndApp (dummyArg : Tree , unapplyAppCall : Tree ): (Tree , Tree ) =
1426+ def rec (unapp : Tree ): (Tree , Tree ) =
1427+ unapp match
1428+ case DynamicUnapply (_) =>
1429+ report.error(em " Structural unapply is not supported " , unapplyFn.srcPos)
1430+ (unapplyFn, unapplyAppCall)
1431+ case Apply (fn, `dummyArg` :: Nil ) =>
1432+ val inlinedUnapplyFn = Inlines .inlinedUnapplyFun(fn)
1433+ (inlinedUnapplyFn, inlinedUnapplyFn.appliedToArgs(`dummyArg` :: Nil ))
1434+ case Apply (fn, args) =>
1435+ val (fn1, app) = rec(fn)
1436+ (fn1, tpd.cpy.Apply (unapp)(app, args))
1437+
1438+ if unapplyAppCall.symbol.isAllOf(Transparent | Inline ) then rec(unapplyAppCall)
1439+ else (unapplyFn, unapplyAppCall)
1440+ end inlinedUnapplyFnAndApp
1441+
1442+ def unapplyImplicits (dummyArg : Tree , unapp : Tree ): List [Tree ] =
1443+ val res = List .newBuilder[Tree ]
1444+ def loop (unapp : Tree ): Unit = unapp match
1445+ case Apply (Apply (unapply, `dummyArg` :: Nil ), args2) => assert(args2.nonEmpty); res ++= args2
1446+ case Apply (unapply, `dummyArg` :: Nil ) =>
1447+ case Inlined (u, _, _) => loop(u)
1448+ case DynamicUnapply (_) => report.error(em " Structural unapply is not supported " , unapplyFn.srcPos)
1449+ case Apply (fn, args) => assert(args.nonEmpty); loop(fn); res ++= args
1450+ case _ => ().assertingErrorsReported
1451+
1452+ loop(unapp)
1453+ res.result()
1454+ end unapplyImplicits
1455+
14111456 /** Add a `Bind` node for each `bound` symbol in a type application `unapp` */
14121457 def addBinders (unapp : Tree , bound : List [Symbol ]) = unapp match {
14131458 case TypeApply (fn, args) =>
@@ -1446,20 +1491,10 @@ trait Applications extends Compatibility {
14461491 unapplyArgType
14471492
14481493 val dummyArg = dummyTreeOfType(ownType)
1449- val unapplyApp = typedExpr(untpd.TypedSplice (Apply (unapplyFn, dummyArg :: Nil )))
1450- def unapplyImplicits (unapp : Tree ): List [Tree ] = {
1451- val res = List .newBuilder[Tree ]
1452- def loop (unapp : Tree ): Unit = unapp match {
1453- case Apply (Apply (unapply, `dummyArg` :: Nil ), args2) => assert(args2.nonEmpty); res ++= args2
1454- case Apply (unapply, `dummyArg` :: Nil ) =>
1455- case Inlined (u, _, _) => loop(u)
1456- case DynamicUnapply (_) => report.error(em " Structural unapply is not supported " , unapplyFn.srcPos)
1457- case Apply (fn, args) => assert(args.nonEmpty); loop(fn); res ++= args
1458- case _ => ().assertingErrorsReported
1459- }
1460- loop(unapp)
1461- res.result()
1462- }
1494+ val (newUnapplyFn, unapplyApp) =
1495+ val unapplyAppCall = withMode(Mode .NoInline ):
1496+ typedExpr(untpd.TypedSplice (Apply (unapplyFn, dummyArg :: Nil )))
1497+ inlinedUnapplyFnAndApp(dummyArg, unapplyAppCall)
14631498
14641499 var argTypes = unapplyArgs(unapplyApp.tpe, unapplyFn, args, tree.srcPos)
14651500 for (argType <- argTypes) assert(! isBounds(argType), unapplyApp.tpe.show)
@@ -1475,7 +1510,7 @@ trait Applications extends Compatibility {
14751510 List .fill(argTypes.length - args.length)(WildcardType )
14761511 }
14771512 val unapplyPatterns = bunchedArgs.lazyZip(argTypes) map (typed(_, _))
1478- val result = assignType(cpy.UnApply (tree)(unapplyFn , unapplyImplicits(unapplyApp), unapplyPatterns), ownType)
1513+ val result = assignType(cpy.UnApply (tree)(newUnapplyFn , unapplyImplicits(dummyArg, unapplyApp), unapplyPatterns), ownType)
14791514 unapp.println(s " unapply patterns = $unapplyPatterns" )
14801515 if (ownType.stripped eq selType.stripped) || ownType.isError then result
14811516 else tryWithTypeTest(Typed (result, TypeTree (ownType)), selType)
0 commit comments