Skip to content

Commit 8e67d6c

Browse files
committed
Refactoring: Separate addOwnerAsHidden from Fresh creation
Also, work towards linking Fresh.fromCap more tightly to transformExplicitType
1 parent 3c9545f commit 8e67d6c

File tree

7 files changed

+42
-29
lines changed

7 files changed

+42
-29
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,7 @@ object CapsOfApply:
764764

765765
abstract class AnnotatedCapability(annotCls: Context ?=> ClassSymbol):
766766
def apply(tp: Type)(using Context): AnnotatedType =
767-
assert(tp.isTrackableRef)
767+
assert(tp.isTrackableRef, i"not a trackable ref: $tp")
768768
tp match
769769
case AnnotatedType(_, annot) =>
770770
assert(!unwrappable.contains(annot.symbol), i"illegal combination of derived capabilities: $annotCls over ${annot.symbol}")

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ object CaptureSet:
419419
defn.captureRoot.termRef.singletonCaptureSet
420420

421421
def fresh(owner: Symbol = NoSymbol)(using Context): CaptureSet =
422-
Fresh(owner).singletonCaptureSet
422+
Fresh.withOwner(owner).singletonCaptureSet
423423

424424
/** The shared capture set `{cap.rd}` */
425425
def shared(using Context): CaptureSet =
@@ -952,8 +952,8 @@ object CaptureSet:
952952
* which are already subject through snapshotting and rollbacks in VarState.
953953
* It's advantageous if we don't need to deal with other pieces of state there.
954954
*/
955-
class HiddenSet(initialOwner: Symbol, initialHidden: Refs = emptyRefs)(using @constructorOnly ictx: Context)
956-
extends Var(initialOwner, initialHidden):
955+
class HiddenSet(initialOwner: Symbol)(using @constructorOnly ictx: Context)
956+
extends Var(initialOwner):
957957
var owningCap: AnnotatedType = uninitialized
958958
var givenOwner: Symbol = initialOwner
959959

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,7 @@ class CheckCaptures extends Recheck, SymTransformer:
846846
var refined: Type = core
847847
var allCaptures: CaptureSet =
848848
if core.derivesFromMutable then initCs ++ CaptureSet.fresh()
849-
else if core.derivesFromCapability then initCs ++ Fresh(core.classSymbol).readOnly.singletonCaptureSet
849+
else if core.derivesFromCapability then initCs ++ Fresh.withOwner(core.classSymbol).readOnly.singletonCaptureSet
850850
else initCs
851851
for (getterName, argType) <- mt.paramNames.lazyZip(argTypes) do
852852
val getter = cls.info.member(getterName).suchThat(_.isRefiningParamAccessor).symbol

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ object Existential:
234234
def apply(t: Type): Type = t match
235235
case t @ Vble(binder) =>
236236
if localBinders.contains(binder) then t // keep bound references
237-
else seen.getOrElseUpdate(t.annot, Fresh(NoSymbol)) // map free references to Fresh()
237+
else seen.getOrElseUpdate(t.annot, Fresh()) // map free references to Fresh()
238238
case t: MethodType =>
239239
// skip parameters
240240
val saved = localBinders
@@ -306,7 +306,7 @@ object Existential:
306306
val (k, v) = it.next
307307
if v.annot eq t.annot then ref = k
308308
if ref == null then
309-
ref = Fresh(NoSymbol)
309+
ref = Fresh()
310310
seen(ref) = t
311311
ref
312312
case _ => mapOver(t)

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

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,29 +47,27 @@ object Fresh:
4747
end Annot
4848

4949
/** Constructor and extractor methods for "fresh" capabilities */
50-
def apply(owner: Symbol, initialHidden: Refs = emptyRefs)(using Context): CaptureRef =
50+
private def make(owner: Symbol)(using Context): CaptureRef =
5151
if ccConfig.useSepChecks then
52-
val hiddenSet = CaptureSet.HiddenSet(owner, initialHidden)
52+
val hiddenSet = CaptureSet.HiddenSet(owner)
5353
val res = AnnotatedType(defn.captureRoot.termRef, Annot(hiddenSet, NoType))
5454
hiddenSet.owningCap = res
5555
//assert(hiddenSet.id != 3)
5656
res
5757
else
5858
defn.captureRoot.termRef
5959

60-
def apply(owner: Symbol, reach: Boolean)(using Context): CaptureRef =
61-
apply(owner, ownerToHidden(owner, reach))
60+
def withOwner(owner: Symbol)(using Context): CaptureRef = make(owner)
6261

63-
def apply(owner: Symbol)(using Context): CaptureRef =
64-
apply(owner, ownerToHidden(owner, reach = false))
62+
def apply()(using Context): CaptureRef = make(NoSymbol)
6563

6664
def unapply(tp: AnnotatedType): Option[CaptureSet.HiddenSet] = tp.annot match
6765
case Annot(hidden, binder) if !binder.exists => Some(hidden)
6866
case _ => None
6967

7068
/** Create an existential */
7169
def existential(binder: MethodType)(using Context): AnnotatedType =
72-
val hiddenSet = CaptureSet.HiddenSet(NoSymbol, emptyRefs)
70+
val hiddenSet = CaptureSet.HiddenSet(NoSymbol)
7371
val res = AnnotatedType(defn.captureRoot.termRef, Annot(hiddenSet, binder))
7472
hiddenSet.owningCap = res
7573
res
@@ -88,17 +86,13 @@ object Fresh:
8886
class FromCap(owner: Symbol)(using Context) extends BiTypeMap, FollowAliasesMap:
8987
thisMap =>
9088

