@@ -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) =>
@@ -977,78 +980,76 @@ object Capabilities:
977980 subst(tp)
978981 end resultToFresh
979982
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)
983+ abstract class CapMap (using Context ) 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)
991+
992+ class ToResult (localResType : Type , mt : MethodicType , fail : Message => Unit )(using Context ) extends CapMap :
993+
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)
1003+
1004+ 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 """ $localResType 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
1018+ case _ =>
1019+ super .mapCapability(c, deep)
9941020
995- object toVar extends CapMap :
1021+ // .showing(i"mapcap $t = $result")
1022+ override def toString = " toVar"
9961023
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)
1024+ object inverse extends BiTypeMap :
1025+ def apply (t : Type ) = mapOver(t)
10061026
10071027 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
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 .LocalInstance (mt.resType))
1035+ primary.setOrigin(fresh)
1036+ fresh
1037+ case origin : FreshCap =>
1038+ origin
10211039 case _ =>
10221040 super .mapCapability(c, deep)
10231041
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
1042+ def inverse = ToResult .this
1043+ override def toString = " toVar.inverse"
1044+ end inverse
1045+ end ToResult
10491046
1050- toVar(tp)
1051- end toResult
1047+ /** Replace all occurrences of `cap` (or fresh) in parts of this type by an existentially bound
1048+ * variable bound by `mt`.
1049+ * Stop at function or method types since these have been mapped before.
1050+ */
1051+ def toResult (tp : Type , mt : MethodicType , fail : Message => Unit )(using Context ): Type =
1052+ ToResult (tp, mt, fail)(tp)
10521053
10531054 /** Map global roots in function results to result roots. Also,
10541055 * map roots in the types of def methods that are parameterless
0 commit comments