@@ -34,6 +34,7 @@ import Denotations.SingleDenotation
34
34
import annotation .threadUnsafe
35
35
36
36
import scala .util .control .NonFatal
37
+ import dotty .tools .dotc .inlines .Inlines
37
38
38
39
object Applications {
39
40
import tpd .*
@@ -1408,6 +1409,36 @@ trait Applications extends Compatibility {
1408
1409
}
1409
1410
}
1410
1411
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
+
1411
1442
/** Add a `Bind` node for each `bound` symbol in a type application `unapp` */
1412
1443
def addBinders (unapp : Tree , bound : List [Symbol ]) = unapp match {
1413
1444
case TypeApply (fn, args) =>
@@ -1446,7 +1477,11 @@ trait Applications extends Compatibility {
1446
1477
unapplyArgType
1447
1478
1448
1479
val dummyArg = dummyTreeOfType(ownType)
1449
- val unapplyApp = typedExpr(untpd.TypedSplice (Apply (unapplyFn, dummyArg :: Nil )))
1480
+ val (newUnapplyFn, unapplyApp) =
1481
+ val unapplyAppCall = withMode(Mode .NoInline ):
1482
+ typedExpr(untpd.TypedSplice (Apply (unapplyFn, dummyArg :: Nil )))
1483
+ inlinedUnapplyFnAndApp(dummyArg, unapplyAppCall)
1484
+
1450
1485
def unapplyImplicits (unapp : Tree ): List [Tree ] = {
1451
1486
val res = List .newBuilder[Tree ]
1452
1487
def loop (unapp : Tree ): Unit = unapp match {
@@ -1475,7 +1510,7 @@ trait Applications extends Compatibility {
1475
1510
List .fill(argTypes.length - args.length)(WildcardType )
1476
1511
}
1477
1512
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(unapplyApp), unapplyPatterns), ownType)
1479
1514
unapp.println(s " unapply patterns = $unapplyPatterns" )
1480
1515
if (ownType.stripped eq selType.stripped) || ownType.isError then result
1481
1516
else tryWithTypeTest(Typed (result, TypeTree (ownType)), selType)
0 commit comments