From 76fce2a6e472840ca0acca74ab40afd0049cff2a Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 23 Nov 2023 16:06:57 +0100 Subject: [PATCH] Add capture checking attributes to TASTy --- .../src/dotty/tools/dotc/core/Definitions.scala | 4 +--- .../dotty/tools/dotc/core/tasty/Attributes.scala | 6 ++++++ .../tools/dotc/core/tasty/TreeUnpickler.scala | 15 ++++----------- .../src/dotty/tools/dotc/transform/Pickler.scala | 3 +++ .../dotty/tools/dotc/transform/PostTyper.scala | 5 ----- tasty/src/dotty/tools/tasty/TastyFormat.scala | 6 ++++++ 6 files changed, 20 insertions(+), 19 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index c500953f49bf..566aec5a1169 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -1038,8 +1038,6 @@ class Definitions { @tu lazy val UncheckedVarianceAnnot: ClassSymbol = requiredClass("scala.annotation.unchecked.uncheckedVariance") @tu lazy val UncheckedCapturesAnnot: ClassSymbol = requiredClass("scala.annotation.unchecked.uncheckedCaptures") @tu lazy val VolatileAnnot: ClassSymbol = requiredClass("scala.volatile") - @tu lazy val WithPureFunsAnnot: ClassSymbol = requiredClass("scala.annotation.internal.WithPureFuns") - @tu lazy val CaptureCheckedAnnot: ClassSymbol = requiredClass("scala.annotation.internal.CaptureChecked") @tu lazy val BeanGetterMetaAnnot: ClassSymbol = requiredClass("scala.annotation.meta.beanGetter") @tu lazy val BeanSetterMetaAnnot: ClassSymbol = requiredClass("scala.annotation.meta.beanSetter") @tu lazy val FieldMetaAnnot: ClassSymbol = requiredClass("scala.annotation.meta.field") @@ -2004,7 +2002,7 @@ class Definitions { @tu lazy val ccExperimental: Set[Symbol] = Set( CapsModule, CapsModule.moduleClass, PureClass, CapabilityAnnot, RequiresCapabilityAnnot, - RetainsAnnot, RetainsByNameAnnot, WithPureFunsAnnot) + RetainsAnnot, RetainsByNameAnnot) // ----- primitive value class machinery ------------------------------------------ diff --git a/compiler/src/dotty/tools/dotc/core/tasty/Attributes.scala b/compiler/src/dotty/tools/dotc/core/tasty/Attributes.scala index 8f815981e68d..7f87b7f4f2b7 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/Attributes.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/Attributes.scala @@ -9,16 +9,22 @@ class Attributes private[tasty]( ) { def scala2StandardLibrary: Boolean = booleanTags(SCALA2STANDARDLIBRARYattr) def explicitNulls: Boolean = booleanTags(EXPLICITNULLSattr) + def captureChecked: Boolean = booleanTags(CAPTURECHECKEDattr) + def withPureFuns: Boolean = booleanTags(WITHPUREFUNSattr) } object Attributes: def apply( scala2StandardLibrary: Boolean, explicitNulls: Boolean, + captureChecked: Boolean, + withPureFuns: Boolean, ): Attributes = val booleanTags = BitSet.newBuilder if scala2StandardLibrary then booleanTags += SCALA2STANDARDLIBRARYattr if explicitNulls then booleanTags += EXPLICITNULLSattr + if captureChecked then booleanTags += CAPTURECHECKEDattr + if withPureFuns then booleanTags += WITHPUREFUNSattr new Attributes(booleanTags.result()) end apply diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 4b80768e1322..1f551028c415 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -92,11 +92,9 @@ class TreeUnpickler(reader: TastyReader, /** The root owner tree. See `OwnerTree` class definition. Set by `enterTopLevel`. */ private var ownerTree: OwnerTree = uninitialized - /** Was unpickled class compiled with pureFunctions? */ - private var withPureFuns: Boolean = false - /** Was unpickled class compiled with capture checks? */ - private var withCaptureChecks: Boolean = false + private val withCaptureChecks: Boolean = + attributeUnpicklerOpt.exists(_.attributes.captureChecked) private val unpicklingScala2Library = attributeUnpicklerOpt.exists(_.attributes.scala2StandardLibrary) @@ -655,13 +653,8 @@ class TreeUnpickler(reader: TastyReader, } registerSym(start, sym) if (isClass) { - if sym.owner.is(Package) then - if annots.exists(_.hasSymbol(defn.CaptureCheckedAnnot)) then - sym.setFlag(CaptureChecked) - withCaptureChecks = true - withPureFuns = true - else if annots.exists(_.hasSymbol(defn.WithPureFunsAnnot)) then - withPureFuns = true + if sym.owner.is(Package) && withCaptureChecks then + sym.setFlag(CaptureChecked) sym.completer.withDecls(newScope) forkAt(templateStart).indexTemplateParams()(using localContext(sym)) } diff --git a/compiler/src/dotty/tools/dotc/transform/Pickler.scala b/compiler/src/dotty/tools/dotc/transform/Pickler.scala index 57b8da058073..c361b50af819 100644 --- a/compiler/src/dotty/tools/dotc/transform/Pickler.scala +++ b/compiler/src/dotty/tools/dotc/transform/Pickler.scala @@ -7,6 +7,7 @@ import Contexts.* import Decorators.* import tasty.* import config.Printers.{noPrinter, pickling} +import config.Feature import java.io.PrintStream import Periods.* import Phases.* @@ -111,6 +112,8 @@ class Pickler extends Phase { val attributes = Attributes( scala2StandardLibrary = ctx.settings.YcompileScala2Library.value, explicitNulls = ctx.settings.YexplicitNulls.value, + captureChecked = Feature.ccEnabled, + withPureFuns = Feature.pureFunsEnabled, ) AttributePickler.pickleAttributes(attributes, pickler, scratch.attributeBuffer) diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index 817debc2eba9..35db363cd864 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -423,11 +423,6 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase => val reference = ctx.settings.sourceroot.value val relativePath = util.SourceFile.relativePath(ctx.compilationUnit.source, reference) sym.addAnnotation(Annotation.makeSourceFile(relativePath, tree.span)) - if sym != defn.WithPureFunsAnnot && sym != defn.CaptureCheckedAnnot then - if Feature.ccEnabled then - sym.addAnnotation(Annotation(defn.CaptureCheckedAnnot, tree.span)) - else if Feature.pureFunsEnabled then - sym.addAnnotation(Annotation(defn.WithPureFunsAnnot, tree.span)) else if !sym.is(Param) && !sym.owner.isOneOf(AbstractOrTrait) then Checking.checkGoodBounds(tree.symbol) diff --git a/tasty/src/dotty/tools/tasty/TastyFormat.scala b/tasty/src/dotty/tools/tasty/TastyFormat.scala index a77ad5d400d5..ebe94cc0a76c 100644 --- a/tasty/src/dotty/tools/tasty/TastyFormat.scala +++ b/tasty/src/dotty/tools/tasty/TastyFormat.scala @@ -273,6 +273,8 @@ Standard Section: "Attributes" Attribute* ```none Attribute = SCALA2STANDARDLIBRARYattr EXPLICITNULLSattr + CAPTURECHECKEDattr + WITHPUREFUNSattr ``` **************************************************************************************/ @@ -611,6 +613,8 @@ object TastyFormat { final val SCALA2STANDARDLIBRARYattr = 1 final val EXPLICITNULLSattr = 2 + final val CAPTURECHECKEDattr = 3 + final val WITHPUREFUNSattr = 4 /** Useful for debugging */ def isLegalTag(tag: Int): Boolean = @@ -830,6 +834,8 @@ object TastyFormat { def attributeTagToString(tag: Int): String = tag match { case SCALA2STANDARDLIBRARYattr => "SCALA2STANDARDLIBRARYattr" case EXPLICITNULLSattr => "EXPLICITNULLSattr" + case CAPTURECHECKEDattr => "CAPTURECHECKEDattr" + case WITHPUREFUNSattr => "WITHPUREFUNSattr" } /** @return If non-negative, the number of leading references (represented as nats) of a length/trees entry.