@@ -198,7 +198,7 @@ object Capabilities:
198
198
i " a fresh root capability $classifierStr$originStr"
199
199
200
200
object FreshCap :
201
- def apply (origin : Origin )(using Context ): FreshCap | GlobalCap . type =
201
+ def apply (origin : Origin )(using Context ): FreshCap =
202
202
FreshCap (ctx.owner, origin)
203
203
204
204
/** A root capability associated with a function type. These are conceptually
@@ -837,6 +837,7 @@ object Capabilities:
837
837
case Formal (pref : ParamRef , app : tpd.Apply )
838
838
case ResultInstance (methType : Type , meth : Symbol )
839
839
case UnapplyInstance (info : MethodType )
840
+ case LocalInstance (restpe : Type )
840
841
case NewMutable (tp : Type )
841
842
case NewCapability (tp : Type )
842
843
case LambdaExpected (respt : Type )
@@ -864,6 +865,8 @@ object Capabilities:
864
865
i " when instantiating $methDescr$mt"
865
866
case UnapplyInstance (info) =>
866
867
i " when instantiating argument of unapply with type $info"
868
+ case LocalInstance (restpe) =>
869
+ i " when instantiating expected result type $restpe of function literal "
867
870
case NewMutable (tp) =>
868
871
i " when constructing mutable $tp"
869
872
case NewCapability (tp) =>
@@ -974,78 +977,76 @@ object Capabilities:
974
977
subst(tp)
975
978
end resultToFresh
976
979
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)
991
1017
992
- object toVar extends CapMap :
1018
+ // .showing(i"mapcap $t = $result")
1019
+ override def toString = " toVar"
993
1020
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)
1003
1023
1004
1024
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
1018
1036
case _ =>
1019
1037
super .mapCapability(c, deep)
1020
1038
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
1046
1043
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)
1049
1050
1050
1051
/** Map global roots in function results to result roots. Also,
1051
1052
* map roots in the types of def methods that are parameterless
0 commit comments