Skip to content

Commit 18c867a

Browse files
committed
Refactorings
1 parent 5bba231 commit 18c867a

File tree

1 file changed

+66
-65
lines changed

1 file changed

+66
-65
lines changed

compiler/src/dotty/tools/dotc/cc/Capability.scala

Lines changed: 66 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)