@@ -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 )
@@ -864,6 +865,8 @@ object Capabilities:
864865 i " when instantiating $methDescr$mt"
865866 case UnapplyInstance (info) =>
866867 i " when instantiating argument of unapply with type $info"
868+ case LocalInstance (restpe) =>
869+ i " when instantiating expected result type $restpe of function literal "
867870 case NewMutable (tp) =>
868871 i " when constructing mutable $tp"
869872 case NewCapability (tp) =>
@@ -974,78 +977,76 @@ object Capabilities:
974977 subst(tp)
975978 end resultToFresh
976979
977- /** Replace all occurrences of `cap` (or fresh) in parts of this type by an existentially bound
978- * variable bound by `mt`.
979- * Stop at function or method types since these have been mapped before.
980- */
981- def toResult (tp : Type , mt : MethodicType , fail : Message => Unit )(using Context ): Type =
982-
983- abstract class CapMap extends BiTypeMap :
984- override def mapOver (t : Type ): Type = t match
985- case t @ FunctionOrMethod (args, res) if variance > 0 && ! t.isAliasFun =>
986- t // `t` should be mapped in this case by a different call to `toResult`. See [[toResultInResults]].
987- case t : (LazyRef | TypeVar ) =>
988- mapConserveSuper(t)
989- case _ =>
990- super .mapOver(t)
980+ abstract class CapMap (using Context ) extends BiTypeMap :
981+ override def mapOver (t : Type ): Type = t match
982+ case t @ FunctionOrMethod (args, res) if variance > 0 && ! t.isAliasFun =>
983+ t // `t` should be mapped in this case by a different call to `toResult`. See [[toResultInResults]].
984+ case t : (LazyRef | TypeVar ) =>
985+ mapConserveSuper(t)
986+ case _ =>
987+ super .mapOver(t)
988+
989+ class ToResult (localResType : Type , mt : MethodicType , fail : Message => Unit )(using Context ) extends CapMap :
990+
991+ def apply (t : Type ) = t match
992+ case defn.FunctionNOf (args, res, contextual) if t.typeSymbol.name.isImpureFunction =>
993+ if variance > 0 then
994+ super .mapOver:
995+ defn.FunctionNOf (args, res, contextual)
996+ .capturing(ResultCap (mt).singletonCaptureSet)
997+ else mapOver(t)
998+ case _ =>
999+ mapOver(t)
1000+
1001+ override def mapCapability (c : Capability , deep : Boolean ) = c match
1002+ case c : (FreshCap | GlobalCap .type ) =>
1003+ if variance > 0 then
1004+ val res = ResultCap (mt)
1005+ c match
1006+ case c : FreshCap => res.setOrigin(c)
1007+ case _ =>
1008+ res
1009+ else
1010+ if variance == 0 then
1011+ fail(em """ $localResType captures the root capability `cap` in invariant position.
1012+ |This capability cannot be converted to an existential in the result type of a function. """ )
1013+ // we accept variance < 0, and leave the cap as it is
1014+ c
1015+ case _ =>
1016+ super .mapCapability(c, deep)
9911017
992- object toVar extends CapMap :
1018+ // .showing(i"mapcap $t = $result")
1019+ override def toString = " toVar"
9931020
994- def apply (t : Type ) = t match
995- case defn.FunctionNOf (args, res, contextual) if t.typeSymbol.name.isImpureFunction =>
996- if variance > 0 then
997- super .mapOver:
998- defn.FunctionNOf (args, res, contextual)
999- .capturing(ResultCap (mt).singletonCaptureSet)
1000- else mapOver(t)
1001- case _ =>
1002- mapOver(t)
1021+ object inverse extends BiTypeMap :
1022+ def apply (t : Type ) = mapOver(t)
10031023
10041024 override def mapCapability (c : Capability , deep : Boolean ) = c match
1005- case c : (FreshCap | GlobalCap .type ) =>
1006- if variance > 0 then
1007- val res = ResultCap (mt)
1008- c match
1009- case c : FreshCap => res.setOrigin(c)
1010- case _ =>
1011- res
1012- else
1013- if variance == 0 then
1014- fail(em """ $tp captures the root capability `cap` in invariant position.
1015- |This capability cannot be converted to an existential in the result type of a function. """ )
1016- // we accept variance < 0, and leave the cap as it is
1017- c
1025+ case c @ ResultCap (`mt`) =>
1026+ // do a reverse getOrElseUpdate on `seen` to produce the
1027+ // `Fresh` assosicated with `t`
1028+ val primary = c.primaryResultCap
1029+ primary.origin match
1030+ case GlobalCap =>
1031+ val fresh = FreshCap (Origin .LocalInstance (mt.resType))
1032+ primary.setOrigin(fresh)
1033+ fresh
1034+ case origin : FreshCap =>
1035+ origin
10181036 case _ =>
10191037 super .mapCapability(c, deep)
10201038
1021- // .showing(i"mapcap $t = $result")
1022- override def toString = " toVar"
1023-
1024- object inverse extends BiTypeMap :
1025- def apply (t : Type ) = mapOver(t)
1026-
1027- override def mapCapability (c : Capability , deep : Boolean ) = c match
1028- case c @ ResultCap (`mt`) =>
1029- // do a reverse getOrElseUpdate on `seen` to produce the
1030- // `Fresh` assosicated with `t`
1031- val primary = c.primaryResultCap
1032- primary.origin match
1033- case GlobalCap =>
1034- val fresh = FreshCap (Origin .Unknown )
1035- primary.setOrigin(fresh)
1036- fresh
1037- case origin : FreshCap =>
1038- origin
1039- case _ =>
1040- super .mapCapability(c, deep)
1041-
1042- def inverse = toVar.this
1043- override def toString = " toVar.inverse"
1044- end inverse
1045- end toVar
1039+ def inverse = ToResult .this
1040+ override def toString = " toVar.inverse"
1041+ end inverse
1042+ end ToResult
10461043
1047- toVar(tp)
1048- end toResult
1044+ /** Replace all occurrences of `cap` (or fresh) in parts of this type by an existentially bound
1045+ * variable bound by `mt`.
1046+ * Stop at function or method types since these have been mapped before.
1047+ */
1048+ def toResult (tp : Type , mt : MethodicType , fail : Message => Unit )(using Context ): Type =
1049+ ToResult (tp, mt, fail)(tp)
10491050
10501051 /** Map global roots in function results to result roots. Also,
10511052 * map roots in the types of def methods that are parameterless
0 commit comments