Skip to content

Commit 6fbf6e3

Browse files
committed
Add a prefix to FreshCaps
1 parent 3c9d209 commit 6fbf6e3

File tree

4 files changed

+32
-5
lines changed

4 files changed

+32
-5
lines changed

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

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,21 @@ object Capabilities:
148148
* @param origin an indication where and why the FreshCap was created, used
149149
* for diagnostics
150150
*/
151-
case class FreshCap private (owner: Symbol, origin: Origin)(using @constructorOnly ctx: Context) extends RootCapability:
152-
val hiddenSet = CaptureSet.HiddenSet(owner, this: @unchecked)
151+
case class FreshCap(val prefix: Type)
152+
(val owner: Symbol, val origin: Origin, origHidden: CaptureSet.HiddenSet | Null)
153+
(using @constructorOnly ctx: Context)
154+
extends RootCapability:
155+
val hiddenSet =
156+
if origHidden == null then CaptureSet.HiddenSet(owner, this: @unchecked)
157+
else origHidden
153158
// fails initialization check without the @unchecked
154159

160+
def derivedFreshCap(newPrefix: Type)(using Context): FreshCap =
161+
if newPrefix eq prefix then this
162+
else FreshCap(newPrefix)(owner, origin, hiddenSet)
163+
164+
//assert(rootId != 10, i"fresh $prefix, ${ctx.owner}")
165+
155166
/** Is this fresh cap (definitely) classified? If that's the case, the
156167
* classifier cannot be changed anymore.
157168
* We need to distinguish `FreshCap`s that can still be classified from
@@ -198,8 +209,10 @@ object Capabilities:
198209
i"a fresh root capability$classifierStr$originStr"
199210

200211
object FreshCap:
212+
def apply(prefix: Type, origin: Origin)(using Context): FreshCap =
213+
new FreshCap(prefix)(ctx.owner, origin, null)
201214
def apply(origin: Origin)(using Context): FreshCap =
202-
FreshCap(ctx.owner, origin)
215+
apply(ctx.owner.skipWeakOwner.thisType, origin)
203216

204217
/** A root capability associated with a function type. These are conceptually
205218
* existentially quantified over the function's result type.
@@ -703,13 +716,23 @@ object Capabilities:
703716
(this eq y)
704717
|| this.match
705718
case x: FreshCap =>
719+
def prefixIsOpen(pre: Type): Boolean = pre match
720+
case NoPrefix | _: ThisType => true
721+
case pre: (TypeRef | AppliedType) if pre.typeSymbol == x.ccOwner.skipWeakOwner => true
722+
case pre: TypeProxy => prefixIsOpen(pre.superType)
723+
case _ => false
724+
706725
vs.ifNotSeen(this)(x.hiddenSet.elems.exists(_.subsumes(y)))
707726
|| x.acceptsLevelOf(y)
708727
&& ( y.tryClassifyAs(x.hiddenSet.classifier)
709728
|| { capt.println(i"$y cannot be classified as $x"); false }
710729
)
711730
&& canAddHidden
712731
&& vs.addHidden(x.hiddenSet, y)
732+
&& (prefixIsOpen(x.prefix)
733+
/*|| { println(i"closed fresh $x, ${x.rootId}, ${x.prefix}, ${x.ccOwner.skipWeakOwner.thisType}")
734+
false
735+
}*/)
713736
case x: ResultCap =>
714737
val result = y match
715738
case y: ResultCap => vs.unify(x, y)

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,8 +559,10 @@ object CaptureSet:
559559
def universal(using Context): Const =
560560
Const(SimpleIdentitySet(GlobalCap))
561561

562+
def fresh(prefix: Type, origin: Origin)(using Context): Const =
563+
FreshCap(prefix, origin).singletonCaptureSet
562564
def fresh(origin: Origin)(using Context): Const =
563-
FreshCap(origin).singletonCaptureSet
565+
fresh(ctx.owner.thisType, origin)
564566

565567
/** The shared capture set `{cap.rd}` */
566568
def shared(using Context): Const =

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
694694
if cls.derivesFrom(defn.Caps_Capability) then
695695
// If cls is a capability class, we need to add a fresh readonly capability to
696696
// ensure we cannot treat the class as pure.
697-
CaptureSet.fresh(Origin.InDecl(cls)).readOnly.subCaptures(cs)
697+
CaptureSet.fresh(cls.thisType, Origin.InDecl(cls)).readOnly.subCaptures(cs)
698698
CapturingType(cinfo.selfType, cs)
699699

700700
// Compute new parent types

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6312,6 +6312,8 @@ object Types extends TypeUtils {
63126312
null
63136313

63146314
def mapCapability(c: Capability, deep: Boolean = false): Capability | (CaptureSet, Boolean) = c match
6315+
case c @ FreshCap(prefix) =>
6316+
c.derivedFreshCap(apply(prefix))
63156317
case c: RootCapability => c
63166318
case Reach(c1) =>
63176319
mapCapability(c1, deep = true)

0 commit comments

Comments
 (0)