@@ -239,7 +239,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
239
239
/** A buffer for bindings that define proxies for actual arguments */
240
240
private val bindingsBuf = new mutable.ListBuffer [ValOrDefDef ]
241
241
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 =
243
243
ctx.newSymbol(ctx.owner, name, flags, info, coord = call.span)
244
244
245
245
/** 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) {
732
732
val gadtSyms = typer.gadtSyms(scrutType)
733
733
734
734
/** 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 `.
736
736
*/
737
737
def reducePattern (
738
- bindingsBuf : mutable.ListBuffer [ValOrDefDef ],
739
- fromBuf : mutable.ListBuffer [TypeSymbol ],
740
- toBuf : mutable.ListBuffer [TypeSymbol ],
738
+ caseBindingMap : mutable.ListBuffer [(Symbol , MemberDef )],
741
739
scrut : TermRef ,
742
740
pat : Tree
743
741
)(implicit ctx : Context ): Boolean = {
744
742
745
743
/** Create a binding of a pattern bound variable with matching part of
746
744
* scrutinee as RHS and type that corresponds to RHS.
747
745
*/
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)))
751
754
}
752
755
753
756
def searchImplicit (sym : TermSymbol , tpt : Tree ) = {
754
757
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)
756
760
evidence.tpe match {
757
761
case fail : Implicits .AmbiguousImplicits =>
758
762
ctx.error(evTyper.missingArgMsg(evidence, tpt.tpe, " " ), tpt.sourcePos)
759
763
true // hard error: return true to stop implicit search here
760
764
case fail : Implicits .SearchFailureType =>
761
765
false
762
766
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)
764
769
true
765
770
}
766
771
}
@@ -810,27 +815,25 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
810
815
extractBindVariance(SimpleIdentityMap .Empty , tpt.tpe)
811
816
}
812
817
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
+
813
823
def registerAsGadtSyms (typeBinds : TypeBindsMap )(implicit ctx : Context ): Unit =
814
824
typeBinds.foreachBinding { case (sym, _) =>
815
825
val TypeBounds (lo, hi) = sym.info.bounds
816
826
ctx.gadt.addBound(sym, lo, isUpper = false )
817
827
ctx.gadt.addBound(sym, hi, isUpper = true )
818
828
}
819
829
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
-
827
830
pat match {
828
831
case Typed (pat1, tpt) =>
829
832
val typeBinds = getTypeBindsMap(pat1, tpt)
830
833
registerAsGadtSyms(typeBinds)
831
834
scrut <:< tpt.tpe && {
832
835
addTypeBindings(typeBinds)
833
- reducePattern(bindingsBuf, fromBuf, toBuf , scrut, pat1)
836
+ reducePattern(caseBindingMap , scrut, pat1)
834
837
}
835
838
case pat @ Bind (name : TermName , Typed (_, tpt)) if isImplicit =>
836
839
val typeBinds = getTypeBindsMap(tpt, tpt)
@@ -840,8 +843,8 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
840
843
true
841
844
}
842
845
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))
845
848
true
846
849
}
847
850
case Ident (nme.WILDCARD ) =>
@@ -864,8 +867,8 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
864
867
case (Nil , Nil ) => true
865
868
case (pat :: pats1, selector :: selectors1) =>
866
869
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) &&
869
872
reduceSubPatterns(pats1, selectors1)
870
873
case _ => false
871
874
}
@@ -892,7 +895,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
892
895
false
893
896
}
894
897
case Inlined (EmptyTree , Nil , ipat) =>
895
- reducePattern(bindingsBuf, fromBuf, toBuf , scrut, ipat)
898
+ reducePattern(caseBindingMap , scrut, ipat)
896
899
case _ => false
897
900
}
898
901
}
@@ -902,32 +905,34 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
902
905
val scrutineeBinding = normalizeBinding(ValDef (scrutineeSym, scrutinee))
903
906
904
907
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)
912
920
}
913
- }
914
- if (! isImplicit) caseBindingsBuf += scrutineeBinding
921
+
922
+ if (! isImplicit) caseBindingMap += (( NoSymbol , scrutineeBinding))
915
923
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
+ }
927
931
}
932
+ if (guardOK) Some ((caseBindings, cdef.body.subst(from, to)))
933
+ else None
928
934
}
929
- else
930
- None
935
+ else None
931
936
}
932
937
933
938
def recur (cases : List [CaseDef ]): MatchRedux = cases match {
@@ -1053,8 +1058,29 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
1053
1058
*/
1054
1059
def dropUnusedDefs (bindings : List [MemberDef ], tree : Tree )(implicit ctx : Context ): (List [MemberDef ], Tree ) = {
1055
1060
// 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 {
1058
1084
val refCount = newMutableSymbolMap[Int ]
1059
1085
val bindingOfSym = newMutableSymbolMap[MemberDef ]
1060
1086
@@ -1063,7 +1089,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
1063
1089
case vdef @ ValDef (_, _, _) => isPureExpr(vdef.rhs)
1064
1090
case _ => false
1065
1091
}
1066
- for (binding <- termBindings if isInlineable(binding)) {
1092
+ for (binding <- bindings if isInlineable(binding)) {
1067
1093
refCount(binding.symbol) = 0
1068
1094
bindingOfSym(binding.symbol) = binding
1069
1095
}
@@ -1121,40 +1147,15 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
1121
1147
}
1122
1148
}
1123
1149
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)
1127
1153
}
1128
1154
else {
1129
1155
val expanded = inlineBindings.transform(tree)
1130
1156
dropUnusedDefs(retained, expanded)
1131
1157
}
1132
1158
}
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
- }
1158
1159
}
1159
1160
1160
1161
private def expandMacro (body : Tree , span : Span )(implicit ctx : Context ) = {
0 commit comments