Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
9fd71cb
chore: enable explicit-nulls in the stdlib
hamzaremmal Jul 18, 2025
6f7c217
Port stdlib to explicit nulls
noti0na1 Aug 26, 2025
27bc67d
Adjust some type parameters
noti0na1 Aug 29, 2025
d654acc
More changes
noti0na1 Aug 30, 2025
e2069a5
Migrate RBT
noti0na1 Aug 31, 2025
30695d9
Another RBT
noti0na1 Sep 1, 2025
e5cdd00
Update TrieMap
noti0na1 Sep 1, 2025
6b1847b
Fix some cc errors
noti0na1 Sep 1, 2025
e48e050
Fix remaining cc errors
noti0na1 Sep 1, 2025
8250521
Clean some unnecessary .nn
noti0na1 Sep 1, 2025
d686933
Removing remaining unnecessary .nn
noti0na1 Sep 1, 2025
f40956a
Fix crush
noti0na1 Sep 1, 2025
81c69ad
Always apply asInstanceOf with arguments
noti0na1 Sep 2, 2025
84a32d1
Refine .nn usages
noti0na1 Sep 2, 2025
119adf5
Address some review comments
noti0na1 Sep 8, 2025
6c06d5c
Make wrappers and convertors non-nullable
noti0na1 Sep 11, 2025
e9663f4
Fix NPEs revealed by tests
noti0na1 Sep 15, 2025
ef97e0d
Fix a missing comment
noti0na1 Sep 15, 2025
f1c5d19
Remove some unnecessary .nn
noti0na1 Sep 15, 2025
8068f4f
Try to migrate sjs library
noti0na1 Sep 15, 2025
aec8221
Update tests about Regex
noti0na1 Sep 15, 2025
f6e084c
Update required type signatures in sjs
noti0na1 Sep 18, 2025
76bee08
NO IDEA FOR NOW :)
noti0na1 Sep 18, 2025
66acc44
Fix MiMa issue
noti0na1 Sep 23, 2025
2d899ef
Keep Yflexify-tasty tests disabled
noti0na1 Sep 24, 2025
4418255
Resolve some review comments
noti0na1 Sep 28, 2025
95c32b9
Update comment in LazyListIterable
noti0na1 Sep 28, 2025
a57cec5
Migrate scaladoc-new
noti0na1 Sep 30, 2025
183af31
Re-enable explicit nulls in compiler
noti0na1 Sep 30, 2025
87e29c9
Update test code
noti0na1 Sep 30, 2025
926393d
Use hack to compile scala3-library for now
noti0na1 Sep 30, 2025
c3ba233
Add comments
noti0na1 Sep 30, 2025
aff2542
Address review comments; avoid inferred flexible types
noti0na1 Oct 1, 2025
5452c87
Address review comments
noti0na1 Oct 1, 2025
c106546
Update Option.apply
noti0na1 Oct 1, 2025
db7bce0
Revert "Update Option.apply"
noti0na1 Oct 2, 2025
e98f6e4
Remove experimental annotation from Option.fromNullable
noti0na1 Oct 2, 2025
ebbd740
Address comments
noti0na1 Oct 3, 2025
e0f96ba
Add mapNull and nullForGC to ScalaRunTime
noti0na1 Oct 3, 2025
694dee6
Address some comments
noti0na1 Oct 3, 2025
be5548a
Re-apply nullable to Option.apply
noti0na1 Oct 5, 2025
4cebbb1
Fix tests
noti0na1 Oct 5, 2025
2afafc9
Update Promise; update build
noti0na1 Oct 5, 2025
437660e
Fix build; remove fromNullable usage
noti0na1 Oct 5, 2025
b50ee94
Address comments; polish Prop to disallow setting null string value
noti0na1 Oct 6, 2025
e6bd8f4
Update UniquenessCache in sjs
noti0na1 Oct 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/MainGenericCompiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,9 @@ object MainGenericCompiler {
val tStopAtLvl="-XX:TieredStopAtLevel=1"
println(s"ignoring deprecated -Oshort flag, please add `-J$addTC` and `-J$tStopAtLvl` flags manually")
process(tail, settings)
case javaOption(stripped) :: tail =>
case javaOption(stripped: String) :: tail =>
process(tail, settings.withJavaArgs(stripped))
case javaPropOption(opt, value) :: tail =>
case javaPropOption(opt: String, value: String) :: tail =>
process(tail, settings.withJavaProps(opt -> value))
case arg :: tail =>
process(tail, settings.withResidualArgs(arg))
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/MainGenericRunner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ object MainGenericRunner {
processArgs(tail, settings.noSave)
case "-with-compiler" :: tail =>
processArgs(tail, settings.withCompiler)
case (o @ javaOption(striped)) :: tail =>
case (o @ javaOption(striped: String)) :: tail =>
processArgs(tail, settings.withJavaArgs(striped).withScalaArgs(o))
case (o @ scalaOption(_*)) :: tail =>
val remainingArgs = CommandLineParser.expandArg(o) ++ tail
Expand Down
8 changes: 4 additions & 4 deletions compiler/src/dotty/tools/backend/sjs/JSDefinitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -289,15 +289,15 @@ final class JSDefinitions()(using Context) {
@threadUnsafe lazy val EnumerationClass = requiredClass("scala.Enumeration")
@threadUnsafe lazy val Enumeration_Value_NoArg = EnumerationClass.requiredValue(nmeValue)
@threadUnsafe lazy val Enumeration_Value_IntArg = EnumerationClass.requiredMethod(nmeValue, List(defn.IntType))
@threadUnsafe lazy val Enumeration_Value_StringArg = EnumerationClass.requiredMethod(nmeValue, List(defn.StringType))
@threadUnsafe lazy val Enumeration_Value_IntStringArg = EnumerationClass.requiredMethod(nmeValue, List(defn.IntType, defn.StringType))
@threadUnsafe lazy val Enumeration_Value_StringArg = EnumerationClass.requiredMethod(nmeValue, List(OrNull(defn.StringType)))
@threadUnsafe lazy val Enumeration_Value_IntStringArg = EnumerationClass.requiredMethod(nmeValue, List(defn.IntType, OrNull(defn.StringType)))
@threadUnsafe lazy val Enumeration_nextName = EnumerationClass.requiredMethod(termName("nextName"))

@threadUnsafe lazy val EnumerationValClass = EnumerationClass.requiredClass("Val")
@threadUnsafe lazy val Enumeration_Val_NoArg = EnumerationValClass.requiredMethod(nme.CONSTRUCTOR, Nil)
@threadUnsafe lazy val Enumeration_Val_IntArg = EnumerationValClass.requiredMethod(nme.CONSTRUCTOR, List(defn.IntType))
@threadUnsafe lazy val Enumeration_Val_StringArg = EnumerationValClass.requiredMethod(nme.CONSTRUCTOR, List(defn.StringType))
@threadUnsafe lazy val Enumeration_Val_IntStringArg = EnumerationValClass.requiredMethod(nme.CONSTRUCTOR, List(defn.IntType, defn.StringType))
@threadUnsafe lazy val Enumeration_Val_StringArg = EnumerationValClass.requiredMethod(nme.CONSTRUCTOR, List(OrNull(defn.StringType)))
@threadUnsafe lazy val Enumeration_Val_IntStringArg = EnumerationValClass.requiredMethod(nme.CONSTRUCTOR, List(defn.IntType, OrNull(defn.StringType)))

def isValueMethod(sym: Symbol)(using Context): Boolean =
sym.name == nmeValue && sym.owner == EnumerationClass
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Comments.scala
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ object Comments {
val raw = ctx.docCtx.flatMap(_.docstring(sym).map(_.raw)).getOrElse("")
defs(sym) ++= defines(raw).map { str =>
val start = skipWhitespace(str, "@define".length)
val (key, Trim(value)) = str.splitAt(skipVariable(str, start)): @unchecked
val (key, Trim(value: String)) = str.splitAt(skipVariable(str, start)): @unchecked
variableName(key.drop(start)) -> value.replaceAll("\\s+\\*+$", "")
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/reporting/messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3000,7 +3000,7 @@ class MissingImplicitArgument(
val idx = paramNames.indexOf(name)
if (idx >= 0) Some(i"${args(idx)}") else None
"""\$\{\s*([^}\s]+)\s*\}""".r.replaceAllIn(raw, (_: Regex.Match) match
case Regex.Groups(v) => quoteReplacement(translate(v).getOrElse("?" + v)).nn
case Regex.Groups(v: String) => quoteReplacement(translate(v).getOrElse("?" + v)).nn
)

/** @param rawMsg Message template with variables, e.g. "Variable A is ${A}"
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ object Scala3:
object LocalSymbol:

def unapply(symbolInfo: SymbolInformation): Option[Int] = symbolInfo.symbol match
case locals(ints) =>
case locals(ints: String) =>
val bi = BigInt(ints)
if bi.isValidInt then
Some(bi.toInt)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/repl/ParseResult.scala
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ object ParseResult {
val sourceCode = source.content().mkString
sourceCode match {
case "" => Newline
case CommandExtract(cmd, arg) => {
case CommandExtract(cmd: String, arg: String) => {
val matchingCommands = commands.filter((command, _) => command.startsWith(cmd))
matchingCommands match {
case Nil => UnknownCommand(cmd)
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/scripting/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ object Main:
writer.close()
end writeJarfile

def pathsep = sys.props("path.separator")
def pathsep: String = sys.props("path.separator").nn

extension(path: String) {
// Normalize path separator, convert relative path to absolute
Expand All @@ -102,4 +102,4 @@ object Main:
def secondChar: String = path.take(2).drop(1).mkString("")
}

lazy val userDir = sys.props("user.dir").norm
lazy val userDir: String = sys.props("user.dir").nn.norm
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/scripting/Util.scala
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ object Util:
end match
end detectMainClassAndMethod

def pathsep = sys.props("path.separator")
def pathsep: String = sys.props("path.separator").nn

end Util

12 changes: 6 additions & 6 deletions compiler/test/dotty/tools/debug/DebugStepAssert.scala
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,17 @@ private[debug] object DebugStepAssert:
given location: CheckFileLocation = CheckFileLocation(checkFile, allLines.size - lines.size + 1)
lines match
case Nil => acc.reverse
case break(className , lineStr) :: tail =>
case break(className: String, lineStr: String) :: tail =>
val breakpointLine = lineStr.toInt
val step = DebugStepAssert(Break(className, breakpointLine), checkClassAndLine(className, breakpointLine))
loop(tail, step :: acc)
case step(pattern) :: tail =>
case step(pattern: String) :: tail =>
val step = DebugStepAssert(Step, checkLineOrMethod(pattern))
loop(tail, step :: acc)
case next(pattern) :: tail =>
case next(pattern: String) :: tail =>
val step = DebugStepAssert(Next, checkLineOrMethod(pattern))
loop(tail, step :: acc)
case eval(expr) :: tail0 =>
case eval(expr: String) :: tail0 =>
val (assertion, tail1) = parseEvalAssertion(tail0)
val step = DebugStepAssert(Eval(expr), assertion)
loop(tail1, step :: acc)
Expand All @@ -78,8 +78,8 @@ private[debug] object DebugStepAssert:
lines match
case Nil => throw new Exception(s"Missing result or error")
case trailing() :: tail => parseEvalAssertion(tail)
case result(expected) :: tail => (checkResult(expected), tail)
case error(expected) :: tail => (checkError(Seq(expected)), tail)
case result(expected: String) :: tail => (checkResult(expected), tail)
case error(expected: String) :: tail => (checkError(Seq(expected)), tail)
case multiLineError() :: tail0 =>
val (expected, tail1) = tail0.span(_.startsWith(" "))
(checkError(expected.map(_.stripPrefix(" "))), tail1)
Expand Down
35 changes: 16 additions & 19 deletions compiler/test/dotty/tools/dotc/CompilationTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,6 @@ class CompilationTests {
).checkCompile()

// Explicit nulls tests
@Ignore
@Test def explicitNullsNeg: Unit = {
implicit val testGroup: TestGroup = TestGroup("explicitNullsNeg")
aggregateTests(
Expand All @@ -214,18 +213,18 @@ class CompilationTests {
compileFilesInDir("tests/explicit-nulls/unsafe-common", explicitNullsOptions `and` "-Yno-flexible-types", FileFilter.exclude(TestSources.negExplicitNullsScala2LibraryTastyExcludelisted)),
).checkExpectedErrors()

locally {
val unsafeFile = compileFile("tests/explicit-nulls/flexible-unpickle/neg/Unsafe_1.scala", explicitNullsOptions without "-Yexplicit-nulls")
val flexibleFile = compileFile("tests/explicit-nulls/flexible-unpickle/neg/Flexible_2.scala",
explicitNullsOptions.and("-Yflexify-tasty").withClasspath(defaultOutputDir + testGroup + "/Unsafe_1/neg/Unsafe_1"))
// locally {
// val unsafeFile = compileFile("tests/explicit-nulls/flexible-unpickle/neg/Unsafe_1.scala", explicitNullsOptions without "-Yexplicit-nulls")
// val flexibleFile = compileFile("tests/explicit-nulls/flexible-unpickle/neg/Flexible_2.scala",
// explicitNullsOptions.and("-Yflexify-tasty").withClasspath(defaultOutputDir + testGroup + "/Unsafe_1/neg/Unsafe_1"))

flexibleFile.keepOutput.checkExpectedErrors()
// unsafeFile.keepOutput.checkCompile()
// flexibleFile.keepOutput.checkExpectedErrors()

List(unsafeFile, flexibleFile).foreach(_.delete())
}
// List(unsafeFile, flexibleFile).foreach(_.delete())
// }
}

@Ignore
@Test def explicitNullsPos: Unit = {
implicit val testGroup: TestGroup = TestGroup("explicitNullsPos")
aggregateTests(
Expand All @@ -234,24 +233,22 @@ class CompilationTests {
compileFilesInDir("tests/explicit-nulls/unsafe-common", explicitNullsOptions `and` "-language:unsafeNulls" `and` "-Yno-flexible-types"),
).checkCompile()

locally {
val tests = List(
compileFile("tests/explicit-nulls/flexible-unpickle/pos/Unsafe_1.scala", explicitNullsOptions `without` "-Yexplicit-nulls"),
compileFile("tests/explicit-nulls/flexible-unpickle/pos/Flexible_2.scala",
explicitNullsOptions.and("-Yflexify-tasty").withClasspath(defaultOutputDir + testGroup + "/Unsafe_1/pos/Unsafe_1")),
).map(_.keepOutput.checkCompile())
// locally {
// val tests = List(
// compileFile("tests/explicit-nulls/flexible-unpickle/pos/Unsafe_1.scala", explicitNullsOptions without "-Yexplicit-nulls"),
// compileFile("tests/explicit-nulls/flexible-unpickle/pos/Flexible_2.scala",
// explicitNullsOptions.and("-Yflexify-tasty").withClasspath(defaultOutputDir + testGroup + "/Unsafe_1/pos/Unsafe_1")),
// ).map(_.keepOutput.checkCompile())

tests.foreach(_.delete())
}
// tests.foreach(_.delete())
// }
}

@Ignore
@Test def explicitNullsWarn: Unit = {
implicit val testGroup: TestGroup = TestGroup("explicitNullsWarn")
compileFilesInDir("tests/explicit-nulls/warn", explicitNullsOptions)
}.checkWarnings()

@Ignore
@Test def explicitNullsRun: Unit = {
implicit val testGroup: TestGroup = TestGroup("explicitNullsRun")
compileFilesInDir("tests/explicit-nulls/run", explicitNullsOptions)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class TraceNameManglingTest extends DottyTest {
}

@Test def escapeBackslashes(): Unit = {
val isWindows = sys.props("os.name").toLowerCase(Locale.ROOT).nn.contains("windows")
val isWindows = sys.props("os.name").nn.toLowerCase(Locale.ROOT).nn.contains("windows")
// It is not possible to create a file with backslash in name on Windows
val filename = if isWindows then "test.scala" else "\\.scala"
checkTraceEvents(
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/dotty/tools/io/ClasspathTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import dotty.tools.io.{ PlainDirectory, Directory, ClassPath }

class ClasspathTest {

def pathsep = sys.props("path.separator")
def pathsep: String = sys.props("path.separator").nn

def isWindows: Boolean = scala.util.Properties.isWin

Expand Down
2 changes: 1 addition & 1 deletion library-js/src/scala/Console.scala
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ import scala.util.DynamicVariable
object Console extends AnsiColor {
private[this] val outVar = new DynamicVariable[PrintStream](java.lang.System.out)
private[this] val errVar = new DynamicVariable[PrintStream](java.lang.System.err)
private[this] val inVar = new DynamicVariable[BufferedReader](null)
private[this] val inVar = new DynamicVariable[BufferedReader](null.asInstanceOf[BufferedReader])
//new BufferedReader(new InputStreamReader(java.lang.System.in)))

protected def setOutDirect(out: PrintStream): Unit = outVar.value = out
Expand Down
14 changes: 7 additions & 7 deletions library-js/src/scala/Enumeration.scala
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ abstract class Enumeration (initial: Int) extends Serializable {
private val vmap: mutable.Map[Int, Value] = new mutable.HashMap

/** The cache listing all values of this enumeration. */
@transient private var vset: ValueSet = null
@transient private var vset: ValueSet | Null = null
@transient @volatile private var vsetDefined = false

/** The mapping from the integer used to identify values to their
Expand All @@ -121,7 +121,7 @@ abstract class Enumeration (initial: Int) extends Serializable {
vset = (ValueSet.newBuilder ++= vmap.values).result()
vsetDefined = true
}
vset
vset.nn
}

/** The integer to use to identify the next created value. */
Expand All @@ -130,7 +130,7 @@ abstract class Enumeration (initial: Int) extends Serializable {
/** The string to use to name the next created value. */
protected var nextName: Iterator[String] = _

private def nextNameOrNull =
private def nextNameOrNull: String | Null =
if (nextName != null && nextName.hasNext) nextName.next() else null

/** The highest integer amongst those used to identify values in this
Expand Down Expand Up @@ -192,7 +192,7 @@ abstract class Enumeration (initial: Int) extends Serializable {
* @param name A human-readable name for that value.
* @return Fresh value called `name`.
*/
protected final def Value(name: String): Value = Value(nextId, name)
protected final def Value(name: String | Null): Value = Value(nextId, name)

/** Creates a fresh value, part of this enumeration, called `name`
* and identified by the integer `i`.
Expand All @@ -202,7 +202,7 @@ abstract class Enumeration (initial: Int) extends Serializable {
* @param name A human-readable name for that value.
* @return Fresh value with the provided identifier `i` and name `name`.
*/
protected final def Value(i: Int, name: String): Value = new Val(i, name)
protected final def Value(i: Int, name: String | Null): Value = new Val(i, name)

/** The type of the enumerated values. */
@SerialVersionUID(7091335633555234129L)
Expand Down Expand Up @@ -231,9 +231,9 @@ abstract class Enumeration (initial: Int) extends Serializable {
* identification behaviour.
*/
@SerialVersionUID(0 - 3501153230598116017L)
protected class Val(i: Int, name: String) extends Value with Serializable {
protected class Val(i: Int, name: String | Null) extends Value with Serializable {
def this(i: Int) = this(i, nextNameOrNull)
def this(name: String) = this(nextId, name)
def this(name: String | Null) = this(nextId, name)
def this() = this(nextId)

assert(!vmap.isDefinedAt(i), "Duplicate id: " + i)
Expand Down
2 changes: 1 addition & 1 deletion library-js/src/scala/Symbol.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ object Symbol extends UniquenessCache[String, Symbol] {
}

// Modified to use Scala.js specific cache
private[scala] abstract class UniquenessCache[K, V >: Null] {
private[scala] abstract class UniquenessCache[K, V] {
private val cache = js.Dictionary.empty[V]

protected def valueFromKey(k: String): V
Expand Down
Loading
Loading