Skip to content

Commit 76fbb6b

Browse files
committed
Refactorings
1 parent 481e173 commit 76fbb6b

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)
@@ -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

Comments
 (0)