@@ -11,7 +11,7 @@ import Symbols._
1111import Types ._
1212import Decorators ._
1313import Constants ._
14- import StdNames .nme
14+ import StdNames ._
1515import Contexts .Context
1616import Names .{Name , TermName , EmptyTermName }
1717import NameOps ._
@@ -602,7 +602,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
602602 newOwners = ctx.owner :: Nil ,
603603 substFrom = ddef.vparamss.head.map(_.symbol),
604604 substTo = argSyms)
605- Block (bindingsBuf.toList, expander.transform(ddef.rhs))
605+ seq (bindingsBuf.toList, expander.transform(ddef.rhs))
606606 case _ => tree
607607 }
608608 case _ => tree
@@ -629,7 +629,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
629629 /** Try to match pattern `pat` against scrutinee reference `scrut`. If successful add
630630 * bindings for variables bound in this pattern to `bindingsBuf`.
631631 */
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 = {
633633 val isImplicit = scrut.info == defn.ImplicitScrutineeTypeRef
634634
635635 def newBinding (name : TermName , flags : FlagSet , rhs : Tree ): Symbol = {
@@ -655,8 +655,32 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
655655
656656 pat match {
657657 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)
658671 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+ }
660684 case pat @ Bind (name : TermName , Typed (_, tpt)) if isImplicit =>
661685 searchImplicit(name, tpt)
662686 case pat @ Bind (name : TermName , body) =>
@@ -706,16 +730,19 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
706730 val scrutineeBinding = normalizeBinding(ValDef (scrutineeSym, scrutinee))
707731
708732 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 {
711738 case ConstantValue (true ) => true
712739 case _ => false
713740 }
714741 }
715- val caseBindingsBuf = new mutable.ListBuffer [MemberDef ]()
716742 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)
719746 Some ((caseBindingsBuf.toList, cdef.body))
720747 else
721748 None
@@ -809,6 +836,8 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
809836 def dropUnusedDefs (bindings : List [MemberDef ], tree : Tree )(implicit ctx : Context ): (List [MemberDef ], Tree ) = {
810837 val refCount = newMutableSymbolMap[Int ]
811838 val bindingOfSym = newMutableSymbolMap[MemberDef ]
839+ val dealiased = new java.util.IdentityHashMap [Type , Type ]()
840+
812841 def isInlineable (binding : MemberDef ) = binding match {
813842 case DefDef (_, Nil , Nil , _, _) => true
814843 case vdef @ ValDef (_, _, _) => isPureExpr(vdef.rhs)
@@ -818,6 +847,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
818847 refCount(binding.symbol) = 0
819848 bindingOfSym(binding.symbol) = binding
820849 }
850+
821851 val countRefs = new TreeTraverser {
822852 override def traverse (t : Tree )(implicit ctx : Context ) = {
823853 def updateRefCount (sym : Symbol , inc : Int ) =
@@ -844,6 +874,45 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
844874 }
845875 } && ! boundSym.is(TransparentImplicitMethod )
846876
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+
847916 val inlineBindings = new TreeMap {
848917 override def transform (t : Tree )(implicit ctx : Context ) = t match {
849918 case t : RefTree =>
@@ -859,17 +928,23 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
859928 case t : Apply =>
860929 val t1 = super .transform(t)
861930 if (t1 `eq` t) t else reducer.betaReduce(t1)
931+ case Block (Nil , expr) =>
932+ super .transform(expr)
862933 case _ =>
863934 super .transform(t)
864935 }
865936 }
866937
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)
870945 }
871946 else {
872- val expanded = inlineBindings.transform(tree )
947+ val expanded = inlineBindings.transform(dealiasedTree )
873948 dropUnusedDefs(retained, expanded)
874949 }
875950 }
0 commit comments