@@ -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 .*
@@ -1392,6 +1393,36 @@ trait Applications extends Compatibility {
13921393 }
13931394 }
13941395
1396+ /** Inlines the unapply function before the dummy argument
1397+ *
1398+ * A call `P.unapply[...](using l1, ..)(`dummy`)(using t1, ..)` becomes
1399+ * ```
1400+ * {
1401+ * class $anon {
1402+ * def unapply(s: S)(using t1: T1, ..): R =
1403+ * ... // inlined code for: P.unapply[...](using l1, ..)(s)(using t1, ..)
1404+ * }
1405+ * new $anon
1406+ * }.unapply(`dummy`)(using t1, ..)
1407+ * ```
1408+ */
1409+ def inlinedUnapplyFnAndApp (dummyArg : Tree , unapplyAppCall : Tree ): (Tree , Tree ) =
1410+ def rec (unapp : Tree ): (Tree , Tree ) =
1411+ unapp match
1412+ case DynamicUnapply (_) =>
1413+ report.error(em " Structural unapply is not supported " , unapplyFn.srcPos)
1414+ (unapplyFn, unapplyAppCall)
1415+ case Apply (fn, `dummyArg` :: Nil ) =>
1416+ val inlinedUnapplyFn = Inlines .inlinedUnapplyFun(fn)
1417+ (inlinedUnapplyFn, inlinedUnapplyFn.appliedToArgs(`dummyArg` :: Nil ))
1418+ case Apply (fn, args) =>
1419+ val (fn1, app) = rec(fn)
1420+ (fn1, tpd.cpy.Apply (unapp)(app, args))
1421+
1422+ if unapplyAppCall.symbol.isAllOf(Transparent | Inline ) then rec(unapplyAppCall)
1423+ else (unapplyFn, unapplyAppCall)
1424+ end inlinedUnapplyFnAndApp
1425+
13951426 /** Add a `Bind` node for each `bound` symbol in a type application `unapp` */
13961427 def addBinders (unapp : Tree , bound : List [Symbol ]) = unapp match {
13971428 case TypeApply (fn, args) =>
@@ -1430,7 +1461,11 @@ trait Applications extends Compatibility {
14301461 unapplyArgType
14311462
14321463 val dummyArg = dummyTreeOfType(ownType)
1433- val unapplyApp = typedExpr(untpd.TypedSplice (Apply (unapplyFn, dummyArg :: Nil )))
1464+ val (newUnapplyFn, unapplyApp) =
1465+ val unapplyAppCall = withMode(Mode .NoInline ):
1466+ typedExpr(untpd.TypedSplice (Apply (unapplyFn, dummyArg :: Nil )))
1467+ inlinedUnapplyFnAndApp(dummyArg, unapplyAppCall)
1468+
14341469 def unapplyImplicits (unapp : Tree ): List [Tree ] = {
14351470 val res = List .newBuilder[Tree ]
14361471 def loop (unapp : Tree ): Unit = unapp match {
@@ -1459,7 +1494,7 @@ trait Applications extends Compatibility {
14591494 List .fill(argTypes.length - args.length)(WildcardType )
14601495 }
14611496 val unapplyPatterns = bunchedArgs.lazyZip(argTypes) map (typed(_, _))
1462- val result = assignType(cpy.UnApply (tree)(unapplyFn , unapplyImplicits(unapplyApp), unapplyPatterns), ownType)
1497+ val result = assignType(cpy.UnApply (tree)(newUnapplyFn , unapplyImplicits(unapplyApp), unapplyPatterns), ownType)
14631498 unapp.println(s " unapply patterns = $unapplyPatterns" )
14641499 if (ownType.stripped eq selType.stripped) || ownType.isError then result
14651500 else tryWithTypeTest(Typed (result, TypeTree (ownType)), selType)
0 commit comments