Skip to content

Commit ab4f0e2

Browse files
authored
Add capture checking attributes to TASTy (#19033)
Replace `@CaptureChecked` and `@WithPureFuns` with TASTy attributes.
2 parents 41e7d95 + 76fce2a commit ab4f0e2

File tree

6 files changed

+20
-19
lines changed

6 files changed

+20
-19
lines changed

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

+1-3
Original file line numberDiff line numberDiff line change
@@ -1038,8 +1038,6 @@ class Definitions {
10381038
@tu lazy val UncheckedVarianceAnnot: ClassSymbol = requiredClass("scala.annotation.unchecked.uncheckedVariance")
10391039
@tu lazy val UncheckedCapturesAnnot: ClassSymbol = requiredClass("scala.annotation.unchecked.uncheckedCaptures")
10401040
@tu lazy val VolatileAnnot: ClassSymbol = requiredClass("scala.volatile")
1041-
@tu lazy val WithPureFunsAnnot: ClassSymbol = requiredClass("scala.annotation.internal.WithPureFuns")
1042-
@tu lazy val CaptureCheckedAnnot: ClassSymbol = requiredClass("scala.annotation.internal.CaptureChecked")
10431041
@tu lazy val BeanGetterMetaAnnot: ClassSymbol = requiredClass("scala.annotation.meta.beanGetter")
10441042
@tu lazy val BeanSetterMetaAnnot: ClassSymbol = requiredClass("scala.annotation.meta.beanSetter")
10451043
@tu lazy val FieldMetaAnnot: ClassSymbol = requiredClass("scala.annotation.meta.field")
@@ -2004,7 +2002,7 @@ class Definitions {
20042002
@tu lazy val ccExperimental: Set[Symbol] = Set(
20052003
CapsModule, CapsModule.moduleClass, PureClass,
20062004
CapabilityAnnot, RequiresCapabilityAnnot,
2007-
RetainsAnnot, RetainsByNameAnnot, WithPureFunsAnnot)
2005+
RetainsAnnot, RetainsByNameAnnot)
20082006

20092007
// ----- primitive value class machinery ------------------------------------------
20102008

compiler/src/dotty/tools/dotc/core/tasty/Attributes.scala

+6
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,22 @@ class Attributes private[tasty](
99
) {
1010
def scala2StandardLibrary: Boolean = booleanTags(SCALA2STANDARDLIBRARYattr)
1111
def explicitNulls: Boolean = booleanTags(EXPLICITNULLSattr)
12+
def captureChecked: Boolean = booleanTags(CAPTURECHECKEDattr)
13+
def withPureFuns: Boolean = booleanTags(WITHPUREFUNSattr)
1214
}
1315

1416
object Attributes:
1517
def apply(
1618
scala2StandardLibrary: Boolean,
1719
explicitNulls: Boolean,
20+
captureChecked: Boolean,
21+
withPureFuns: Boolean,
1822
): Attributes =
1923
val booleanTags = BitSet.newBuilder
2024
if scala2StandardLibrary then booleanTags += SCALA2STANDARDLIBRARYattr
2125
if explicitNulls then booleanTags += EXPLICITNULLSattr
26+
if captureChecked then booleanTags += CAPTURECHECKEDattr
27+
if withPureFuns then booleanTags += WITHPUREFUNSattr
2228
new Attributes(booleanTags.result())
2329
end apply
2430

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

+4-11
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,9 @@ class TreeUnpickler(reader: TastyReader,
9292
/** The root owner tree. See `OwnerTree` class definition. Set by `enterTopLevel`. */
9393
private var ownerTree: OwnerTree = uninitialized
9494

95-
/** Was unpickled class compiled with pureFunctions? */
96-
private var withPureFuns: Boolean = false
97-
9895
/** Was unpickled class compiled with capture checks? */
99-
private var withCaptureChecks: Boolean = false
96+
private val withCaptureChecks: Boolean =
97+
attributeUnpicklerOpt.exists(_.attributes.captureChecked)
10098

10199
private val unpicklingScala2Library =
102100
attributeUnpicklerOpt.exists(_.attributes.scala2StandardLibrary)
@@ -655,13 +653,8 @@ class TreeUnpickler(reader: TastyReader,
655653
}
656654
registerSym(start, sym)
657655
if (isClass) {
658-
if sym.owner.is(Package) then
659-
if annots.exists(_.hasSymbol(defn.CaptureCheckedAnnot)) then
660-
sym.setFlag(CaptureChecked)
661-
withCaptureChecks = true
662-
withPureFuns = true
663-
else if annots.exists(_.hasSymbol(defn.WithPureFunsAnnot)) then
664-
withPureFuns = true
656+
if sym.owner.is(Package) && withCaptureChecks then
657+
sym.setFlag(CaptureChecked)
665658
sym.completer.withDecls(newScope)
666659
forkAt(templateStart).indexTemplateParams()(using localContext(sym))
667660
}

compiler/src/dotty/tools/dotc/transform/Pickler.scala

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Contexts.*
77
import Decorators.*
88
import tasty.*
99
import config.Printers.{noPrinter, pickling}
10+
import config.Feature
1011
import java.io.PrintStream
1112
import Periods.*
1213
import Phases.*
@@ -111,6 +112,8 @@ class Pickler extends Phase {
111112
val attributes = Attributes(
112113
scala2StandardLibrary = ctx.settings.YcompileScala2Library.value,
113114
explicitNulls = ctx.settings.YexplicitNulls.value,
115+
captureChecked = Feature.ccEnabled,
116+
withPureFuns = Feature.pureFunsEnabled,
114117
)
115118
AttributePickler.pickleAttributes(attributes, pickler, scratch.attributeBuffer)
116119

compiler/src/dotty/tools/dotc/transform/PostTyper.scala

-5
Original file line numberDiff line numberDiff line change
@@ -423,11 +423,6 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
423423
val reference = ctx.settings.sourceroot.value
424424
val relativePath = util.SourceFile.relativePath(ctx.compilationUnit.source, reference)
425425
sym.addAnnotation(Annotation.makeSourceFile(relativePath, tree.span))
426-
if sym != defn.WithPureFunsAnnot && sym != defn.CaptureCheckedAnnot then
427-
if Feature.ccEnabled then
428-
sym.addAnnotation(Annotation(defn.CaptureCheckedAnnot, tree.span))
429-
else if Feature.pureFunsEnabled then
430-
sym.addAnnotation(Annotation(defn.WithPureFunsAnnot, tree.span))
431426
else
432427
if !sym.is(Param) && !sym.owner.isOneOf(AbstractOrTrait) then
433428
Checking.checkGoodBounds(tree.symbol)

tasty/src/dotty/tools/tasty/TastyFormat.scala

+6
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ Standard Section: "Attributes" Attribute*
273273
```none
274274
Attribute = SCALA2STANDARDLIBRARYattr
275275
EXPLICITNULLSattr
276+
CAPTURECHECKEDattr
277+
WITHPUREFUNSattr
276278
```
277279
278280
**************************************************************************************/
@@ -611,6 +613,8 @@ object TastyFormat {
611613

612614
final val SCALA2STANDARDLIBRARYattr = 1
613615
final val EXPLICITNULLSattr = 2
616+
final val CAPTURECHECKEDattr = 3
617+
final val WITHPUREFUNSattr = 4
614618

615619
/** Useful for debugging */
616620
def isLegalTag(tag: Int): Boolean =
@@ -830,6 +834,8 @@ object TastyFormat {
830834
def attributeTagToString(tag: Int): String = tag match {
831835
case SCALA2STANDARDLIBRARYattr => "SCALA2STANDARDLIBRARYattr"
832836
case EXPLICITNULLSattr => "EXPLICITNULLSattr"
837+
case CAPTURECHECKEDattr => "CAPTURECHECKEDattr"
838+
case WITHPUREFUNSattr => "WITHPUREFUNSattr"
833839
}
834840

835841
/** @return If non-negative, the number of leading references (represented as nats) of a length/trees entry.

0 commit comments

Comments
 (0)