From 075f5e62c76f06d5eade95725739ac5d1e011713 Mon Sep 17 00:00:00 2001 From: Hamza Remmal Date: Tue, 4 Feb 2025 23:28:37 +0100 Subject: [PATCH 1/4] chore: Consider source code as Scala 2 under `-Ycompile-scala2-library` --- compiler/src/dotty/tools/dotc/typer/Namer.scala | 4 +++- project/Scala2LibraryBootstrappedMiMaFilters.scala | 7 ------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 21ef0fc5d123..07f19b420c1a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -246,7 +246,9 @@ class Namer { typer: Typer => tree match { case tree: TypeDef if tree.isClassDef => - val flags = checkFlags(tree.mods.flags) + var flags = checkFlags(tree.mods.flags) + if ctx.settings.YcompileScala2Library.value then + flags |= Scala2x val name = checkNoConflict(tree.name, flags.is(Private), tree.span).asTypeName val cls = createOrRefine[ClassSymbol](tree, name, flags, ctx.owner, diff --git a/project/Scala2LibraryBootstrappedMiMaFilters.scala b/project/Scala2LibraryBootstrappedMiMaFilters.scala index f30a072955b0..d93f67c8291c 100644 --- a/project/Scala2LibraryBootstrappedMiMaFilters.scala +++ b/project/Scala2LibraryBootstrappedMiMaFilters.scala @@ -66,17 +66,10 @@ object Scala2LibraryBootstrappedMiMaFilters { ProblemFilters.exclude[FinalMethodProblem]("scala.io.Source.NoPositioner"), ProblemFilters.exclude[FinalMethodProblem]("scala.io.Source.RelaxedPosition"), ProblemFilters.exclude[FinalMethodProblem]("scala.io.Source.RelaxedPositioner"), - ProblemFilters.exclude[IncompatibleResultTypeProblem]("scala.collection.immutable.SortedMapOps.coll"), - ProblemFilters.exclude[IncompatibleResultTypeProblem]("scala.collection.immutable.TreeMap.empty"), - ProblemFilters.exclude[IncompatibleResultTypeProblem]("scala.collection.immutable.TreeMap.fromSpecific"), - ProblemFilters.exclude[IncompatibleResultTypeProblem]("scala.collection.mutable.ArrayBuilder#ofUnit.addAll"), - ProblemFilters.exclude[IncompatibleResultTypeProblem]("scala.collection.mutable.TreeMap.empty"), - ProblemFilters.exclude[IncompatibleResultTypeProblem]("scala.collection.mutable.TreeMap.fromSpecific"), ProblemFilters.exclude[IncompatibleResultTypeProblem]("scala.reflect.ManifestFactory#NothingManifest.newArray"), ProblemFilters.exclude[IncompatibleResultTypeProblem]("scala.reflect.ManifestFactory#NullManifest.newArray"), ProblemFilters.exclude[MissingFieldProblem]("scala.collection.ArrayOps#ReverseIterator.xs"), ProblemFilters.exclude[MissingFieldProblem]("scala.runtime.NonLocalReturnControl.value"), - ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.collection.immutable.SortedMapOps.coll"), ) ++ Seq( // DirectMissingMethodProblem "scala.collection.LinearSeqIterator#LazyCell.this", From 965dbfa0681db7ac15bafdb93ad4efec766f29e7 Mon Sep 17 00:00:00 2001 From: Hamza Remmal Date: Wed, 5 Feb 2025 00:44:52 +0100 Subject: [PATCH 2/4] chore: Do not report macro warning for String interpolators --- compiler/src/dotty/tools/dotc/transform/PostTyper.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index 46beb262c23f..df74e102f693 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -256,7 +256,10 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase => for publicInBinaryAnnot <- publicInBinaryAnnotOpt do sym.addAnnotation(publicInBinaryAnnot) else sym.keepAnnotationsCarrying(thisPhase, Set(defn.GetterMetaAnnot, defn.FieldMetaAnnot), orNoneOf = defn.NonBeanMetaAnnots) - if sym.isScala2Macro && !ctx.settings.XignoreScala2Macros.value then + if sym.isScala2Macro && !ctx.settings.XignoreScala2Macros.value && + sym != defn.StringContext_raw && + sym != defn.StringContext_f && + sym != defn.StringContext_s then if !sym.owner.unforcedDecls.exists(p => !p.isScala2Macro && p.name == sym.name && p.signature == sym.signature) // Allow scala.reflect.materializeClassTag to be able to compile scala/reflect/package.scala // This should be removed on Scala 3.x From 78c74736fb800cc38a7fe67cab65b630f4cb925d Mon Sep 17 00:00:00 2001 From: Hamza Remmal Date: Thu, 6 Feb 2025 13:53:08 +0100 Subject: [PATCH 3/4] chore: Allow to write tasty for Scala2 symbols under -Ycompile-scala2-library --- compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala | 2 +- project/Scala2LibraryBootstrappedMiMaFilters.scala | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 7b80c7c80a21..cf9885d16d1f 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -861,7 +861,7 @@ class TreePickler(pickler: TastyPickler, attributes: Attributes) { assert(isModifierTag(tag)) writeByte(tag) } - assert(!flags.is(Scala2x)) + if flags.is(Scala2x) then assert(attributes.scala2StandardLibrary) if (flags.is(Private)) writeModTag(PRIVATE) if (flags.is(Protected)) writeModTag(PROTECTED) if (flags.is(Final, butNot = Module)) writeModTag(FINAL) diff --git a/project/Scala2LibraryBootstrappedMiMaFilters.scala b/project/Scala2LibraryBootstrappedMiMaFilters.scala index d93f67c8291c..70070fddf3e2 100644 --- a/project/Scala2LibraryBootstrappedMiMaFilters.scala +++ b/project/Scala2LibraryBootstrappedMiMaFilters.scala @@ -66,8 +66,6 @@ object Scala2LibraryBootstrappedMiMaFilters { ProblemFilters.exclude[FinalMethodProblem]("scala.io.Source.NoPositioner"), ProblemFilters.exclude[FinalMethodProblem]("scala.io.Source.RelaxedPosition"), ProblemFilters.exclude[FinalMethodProblem]("scala.io.Source.RelaxedPositioner"), - ProblemFilters.exclude[IncompatibleResultTypeProblem]("scala.reflect.ManifestFactory#NothingManifest.newArray"), - ProblemFilters.exclude[IncompatibleResultTypeProblem]("scala.reflect.ManifestFactory#NullManifest.newArray"), ProblemFilters.exclude[MissingFieldProblem]("scala.collection.ArrayOps#ReverseIterator.xs"), ProblemFilters.exclude[MissingFieldProblem]("scala.runtime.NonLocalReturnControl.value"), ) ++ From 19c42eec5a354b8c14f8f1647439fc02413497be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20Bra=C4=8Devac?= Date: Tue, 11 Feb 2025 16:21:56 +0100 Subject: [PATCH 4/4] Fix: adapt scala2-library-cc to Scala 2 semantics --- .../scala/collection/concurrent/TrieMap.scala | 3 ++- .../src/scala/collection/immutable/Range.scala | 3 ++- .../collection/mutable/UnrolledBuffer.scala | 16 +++++++++------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/scala2-library-cc/src/scala/collection/concurrent/TrieMap.scala b/scala2-library-cc/src/scala/collection/concurrent/TrieMap.scala index 3bcbc60c8744..9c150e19ab9c 100644 --- a/scala2-library-cc/src/scala/collection/concurrent/TrieMap.scala +++ b/scala2-library-cc/src/scala/collection/concurrent/TrieMap.scala @@ -1071,6 +1071,7 @@ object TrieMap extends MapFactory[TrieMap] { // non-final as an extension point for parallel collections private[collection] class TrieMapIterator[K, V](var level: Int, private var ct: TrieMap[K, V], mustInit: Boolean = true) extends AbstractIterator[(K, V)] { + this:TrieMapIterator[K, V]^ => private val stack = new Array[Array[BasicNode]](7) private val stackpos = new Array[Int](7) private var depth = -1 @@ -1161,7 +1162,7 @@ private[collection] class TrieMapIterator[K, V](var level: Int, private var ct: /** Returns a sequence of iterators over subsets of this iterator. * It's used to ease the implementation of splitters for a parallel version of the TrieMap. */ - protected def subdivide(): Seq[Iterator[(K, V)]] = if (subiter ne null) { + protected def subdivide(): Seq[Iterator[(K, V)]^{this}] = if (subiter ne null) { // the case where an LNode is being iterated val it = newIterator(level + 1, ct, _mustInit = false) it.depth = -1 diff --git a/scala2-library-cc/src/scala/collection/immutable/Range.scala b/scala2-library-cc/src/scala/collection/immutable/Range.scala index 459591d1a9cb..11fed1d9b1af 100644 --- a/scala2-library-cc/src/scala/collection/immutable/Range.scala +++ b/scala2-library-cc/src/scala/collection/immutable/Range.scala @@ -643,6 +643,7 @@ private class RangeIterator( lastElement: Int, initiallyEmpty: Boolean ) extends AbstractIterator[Int] with Serializable { + this: RangeIterator^ => private[this] var _hasNext: Boolean = !initiallyEmpty private[this] var _next: Int = start override def knownSize: Int = if (_hasNext) (lastElement - _next) / step + 1 else 0 @@ -656,7 +657,7 @@ private class RangeIterator( value } - override def drop(n: Int): Iterator[Int] = { + override def drop(n: Int): Iterator[Int]^{this} = { if (n > 0) { val longPos = _next.toLong + step * n if (step > 0) { diff --git a/scala2-library-cc/src/scala/collection/mutable/UnrolledBuffer.scala b/scala2-library-cc/src/scala/collection/mutable/UnrolledBuffer.scala index cfb6d014ae9d..0b7da1430f38 100644 --- a/scala2-library-cc/src/scala/collection/mutable/UnrolledBuffer.scala +++ b/scala2-library-cc/src/scala/collection/mutable/UnrolledBuffer.scala @@ -18,6 +18,7 @@ import scala.collection.generic.DefaultSerializable import scala.reflect.ClassTag import scala.collection.immutable.Nil import language.experimental.captureChecking +import caps.unsafe.unsafeAssumePure /** A buffer that stores elements in an unrolled linked list. * @@ -259,13 +260,14 @@ object UnrolledBuffer extends StrictOptimizedClassTagSeqFactory[UnrolledBuffer] /** Unrolled buffer node. */ class Unrolled[T: ClassTag] private[collection] (var size: Int, var array: Array[T], var next: Unrolled[T], val buff: UnrolledBuffer[T] = null) { + //this: Unrolled[T]^ => private[collection] def this() = this(0, new Array[T](unrolledlength), null, null) private[collection] def this(b: UnrolledBuffer[T]) = this(0, new Array[T](unrolledlength), null, b) private def nextlength = if (buff eq null) unrolledlength else buff.calcNextLength(array.length) // adds and returns itself or the new unrolled if full - @tailrec final def append(elem: T): Unrolled[T] = if (size < array.length) { + @tailrec final def append(elem: T): Unrolled[T]^{this} = if (size < array.length) { array(size) = elem size += 1 this @@ -307,21 +309,21 @@ object UnrolledBuffer extends StrictOptimizedClassTagSeqFactory[UnrolledBuffer] if (idx < size) array(idx) else next.apply(idx - size) @tailrec final def update(idx: Int, newelem: T): Unit = if (idx < size) array(idx) = newelem else next.update(idx - size, newelem) - @tailrec final def locate(idx: Int): Unrolled[T] = + @tailrec final def locate(idx: Int): Unrolled[T]^{this} = if (idx < size) this else next.locate(idx - size) - def prepend(elem: T) = if (size < array.length) { + def prepend(elem: T): Unrolled[T] = if (size < array.length) { // shift the elements of the array right // then insert the element shiftright() array(0) = elem size += 1 - this + this.unsafeAssumePure } else { // allocate a new node and store element // then make it point to this val newhead = new Unrolled[T](buff) newhead append elem - newhead.next = this + newhead.next = this.unsafeAssumePure newhead } // shifts right assuming enough space @@ -340,7 +342,7 @@ object UnrolledBuffer extends StrictOptimizedClassTagSeqFactory[UnrolledBuffer] val r = array(idx) shiftleft(idx) size -= 1 - if (tryMergeWithNext()) buffer.lastPtr = this + if (tryMergeWithNext()) buffer.lastPtr = this.unsafeAssumePure r } else next.remove(idx - size, buffer) @@ -397,7 +399,7 @@ object UnrolledBuffer extends StrictOptimizedClassTagSeqFactory[UnrolledBuffer] curr.next = newnextnode // try to merge the last node of this with the newnextnode and fix tail pointer if needed - if (curr.tryMergeWithNext()) buffer.lastPtr = curr + if (curr.tryMergeWithNext()) buffer.lastPtr = curr.unsafeAssumePure else if (newnextnode.next eq null) buffer.lastPtr = newnextnode appended }