@@ -11,7 +11,7 @@ import Symbols._
11
11
import Types ._
12
12
import Decorators ._
13
13
import Constants ._
14
- import StdNames .nme
14
+ import StdNames ._
15
15
import Contexts .Context
16
16
import Names .{Name , TermName , EmptyTermName }
17
17
import NameOps ._
@@ -602,7 +602,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
602
602
newOwners = ctx.owner :: Nil ,
603
603
substFrom = ddef.vparamss.head.map(_.symbol),
604
604
substTo = argSyms)
605
- Block (bindingsBuf.toList, expander.transform(ddef.rhs))
605
+ seq (bindingsBuf.toList, expander.transform(ddef.rhs))
606
606
case _ => tree
607
607
}
608
608
case _ => tree
@@ -629,7 +629,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
629
629
/** Try to match pattern `pat` against scrutinee reference `scrut`. If successful add
630
630
* bindings for variables bound in this pattern to `bindingsBuf`.
631
631
*/
632
- def reducePattern (bindingsBuf : mutable.ListBuffer [MemberDef ], scrut : TermRef , pat : Tree ): Boolean = {
632
+ def reducePattern (bindingsBuf : mutable.ListBuffer [MemberDef ], scrut : TermRef , pat : Tree )( implicit ctx : Context ) : Boolean = {
633
633
val isImplicit = scrut.info == defn.ImplicitScrutineeTypeRef
634
634
635
635
def newBinding (name : TermName , flags : FlagSet , rhs : Tree ): Symbol = {
@@ -655,8 +655,32 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
655
655
656
656
pat match {
657
657
case Typed (pat1, tpt) =>
658
+ val getBoundVars = new TreeAccumulator [List [TypeSymbol ]] {
659
+ def apply (syms : List [TypeSymbol ], t : Tree )(implicit ctx : Context ) = {
660
+ val syms1 = t match {
661
+ case t : Bind if t.symbol.isType && t.name != tpnme.WILDCARD =>
662
+ t.symbol.asType :: syms
663
+ case _ =>
664
+ syms
665
+ }
666
+ foldOver(syms1, t)
667
+ }
668
+ }
669
+ val boundVars = getBoundVars(Nil , tpt)
670
+ for (bv <- boundVars) ctx.gadt.setBounds(bv, bv.info.bounds)
658
671
if (isImplicit) searchImplicit(nme.WILDCARD , tpt)
659
- else scrut <:< tpt.tpe && reducePattern(bindingsBuf, scrut, pat1)
672
+ else scrut <:< tpt.tpe && {
673
+ for (bv <- boundVars) {
674
+ bv.info = TypeAlias (ctx.gadt.bounds(bv).lo)
675
+ // FIXME: This is very crude. We should approximate with lower or higher bound depending
676
+ // on variance, and we should also take care of recursive bounds. Basically what
677
+ // ConstraintHandler#approximation does. However, this only works for constrained paramrefs
678
+ // not GADT-bound variables. Hopefully we will get some way to improve this when we
679
+ // re-implement GADTs in terms of constraints.
680
+ bindingsBuf += TypeDef (bv)
681
+ }
682
+ reducePattern(bindingsBuf, scrut, pat1)
683
+ }
660
684
case pat @ Bind (name : TermName , Typed (_, tpt)) if isImplicit =>
661
685
searchImplicit(name, tpt)
662
686
case pat @ Bind (name : TermName , body) =>
@@ -706,16 +730,19 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
706
730
val scrutineeBinding = normalizeBinding(ValDef (scrutineeSym, scrutinee))
707
731
708
732
def reduceCase (cdef : untpd.CaseDef ): MatchRedux = {
709
- def guardOK = cdef.guard.isEmpty || {
710
- typer.typed(cdef.guard, defn.BooleanType ) match {
733
+ val caseBindingsBuf = new mutable.ListBuffer [MemberDef ]()
734
+ def guardOK (implicit ctx : Context ) = cdef.guard.isEmpty || {
735
+ val guardCtx = ctx.fresh.setNewScope
736
+ caseBindingsBuf.foreach(binding => guardCtx.enter(binding.symbol))
737
+ typer.typed(cdef.guard, defn.BooleanType )(guardCtx) match {
711
738
case ConstantValue (true ) => true
712
739
case _ => false
713
740
}
714
741
}
715
- val caseBindingsBuf = new mutable.ListBuffer [MemberDef ]()
716
742
if (scrutType != defn.ImplicitScrutineeTypeRef ) caseBindingsBuf += scrutineeBinding
717
- val pat1 = typer.typedPattern(cdef.pat, scrutType)(typer.gadtContext(gadtSyms))
718
- if (reducePattern(caseBindingsBuf, scrutineeSym.termRef, pat1) && guardOK)
743
+ val gadtCtx = typer.gadtContext(gadtSyms).addMode(Mode .GADTflexible )
744
+ val pat1 = typer.typedPattern(cdef.pat, scrutType)(gadtCtx)
745
+ if (reducePattern(caseBindingsBuf, scrutineeSym.termRef, pat1)(gadtCtx) && guardOK)
719
746
Some ((caseBindingsBuf.toList, cdef.body))
720
747
else
721
748
None
@@ -809,6 +836,8 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
809
836
def dropUnusedDefs (bindings : List [MemberDef ], tree : Tree )(implicit ctx : Context ): (List [MemberDef ], Tree ) = {
810
837
val refCount = newMutableSymbolMap[Int ]
811
838
val bindingOfSym = newMutableSymbolMap[MemberDef ]
839
+ val dealiased = new java.util.IdentityHashMap [Type , Type ]()
840
+
812
841
def isInlineable (binding : MemberDef ) = binding match {
813
842
case DefDef (_, Nil , Nil , _, _) => true
814
843
case vdef @ ValDef (_, _, _) => isPureExpr(vdef.rhs)
@@ -818,6 +847,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
818
847
refCount(binding.symbol) = 0
819
848
bindingOfSym(binding.symbol) = binding
820
849
}
850
+
821
851
val countRefs = new TreeTraverser {
822
852
override def traverse (t : Tree )(implicit ctx : Context ) = {
823
853
def updateRefCount (sym : Symbol , inc : Int ) =
@@ -844,6 +874,45 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
844
874
}
845
875
} && ! boundSym.is(TransparentImplicitMethod )
846
876
877
+ val (termBindings, typeBindings) = bindings.partition(_.symbol.isTerm)
878
+
879
+ /** drop any referenced type symbols from the given set of type symbols */
880
+ val dealiasTypeBindings = new TreeMap {
881
+ val boundTypes = typeBindings.map(_.symbol).toSet
882
+
883
+ val dealias = new TypeMap {
884
+ override def apply (tp : Type ) = dealiased.get(tp) match {
885
+ case null =>
886
+ val tp1 = mapOver {
887
+ tp match {
888
+ case tp : TypeRef if boundTypes.contains(tp.symbol) =>
889
+ val TypeAlias (alias) = tp.info
890
+ alias
891
+ case _ => tp
892
+ }
893
+ }
894
+ dealiased.put(tp, tp1)
895
+ tp1
896
+ case tp1 => tp1
897
+ }
898
+ }
899
+
900
+ override def transform (t : Tree )(implicit ctx : Context ) = {
901
+ val dealiasedType = dealias(t.tpe)
902
+ val t1 = t match {
903
+ case t : RefTree =>
904
+ if (boundTypes.contains(t.symbol)) TypeTree (dealiasedType).withPos(t.pos)
905
+ else t.withType(dealiasedType)
906
+ case t : DefTree =>
907
+ t.symbol.info = dealias(t.symbol.info)
908
+ t
909
+ case _ =>
910
+ t.withType(dealiasedType)
911
+ }
912
+ super .transform(t1)
913
+ }
914
+ }
915
+
847
916
val inlineBindings = new TreeMap {
848
917
override def transform (t : Tree )(implicit ctx : Context ) = t match {
849
918
case t : RefTree =>
@@ -859,17 +928,23 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
859
928
case t : Apply =>
860
929
val t1 = super .transform(t)
861
930
if (t1 `eq` t) t else reducer.betaReduce(t1)
931
+ case Block (Nil , expr) =>
932
+ super .transform(expr)
862
933
case _ =>
863
934
super .transform(t)
864
935
}
865
936
}
866
937
867
- val retained = bindings.filterConserve(binding => retain(binding.symbol))
868
- if (retained `eq` bindings) {
869
- (bindings, tree)
938
+ val dealiasedTermBindings =
939
+ termBindings.mapconserve(dealiasTypeBindings.transform).asInstanceOf [List [MemberDef ]]
940
+ val dealiasedTree = dealiasTypeBindings.transform(tree)
941
+
942
+ val retained = dealiasedTermBindings.filterConserve(binding => retain(binding.symbol))
943
+ if (retained `eq` dealiasedTermBindings) {
944
+ (dealiasedTermBindings, dealiasedTree)
870
945
}
871
946
else {
872
- val expanded = inlineBindings.transform(tree )
947
+ val expanded = inlineBindings.transform(dealiasedTree )
873
948
dropUnusedDefs(retained, expanded)
874
949
}
875
950
}
0 commit comments