diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index 4b06140f75c2..405f9144b146 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -308,8 +308,8 @@ object Flags { */ val (_, StableRealizable @ _, _) = newFlags(24, "") - /** A case parameter accessor */ - val (_, CaseAccessor @ _, _) = newFlags(25, "") + /** A case parameter accessor / an unpickled Scala 2 TASTy (only for Scala 2 stdlib) */ + val (_, CaseAccessor @ _, Scala2Tasty @ _) = newFlags(25, "", "") /** A Scala 2x super accessor / an unpickled Scala 2.x class */ val (SuperParamAliasOrScala2x @ _, SuperParamAlias @ _, Scala2x @ _) = newFlags(26, "", "") diff --git a/compiler/src/dotty/tools/dotc/core/tasty/AttributeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/AttributeUnpickler.scala index 5c9b89bf3b0a..6df2cfd0f73d 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/AttributeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/AttributeUnpickler.scala @@ -3,7 +3,7 @@ package core.tasty import scala.language.unsafeNulls -import dotty.tools.tasty.{TastyReader, TastyBuffer} +import dotty.tools.tasty.{TastyFormat, TastyReader, TastyBuffer} import java.nio.charset.StandardCharsets @@ -23,4 +23,6 @@ class AttributeUnpickler(reader: TastyReader): attributesBuilder.result() } + def scala2Stdlib: Boolean = attributes.contains(TastyFormat.Scala2StandardLibraryAttribute) + end AttributeUnpickler diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 71d7f99c2ed2..0e449559393b 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -99,6 +99,9 @@ class TreeUnpickler(reader: TastyReader, /** Was unpickled class compiled with capture checks? */ private var withCaptureChecks: Boolean = false + private val unpicklingScala2Lib = + attributeUnpicklerOpt.exists(_.scala2Stdlib) + private def registerSym(addr: Addr, sym: Symbol) = symAtAddr(addr) = sym @@ -610,7 +613,8 @@ class TreeUnpickler(reader: TastyReader, val rhsStart = currentAddr val rhsIsEmpty = nothingButMods(end) if (!rhsIsEmpty) skipTree() - val (givenFlags, annotFns, privateWithin) = readModifiers(end) + val (givenFlags0, annotFns, privateWithin) = readModifiers(end) + val givenFlags = if isClass && unpicklingScala2Lib then givenFlags0 | Scala2x | Scala2Tasty else givenFlags0 pickling.println(i"creating symbol $name at $start with flags ${givenFlags.flagsString}, isAbsType = $isAbsType, $ttag") val flags = normalizeFlags(tag, givenFlags, name, isAbsType, rhsIsEmpty) def adjustIfModule(completer: LazyType) = diff --git a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala index 19124357a0bd..262f8d6bdce0 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala @@ -77,7 +77,7 @@ class ExtensionMethods extends MiniPhase with DenotTransformer with FullParamete // Create extension methods, except if the class comes from Scala 2 // because it adds extension methods before pickling. - if (!(valueClass.is(Scala2x))) + if !valueClass.is(Scala2x, butNot = Scala2Tasty) then for (decl <- valueClass.classInfo.decls) if isMethodWithExtension(decl) then enterInModuleClass(createExtensionMethod(decl, moduleClassSym.symbol)) diff --git a/compiler/src/dotty/tools/dotc/transform/Pickler.scala b/compiler/src/dotty/tools/dotc/transform/Pickler.scala index 8976cd97c7a6..c6da8aca8e41 100644 --- a/compiler/src/dotty/tools/dotc/transform/Pickler.scala +++ b/compiler/src/dotty/tools/dotc/transform/Pickler.scala @@ -16,6 +16,7 @@ import reporting.{ThrowingReporter, Profile, Message} import collection.mutable import util.concurrent.{Executor, Future} import compiletime.uninitialized +import dotty.tools.tasty.TastyFormat.Scala2StandardLibraryAttribute object Pickler { val name: String = "pickler" @@ -108,7 +109,9 @@ class Pickler extends Phase { pickler, treePkl.buf.addrOfTree, treePkl.docString, tree, scratch.commentBuffer) - val attributes = Nil // TODO add attributes here + val attributes = + if ctx.settings.Yscala2Stdlib.value then List(Scala2StandardLibraryAttribute) + else Nil AttributePickler.pickleAttributes(attributes, pickler, scratch.attributeBuffer) val pickled = pickler.assembleParts() diff --git a/scala2-library-tasty-tests/src/Main.scala b/scala2-library-tasty-tests/src/Main.scala index b579baf6513d..b33219271201 100644 --- a/scala2-library-tasty-tests/src/Main.scala +++ b/scala2-library-tasty-tests/src/Main.scala @@ -17,6 +17,7 @@ object HelloWorld: testScala2ObjectParents() testScala2CaseClassUnderscoreMembers() testScalaNumberUnderlying() + testArrayOps() scala.collection.mutable.UnrolledBufferTest.test() } @@ -68,3 +69,9 @@ object HelloWorld: val _: Object = MyNumber2(BigInt(1)).underlying val _: Object = (MyNumber2(BigInt(1)): ScalaNumber).underlying } + + def testArrayOps() = { + new collection.ArrayOps[String](Array[String]("foo")).exists(x => true) + } + +end HelloWorld diff --git a/tasty/src/dotty/tools/tasty/TastyFormat.scala b/tasty/src/dotty/tools/tasty/TastyFormat.scala index 4c37379a1e9c..ae8b4dfd8f2d 100644 --- a/tasty/src/dotty/tools/tasty/TastyFormat.scala +++ b/tasty/src/dotty/tools/tasty/TastyFormat.scala @@ -366,6 +366,8 @@ object TastyFormat { final val CommentsSection = "Comments" final val AttributesSection = "Attributes" + final val Scala2StandardLibraryAttribute = "Scala2StandardLibrary" + /** Tags used to serialize names, should update [[TastyFormat$.nameTagToString]] if a new constant is added */ class NameTags { final val UTF8 = 1 // A simple name in UTF8 encoding.