@@ -198,7 +198,7 @@ object Capabilities:
198198 i " a fresh root capability $classifierStr$originStr"
199199
200200 object FreshCap :
201- def apply (origin : Origin )(using Context ): FreshCap | GlobalCap . type =
201+ def apply (origin : Origin )(using Context ): FreshCap =
202202 FreshCap (ctx.owner, origin)
203203
204204 /** A root capability associated with a function type. These are conceptually
@@ -837,6 +837,7 @@ object Capabilities:
837837 case Formal (pref : ParamRef , app : tpd.Apply )
838838 case ResultInstance (methType : Type , meth : Symbol )
839839 case UnapplyInstance (info : MethodType )
840+ case LocalInstance (restpe : Type )
840841 case NewMutable (tp : Type )
841842 case NewCapability (tp : Type )
842843 case LambdaExpected (respt : Type )
@@ -865,6 +866,8 @@ object Capabilities:
865866 i " when instantiating $methDescr$mt"
866867 case UnapplyInstance (info) =>
867868 i " when instantiating argument of unapply with type $info"
869+ case LocalInstance (restpe) =>
870+ i " when instantiating expected result type $restpe of function literal "
868871 case NewMutable (tp) =>
869872 i " when constructing mutable $tp"
870873 case NewCapability (tp) =>
@@ -948,6 +951,69 @@ object Capabilities:
948951 def freshToCap (param : Symbol , tp : Type )(using Context ): Type =
949952 CapToFresh (Origin .Parameter (param)).inverse(tp)
950953
954+ /** The local dual of a result type of a closure type.
955+ * @param binder the method type of the anonymous function whose result is mapped
956+ * @pre the context's owner is the anonymous function
957+ */
958+ class Internalize (binder : MethodType )(using Context ) extends BiTypeMap :
959+ thisMap =>
960+
961+ val sym = ctx.owner
962+ assert(sym.isAnonymousFunction)
963+ val paramSyms = atPhase(ctx.phase.prev):
964+ // We need to ask one phase before since `sym` should not be completed as a side effect.
965+ // The result of Internalize is used to se the result type of an anonymous function, and
966+ // the new info of that function is built with the result.
967+ sym.paramSymss.head
968+ val resultToFresh = EqHashMap [ResultCap , FreshCap ]()
969+ val freshToResult = EqHashMap [FreshCap , ResultCap ]()
970+
971+ override def apply (t : Type ) =
972+ if variance < 0 then t
973+ else t match
974+ case t : ParamRef =>
975+ if t.binder == this .binder then paramSyms(t.paramNum).termRef else t
976+ case _ => mapOver(t)
977+
978+ override def mapCapability (c : Capability , deep : Boolean ): Capability = c match
979+ case r : ResultCap if r.binder == this .binder =>
980+ resultToFresh.get(r) match
981+ case Some (f) => f
982+ case None =>
983+ val f = FreshCap (Origin .LocalInstance (binder.resType))
984+ resultToFresh(r) = f
985+ freshToResult(f) = r
986+ f
987+ case _ =>
988+ super .mapCapability(c, deep)
989+
990+ class Inverse extends BiTypeMap :
991+ def apply (t : Type ): Type =
992+ if variance < 0 then t
993+ else t match
994+ case t : TermRef if paramSyms.contains(t) =>
995+ binder.paramRefs(paramSyms.indexOf(t.symbol))
996+ case _ => mapOver(t)
997+
998+ override def mapCapability (c : Capability , deep : Boolean ): Capability = c match
999+ case f : FreshCap if f.owner == sym =>
1000+ freshToResult.get(f) match
1001+ case Some (r) => r
1002+ case None =>
1003+ val r = ResultCap (binder)
1004+ resultToFresh(r) = f
1005+ freshToResult(f) = r
1006+ r
1007+ case _ => super .mapCapability(c, deep)
1008+
1009+ def inverse = thisMap
1010+ override def toString = thisMap.toString + " .inverse"
1011+ end Inverse
1012+
1013+ override def toString = " InternalizeClosureResult"
1014+ def inverse = Inverse ()
1015+ end Internalize
1016+
9511017 /** Map top-level free existential variables one-to-one to Fresh instances */
9521018 def resultToFresh (tp : Type , origin : Origin )(using Context ): Type =
9531019 val subst = new TypeMap :
@@ -977,78 +1043,76 @@ object Capabilities:
9771043 subst(tp)
9781044 end resultToFresh
9791045
980- /** Replace all occurrences of `cap` (or fresh) in parts of this type by an existentially bound
981- * variable bound by `mt`.
982- * Stop at function or method types since these have been mapped before.
983- */
984- def toResult (tp : Type , mt : MethodicType , fail : Message => Unit )(using Context ): Type =
985-
986- abstract class CapMap extends BiTypeMap :
987- override def mapOver (t : Type ): Type = t match
988- case t @ FunctionOrMethod (args, res) if variance > 0 && ! t.isAliasFun =>
989- t // `t` should be mapped in this case by a different call to `toResult`. See [[toResultInResults]].
990- case t : (LazyRef | TypeVar ) =>
991- mapConserveSuper(t)
992- case _ =>
993- super .mapOver(t)
1046+ abstract class CapMap (using Context ) extends BiTypeMap :
1047+ override def mapOver (t : Type ): Type = t match
1048+ case t @ FunctionOrMethod (args, res) if variance > 0 && ! t.isAliasFun =>
1049+ t // `t` should be mapped in this case by a different call to `toResult`. See [[toResultInResults]].
1050+ case t : (LazyRef | TypeVar ) =>
1051+ mapConserveSuper(t)
1052+ case _ =>
1053+ super .mapOver(t)
1054+
1055+ class ToResult (localResType : Type , mt : MethodicType , fail : Message => Unit )(using Context ) extends CapMap :
1056+
1057+ def apply (t : Type ) = t match
1058+ case defn.FunctionNOf (args, res, contextual) if t.typeSymbol.name.isImpureFunction =>
1059+ if variance > 0 then
1060+ super .mapOver:
1061+ defn.FunctionNOf (args, res, contextual)
1062+ .capturing(ResultCap (mt).singletonCaptureSet)
1063+ else mapOver(t)
1064+ case _ =>
1065+ mapOver(t)
1066+
1067+ override def mapCapability (c : Capability , deep : Boolean ) = c match
1068+ case c : (FreshCap | GlobalCap .type ) =>
1069+ if variance > 0 then
1070+ val res = ResultCap (mt)
1071+ c match
1072+ case c : FreshCap => res.setOrigin(c)
1073+ case _ =>
1074+ res
1075+ else
1076+ if variance == 0 then
1077+ fail(em """ $localResType captures the root capability `cap` in invariant position.
1078+ |This capability cannot be converted to an existential in the result type of a function. """ )
1079+ // we accept variance < 0, and leave the cap as it is
1080+ c
1081+ case _ =>
1082+ super .mapCapability(c, deep)
9941083
995- object toVar extends CapMap :
1084+ // .showing(i"mapcap $t = $result")
1085+ override def toString = " toVar"
9961086
997- def apply (t : Type ) = t match
998- case defn.FunctionNOf (args, res, contextual) if t.typeSymbol.name.isImpureFunction =>
999- if variance > 0 then
1000- super .mapOver:
1001- defn.FunctionNOf (args, res, contextual)
1002- .capturing(ResultCap (mt).singletonCaptureSet)
1003- else mapOver(t)
1004- case _ =>
1005- mapOver(t)
1087+ object inverse extends BiTypeMap :
1088+ def apply (t : Type ) = mapOver(t)
10061089
10071090 override def mapCapability (c : Capability , deep : Boolean ) = c match
1008- case c : (FreshCap | GlobalCap .type ) =>
1009- if variance > 0 then
1010- val res = ResultCap (mt)
1011- c match
1012- case c : FreshCap => res.setOrigin(c)
1013- case _ =>
1014- res
1015- else
1016- if variance == 0 then
1017- fail(em """ $tp captures the root capability `cap` in invariant position.
1018- |This capability cannot be converted to an existential in the result type of a function. """ )
1019- // we accept variance < 0, and leave the cap as it is
1020- c
1091+ case c @ ResultCap (`mt`) =>
1092+ // do a reverse getOrElseUpdate on `seen` to produce the
1093+ // `Fresh` assosicated with `t`
1094+ val primary = c.primaryResultCap
1095+ primary.origin match
1096+ case GlobalCap =>
1097+ val fresh = FreshCap (Origin .LocalInstance (mt.resType))
1098+ primary.setOrigin(fresh)
1099+ fresh
1100+ case origin : FreshCap =>
1101+ origin
10211102 case _ =>
10221103 super .mapCapability(c, deep)
10231104
1024- // .showing(i"mapcap $t = $result")
1025- override def toString = " toVar"
1026-
1027- object inverse extends BiTypeMap :
1028- def apply (t : Type ) = mapOver(t)
1029-
1030- override def mapCapability (c : Capability , deep : Boolean ) = c match
1031- case c @ ResultCap (`mt`) =>
1032- // do a reverse getOrElseUpdate on `seen` to produce the
1033- // `Fresh` assosicated with `t`
1034- val primary = c.primaryResultCap
1035- primary.origin match
1036- case GlobalCap =>
1037- val fresh = FreshCap (Origin .Unknown )
1038- primary.setOrigin(fresh)
1039- fresh
1040- case origin : FreshCap =>
1041- origin
1042- case _ =>
1043- super .mapCapability(c, deep)
1044-
1045- def inverse = toVar.this
1046- override def toString = " toVar.inverse"
1047- end inverse
1048- end toVar
1105+ def inverse = ToResult .this
1106+ override def toString = " toVar.inverse"
1107+ end inverse
1108+ end ToResult
10491109
1050- toVar(tp)
1051- end toResult
1110+ /** Replace all occurrences of `cap` (or fresh) in parts of this type by an existentially bound
1111+ * variable bound by `mt`.
1112+ * Stop at function or method types since these have been mapped before.
1113+ */
1114+ def toResult (tp : Type , mt : MethodicType , fail : Message => Unit )(using Context ): Type =
1115+ ToResult (tp, mt, fail)(tp)
10521116
10531117 /** Map global roots in function results to result roots. Also,
10541118 * map roots in the types of def methods that are parameterless
0 commit comments