91-
private var reach = false
92-
9389
override def apply(t: Type) =
9490
if variance <= 0 then t
9591
else t match
9692
case t: CaptureRef if t.isCap =>
97-
Fresh(owner, ownerToHidden(owner, reach))
98-
case t @ CapturingType(_, refs) =>
99-
val savedReach = reach
100-
if t.isBoxed then reach = true
101-
try mapOver(t) finally reach = savedReach
93+
Fresh.withOwner(owner)
94+
case t @ CapturingType(_, _) =>
95+
mapOver(t)
10296
case t @ AnnotatedType(parent, ann) =>
10397
val parent1 = this(parent)
10498
if ann.symbol.isRetains && ann.tree.toCaptureSet.containsCap then

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

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import transform.{PreRecheck, Recheck}, Recheck.*
1414
import CaptureSet.{IdentityCaptRefMap, IdempotentCaptRefMap}
1515
import Synthetics.isExcluded
1616
import util.SimpleIdentitySet
17+
import util.chaining.*
1718
import reporting.Message
1819
import printing.{Printer, Texts}, Texts.{Text, Str}
1920
import collection.mutable
@@ -132,7 +133,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
132133
def mappedInfo =
133134
if toBeUpdated.contains(sym)
134135
then symd.info // don't transform symbols that will anyway be updated
135-
else Fresh.fromCap(transformExplicitType(symd.info, sym), sym)
136+
else Fresh.fromCap(transformExplicitType(symd.info, sym), sym).tap(addOwnerAsHidden(_, sym))
136137
if Synthetics.needsTransform(symd) then
137138
Synthetics.transform(symd, mappedInfo)
138139
else if isPreCC(sym) then
@@ -489,6 +490,22 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
489490
extension (sym: Symbol) def nextInfo(using Context): Type =
490491
atPhase(thisPhase.next)(sym.info)
491492

493+
private def addOwnerAsHidden(tp: Type, owner: Symbol)(using Context): Unit =
494+
val ref = owner.termRef
495+
def add = new TypeTraverser:
496+
var reach = false
497+
def traverse(t: Type): Unit = t match
498+
case Fresh(hidden) =>
499+
if reach then hidden.elems += ref.reach
500+
else if ref.isTracked then hidden.elems += ref
501+
case t @ CapturingType(_, _) if t.isBoxed && !reach =>
502+
reach = true
503+
try traverseChildren(t) finally reach = false
504+
case _ =>
505+
traverseChildren(t)
506+
if ref.isTrackableRef then add.traverse(tp)
507+
end addOwnerAsHidden
508+
492509
/** A traverser that adds knownTypes and updates symbol infos */
493510
def setupTraverser(checker: CheckerAPI) = new TreeTraverserWithPreciseImportContexts:
494511
import checker.*
@@ -503,15 +520,17 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
503520
var transformed =
504521
if tree.isInferred
505522
then transformInferredType(tree.tpe)
506-
else transformExplicitType(tree.tpe, sym, tptToCheck = tree)
523+
else
524+
val transformed = transformExplicitType(tree.tpe, sym, tptToCheck = tree)
525+
if boxed then transformed
526+
else Fresh.fromCap(transformed, sym).tap(addOwnerAsHidden(_, sym))
507527
if boxed then transformed = box(transformed)
508528
if sym.is(Param) && (transformed ne tree.tpe) then
509529
paramSigChange += tree
510530
tree.setNuType(
511531
if boxed then transformed
512532
else if sym.hasAnnotation(defn.UncheckedCapturesAnnot) then makeUnchecked(transformed)
513-
else if tree.isInferred then transformed
514-
else Fresh.fromCap(transformed, sym))
533+
else transformed)
515534

516535
/** Transform the type of a val or var or the result type of a def */
517536
def transformResultType(tpt: TypeTree, sym: Symbol)(using Context): Unit =
@@ -899,7 +918,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
899918
def apply(t: Type) = t match
900919
case t @ CapturingType(parent, refs) =>
901920
val parent1 = this(parent)
902-
if refs.isUniversal then t.derivedCapturingType(parent1, CaptureSet.Fluid)
921+
if refs.isUniversalOrFresh then t.derivedCapturingType(parent1, CaptureSet.Fluid)
903922
else t
904923
case _ => mapFollowingAliases(t)
905924

tests/neg-custom-args/captures/sepchecks2.check

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
| Separation failure: argument of type List[box () ->{c} Unit]
1111
| to method foo: (xs: List[box () => Unit], y: Object^): Nothing
1212
| corresponds to capture-polymorphic formal parameter xs of type List[box () => Unit]
13-
| and hides capabilities {<none>*, c}.
13+
| and hides capabilities {c}.
1414
| Some of these overlap with the captures of the second argument with type (c : Object^).
1515
|
16-
| Hidden set of current argument : {<none>*, c}
17-
| Hidden footprint of current argument : {<none>*, c}
16+
| Hidden set of current argument : {c}
17+
| Hidden footprint of current argument : {c}
1818
| Capture set of second argument : {c}
1919
| Footprint set of second argument : {c}
2020
| The two sets overlap at : {c}

0 commit comments

Comments
 (0)