Skip to content

Commit

Permalink
Add Scala 2.12 support (scala-native#1877)
Browse files Browse the repository at this point in the history
The Scala 2.12 changelog can be found at
https://www.scala-lang.org/news/2.12.0/
This PR takes into account all the changes and adapts them for
Scala Native.

---

Lambdas

In order to keep the NIR changes to a minimum, we continue
generating a `FunctionN` class with an `apply` method for each
lambda. All the lambda captures are stored inside the class
instance and initialised via its constructor. The `apply` method
calls the generated `$anonfun` method, also extracting and
forwarding the captures.

---

NIR changes

Scala 2.12 now compiles trait methods as default methods in Java
interfaces. This means that the NIR was enhanced to support default
methods. The biggest impact of that is found in the reachability
analysis (`Reach.scala`).

---

Scala 2.11 cross-compilation

In order to keep the project compilable with Scala 2.11, a
`scala.scalanative.nscplugin.NirCompat` component is introduced in
`nscplugin`. This allows the compiler plugin to function with both
Scala 2.11 and 2.12.

In addition, some tests need to know under which Scala version they
are running. We use `sbt-buildinfo` to provide Scala version
information to the projects that need them (mainly for `unit-tests`
and `tools` tests).

---

Co-authored-by: Denys Shabalin <denys.shabalin@epfl.ch>
  • Loading branch information
2 people authored and WojciechMazur committed Aug 25, 2021
1 parent 29418e3 commit 469ac89
Show file tree
Hide file tree
Showing 108 changed files with 9,673 additions and 281 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ sudo: required

scala:
- "2.11.12"
- "2.12.12"

os: linux
dist: trusty
Expand Down Expand Up @@ -36,7 +37,7 @@ script:
- java -version
- if [ "$MODE" == "source-checks" ]; then ./scripts/source-checks; fi
- if [ "$MODE" == "test-tools" ]; then
sbt "-no-colors" "-J-Xmx3G" test-tools;
sbt "++ $TRAVIS_SCALA_VERSION -v" "-no-colors" "-J-Xmx3G" test-tools;
fi
- if [ "$MODE" == "test-runtime" ]; then
./ci-docker/load-cached-images.sh
Expand Down
53 changes: 34 additions & 19 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import java.io.File.pathSeparator
import scala.collection.mutable
import scala.util.Try

val sbt10Version = "1.1.6" // minimum version
val sbt10ScalaVersion = "2.12.11"
val libScalaVersion = "2.11.12"
val libCrossScalaVersions = Seq("2.11.8", "2.11.11", libScalaVersion)
import build.ScalaVersions._

// Convert "SomeName" to "some-name".
def convertCamelKebab(name: String): String = {
Expand Down Expand Up @@ -38,7 +35,8 @@ inThisBuild(
Def.settings(
organization := "org.scala-native", // Maven <groupId>
version := nativeVersion, // Maven <version>
scalaVersion := libScalaVersion,
scalaVersion := scala212,
crossScalaVersions := libCrossScalaVersions,
scalacOptions ++= Seq(
"-deprecation",
"-encoding",
Expand All @@ -48,7 +46,8 @@ inThisBuild(
"-unchecked",
"-Xfatal-warnings"
)
))
)
)

addCommandAlias(
"test-all",
Expand Down Expand Up @@ -187,10 +186,22 @@ lazy val toolSettings: Seq[Setting[_]] =
Def.settings(
sbtVersion := sbt10Version,
crossSbtVersions := List(sbt10Version),
scalaVersion := sbt10ScalaVersion,
crossScalaVersions := Seq(sbt10ScalaVersion),
javacOptions ++= Seq("-encoding", "utf8")
)

lazy val buildInfoSettings: Seq[Setting[_]] =
Def.settings(
buildInfoPackage := "scala.scalanative.buildinfo",
buildInfoObject := "ScalaNativeBuildInfo",
buildInfoKeys := Seq[BuildInfoKey](
version,
sbtVersion,
scalaVersion,
"nativeScalaVersion" -> (nativelib / scalaVersion).value
)
)

lazy val util =
project
.in(file("util"))
Expand Down Expand Up @@ -227,6 +238,8 @@ lazy val tools =
.in(file("tools"))
.settings(toolSettings)
.settings(mavenPublishSettings)
.enablePlugins(BuildInfoPlugin)
.settings(buildInfoSettings)
.settings(
libraryDependencies ++= Seq(
scalacheckDep,
Expand Down Expand Up @@ -280,8 +293,9 @@ lazy val sbtPluginSettings: Seq[Setting[_]] =
scriptedLaunchOpts.value ++
Seq("-Xmx1024M",
"-XX:MaxMetaspaceSize=256M",
"-Dplugin.version=" + version.value) ++
ivyPaths.value.ivyHome.map(home => s"-Dsbt.ivy.home=${home}").toSeq
"-Dplugin.version=" + version.value,
"-Dscala.version=" + (nativelib / scalaVersion).value) ++
ivyPaths.value.ivyHome.map(home => s"-Dsbt.ivy.home=$home").toSeq
}
)

Expand All @@ -291,7 +305,7 @@ lazy val sbtScalaNative =
.enablePlugins(SbtPlugin)
.settings(sbtPluginSettings)
.settings(
crossScalaVersions := libCrossScalaVersions,
crossScalaVersions := Seq(sbt10ScalaVersion),
addSbtPlugin("org.portable-scala" % "sbt-platform-deps" % "1.0.0"),
sbtTestDirectory := (ThisBuild / baseDirectory).value / "scripted-tests",
// publish the other projects before running scripted tests.
Expand Down Expand Up @@ -395,14 +409,15 @@ lazy val scalalib =
.in(file("scalalib"))
.enablePlugins(MyScalaNativePlugin)
.settings(
// This build uses libScalaVersion, which is currently 2.11.12
// to compile what appears to be 2.11.0 sources. This yields 114
// This build uses Scala 2.11 version 2.11.12 to compile
// what appears to be 2.11.0 sources. This yields 114
// deprecations. Editing those sources is not an option (long story),
// so do not spend compile time looking for the deprecations.
// Keep the log file clean so that real issues stand out.
// This futzing can probably removed for scala >= 2.12.
scalacOptions -= "-deprecation",
scalacOptions += "-deprecation:false"
scalacOptions += "-deprecation:false",
// The option below is needed since Scala 2.12.12.
scalacOptions += "-language:postfixOps"
)
.settings(mavenPublishSettings)
.settings(
Expand Down Expand Up @@ -546,7 +561,8 @@ lazy val allCoreLibs: Project =
lazy val tests =
project
.in(file("unit-tests"))
.enablePlugins(MyScalaNativePlugin)
.enablePlugins(MyScalaNativePlugin, BuildInfoPlugin)
.settings(buildInfoSettings)
.settings(
scalacOptions -= "-deprecation",
scalacOptions += "-deprecation:false"
Expand Down Expand Up @@ -615,7 +631,7 @@ lazy val testingCompiler =
)
.dependsOn(testingCompilerInterface)

lazy val testInterfaceCommonSourcesSettings = Seq(
lazy val testInterfaceCommonSourcesSettings: Seq[Setting[_]] = Seq(
unmanagedSourceDirectories in Compile += baseDirectory.value.getParentFile / "test-interface-common/src/main/scala",
unmanagedSourceDirectories in Test += baseDirectory.value.getParentFile / "test-interface-common/src/test/scala"
)
Expand Down Expand Up @@ -647,7 +663,6 @@ lazy val testRunner =
.settings(mavenPublishSettings)
.settings(testInterfaceCommonSourcesSettings)
.settings(
crossScalaVersions := Seq(sbt10ScalaVersion),
libraryDependencies ++= Seq(
"org.scala-sbt" % "test-interface" % "1.0",
"com.novocode" % "junit-interface" % "0.11" % "test"
Expand Down Expand Up @@ -716,7 +731,7 @@ lazy val junitTestOutputsJVM =
.in(file("junit-test/output-jvm"))
.settings(
commonJUnitTestOutputsSettings,
scalaVersion := sbt10ScalaVersion,
crossScalaVersions := Seq(sbt10ScalaVersion),
libraryDependencies ++= Seq(
"com.novocode" % "junit-interface" % "0.11" % "test"
)
Expand All @@ -737,7 +752,7 @@ lazy val junitAsyncJVM =
project
.in(file("junit-async/jvm"))
.settings(
scalaVersion := sbt10ScalaVersion,
crossScalaVersions := Seq(sbt10ScalaVersion),
nameSettings,
publishArtifact := false
)
2 changes: 1 addition & 1 deletion ci-docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ USER scala-native

WORKDIR /home/scala-native/scala-native

CMD sbt -no-colors -J-Xmx3G "set scriptedBufferLog in sbtScalaNative := false" "$TEST_COMMAND"
CMD sbt "++ $TRAVIS_SCALA_VERSION -v" -no-colors -J-Xmx3G "set scriptedBufferLog in sbtScalaNative := false" "$TEST_COMMAND"
1 change: 1 addition & 0 deletions ci-docker/run-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ docker run -v $HOME/.ivy2:/home/scala-native/.ivy2 \
-e SCALANATIVE_GC=$SCALANATIVE_GC \
-e SCALANATIVE_OPTIMIZE=$SCALANATIVE_OPTIMIZE \
-e TEST_COMMAND=$TEST_COMMAND \
-e TRAVIS_SCALA_VERSION=$TRAVIS_SCALA_VERSION \
-it scala-native-testing:linux-$TARGET_DOCKER_PLATFORM;
3 changes: 2 additions & 1 deletion javalib/src/main/scala/java/lang/Boolean.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ final class Boolean(val _value: scala.Boolean) extends Comparable[Boolean] {
}

object Boolean {
final val TYPE = classOf[scala.Boolean]
final val TYPE =
scala.Predef.classOf[scala.scalanative.runtime.PrimitiveBoolean]
final val TRUE: Boolean = new Boolean(true)
final val FALSE: Boolean = new Boolean(false)

Expand Down
8 changes: 4 additions & 4 deletions javalib/src/main/scala/java/lang/Byte.scala
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ final class Byte(val _value: scala.Byte) extends Number with Comparable[Byte] {
protected def +(x: String): String = _value + x

protected def <<(x: scala.Int): scala.Int = _value << x
protected def <<(x: scala.Long): scala.Int = _value << x
protected def <<(x: scala.Long): scala.Int = _value << x.toInt
protected def >>>(x: scala.Int): scala.Int = _value >>> x
protected def >>>(x: scala.Long): scala.Int = _value >>> x
protected def >>>(x: scala.Long): scala.Int = _value >>> x.toInt
protected def >>(x: scala.Int): scala.Int = _value >> x
protected def >>(x: scala.Long): scala.Int = _value >> x
protected def >>(x: scala.Long): scala.Int = _value >> x.toInt

protected def <(x: scala.Byte): scala.Boolean = _value < x
protected def <(x: scala.Short): scala.Boolean = _value < x
Expand Down Expand Up @@ -175,7 +175,7 @@ final class Byte(val _value: scala.Byte) extends Number with Comparable[Byte] {
}

object Byte {
final val TYPE = classOf[scala.Byte]
final val TYPE = scala.Predef.classOf[scala.scalanative.runtime.PrimitiveByte]
final val SIZE = 8
final val BYTES = 1

Expand Down
8 changes: 4 additions & 4 deletions javalib/src/main/scala/java/lang/Character.scala
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ class Character(val _value: scala.Char)
protected def +(x: String): String = _value + x

protected def <<(x: scala.Int): scala.Int = _value << x
protected def <<(x: scala.Long): scala.Int = _value << x
protected def <<(x: scala.Long): scala.Int = _value << x.toInt
protected def >>>(x: scala.Int): scala.Int = _value >>> x
protected def >>>(x: scala.Long): scala.Int = _value >>> x
protected def >>>(x: scala.Long): scala.Int = _value >>> x.toInt
protected def >>(x: scala.Int): scala.Int = _value >> x
protected def >>(x: scala.Long): scala.Int = _value >> x
protected def >>(x: scala.Long): scala.Int = _value >> x.toInt

protected def ==(x: scala.Byte): scala.Boolean = _value == x
protected def ==(x: scala.Short): scala.Boolean = _value == x
Expand Down Expand Up @@ -179,7 +179,7 @@ class Character(val _value: scala.Char)
}

object Character {
final val TYPE = classOf[scala.Char]
final val TYPE = scala.Predef.classOf[scala.scalanative.runtime.PrimitiveChar]
final val MIN_VALUE = '\u0000'
final val MAX_VALUE = '\uffff'
final val SIZE = 16
Expand Down
3 changes: 2 additions & 1 deletion javalib/src/main/scala/java/lang/Double.scala
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ object Double {
final val NEGATIVE_INFINITY = 1.0 / -0.0
final val POSITIVE_INFINITY = 1.0 / 0.0
final val SIZE = 64
final val TYPE = classOf[scala.Double]
final val TYPE =
scala.Predef.classOf[scala.scalanative.runtime.PrimitiveDouble]

@inline def compare(x: scala.Double, y: scala.Double): scala.Int =
if (x > y) 1
Expand Down
3 changes: 2 additions & 1 deletion javalib/src/main/scala/java/lang/Float.scala
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@ object Float {
final val NEGATIVE_INFINITY = 1.0f / -0.0f
final val POSITIVE_INFINITY = 1.0f / 0.0f
final val SIZE = 32
final val TYPE = classOf[scala.Float]
final val TYPE =
scala.Predef.classOf[scala.scalanative.runtime.PrimitiveFloat]

@inline def compare(x: scala.Float, y: scala.Float): scala.Int =
if (x > y) 1
Expand Down
8 changes: 4 additions & 4 deletions javalib/src/main/scala/java/lang/Integer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@ final class Integer(val _value: scala.Int)
protected def +(x: String): String = _value + x

protected def <<(x: scala.Int): scala.Int = _value << x
protected def <<(x: scala.Long): scala.Int = _value << x
protected def <<(x: scala.Long): scala.Int = _value << x.toInt
protected def >>>(x: scala.Int): scala.Int = _value >>> x
protected def >>>(x: scala.Long): scala.Int = _value >>> x
protected def >>>(x: scala.Long): scala.Int = _value >>> x.toInt
protected def >>(x: scala.Int): scala.Int = _value >> x
protected def >>(x: scala.Long): scala.Int = _value >> x
protected def >>(x: scala.Long): scala.Int = _value >> x.toInt

protected def <(x: scala.Byte): scala.Boolean = _value < x
protected def <(x: scala.Short): scala.Boolean = _value < x
Expand Down Expand Up @@ -189,7 +189,7 @@ private[lang] object IntegerCache {
object Integer {
import IntegerDecimalScale.decimalScale

final val TYPE = classOf[scala.Int]
final val TYPE = scala.Predef.classOf[scala.scalanative.runtime.PrimitiveInt]
final val MIN_VALUE = -2147483648
final val MAX_VALUE = 2147483647
final val SIZE = 32
Expand Down
2 changes: 1 addition & 1 deletion javalib/src/main/scala/java/lang/Long.scala
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ final class Long(val _value: scala.Long) extends Number with Comparable[Long] {
}

object Long {
final val TYPE = classOf[scala.Long]
final val TYPE = scala.Predef.classOf[scala.scalanative.runtime.PrimitiveLong]
final val MIN_VALUE = -9223372036854775808L
final val MAX_VALUE = 9223372036854775807L
final val SIZE = 64
Expand Down
9 changes: 5 additions & 4 deletions javalib/src/main/scala/java/lang/Short.scala
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,11 @@ final class Short(val _value: scala.Short)
protected def +(x: String): String = _value + x

protected def <<(x: scala.Int): scala.Int = _value << x
protected def <<(x: scala.Long): scala.Int = _value << x
protected def <<(x: scala.Long): scala.Int = _value << x.toInt
protected def >>>(x: scala.Int): scala.Int = _value >>> x
protected def >>>(x: scala.Long): scala.Int = _value >>> x
protected def >>>(x: scala.Long): scala.Int = _value >>> x.toInt
protected def >>(x: scala.Int): scala.Int = _value >> x
protected def >>(x: scala.Long): scala.Int = _value >> x
protected def >>(x: scala.Long): scala.Int = _value >> x.toInt

protected def <(x: scala.Byte): scala.Boolean = _value < x
protected def <(x: scala.Short): scala.Boolean = _value < x
Expand Down Expand Up @@ -176,7 +176,8 @@ final class Short(val _value: scala.Short)
}

object Short {
final val TYPE = classOf[scala.Short]
final val TYPE =
scala.Predef.classOf[scala.scalanative.runtime.PrimitiveShort]
final val SIZE = 16
final val BYTES = 2

Expand Down
4 changes: 2 additions & 2 deletions javalib/src/main/scala/java/nio/file/Files.scala
Original file line number Diff line number Diff line change
Expand Up @@ -735,8 +735,8 @@ object Files {

private def setAttributes(path: Path, attrs: Array[FileAttribute[_]]): Unit =
attrs.map(a => (a.name, a.value)).toMap.foreach {
case (name, value: Object) =>
setAttribute(path, name, value, Array.empty)
case (name, value) =>
setAttribute(path, name, value.asInstanceOf[AnyRef], Array.empty)
}

private val attributesClassesToViews
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ final class UInt private[scalanative] (private[scalanative] val underlying: Int)
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
@inline final def <<(x: Long): UInt = new UInt(underlying << x)
@inline final def <<(x: Long): UInt = new UInt(underlying << x.toInt)

/**
* Returns this value bit-shifted right by the specified number of bits,
Expand All @@ -73,7 +73,7 @@ final class UInt private[scalanative] (private[scalanative] val underlying: Int)
* // 00011111 11111111 11111111 11111101
* }}}
*/
@inline final def >>>(x: Long): UInt = new UInt(underlying >>> x)
@inline final def >>>(x: Long): UInt = new UInt(underlying >>> x.toInt)

/**
* Returns this value bit-shifted left by the specified number of bits,
Expand All @@ -95,7 +95,7 @@ final class UInt private[scalanative] (private[scalanative] val underlying: Int)
* // 11111111 11111111 11111111 11111101
* }}}
*/
@inline final def >>(x: Long): UInt = new UInt(underlying >> x)
@inline final def >>(x: Long): UInt = new UInt(underlying >> x.toInt)

@inline final override def compareTo(x: UInt): Int =
JInteger.compareUnsigned(underlying, x.underlying)
Expand Down
8 changes: 4 additions & 4 deletions nir/src/main/scala/scala/scalanative/nir/Attrs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ object Attr {
final case object Abstract extends Attr
}

final case class Attrs(inline: Inline = MayInline,
final case class Attrs(inlineHint: Inline = MayInline,
specialize: Specialize = MaySpecialize,
opt: Opt = UnOpt,
isExtern: Boolean = false,
Expand All @@ -43,7 +43,7 @@ final case class Attrs(inline: Inline = MayInline,
def toSeq: Seq[Attr] = {
val out = mutable.UnrolledBuffer.empty[Attr]

if (inline != MayInline) out += inline
if (inlineHint != MayInline) out += inlineHint
if (specialize != MaySpecialize) out += specialize
if (opt != UnOpt) out += opt
if (isExtern) out += Extern
Expand All @@ -58,8 +58,8 @@ final case class Attrs(inline: Inline = MayInline,
object Attrs {
val None = new Attrs()

def fromSeq(attrs: Seq[Attr]) = {
var inline = None.inline
def fromSeq(attrs: Seq[Attr]): Attrs = {
var inline = None.inlineHint
var specialize = None.specialize
var opt = None.opt
var isExtern = false
Expand Down
Loading

0 comments on commit 469ac89

Please sign in to comment.