Skip to content

Migrating the main compiler to explicit nulls #14032

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Mar 6, 2022
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/MainGenericRunner.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dotty.tools

import scala.language.unsafeNulls

import scala.annotation.tailrec
import scala.io.Source
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/backend/jvm/AsmUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package dotty.tools
package backend
package jvm

import scala.language.unsafeNulls

import scala.tools.asm.tree.{AbstractInsnNode}
import java.io.PrintWriter
import scala.tools.asm.util.{TraceClassVisitor, TraceMethodVisitor, Textifier}
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/backend/jvm/BCodeAsmCommon.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package dotty.tools
package backend
package jvm

import scala.language.unsafeNulls

import dotty.tools.dotc.core.Flags._
import dotty.tools.dotc.core.Symbols._
import dotty.tools.dotc.report
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package dotty.tools
package backend
package jvm

import scala.language.unsafeNulls

import scala.annotation.switch
import scala.collection.mutable.SortedMap

Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package dotty.tools
package backend
package jvm

import scala.language.unsafeNulls

import scala.annotation.threadUnsafe
import scala.tools.asm
import scala.tools.asm.AnnotationVisitor
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/backend/jvm/BCodeIdiomatic.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package dotty.tools
package backend
package jvm

import scala.language.unsafeNulls

import scala.tools.asm
import scala.annotation.switch
import Primitives.{NE, EQ, TestOp, ArithmeticOp}
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package dotty.tools
package backend
package jvm

import scala.language.unsafeNulls

import scala.collection.{ mutable, immutable }

import scala.tools.asm

import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.ast.TreeTypeMap
import dotty.tools.dotc.CompilationUnit
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/backend/jvm/BCodeSyncAndTry.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package dotty.tools
package backend
package jvm

import scala.language.unsafeNulls

import scala.collection.immutable
import scala.tools.asm

Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/backend/jvm/BTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package dotty.tools
package backend
package jvm

import scala.language.unsafeNulls

import scala.tools.asm

/**
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/backend/jvm/BytecodeWriters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package dotty.tools
package backend
package jvm

import scala.language.unsafeNulls

import java.io.{ DataOutputStream, FileOutputStream, IOException, File as JFile }
import java.nio.channels.ClosedByInterruptException
import dotty.tools.io._
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package dotty.tools.backend.jvm

import scala.language.unsafeNulls

import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.core.Flags._
import dotty.tools.dotc.transform.SymUtils._
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/dotty/tools/backend/jvm/GenBCode.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package dotty.tools.backend.jvm

import scala.language.unsafeNulls

import dotty.tools.dotc.CompilationUnit
import dotty.tools.dotc.ast.Trees.{PackageDef, ValDef}
import dotty.tools.dotc.ast.tpd
Expand Down Expand Up @@ -73,7 +75,7 @@ class GenBCode extends Phase {
try super.runOn(units)
finally outputDir match {
case jar: JarArchive =>
if (ctx.run.suspendedUnits.nonEmpty)
if (ctx.run.nn.suspendedUnits.nonEmpty)
// If we close the jar the next run will not be able to write on the jar.
// But if we do not close it we cannot use it as part of the macro classpath of the suspended files.
report.error("Can not suspend and output to a jar at the same time. See suspension with -Xprint-suspension.")
Expand Down
5 changes: 2 additions & 3 deletions compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package dotty.tools.backend.sjs

import scala.annotation.switch
import scala.language.unsafeNulls

import scala.annotation.switch
import scala.collection.mutable

import dotty.tools.FatalError

import dotty.tools.dotc.CompilationUnit
import dotty.tools.dotc.ast.tpd

import dotty.tools.dotc.core._
import Contexts._
import Decorators._
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/dotty/tools/backend/sjs/JSDefinitions.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package dotty.tools.backend.sjs

import dotty.tools.dotc.core._
import scala.language.unsafeNulls

import scala.annotation.threadUnsafe

import dotty.tools.dotc.core._
import Types._
import Contexts._
import Symbols._
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/backend/sjs/JSEncoding.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package dotty.tools.backend.sjs

import scala.language.unsafeNulls

import scala.collection.mutable

import dotty.tools.dotc.core._
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/backend/sjs/JSExportsGen.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package dotty.tools.backend.sjs

import scala.annotation.tailrec
import scala.language.unsafeNulls

import scala.annotation.tailrec
import scala.collection.mutable

import dotty.tools.dotc.core._
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/backend/sjs/JSPositions.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package dotty.tools.backend.sjs

import scala.language.unsafeNulls

import java.net.{URI, URISyntaxException}

import dotty.tools.dotc.core._
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/Bench.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ object Bench extends Driver:
println(s"time elapsed: ${times(i)}ms")
if ctx.settings.Xprompt.value then
print("hit <return> to continue >")
System.in.read()
System.in.nn.read()
println()
reporter

Expand Down
20 changes: 16 additions & 4 deletions compiler/src/dotty/tools/dotc/CompilationUnit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import typer.Nullables
import transform.SymUtils._
import core.Decorators._
import config.SourceVersion
import scala.annotation.internal.sharable

class CompilationUnit protected (val source: SourceFile) {

Expand Down Expand Up @@ -70,20 +71,30 @@ class CompilationUnit protected (val source: SourceFile) {
if (ctx.settings.XprintSuspension.value)
report.echo(i"suspended: $this")
suspended = true
ctx.run.suspendedUnits += this
ctx.run.nn.suspendedUnits += this
if ctx.phase == Phases.inliningPhase then
suspendedAtInliningPhase = true
throw CompilationUnit.SuspendException()

private var myAssignmentSpans: Map[Int, List[Span]] = null
private var myAssignmentSpans: Map[Int, List[Span]] | Null = null

/** A map from (name-) offsets of all local variables in this compilation unit
* that can be tracked for being not null to the list of spans of assignments
* to these variables.
*/
def assignmentSpans(using Context): Map[Int, List[Span]] =
if myAssignmentSpans == null then myAssignmentSpans = Nullables.assignmentSpans
myAssignmentSpans
myAssignmentSpans.nn
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing this is needed because the flow typing only applies for local variables, not for class fields.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. Perhaps we could do something for private fields, but it would still be unsound in the presence of threads.

