@@ -15,7 +15,7 @@ import StdNames.nme
1515import Contexts .Context
1616import Names .{Name , TermName , EmptyTermName }
1717import NameOps ._
18- import NameKinds .{ClassifiedNameKind , InlineAccessorName }
18+ import NameKinds .{ClassifiedNameKind , InlineAccessorName , UniqueName }
1919import ProtoTypes .selectionProto
2020import SymDenotations .SymDenotation
2121import Annotations ._
@@ -216,7 +216,8 @@ object Inliner {
216216 for (iref <- referenced.implicitRefs.toList) yield {
217217 val localImplicit = iref.symbol.asTerm.copy(
218218 owner = inlineMethod,
219- flags = Implicit | Method ,
219+ name = UniqueName .fresh(iref.symbol.name.asTermName),
220+ flags = Implicit | Method | Stable ,
220221 info = iref.symbol.info.ensureMethodic,
221222 coord = inlineMethod.pos).asTerm
222223 polyDefDef(localImplicit, tps => vrefss =>
@@ -530,10 +531,12 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
530531 /** All bindings in `bindingsBuf` except bindings of inlineable closures */
531532 val bindings = bindingsBuf.toList.map(_.withPos(call.pos))
532533
534+ val (finalBindings, finalExpansion) = dropUnusedDefs(bindings, expansion1)
535+
533536 // println(i"bindings buf = ${bindingsBuf.toList}%; %")
534537 // println(i"bindings = ${bindings.toList}%; %")
535538
536- tpd.Inlined (call, bindings, expansion1 )
539+ tpd.Inlined (call, finalBindings, finalExpansion )
537540 }
538541 }
539542
@@ -625,4 +628,76 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
625628
626629 override def newLikeThis : Typer = new InlineTyper
627630 }
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+ }
628703}
0 commit comments