@@ -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 )
@@ -865,6 +866,8 @@ object Capabilities:
865
866
i " when instantiating $methDescr$mt"
866
867
case UnapplyInstance (info) =>
867
868
i " when instantiating argument of unapply with type $info"
869
+ case LocalInstance (restpe) =>
870
+ i " when instantiating expected result type $restpe of function literal "
868
871
case NewMutable (tp) =>
869
872
i " when constructing mutable $tp"
870
873
case NewCapability (tp) =>
@@ -977,78 +980,76 @@ object Capabilities:
977
980
subst(tp)
978
981
end resultToFresh
979
982
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)
994
1020
995
- object toVar extends CapMap :
1021
+ // .showing(i"mapcap $t = $result")
1022
+ override def toString = " toVar"
996
1023
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)
1006
1026
1007
1027
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
1021
1039
case _ =>
1022
1040
super .mapCapability(c, deep)
1023
1041
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
1049
1046
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)
1052
1053
1053
1054
/** Map global roots in function results to result roots. Also,
1054
1055
* map roots in the types of def methods that are parameterless
0 commit comments