@@ -730,35 +730,40 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
730
730
val gadtSyms = typer.gadtSyms(scrutType)
731
731
732
732
/** Try to match pattern `pat` against scrutinee reference `scrut`. If successful add
733
- * bindings for variables bound in this pattern to `bindingsBuf `.
733
+ * bindings for variables bound in this pattern to `caseBindingMap `.
734
734
*/
735
735
def reducePattern (
736
- bindingsBuf : mutable.ListBuffer [ValOrDefDef ],
737
- fromBuf : mutable.ListBuffer [TypeSymbol ],
738
- toBuf : mutable.ListBuffer [TypeSymbol ],
736
+ caseBindingMap : mutable.ListBuffer [(Symbol , MemberDef )],
739
737
scrut : TermRef ,
740
738
pat : Tree
741
739
)(implicit ctx : Context ): Boolean = {
742
740
743
741
/** Create a binding of a pattern bound variable with matching part of
744
742
* scrutinee as RHS and type that corresponds to RHS.
745
743
*/
746
- def newBinding (sym : TermSymbol , rhs : Tree ): Unit = {
747
- sym.info = rhs.tpe.widenTermRefExpr
748
- bindingsBuf += ValDef (sym, constToLiteral(rhs)).withSpan(sym.span)
744
+ def newTermBinding (sym : TermSymbol , rhs : Tree ): Unit = {
745
+ val copied = sym.copy(info = rhs.tpe.widenTermRefExpr, coord = sym.coord).asTerm
746
+ caseBindingMap += ((sym, ValDef (copied, constToLiteral(rhs)).withSpan(sym.span)))
747
+ }
748
+
749
+ def newTypeBinding (sym : TypeSymbol , alias : Type ): Unit = {
750
+ val copied = sym.copy(info = TypeAlias (alias), coord = sym.coord).asType
751
+ caseBindingMap += ((sym, TypeDef (copied)))
749
752
}
750
753
751
754
def searchImplicit (sym : TermSymbol , tpt : Tree ) = {
752
755
val evTyper = new Typer
753
- val evidence = evTyper.inferImplicitArg(tpt.tpe, tpt.span)(ctx.fresh.setTyper(evTyper))
756
+ val evCtx = ctx.fresh.setTyper(evTyper)
757
+ val evidence = evTyper.inferImplicitArg(tpt.tpe, tpt.span)(evCtx)
754
758
evidence.tpe match {
755
759
case fail : Implicits .AmbiguousImplicits =>
756
760
ctx.error(evTyper.missingArgMsg(evidence, tpt.tpe, " " ), tpt.sourcePos)
757
761
true // hard error: return true to stop implicit search here
758
762
case fail : Implicits .SearchFailureType =>
759
763
false
760
764
case _ =>
761
- newBinding(sym, evidence)
765
+ // inliner.println(i"inferred implicit $sym: ${sym.info} with $evidence: ${evidence.tpe.widen}, ${evCtx.gadt.constraint}, ${evCtx.typerState.constraint}")
766
+ newTermBinding(sym, evidence)
762
767
true
763
768
}
764
769
}
@@ -808,27 +813,25 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
808
813
extractBindVariance(SimpleIdentityMap .Empty , tpt.tpe)
809
814
}
810
815
816
+ def addTypeBindings (typeBinds : TypeBindsMap )(implicit ctx : Context ): Unit =
817
+ typeBinds.foreachBinding { case (sym, shouldBeMinimized) =>
818
+ newTypeBinding(sym, ctx.gadt.approximation(sym, fromBelow = shouldBeMinimized))
819
+ }
820
+
811
821
def registerAsGadtSyms (typeBinds : TypeBindsMap )(implicit ctx : Context ): Unit =
812
822
typeBinds.foreachBinding { case (sym, _) =>
813
823
val TypeBounds (lo, hi) = sym.info.bounds
814
824
ctx.gadt.addBound(sym, lo, isUpper = false )
815
825
ctx.gadt.addBound(sym, hi, isUpper = true )
816
826
}
817
827
818
- def addTypeBindings (typeBinds : TypeBindsMap )(implicit ctx : Context ): Unit =
819
- typeBinds.foreachBinding { case (sym, shouldBeMinimized) =>
820
- val copied = sym.copy(info = TypeAlias (ctx.gadt.approximation(sym, fromBelow = shouldBeMinimized))).asType
821
- fromBuf += sym
822
- toBuf += copied
823
- }
824
-
825
828
pat match {
826
829
case Typed (pat1, tpt) =>
827
830
val typeBinds = getTypeBindsMap(pat1, tpt)
828
831
registerAsGadtSyms(typeBinds)
829
832
scrut <:< tpt.tpe && {
830
833
addTypeBindings(typeBinds)
831
- reducePattern(bindingsBuf, fromBuf, toBuf , scrut, pat1)
834
+ reducePattern(caseBindingMap , scrut, pat1)
832
835
}
833
836
case pat @ Bind (name : TermName , Typed (_, tpt)) if isImplicit =>
834
837
val typeBinds = getTypeBindsMap(tpt, tpt)
@@ -838,8 +841,8 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
838
841
true
839
842
}
840
843
case pat @ Bind (name : TermName , body) =>
841
- reducePattern(bindingsBuf, fromBuf, toBuf , scrut, body) && {
842
- if (name != nme.WILDCARD ) newBinding (pat.symbol.asTerm, ref(scrut))
844
+ reducePattern(caseBindingMap , scrut, body) && {
845
+ if (name != nme.WILDCARD ) newTermBinding (pat.symbol.asTerm, ref(scrut))
843
846
true
844
847
}
845
848
case Ident (nme.WILDCARD ) =>
@@ -862,8 +865,8 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
862
865
case (Nil , Nil ) => true
863
866
case (pat :: pats1, selector :: selectors1) =>
864
867
val elem = newSym(InlineBinderName .fresh(), Synthetic , selector.tpe.widenTermRefExpr).asTerm
865
- newBinding( elem, selector)
866
- reducePattern(bindingsBuf, fromBuf, toBuf , elem.termRef, pat) &&
868
+ caseBindingMap += (( NoSymbol , ValDef ( elem, constToLiteral( selector)).withSpan(elem.span)) )
869
+ reducePattern(caseBindingMap , elem.termRef, pat) &&
867
870
reduceSubPatterns(pats1, selectors1)
868
871
case _ => false
869
872
}
@@ -890,7 +893,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
890
893
false
891
894
}
892
895
case Inlined (EmptyTree , Nil , ipat) =>
893
- reducePattern(bindingsBuf, fromBuf, toBuf , scrut, ipat)
896
+ reducePattern(caseBindingMap , scrut, ipat)
894
897
case _ => false
895
898
}
896
899
}
@@ -900,30 +903,34 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
900
903
val scrutineeBinding = normalizeBinding(ValDef (scrutineeSym, scrutinee))
901
904
902
905
def reduceCase (cdef : CaseDef ): MatchRedux = {
903
- val caseBindingsBuf = new mutable.ListBuffer [ValOrDefDef ]()
904
- def guardOK (implicit ctx : Context ) = cdef.guard.isEmpty || {
905
- typer.typed(cdef.guard, defn.BooleanType ) match {
906
- case ConstantValue (true ) => true
907
- case _ => false
906
+ val caseBindingMap = new mutable.ListBuffer [(Symbol , MemberDef )]()
907
+
908
+ def substBindings (
909
+ bindings : List [(Symbol , MemberDef )],
910
+ bbuf : mutable.ListBuffer [MemberDef ],
911
+ from : List [Symbol ], to : List [Symbol ]): (List [MemberDef ], List [Symbol ], List [Symbol ]) =
912
+ bindings match {
913
+ case (sym, binding) :: rest =>
914
+ bbuf += binding.subst(from, to).asInstanceOf [MemberDef ]
915
+ if (sym.exists) substBindings(rest, bbuf, sym :: from, binding.symbol :: to)
916
+ else substBindings(rest, bbuf, from, to)
917
+ case Nil => (bbuf.toList, from, to)
908
918
}
909
- }
910
- if (! isImplicit) caseBindingsBuf += scrutineeBinding
919
+
920
+ if (! isImplicit) caseBindingMap += (( NoSymbol , scrutineeBinding))
911
921
val gadtCtx = typer.gadtContext(gadtSyms).addMode(Mode .GADTflexible )
912
- val fromBuf = mutable.ListBuffer .empty[TypeSymbol ]
913
- val toBuf = mutable.ListBuffer .empty[TypeSymbol ]
914
- if (reducePattern(caseBindingsBuf, fromBuf, toBuf, scrutineeSym.termRef, cdef.pat)(gadtCtx) && guardOK) {
915
- val caseBindings = caseBindingsBuf.toList
916
- val from = fromBuf.toList
917
- val to = toBuf.toList
918
- if (from.isEmpty) Some ((caseBindings, cdef.body))
919
- else {
920
- val Block (stats, expr) = tpd.Block (caseBindings, cdef.body).subst(from, to)
921
- val typeDefs = to.collect { case sym if sym.name != tpnme.WILDCARD => tpd.TypeDef (sym).withSpan(sym.span) }
922
- Some ((typeDefs ::: stats.asInstanceOf [List [MemberDef ]], expr))
922
+ if (reducePattern(caseBindingMap, scrutineeSym.termRef, cdef.pat)(gadtCtx)) {
923
+ val (caseBindings, from, to) = substBindings(caseBindingMap.toList, mutable.ListBuffer (), Nil , Nil )
924
+ val guardOK = cdef.guard.isEmpty || {
925
+ typer.typed(cdef.guard.subst(from, to), defn.BooleanType ) match {
926
+ case ConstantValue (true ) => true
927
+ case _ => false
928
+ }
923
929
}
930
+ if (guardOK) Some ((caseBindings, cdef.body.subst(from, to)))
931
+ else None
924
932
}
925
- else
926
- None
933
+ else None
927
934
}
928
935
929
936
def recur (cases : List [CaseDef ]): MatchRedux = cases match {
0 commit comments