An alternative would be

if myAssignmentSpans == null then
  val ret = Nullables.assignmentSpans
  myAssignmentSpans = ret
  ret
else
  myAssignmentSpans

But that's more verbose than the .nn.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could try this one

import scala.util.chaining.*
if myAssignmentSpans == null then Nullables.assignmentSpans.tap(myAssignmentSpans = _)
else myAssignmentSpans

}

@sharable object NoCompilationUnit extends CompilationUnit(NoSource) {

override def isJava: Boolean = false

override def suspend()(using Context): Nothing =
throw CompilationUnit.SuspendException()

override def assignmentSpans(using Context): Map[Int, List[Span]] = Map.empty
}

object CompilationUnit {
Expand All @@ -92,7 +103,8 @@ object CompilationUnit {

/** Make a compilation unit for top class `clsd` with the contents of the `unpickled` tree */
def apply(clsd: ClassDenotation, unpickled: Tree, forceTrees: Boolean)(using Context): CompilationUnit =
apply(new SourceFile(clsd.symbol.associatedFile, Array.empty[Char]), unpickled, forceTrees)
val file = clsd.symbol.associatedFile.nn
apply(new SourceFile(file, Array.empty[Char]), unpickled, forceTrees)

/** Make a compilation unit, given picked bytes and unpickled tree */
def apply(source: SourceFile, unpickled: Tree, forceTrees: Boolean)(using Context): CompilationUnit = {
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ class Compiler {

def reset()(using Context): Unit = {
ctx.base.reset()
if (ctx.run != null) ctx.run.reset()
val run = ctx.run
if (run != null) run.reset()
}

def newRun(using Context): Run = {
Expand Down
16 changes: 8 additions & 8 deletions compiler/src/dotty/tools/dotc/Driver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ class Driver {

protected def emptyReporter: Reporter = new StoreReporter(null)

protected def doCompile(compiler: Compiler, files: List[AbstractFile])(using Context): Reporter =
protected def doCompile(compiler: Compiler, files: List[AbstractFile])(using Context): Reporter =
if files.nonEmpty then
try
val run = compiler.newRun
run.compile(files)
finish(compiler, run)
catch
case ex: FatalError =>
report.error(ex.getMessage) // signals that we should fail compilation.
report.error(ex.getMessage.nn) // signals that we should fail compilation.
case ex: TypeError =>
println(s"${ex.toMessage} while compiling ${files.map(_.path).mkString(", ")}")
throw ex
Expand Down Expand Up @@ -111,7 +111,7 @@ class Driver {
.distinct
val ctx1 = ctx.fresh
val fullClassPath =
(newEntries :+ ctx.settings.classpath.value).mkString(java.io.File.pathSeparator)
(newEntries :+ ctx.settings.classpath.value).mkString(java.io.File.pathSeparator.nn)
ctx1.setSetting(ctx1.settings.classpath, fullClassPath)
else ctx

Expand All @@ -134,8 +134,8 @@ class Driver {
* process. No callbacks will be executed if this is `null`.
* @return
*/
final def process(args: Array[String], simple: interfaces.SimpleReporter,
callback: interfaces.CompilerCallback): interfaces.ReporterResult = {
final def process(args: Array[String], simple: interfaces.SimpleReporter | Null,
callback: interfaces.CompilerCallback | Null): interfaces.ReporterResult = {
val reporter = if (simple == null) null else Reporter.fromSimpleReporter(simple)
process(args, reporter, callback)
}
Expand All @@ -153,8 +153,8 @@ class Driver {
* @return The `Reporter` used. Use `Reporter#hasErrors` to check
* if compilation succeeded.
*/
final def process(args: Array[String], reporter: Reporter = null,
callback: interfaces.CompilerCallback = null): Reporter = {
final def process(args: Array[String], reporter: Reporter | Null = null,
callback: interfaces.CompilerCallback | Null = null): Reporter = {
val compileCtx = initCtx.fresh
if (reporter != null)
compileCtx.setReporter(reporter)
Expand All @@ -172,7 +172,7 @@ class Driver {
* with sbt.
*/
final def process(args: Array[String]): Reporter =
process(args, null: Reporter, null: interfaces.CompilerCallback)
process(args, null: Reporter | Null, null: interfaces.CompilerCallback | Null)

/** Entry point to the compiler using a custom `Context`.
*
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/Resident.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ class Resident extends Driver {
nextCtx = rootCtx
line = getLine()
}
if (line.startsWith(quit)) ctx.reporter
else loop(line split "\\s+", nextCtx)
if line.startsWith(quit) then ctx.reporter
else loop((line split "\\s+").asInstanceOf[Array[String]], nextCtx)
case None =>
prevCtx.reporter
}
Expand Down
18 changes: 9 additions & 9 deletions compiler/src/dotty/tools/dotc/Run.scala
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint

private var compiling = false

private var myUnits: List[CompilationUnit] = _
private var myUnitsCached: List[CompilationUnit] = _
private var myUnits: List[CompilationUnit] = Nil
private var myUnitsCached: List[CompilationUnit] = Nil
private var myFiles: Set[AbstractFile] = _

// `@nowarn` annotations by source file, populated during typer
Expand All @@ -73,7 +73,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
// When the REPL creates a new run (ReplDriver.compile), parsing is already done in the old context, with the
// previous Run. Parser warnings were suspended in the old run and need to be copied over so they are not lost.
// Same as scala/scala/commit/79ca1408c7.
def initSuspendedMessages(oldRun: Run) = if oldRun != null then
def initSuspendedMessages(oldRun: Run | Null) = if oldRun != null then
mySuspendedMessages.clear()
mySuspendedMessages ++= oldRun.mySuspendedMessages

Expand Down Expand Up @@ -170,7 +170,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
compileSources(sources)
catch
case NonFatal(ex) =>
if units != null then report.echo(i"exception occurred while compiling $units%, %")
if units.nonEmpty then report.echo(i"exception occurred while compiling $units%, %")
else report.echo(s"exception occurred while compiling ${files.map(_.name).mkString(", ")}")
throw ex

Expand Down Expand Up @@ -309,7 +309,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
val uuid = java.util.UUID.randomUUID().toString
val ext = if (isJava) ".java" else ".scala"
val virtualFile = new VirtualFile(s"compileFromString-$uuid.$ext")
val writer = new BufferedWriter(new OutputStreamWriter(virtualFile.output, StandardCharsets.UTF_8.name)) // buffering is still advised by javadoc
val writer = new BufferedWriter(new OutputStreamWriter(virtualFile.output, StandardCharsets.UTF_8.nn.name)) // buffering is still advised by javadoc
writer.write(source)
writer.close()
new SourceFile(virtualFile, Codec.UTF8)
Expand All @@ -332,8 +332,8 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
super[ImplicitRunInfo].reset()
super[ConstraintRunInfo].reset()
myCtx = null
myUnits = null
myUnitsCached = null
myUnits = Nil
myUnitsCached = Nil
}

/** Produces the following contexts, from outermost to innermost
Expand Down Expand Up @@ -366,9 +366,9 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
start.setRun(this: @unchecked)
}

private var myCtx = rootContext(using ictx)
private var myCtx: Context | Null = rootContext(using ictx)

/** The context created for this run */
given runContext[Dummy_so_its_a_def]: Context = myCtx
given runContext[Dummy_so_its_a_def]: Context = myCtx.nn
assert(runContext.runId <= Periods.MaxPossibleRunId)
}
Loading