Skip to content

Commit 729d743

Browse files
authored
Separation checking for product types (#22539)
This is based on #22588 and contains changes to make product types containing fresh entities work (at least in simple cases). There's a neat combination with both path capabilities and reach capabilities which makes this work. In short, if we have ```scala class Ref { var current: Int } case class Pair[+A, +B](fst: A, snd: B) ``` then we can form a `Pair[Ref^, Ref^]`: ```scala val r1 = Ref() val r2 = Ref() val p_exact: Pair[Ref^{r1}, Ref^{r2}] = Pair(r1, r2) val p: Pair[Ref^, Ref^] = p_exact ``` And if `p` has this type, then we can also take it apart: ```scala val x = p.fst val y = p.snd ``` With types added, this is ```scala val x: Ref^{p.fst*} = p.fst val y: Ref^{p.snd*} = p.snd ``` That is, we can get at the position of the boxed first element with `p.fst` and we can access what's in the box via `p.fst*`. Furthermore, `p.fst*` is known to be separate from `p.snd*`, so this means we can form another pair from them: ```scala val p2: Pair[Ref^, Ref^] = Pair(x, y) ``` In short, separation is preserved by forming products and taking them apart. It took quite a bit of work to get there.
2 parents c9eaa14 + 48a52a2 commit 729d743

File tree

218 files changed

+6190
-1917
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

218 files changed

+6190
-1917
lines changed

.jvmopts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
-Xss1m
2-
-Xms512m
3-
-Xmx4096m
2+
-Xms1024m
3+
-Xmx8192m
44
-XX:MaxInlineLevel=35
55
-XX:ReservedCodeCacheSize=512m

compiler/src/dotty/tools/backend/jvm/BTypesFromSymbols.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ class BTypesFromSymbols[I <: DottyBackendInterface](val int: I, val frontendAcce
285285
// tests/run/serialize.scala and https://github.com/typelevel/cats-effect/pull/2360).
286286
val privateFlag = !sym.isClass && (sym.is(Private) || (sym.isPrimaryConstructor && sym.owner.isTopLevelModuleClass))
287287

288-
val finalFlag = sym.is(Final) && !toDenot(sym).isClassConstructor && !sym.is(Mutable, butNot = Accessor) && !sym.enclosingClass.is(Trait)
288+
val finalFlag = sym.is(Final) && !toDenot(sym).isClassConstructor && !sym.isMutableVar && !sym.enclosingClass.is(Trait)
289289

290290
import asm.Opcodes.*
291291
import GenBCodeOps.addFlagIf

compiler/src/dotty/tools/dotc/ast/Desugar.scala

+2
Original file line numberDiff line numberDiff line change
@@ -2262,6 +2262,8 @@ object desugar {
22622262
New(ref(defn.RepeatedAnnot.typeRef), Nil :: Nil))
22632263
else if op.name == nme.CC_REACH then
22642264
Apply(ref(defn.Caps_reachCapability), t :: Nil)
2265+
else if op.name == nme.CC_READONLY then
2266+
Apply(ref(defn.Caps_readOnlyCapability), t :: Nil)
22652267
else
22662268
assert(ctx.mode.isExpr || ctx.reporter.errorsReported || ctx.mode.is(Mode.Interactive), ctx.mode)
22672269
Select(t, op.name)

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
759759
*/
760760
def isVariableOrGetter(tree: Tree)(using Context): Boolean = {
761761
def sym = tree.symbol
762-
def isVar = sym.is(Mutable)
762+
def isVar = sym.isMutableVarOrAccessor
763763
def isGetter =
764764
mayBeVarGetter(sym) && sym.owner.info.member(sym.name.asTermName.setterName).exists
765765

compiler/src/dotty/tools/dotc/ast/untpd.scala

+3
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
206206

207207
case class Var()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Mutable)
208208

209+
case class Mut()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Mutable)
210+
209211
case class Implicit()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Implicit)
210212

211213
case class Given()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Given)
@@ -332,6 +334,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
332334

333335
def isEnumCase: Boolean = isEnum && is(Case)
334336
def isEnumClass: Boolean = isEnum && !is(Case)
337+
def isMutableVar: Boolean = is(Mutable) && mods.exists(_.isInstanceOf[Mod.Var])
335338
}
336339

337340
@sharable val EmptyModifiers: Modifiers = Modifiers()

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ case class CaptureAnnotation(refs: CaptureSet, boxed: Boolean)(cls: Symbol) exte
4242
case cr: TermRef => ref(cr)
4343
case cr: TermParamRef => untpd.Ident(cr.paramName).withType(cr)
4444
case cr: ThisType => This(cr.cls)
45-
// TODO: Will crash if the type is an annotated type, for example `cap?`
45+
case root(_) => ref(root.cap)
46+
// TODO: Will crash if the type is an annotated type, for example `cap.rd`
4647
}
4748
val arg = repeated(elems, TypeTree(defn.AnyType))
4849
New(symbol.typeRef, arg :: Nil)

0 commit comments

Comments
 (0)