@@ -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 .*
@@ -1392,6 +1393,50 @@ trait Applications extends Compatibility {
1392
1393
}
1393
1394
}
1394
1395
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
+
1426
+ def unapplyImplicits (dummyArg : Tree , unapp : Tree ): List [Tree ] =
1427
+ val res = List .newBuilder[Tree ]
1428
+ def loop (unapp : Tree ): Unit = unapp match
1429
+ case Apply (Apply (unapply, `dummyArg` :: Nil ), args2) => assert(args2.nonEmpty); res ++= args2
1430
+ case Apply (unapply, `dummyArg` :: Nil ) =>
1431
+ case Inlined (u, _, _) => loop(u)
1432
+ case DynamicUnapply (_) => report.error(em " Structural unapply is not supported " , unapplyFn.srcPos)
1433
+ case Apply (fn, args) => assert(args.nonEmpty); loop(fn); res ++= args
1434
+ case _ => ().assertingErrorsReported
1435
+
1436
+ loop(unapp)
1437
+ res.result()
1438
+ end unapplyImplicits
1439
+
1395
1440
/** Add a `Bind` node for each `bound` symbol in a type application `unapp` */
1396
1441
def addBinders (unapp : Tree , bound : List [Symbol ]) = unapp match {
1397
1442
case TypeApply (fn, args) =>
@@ -1430,20 +1475,10 @@ trait Applications extends Compatibility {
1430
1475
unapplyArgType
1431
1476
1432
1477
val dummyArg = dummyTreeOfType(ownType)
1433
- val unapplyApp = typedExpr(untpd.TypedSplice (Apply (unapplyFn, dummyArg :: Nil )))
1434
- def unapplyImplicits (unapp : Tree ): List [Tree ] = {
1435
- val res = List .newBuilder[Tree ]
1436
- def loop (unapp : Tree ): Unit = unapp match {
1437
- case Apply (Apply (unapply, `dummyArg` :: Nil ), args2) => assert(args2.nonEmpty); res ++= args2
1438
- case Apply (unapply, `dummyArg` :: Nil ) =>
1439
- case Inlined (u, _, _) => loop(u)
1440
- case DynamicUnapply (_) => report.error(em " Structural unapply is not supported " , unapplyFn.srcPos)
1441
- case Apply (fn, args) => assert(args.nonEmpty); loop(fn); res ++= args
1442
- case _ => ().assertingErrorsReported
1443
- }
1444
- loop(unapp)
1445
- res.result()
1446
- }
1478
+ val (newUnapplyFn, unapplyApp) =
1479
+ val unapplyAppCall = withMode(Mode .NoInline ):
1480
+ typedExpr(untpd.TypedSplice (Apply (unapplyFn, dummyArg :: Nil )))
1481
+ inlinedUnapplyFnAndApp(dummyArg, unapplyAppCall)
1447
1482
1448
1483
var argTypes = unapplyArgs(unapplyApp.tpe, unapplyFn, args, tree.srcPos)
1449
1484
for (argType <- argTypes) assert(! isBounds(argType), unapplyApp.tpe.show)
@@ -1459,7 +1494,7 @@ trait Applications extends Compatibility {
1459
1494
List .fill(argTypes.length - args.length)(WildcardType )
1460
1495
}
1461
1496
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(dummyArg, unapplyApp), unapplyPatterns), ownType)
1463
1498
unapp.println(s " unapply patterns = $unapplyPatterns" )
1464
1499
if (ownType.stripped eq selType.stripped) || ownType.isError then result
1465
1500
else tryWithTypeTest(Typed (result, TypeTree (ownType)), selType)
0 commit comments