Skip to content

Commit

Permalink
chore: first draft of the stdlib
Browse files Browse the repository at this point in the history
  • Loading branch information
hamzaremmal committed Feb 5, 2025
1 parent 0ea05aa commit 8a3868e
Show file tree
Hide file tree
Showing 10 changed files with 3,454 additions and 78 deletions.
7 changes: 5 additions & 2 deletions project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import sbt.Package.ManifestAttributes
import sbt.PublishBinPlugin.autoImport._
import dotty.tools.sbtplugin.RepublishPlugin
import dotty.tools.sbtplugin.RepublishPlugin.autoImport._
import dotty.tools.sbtplugin.ScalaLibraryPlugin

import sbt.plugins.SbtPlugin
import sbt.ScriptedPlugin.autoImport._
import xerial.sbt.Sonatype.autoImport._
Expand All @@ -32,6 +34,8 @@ import sbtbuildinfo.BuildInfoPlugin.autoImport._
import sbttastymima.TastyMiMaPlugin
import sbttastymima.TastyMiMaPlugin.autoImport._

import scala.jdk.CollectionConverters._

import scala.util.Properties.isJavaAtLeast

import org.portablescala.sbtplatformdeps.PlatformDepsPlugin.autoImport._
Expand Down Expand Up @@ -1207,9 +1211,9 @@ object Build {
* This version of the library is not (yet) TASTy/binary compatible with the Scala 2 compiled library.
*/
lazy val `scala2-library-bootstrapped` = project.in(file("scala2-library-bootstrapped")).
enablePlugins(ScalaLibraryPlugin).
withCommonSettings(Bootstrapped).
dependsOn(dottyCompiler(Bootstrapped) % "provided; compile->runtime; test->test").
settings(commonBootstrappedSettings).
settings(scala2LibraryBootstrappedSettings).
settings(moduleName := "scala2-library")
// -Ycheck:all is set in project/scripts/scala2-library-tasty-mima.sh
Expand All @@ -1221,7 +1225,6 @@ object Build {
lazy val `scala2-library-cc` = project.in(file("scala2-library-cc")).
withCommonSettings(Bootstrapped).
dependsOn(dottyCompiler(Bootstrapped) % "provided; compile->runtime; test->test").
settings(commonBootstrappedSettings).
settings(scala2LibraryBootstrappedSettings).
settings(
moduleName := "scala2-library-cc",
Expand Down
105 changes: 29 additions & 76 deletions project/Scala2LibraryBootstrappedMiMaFilters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,82 +4,35 @@ import com.typesafe.tools.mima.core._
object Scala2LibraryBootstrappedMiMaFilters {

val BackwardsBreakingChanges: Map[String, Seq[ProblemFilter]] = Map(
Build.stdlibBootstrappedVersion -> {
Seq(
// Files that are not compiled in the bootstrapped library
ProblemFilters.exclude[MissingClassProblem]("scala.AnyVal"),

// Scala language features
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.language.<clinit>"),
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.language#experimental.<clinit>"),
ProblemFilters.exclude[FinalClassProblem]("scala.language$experimental$"),
ProblemFilters.exclude[FinalClassProblem]("scala.languageFeature$*$"),

// trait $init$
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.*.$init$"),

// Value class extension methods
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.*$extension"),

// Companion module class
ProblemFilters.exclude[FinalClassProblem]("scala.*$"),

// Scala 2 intrinsic macros
ProblemFilters.exclude[FinalMethodProblem]("scala.StringContext.s"),

// Specialization?
ProblemFilters.exclude[MissingFieldProblem]("scala.Tuple1._1"), // field _1 in class scala.Tuple1 does not have a correspondent in current version
ProblemFilters.exclude[MissingFieldProblem]("scala.Tuple2._1"), // field _1 in class scala.Tuple2 does not have a correspondent in current version
ProblemFilters.exclude[MissingFieldProblem]("scala.Tuple2._2"), // field _2 in class scala.Tuple2 does not have a correspondent in current version

// Scala 2 specialization
ProblemFilters.exclude[MissingClassProblem]("scala.*$sp"),
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.*$sp"),
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.*#*#sp.$init$"),
ProblemFilters.exclude[MissingTypesProblem]("scala.collection.DoubleStepper"),
ProblemFilters.exclude[MissingTypesProblem]("scala.collection.immutable.DoubleVectorStepper"),
ProblemFilters.exclude[MissingTypesProblem]("scala.collection.immutable.IntVectorStepper"),
ProblemFilters.exclude[MissingTypesProblem]("scala.collection.immutable.LongVectorStepper"),
ProblemFilters.exclude[MissingTypesProblem]("scala.collection.IntStepper"),
ProblemFilters.exclude[MissingTypesProblem]("scala.collection.LongStepper"),
ProblemFilters.exclude[MissingTypesProblem]("scala.jdk.DoubleAccumulator"),
ProblemFilters.exclude[MissingTypesProblem]("scala.jdk.FunctionWrappers$*"),
ProblemFilters.exclude[MissingTypesProblem]("scala.jdk.IntAccumulator"),
ProblemFilters.exclude[MissingTypesProblem]("scala.jdk.LongAccumulator"),
ProblemFilters.exclude[FinalClassProblem]("scala.collection.ArrayOps$ReverseIterator"),
ProblemFilters.exclude[FinalClassProblem]("scala.Tuple1"),
ProblemFilters.exclude[FinalClassProblem]("scala.Tuple2"),

// other
ProblemFilters.exclude[FinalMethodProblem]("scala.Enumeration.ValueOrdering"),
ProblemFilters.exclude[FinalMethodProblem]("scala.Enumeration.ValueSet"),
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",
"scala.collection.mutable.PriorityQueue#ResizableArrayAccess.this",
"scala.concurrent.BatchingExecutor#AbstractBatch.this",
"scala.concurrent.Channel#LinkedList.this",
"scala.Enumeration#ValueOrdering.this",
"scala.io.Source#RelaxedPosition.this",
"scala.collection.IterableOnceOps#Maximized.this", // New in 2.13.11: private inner class
"scala.util.Properties.<clinit>",
"scala.util.Sorting.scala$util$Sorting$$mergeSort$default$5",
).map(ProblemFilters.exclude[DirectMissingMethodProblem])
}
Build.stdlibBootstrappedVersion -> Seq(
// Scala language features (not really a problem)
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.language.<clinit>"),
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.language#experimental.<clinit>"),
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.util.Properties.<clinit>"),

// Companion module class (not really a problem)
ProblemFilters.exclude[FinalClassProblem]("scala.*$"),
ProblemFilters.exclude[FinalMethodProblem]("scala.io.Source.NoPositioner"),
ProblemFilters.exclude[FinalMethodProblem]("scala.io.Source.RelaxedPosition"),
ProblemFilters.exclude[FinalMethodProblem]("scala.io.Source.RelaxedPositioner"),
ProblemFilters.exclude[FinalMethodProblem]("scala.Enumeration.ValueOrdering"),
ProblemFilters.exclude[FinalMethodProblem]("scala.Enumeration.ValueSet"),
ProblemFilters.exclude[FinalMethodProblem]("scala.StringContext.s"),

// Need to be fixed
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.*.$init$"),
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.*$extension"),
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[ReversedMissingMethodProblem]("scala.collection.immutable.SortedMapOps.coll"),
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.util.Sorting.scala$util$Sorting$$mergeSort$default$5")
)
)

val ForwardsBreakingChanges: Map[String, Seq[ProblemFilter]] = Map(
Expand Down
107 changes: 107 additions & 0 deletions project/ScalaLibraryPlugin.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package dotty.tools.sbtplugin

import sbt.*
import sbt.Keys.*
import scala.jdk.CollectionConverters.*
import java.nio.file.Files

object ScalaLibraryPlugin extends AutoPlugin {

override def trigger = noTrigger

val fetchScala2ClassFiles = taskKey[(Set[File], File)]("Fetch the files to use that were compiled with Scala 2")
//val scala2LibraryVersion = settingKey[String]("Version of the Scala 2 Standard Library")

override def projectSettings = Seq (
fetchScala2ClassFiles := {
val stream = streams.value
val cache = stream.cacheDirectory
val target = cache / "scala-library-classes"
val report = update.value

val scalaLibraryBinaryJar = report.select(
configuration = configurationFilter(),
module = (_: ModuleID).name == "scala-library",
artifact = artifactFilter(`type` = "jar")).headOption.getOrElse {
sys.error(s"Could not fetch scala-library binary JAR")
}

if (!target.exists()) {
IO.createDirectory(target)
}

(FileFunction.cached(cache / "fetch-scala-library-classes", FilesInfo.lastModified, FilesInfo.exists) { _ =>
stream.log.info(s"Unpacking scala-library binaries to persistent directory: ${target.getAbsolutePath}")
IO.unzip(scalaLibraryBinaryJar, target)
(target ** "*.class").get.toSet
} (Set(scalaLibraryBinaryJar)), target)

},
(Compile / compile) := {
val stream = streams.value
val target = (Compile / classDirectory).value
val (files, reference) = fetchScala2ClassFiles.value;
val analysis = (Compile / compile).value
stream.log.info(s"Copying files from Scala 2 Standard Library to $target")
for (file <- files; id <- file.relativeTo(reference).map(_.toString())) {
if (filesToCopy(id)) {
stream.log.debug(s"Copying file '${id}' to ${target / id}")
IO.copyFile(file, target / id)
}
}

val overwrittenBinaries = Files.walk((Compile / classDirectory).value.toPath())
.iterator()
.asScala
.map(_.toFile)
.map(_.relativeTo((Compile / classDirectory).value).get)
.toSet
val diff = files.filterNot(_.relativeTo(reference).exists(overwrittenBinaries))

IO.copy(diff.map { file =>
file -> (Compile / classDirectory).value / file.relativeTo(reference).get.getPath
})

analysis
}
)

private lazy val filesToCopy = Set(
"scala/Tuple1.class",
"scala/Tuple2.class",
"scala/collection/DoubleStepper.class",
"scala/collection/IntStepper.class",
"scala/collection/LongStepper.class",
"scala/collection/immutable/DoubleVectorStepper.class",
"scala/collection/immutable/IntVectorStepper.class",
"scala/collection/immutable/LongVectorStepper.class",
"scala/jdk/DoubleAccumulator.class",
"scala/jdk/IntAccumulator.class",
"scala/jdk/LongAccumulator.class",
"scala/jdk/FunctionWrappers$FromJavaDoubleBinaryOperator.class",
"scala/jdk/FunctionWrappers$FromJavaBooleanSupplier.class",
"scala/jdk/FunctionWrappers$FromJavaDoubleConsumer.class",
"scala/jdk/FunctionWrappers$FromJavaDoublePredicate.class",
"scala/jdk/FunctionWrappers$FromJavaDoubleSupplier.class",
"scala/jdk/FunctionWrappers$FromJavaDoubleToIntFunction.class",
"scala/jdk/FunctionWrappers$FromJavaDoubleToLongFunction.class",
"scala/jdk/FunctionWrappers$FromJavaIntBinaryOperator.class",
"scala/jdk/FunctionWrappers$FromJavaDoubleUnaryOperator.class",
"scala/jdk/FunctionWrappers$FromJavaIntPredicate.class",
"scala/jdk/FunctionWrappers$FromJavaIntConsumer.class",
"scala/jdk/FunctionWrappers$FromJavaIntSupplier.class",
"scala/jdk/FunctionWrappers$FromJavaIntToDoubleFunction.class",
"scala/jdk/FunctionWrappers$FromJavaIntToLongFunction.class",
"scala/jdk/FunctionWrappers$FromJavaIntUnaryOperator.class",
"scala/jdk/FunctionWrappers$FromJavaLongBinaryOperator.class",
"scala/jdk/FunctionWrappers$FromJavaLongConsumer.class",
"scala/jdk/FunctionWrappers$FromJavaLongPredicate.class",
"scala/jdk/FunctionWrappers$FromJavaLongSupplier.class",
"scala/jdk/FunctionWrappers$FromJavaLongToDoubleFunction.class",
"scala/jdk/FunctionWrappers$FromJavaLongToIntFunction.class",
"scala/jdk/FunctionWrappers$FromJavaLongUnaryOperator.class",
"scala/collection/ArrayOps$ReverseIterator.class",
"scala/runtime/NonLocalReturnControl.class",
)

}
Loading

0 comments on commit 8a3868e

Please sign in to comment.