@@ -239,7 +239,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
239239 /** A buffer for bindings that define proxies for actual arguments */
240240 private val bindingsBuf = new mutable.ListBuffer [ValOrDefDef ]
241241
242- private def newSym (name : Name , flags : FlagSet , info : Type ): Symbol =
242+ private def newSym (name : Name , flags : FlagSet , info : Type )( implicit ctx : Context ) : Symbol =
243243 ctx.newSymbol(ctx.owner, name, flags, info, coord = call.span)
244244
245245 /** A binding for the parameter of an inline method. This is a `val` def for
@@ -732,35 +732,40 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
732732 val gadtSyms = typer.gadtSyms(scrutType)
733733
734734 /** Try to match pattern `pat` against scrutinee reference `scrut`. If successful add
735- * bindings for variables bound in this pattern to `bindingsBuf `.
735+ * bindings for variables bound in this pattern to `caseBindingMap `.
736736 */
737737 def reducePattern (
738- bindingsBuf : mutable.ListBuffer [ValOrDefDef ],
739- fromBuf : mutable.ListBuffer [TypeSymbol ],
740- toBuf : mutable.ListBuffer [TypeSymbol ],
738+ caseBindingMap : mutable.ListBuffer [(Symbol , MemberDef )],
741739 scrut : TermRef ,
742740 pat : Tree
743741 )(implicit ctx : Context ): Boolean = {
744742
745743 /** Create a binding of a pattern bound variable with matching part of
746744 * scrutinee as RHS and type that corresponds to RHS.
747745 */
748- def newBinding (sym : TermSymbol , rhs : Tree ): Unit = {
749- sym.info = rhs.tpe.widenTermRefExpr
750- bindingsBuf += ValDef (sym, constToLiteral(rhs)).withSpan(sym.span)
746+ def newTermBinding (sym : TermSymbol , rhs : Tree ): Unit = {
747+ val copied = sym.copy(info = rhs.tpe.widenTermRefExpr, coord = sym.coord).asTerm
748+ caseBindingMap += ((sym, ValDef (copied, constToLiteral(rhs)).withSpan(sym.span)))
749+ }
750+
751+ def newTypeBinding (sym : TypeSymbol , alias : Type ): Unit = {
752+ val copied = sym.copy(info = TypeAlias (alias), coord = sym.coord).asType
753+ caseBindingMap += ((sym, TypeDef (copied)))
751754 }
752755
753756 def searchImplicit (sym : TermSymbol , tpt : Tree ) = {
754757 val evTyper = new Typer
755- val evidence = evTyper.inferImplicitArg(tpt.tpe, tpt.span)(ctx.fresh.setTyper(evTyper))
758+ val evCtx = ctx.fresh.setTyper(evTyper)
759+ val evidence = evTyper.inferImplicitArg(tpt.tpe, tpt.span)(evCtx)
756760 evidence.tpe match {
757761 case fail : Implicits .AmbiguousImplicits =>
758762 ctx.error(evTyper.missingArgMsg(evidence, tpt.tpe, " " ), tpt.sourcePos)
759763 true // hard error: return true to stop implicit search here
760764 case fail : Implicits .SearchFailureType =>
761765 false
762766 case _ =>
763- newBinding(sym, evidence)
767+ // inliner.println(i"inferred implicit $sym: ${sym.info} with $evidence: ${evidence.tpe.widen}, ${evCtx.gadt.constraint}, ${evCtx.typerState.constraint}")
768+ newTermBinding(sym, evidence)
764769 true
765770 }
766771 }
@@ -810,27 +815,25 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
810815 extractBindVariance(SimpleIdentityMap .Empty , tpt.tpe)
811816 }
812817
818+ def addTypeBindings (typeBinds : TypeBindsMap )(implicit ctx : Context ): Unit =
819+ typeBinds.foreachBinding { case (sym, shouldBeMinimized) =>
820+ newTypeBinding(sym, ctx.gadt.approximation(sym, fromBelow = shouldBeMinimized))
821+ }
822+
813823 def registerAsGadtSyms (typeBinds : TypeBindsMap )(implicit ctx : Context ): Unit =
814824 typeBinds.foreachBinding { case (sym, _) =>
815825 val TypeBounds (lo, hi) = sym.info.bounds
816826 ctx.gadt.addBound(sym, lo, isUpper = false )
817827 ctx.gadt.addBound(sym, hi, isUpper = true )
818828 }
819829
820- def addTypeBindings (typeBinds : TypeBindsMap )(implicit ctx : Context ): Unit =
821- typeBinds.foreachBinding { case (sym, shouldBeMinimized) =>
822- val copied = sym.copy(info = TypeAlias (ctx.gadt.approximation(sym, fromBelow = shouldBeMinimized))).asType
823- fromBuf += sym
824- toBuf += copied
825- }
826-
827830 pat match {
828831 case Typed (pat1, tpt) =>
829832 val typeBinds = getTypeBindsMap(pat1, tpt)
830833 registerAsGadtSyms(typeBinds)
831834 scrut <:< tpt.tpe && {
832835 addTypeBindings(typeBinds)
833- reducePattern(bindingsBuf, fromBuf, toBuf , scrut, pat1)
836+ reducePattern(caseBindingMap , scrut, pat1)
834837 }
835838 case pat @ Bind (name : TermName , Typed (_, tpt)) if isImplicit =>
836839 val typeBinds = getTypeBindsMap(tpt, tpt)
@@ -840,8 +843,8 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
840843 true
841844 }
842845 case pat @ Bind (name : TermName , body) =>
843- reducePattern(bindingsBuf, fromBuf, toBuf , scrut, body) && {
844- if (name != nme.WILDCARD ) newBinding (pat.symbol.asTerm, ref(scrut))
846+ reducePattern(caseBindingMap , scrut, body) && {
847+ if (name != nme.WILDCARD ) newTermBinding (pat.symbol.asTerm, ref(scrut))
845848 true
846849 }
847850 case Ident (nme.WILDCARD ) =>
@@ -864,8 +867,8 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
864867 case (Nil , Nil ) => true
865868 case (pat :: pats1, selector :: selectors1) =>
866869 val elem = newSym(InlineBinderName .fresh(), Synthetic , selector.tpe.widenTermRefExpr).asTerm
867- newBinding( elem, selector)
868- reducePattern(bindingsBuf, fromBuf, toBuf , elem.termRef, pat) &&
870+ caseBindingMap += (( NoSymbol , ValDef ( elem, constToLiteral( selector)).withSpan(elem.span)) )
871+ reducePattern(caseBindingMap , elem.termRef, pat) &&
869872 reduceSubPatterns(pats1, selectors1)
870873 case _ => false
871874 }
@@ -892,7 +895,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
892895 false
893896 }
894897 case Inlined (EmptyTree , Nil , ipat) =>
895- reducePattern(bindingsBuf, fromBuf, toBuf , scrut, ipat)
898+ reducePattern(caseBindingMap , scrut, ipat)
896899 case _ => false
897900 }
898901 }
@@ -902,32 +905,34 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
902905 val scrutineeBinding = normalizeBinding(ValDef (scrutineeSym, scrutinee))
903906
904907 def reduceCase (cdef : CaseDef ): MatchRedux = {
905- val caseBindingsBuf = new mutable.ListBuffer [ValOrDefDef ]()
906- def guardOK (implicit ctx : Context ) = cdef.guard.isEmpty || {
907- val guardCtx = ctx.fresh.setNewScope
908- caseBindingsBuf.foreach(binding => guardCtx.enter(binding.symbol))
909- typer.typed(cdef.guard, defn.BooleanType )(guardCtx) match {
910- case ConstantValue (true ) => true
911- case _ => false
908+ val caseBindingMap = new mutable.ListBuffer [(Symbol , MemberDef )]()
909+
910+ def substBindings (
911+ bindings : List [(Symbol , MemberDef )],
912+ bbuf : mutable.ListBuffer [MemberDef ],
913+ from : List [Symbol ], to : List [Symbol ]): (List [MemberDef ], List [Symbol ], List [Symbol ]) =
914+ bindings match {
915+ case (sym, binding) :: rest =>
916+ bbuf += binding.subst(from, to).asInstanceOf [MemberDef ]
917+ if (sym.exists) substBindings(rest, bbuf, sym :: from, binding.symbol :: to)
918+ else substBindings(rest, bbuf, from, to)
919+ case Nil => (bbuf.toList, from, to)
912920 }
913- }
914- if (! isImplicit) caseBindingsBuf += scrutineeBinding
921+
922+ if (! isImplicit) caseBindingMap += (( NoSymbol , scrutineeBinding))
915923 val gadtCtx = typer.gadtContext(gadtSyms).addMode(Mode .GADTflexible )
916- val fromBuf = mutable.ListBuffer .empty[TypeSymbol ]
917- val toBuf = mutable.ListBuffer .empty[TypeSymbol ]
918- if (reducePattern(caseBindingsBuf, fromBuf, toBuf, scrutineeSym.termRef, cdef.pat)(gadtCtx) && guardOK) {
919- val caseBindings = caseBindingsBuf.toList
920- val from = fromBuf.toList
921- val to = toBuf.toList
922- if (from.isEmpty) Some ((caseBindings, cdef.body))
923- else {
924- val Block (stats, expr) = tpd.Block (caseBindings, cdef.body).subst(from, to)
925- val typeDefs = to.collect { case sym if sym.name != tpnme.WILDCARD => tpd.TypeDef (sym).withSpan(sym.span) }
926- Some ((typeDefs ::: stats.asInstanceOf [List [MemberDef ]], expr))
924+ if (reducePattern(caseBindingMap, scrutineeSym.termRef, cdef.pat)(gadtCtx)) {
925+ val (caseBindings, from, to) = substBindings(caseBindingMap.toList, mutable.ListBuffer (), Nil , Nil )
926+ val guardOK = cdef.guard.isEmpty || {
927+ typer.typed(cdef.guard.subst(from, to), defn.BooleanType ) match {
928+ case ConstantValue (true ) => true
929+ case _ => false
930+ }
927931 }
932+ if (guardOK) Some ((caseBindings, cdef.body.subst(from, to)))
933+ else None
928934 }
929- else
930- None
935+ else None
931936 }
932937
933938 def recur (cases : List [CaseDef ]): MatchRedux = cases match {
@@ -1053,8 +1058,29 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
10531058 */
10541059 def dropUnusedDefs (bindings : List [MemberDef ], tree : Tree )(implicit ctx : Context ): (List [MemberDef ], Tree ) = {
10551060 // inlining.println(i"drop unused $bindings%, % in $tree")
1056-
1057- def inlineTermBindings (termBindings : List [MemberDef ], tree : Tree )(implicit ctx : Context ): (List [MemberDef ], Tree ) = {
1061+ val (termBindings, typeBindings) = bindings.partition(_.symbol.isTerm)
1062+ if (typeBindings.nonEmpty) {
1063+ val typeBindingsSet = typeBindings.foldLeft[SimpleIdentitySet [Symbol ]](SimpleIdentitySet .empty)(_ + _.symbol)
1064+ val inlineTypeBindings = new TreeTypeMap (
1065+ typeMap = new TypeMap () {
1066+ override def apply (tp : Type ): Type = tp match {
1067+ case tr : TypeRef if tr.prefix.eq(NoPrefix ) && typeBindingsSet.contains(tr.symbol) =>
1068+ val TypeAlias (res) = tr.info
1069+ res
1070+ case tp => mapOver(tp)
1071+ }
1072+ },
1073+ treeMap = {
1074+ case ident : Ident if ident.isType && typeBindingsSet.contains(ident.symbol) =>
1075+ val TypeAlias (r) = ident.symbol.info
1076+ TypeTree (r).withSpan(ident.span)
1077+ case tree => tree
1078+ }
1079+ )
1080+ val Block (termBindings1, tree1) = inlineTypeBindings(Block (termBindings, tree))
1081+ dropUnusedDefs(termBindings1.asInstanceOf [List [ValOrDefDef ]], tree1)
1082+ }
1083+ else {
10581084 val refCount = newMutableSymbolMap[Int ]
10591085 val bindingOfSym = newMutableSymbolMap[MemberDef ]
10601086
@@ -1063,7 +1089,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
10631089 case vdef @ ValDef (_, _, _) => isPureExpr(vdef.rhs)
10641090 case _ => false
10651091 }
1066- for (binding <- termBindings if isInlineable(binding)) {
1092+ for (binding <- bindings if isInlineable(binding)) {
10671093 refCount(binding.symbol) = 0
10681094 bindingOfSym(binding.symbol) = binding
10691095 }
@@ -1121,40 +1147,15 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
11211147 }
11221148 }
11231149
1124- val retained = termBindings .filterConserve(binding => retain(binding.symbol))
1125- if (retained `eq` termBindings ) {
1126- (termBindings , tree)
1150+ val retained = bindings .filterConserve(binding => retain(binding.symbol))
1151+ if (retained `eq` bindings ) {
1152+ (bindings , tree)
11271153 }
11281154 else {
11291155 val expanded = inlineBindings.transform(tree)
11301156 dropUnusedDefs(retained, expanded)
11311157 }
11321158 }
1133-
1134- val (termBindings, typeBindings) = bindings.partition(_.symbol.isTerm)
1135- if (typeBindings.isEmpty) inlineTermBindings(termBindings, tree)
1136- else {
1137- val typeBindingsSet = typeBindings.foldLeft[SimpleIdentitySet [Symbol ]](SimpleIdentitySet .empty)(_ + _.symbol)
1138- val inlineTypeBindings = new TreeTypeMap (
1139- typeMap = new TypeMap () {
1140- override def apply (tp : Type ): Type = tp match {
1141- case tr : TypeRef if tr.prefix.eq(NoPrefix ) && typeBindingsSet.contains(tr.symbol) =>
1142- val TypeAlias (res) = tr.info
1143- res
1144- case tp => mapOver(tp)
1145- }
1146- },
1147- treeMap = {
1148- case ident : Ident if ident.isType && typeBindingsSet.contains(ident.symbol) =>
1149- val TypeAlias (r) = ident.symbol.info
1150- TypeTree (r).withSpan(ident.span)
1151- case tree => tree
1152- }
1153- )
1154-
1155- val Block (termBindings1, tree1) = inlineTypeBindings(Block (termBindings, tree))
1156- inlineTermBindings(termBindings1.asInstanceOf [List [ValOrDefDef ]], tree1)
1157- }
11581159 }
11591160
11601161 private def expandMacro (body : Tree , span : Span )(implicit ctx : Context ) = {
0 commit comments