@@ -23,6 +23,7 @@ import printing.Texts.Text
23
23
import reporting .{Message , trace }
24
24
import NameOps .isImpureFunction
25
25
import annotation .internal .sharable
26
+ import collection .immutable
26
27
27
28
/** Capabilities are members of capture sets. They partially overlap with types
28
29
* as shown in the trait hierarchy below.
@@ -147,10 +148,30 @@ object Capabilities:
147
148
* @param origin an indication where and why the FreshCap was created, used
148
149
* for diagnostics
149
150
*/
150
- case class FreshCap (owner : Symbol , origin : Origin )(using @ constructorOnly ctx : Context ) extends RootCapability :
151
- 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
152
158
// fails initialization check without the @unchecked
153
159
160
+ def derivedFreshCap (newPrefix : Type )(using Context ): FreshCap =
161
+ if newPrefix eq prefix then this
162
+ else if newPrefix eq hiddenSet.owningCap.prefix then
163
+ hiddenSet.owningCap
164
+ else
165
+ hiddenSet.derivedCaps
166
+ .getOrElseUpdate(newPrefix, FreshCap (newPrefix)(owner, origin, hiddenSet))
167
+
168
+ /** A map from context owners to skolem TermRefs that were created by ensurePath
169
+ * TypeMap's mapCapability.
170
+ */
171
+ var skolems : immutable.Map [Symbol , TermRef ] = immutable.HashMap .empty
172
+
173
+ // assert(rootId != 10, i"fresh $prefix, ${ctx.owner}")
174
+
154
175
/** Is this fresh cap (definitely) classified? If that's the case, the
155
176
* classifier cannot be changed anymore.
156
177
* We need to distinguish `FreshCap`s that can still be classified from
@@ -167,12 +188,6 @@ object Capabilities:
167
188
case _ => false
168
189
169
190
/** Is this fresh cap at the right level to be able to subsume `ref`?
170
- * Only outer freshes can be subsumed.
171
- * TODO Can we merge this with levelOK? Right now we use two different schemes:
172
- * - For level checking capsets with levelOK: Check that the visibility of the element
173
- * os not properly contained in the captset owner.
174
- * - For level checking elements subsumed by FreshCaps: Check that the widened scope
175
- * (using levelOwner) of the elements contains the owner of the FreshCap.
176
191
*/
177
192
def acceptsLevelOf (ref : Capability )(using Context ): Boolean =
178
193
if ccConfig.useFreshLevels && ! CCState .collapseFresh then
@@ -203,8 +218,12 @@ object Capabilities:
203
218
i " a fresh root capability $classifierStr$originStr"
204
219
205
220
object FreshCap :
221
+ def apply (owner : Symbol , prefix : Type , origin : Origin )(using Context ): FreshCap =
222
+ new FreshCap (prefix)(owner, origin, null )
223
+ def apply (owner : Symbol , origin : Origin )(using Context ): FreshCap =
224
+ apply(owner, owner.skipWeakOwner.thisType, origin)
206
225
def apply (origin : Origin )(using Context ): FreshCap =
207
- FreshCap (ctx.owner, origin)
226
+ apply (ctx.owner, origin)
208
227
209
228
/** A root capability associated with a function type. These are conceptually
210
229
* existentially quantified over the function's result type.
@@ -441,6 +460,7 @@ object Capabilities:
441
460
* the form this.C but their pathroot is still this.C, not this.
442
461
*/
443
462
final def pathRoot (using Context ): Capability = this match
463
+ case FreshCap (pre : Capability ) => pre.pathRoot
444
464
case _ : RootCapability => this
445
465
case self : DerivedCapability => self.underlying.pathRoot
446
466
case self : CoreCapability => self.dealias match
@@ -485,7 +505,13 @@ object Capabilities:
485
505
case TermRef (prefix : Capability , _) => prefix.ccOwner
486
506
case self : NamedType => self.symbol
487
507
case self : DerivedCapability => self.underlying.ccOwner
488
- case self : FreshCap => self.hiddenSet.owner
508
+ case self : FreshCap =>
509
+ val setOwner = self.hiddenSet.owner
510
+ self.prefix match
511
+ case prefix : ThisType if setOwner.isTerm && setOwner.owner == prefix.cls =>
512
+ setOwner
513
+ case prefix : Capability => prefix.ccOwner
514
+ case _ => setOwner
489
515
case _ /* : GlobalCap | ResultCap | ParamRef */ => NoSymbol
490
516
491
517
final def visibility (using Context ): Symbol = this match
@@ -732,12 +758,25 @@ object Capabilities:
732
758
(this eq y)
733
759
|| this .match
734
760
case x : FreshCap =>
761
+ def classifierOK =
762
+ if y.tryClassifyAs(x.hiddenSet.classifier) then true
763
+ else
764
+ capt.println(i " $y cannot be classified as $x" )
765
+ false
766
+
767
+ def prefixAllowsAddHidden : Boolean =
768
+ CCState .collapseFresh || x.prefix.match
769
+ case NoPrefix => true
770
+ case pre : ThisType => x.ccOwner.isContainedIn(pre.cls)
771
+ case pre =>
772
+ capt.println(i " fresh not open $x, ${x.rootId}, $pre, ${x.ccOwner.skipWeakOwner.thisType}" )
773
+ false
774
+
735
775
vs.ifNotSeen(this )(x.hiddenSet.elems.exists(_.subsumes(y)))
736
776
|| x.acceptsLevelOf(y)
737
- && ( y.tryClassifyAs(x.hiddenSet.classifier)
738
- || { capt.println(i " $y cannot be classified as $x" ); false }
739
- )
777
+ && classifierOK
740
778
&& canAddHidden
779
+ && prefixAllowsAddHidden
741
780
&& vs.addHidden(x.hiddenSet, y)
742
781
case x : ResultCap =>
743
782
val result = y match
0 commit comments