@@ -15,7 +15,7 @@ import StdNames.nme
15
15
import Contexts .Context
16
16
import Names .{Name , TermName , EmptyTermName }
17
17
import NameOps ._
18
- import NameKinds .{ClassifiedNameKind , InlineAccessorName }
18
+ import NameKinds .{ClassifiedNameKind , InlineAccessorName , UniqueName }
19
19
import ProtoTypes .selectionProto
20
20
import SymDenotations .SymDenotation
21
21
import Annotations ._
@@ -216,7 +216,8 @@ object Inliner {
216
216
for (iref <- referenced.implicitRefs.toList) yield {
217
217
val localImplicit = iref.symbol.asTerm.copy(
218
218
owner = inlineMethod,
219
- flags = Implicit | Method ,
219
+ name = UniqueName .fresh(iref.symbol.name.asTermName),
220
+ flags = Implicit | Method | Stable ,
220
221
info = iref.symbol.info.ensureMethodic,
221
222
coord = inlineMethod.pos).asTerm
222
223
polyDefDef(localImplicit, tps => vrefss =>
@@ -530,10 +531,12 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
530
531
/** All bindings in `bindingsBuf` except bindings of inlineable closures */
531
532
val bindings = bindingsBuf.toList.map(_.withPos(call.pos))
532
533
534
+ val (finalBindings, finalExpansion) = dropUnusedDefs(bindings, expansion1)
535
+
533
536
// println(i"bindings buf = ${bindingsBuf.toList}%; %")
534
537
// println(i"bindings = ${bindings.toList}%; %")
535
538
536
- tpd.Inlined (call, bindings, expansion1 )
539
+ tpd.Inlined (call, finalBindings, finalExpansion )
537
540
}
538
541
}
539
542
@@ -625,4 +628,76 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
625
628
626
629
override def newLikeThis : Typer = new InlineTyper
627
630
}
631
+
632
+ /** Drop any side-effect-free bindings that are unused in expansion or other reachable bindings.
633
+ * Inline def bindings that are used only once.
634
+ */
635
+ def dropUnusedDefs (bindings : List [ValOrDefDef ], tree : Tree )(implicit ctx : Context ): (List [ValOrDefDef ], Tree ) = {
636
+ val refCount = newMutableSymbolMap[Int ]
637
+ val bindingOfSym = newMutableSymbolMap[ValOrDefDef ]
638
+ def isInlineable (binding : ValOrDefDef ) = binding match {
639
+ case DefDef (_, Nil , Nil , _, _) => true
640
+ case vdef @ ValDef (_, _, _) => isPureExpr(vdef.rhs)
641
+ case _ => false
642
+ }
643
+ for (binding <- bindings if isInlineable(binding)) {
644
+ refCount(binding.symbol) = 0
645
+ bindingOfSym(binding.symbol) = binding
646
+ }
647
+ val countRefs = new TreeTraverser {
648
+ override def traverse (t : Tree )(implicit ctx : Context ) = {
649
+ t match {
650
+ case t : RefTree =>
651
+ refCount.get(t.symbol) match {
652
+ case Some (x) => refCount(t.symbol) = x + 1
653
+ case none =>
654
+ }
655
+ case _ : New | _ : TypeTree =>
656
+ // println(i"refcount ${t.tpe}")
657
+ t.tpe.foreachPart {
658
+ case ref : TermRef =>
659
+ refCount.get(ref.symbol) match {
660
+ case Some (x) => refCount(ref.symbol) = x + 2
661
+ case none =>
662
+ }
663
+ case _ =>
664
+ }
665
+ case _ =>
666
+ }
667
+ traverseChildren(t)
668
+ }
669
+ }
670
+ countRefs.traverse(tree)
671
+ for (binding <- bindings) countRefs.traverse(binding.rhs)
672
+ val inlineBindings = new TreeMap {
673
+ override def transform (t : Tree )(implicit ctx : Context ) =
674
+ super .transform {
675
+ t match {
676
+ case t : RefTree =>
677
+ val sym = t.symbol
678
+ refCount.get(sym) match {
679
+ case Some (1 ) if sym.is(Method ) =>
680
+ bindingOfSym(sym).rhs.changeOwner(sym, ctx.owner)
681
+ case none => t
682
+ }
683
+ case _ => t
684
+ }
685
+ }
686
+ }
687
+ def retain (binding : ValOrDefDef ) = refCount.get(binding.symbol) match {
688
+ case Some (x) => x > 1 || x == 1 && ! binding.symbol.is(Method )
689
+ case none => true
690
+ }
691
+ val retained = bindings.filterConserve(retain)
692
+ if (retained `eq` bindings) {
693
+ // println(i"DONE\n${bindings}%\n% ;;;\n ${tree}")
694
+ (bindings, tree)
695
+ }
696
+ else {
697
+ val expanded = inlineBindings.transform(tree)
698
+ // println(i"ref counts: ${refCount.toMap map { case (sym, count) => i"$sym -> $count" }}")
699
+ // println(i"""MAPPING\n${bindings}%\n% ;;;\n ${tree} \n------->\n${retained}%\n%;;;\n ${expanded} """)
700
+ dropUnusedDefs(retained, expanded)
701
+ }
702
+ }
628
703
}
0 commit comments