diff --git a/compiler/src/dotty/tools/MainGenericRunner.scala b/compiler/src/dotty/tools/MainGenericRunner.scala index dc709276f4f1..dca7178c52f5 100644 --- a/compiler/src/dotty/tools/MainGenericRunner.scala +++ b/compiler/src/dotty/tools/MainGenericRunner.scala @@ -1,5 +1,6 @@ package dotty.tools +import scala.language.unsafeNulls import scala.annotation.tailrec import scala.io.Source diff --git a/compiler/src/dotty/tools/backend/jvm/AsmUtils.scala b/compiler/src/dotty/tools/backend/jvm/AsmUtils.scala index 8a71a09aa7ab..e6393ce82054 100644 --- a/compiler/src/dotty/tools/backend/jvm/AsmUtils.scala +++ b/compiler/src/dotty/tools/backend/jvm/AsmUtils.scala @@ -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} diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeAsmCommon.scala b/compiler/src/dotty/tools/backend/jvm/BCodeAsmCommon.scala index e72d94fff82f..d95638be2695 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeAsmCommon.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeAsmCommon.scala @@ -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 diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala b/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala index ed7a65000ce2..e549bfdf882e 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala @@ -2,6 +2,8 @@ package dotty.tools package backend package jvm +import scala.language.unsafeNulls + import scala.annotation.switch import scala.collection.mutable.SortedMap diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala b/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala index 3321a061325e..f254dea184ed 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala @@ -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 diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeIdiomatic.scala b/compiler/src/dotty/tools/backend/jvm/BCodeIdiomatic.scala index 0518392e1dd7..83ebc99c1e20 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeIdiomatic.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeIdiomatic.scala @@ -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} diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala b/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala index 8e4bec9acb8e..f668a1b68a5f 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala @@ -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 diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeSyncAndTry.scala b/compiler/src/dotty/tools/backend/jvm/BCodeSyncAndTry.scala index 344c9bf22be8..3afa13d18c98 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeSyncAndTry.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeSyncAndTry.scala @@ -2,6 +2,8 @@ package dotty.tools package backend package jvm +import scala.language.unsafeNulls + import scala.collection.immutable import scala.tools.asm diff --git a/compiler/src/dotty/tools/backend/jvm/BTypes.scala b/compiler/src/dotty/tools/backend/jvm/BTypes.scala index 42f950af312b..da3bead08835 100644 --- a/compiler/src/dotty/tools/backend/jvm/BTypes.scala +++ b/compiler/src/dotty/tools/backend/jvm/BTypes.scala @@ -2,6 +2,8 @@ package dotty.tools package backend package jvm +import scala.language.unsafeNulls + import scala.tools.asm /** diff --git a/compiler/src/dotty/tools/backend/jvm/BytecodeWriters.scala b/compiler/src/dotty/tools/backend/jvm/BytecodeWriters.scala index 1c721552485b..4fcdee72b03a 100644 --- a/compiler/src/dotty/tools/backend/jvm/BytecodeWriters.scala +++ b/compiler/src/dotty/tools/backend/jvm/BytecodeWriters.scala @@ -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._ diff --git a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index b6392ec80b4e..5461ff81341c 100644 --- a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -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._ diff --git a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala index 1bf0b697ef50..6a763a9c0744 100644 --- a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala @@ -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 @@ -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.") diff --git a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala index 901355945672..0a7fc0e0ad10 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala @@ -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._ diff --git a/compiler/src/dotty/tools/backend/sjs/JSDefinitions.scala b/compiler/src/dotty/tools/backend/sjs/JSDefinitions.scala index 1b24a24101a1..99dad4deb203 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSDefinitions.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSDefinitions.scala @@ -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._ diff --git a/compiler/src/dotty/tools/backend/sjs/JSEncoding.scala b/compiler/src/dotty/tools/backend/sjs/JSEncoding.scala index a2b2fed93d83..c2e0dea3841b 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSEncoding.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSEncoding.scala @@ -1,5 +1,7 @@ package dotty.tools.backend.sjs +import scala.language.unsafeNulls + import scala.collection.mutable import dotty.tools.dotc.core._ diff --git a/compiler/src/dotty/tools/backend/sjs/JSExportsGen.scala b/compiler/src/dotty/tools/backend/sjs/JSExportsGen.scala index 3a9476d9638a..bee783af258f 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSExportsGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSExportsGen.scala @@ -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._ diff --git a/compiler/src/dotty/tools/backend/sjs/JSPositions.scala b/compiler/src/dotty/tools/backend/sjs/JSPositions.scala index 454b5b5c3a5c..37591ecadd69 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSPositions.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSPositions.scala @@ -1,5 +1,7 @@ package dotty.tools.backend.sjs +import scala.language.unsafeNulls + import java.net.{URI, URISyntaxException} import dotty.tools.dotc.core._ diff --git a/compiler/src/dotty/tools/dotc/Bench.scala b/compiler/src/dotty/tools/dotc/Bench.scala index d555ad14a493..c9c032b0ae7d 100644 --- a/compiler/src/dotty/tools/dotc/Bench.scala +++ b/compiler/src/dotty/tools/dotc/Bench.scala @@ -30,7 +30,7 @@ object Bench extends Driver: println(s"time elapsed: ${times(i)}ms") if ctx.settings.Xprompt.value then print("hit to continue >") - System.in.read() + System.in.nn.read() println() reporter diff --git a/compiler/src/dotty/tools/dotc/CompilationUnit.scala b/compiler/src/dotty/tools/dotc/CompilationUnit.scala index 413d616f108d..df2b586ac6ae 100644 --- a/compiler/src/dotty/tools/dotc/CompilationUnit.scala +++ b/compiler/src/dotty/tools/dotc/CompilationUnit.scala @@ -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) { @@ -70,12 +71,12 @@ 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 @@ -83,7 +84,17 @@ class CompilationUnit protected (val source: SourceFile) { */ def assignmentSpans(using Context): Map[Int, List[Span]] = if myAssignmentSpans == null then myAssignmentSpans = Nullables.assignmentSpans - myAssignmentSpans + myAssignmentSpans.nn +} + +@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 { @@ -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 = { diff --git a/compiler/src/dotty/tools/dotc/Compiler.scala b/compiler/src/dotty/tools/dotc/Compiler.scala index 1ddc626d2646..44e28bcdd446 100644 --- a/compiler/src/dotty/tools/dotc/Compiler.scala +++ b/compiler/src/dotty/tools/dotc/Compiler.scala @@ -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 = { diff --git a/compiler/src/dotty/tools/dotc/Driver.scala b/compiler/src/dotty/tools/dotc/Driver.scala index 81331ce06e9b..14a71463c66d 100644 --- a/compiler/src/dotty/tools/dotc/Driver.scala +++ b/compiler/src/dotty/tools/dotc/Driver.scala @@ -28,7 +28,7 @@ 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 @@ -36,7 +36,7 @@ class Driver { 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 @@ -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 @@ -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) } @@ -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) @@ -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`. * diff --git a/compiler/src/dotty/tools/dotc/Resident.scala b/compiler/src/dotty/tools/dotc/Resident.scala index 810369ec0f29..0b9bca0dc75b 100644 --- a/compiler/src/dotty/tools/dotc/Resident.scala +++ b/compiler/src/dotty/tools/dotc/Resident.scala @@ -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 } diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala index 3c48e737cff8..4dd7b591032c 100644 --- a/compiler/src/dotty/tools/dotc/Run.scala +++ b/compiler/src/dotty/tools/dotc/Run.scala @@ -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 @@ -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 @@ -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 @@ -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) @@ -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 @@ -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) } diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 3b9e12e28ad1..1e0a2aa662fa 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -521,9 +521,9 @@ object desugar { val enumCompanionRef = TermRefTree() val enumImport = Import(enumCompanionRef, enumCases.flatMap(caseIds).map( - enumCase => + enumCase => ImportSelector(enumCase.withSpan(enumCase.span.startPos)) - ) + ) ) (enumImport :: enumStats, enumCases, enumCompanionRef) } @@ -1134,7 +1134,7 @@ object desugar { val matchExpr = if (tupleOptimizable) rhs else - val caseDef = CaseDef(pat, EmptyTree, makeTuple(ids)) + val caseDef = CaseDef(pat, EmptyTree, makeTuple(ids)) Match(makeSelector(rhs, MatchCheck.IrrefutablePatDef), caseDef :: Nil) vars match { case Nil if !mods.is(Lazy) => @@ -1155,11 +1155,11 @@ object desugar { val restDefs = for (((named, tpt), n) <- vars.zipWithIndex if named.name != nme.WILDCARD) yield - if mods.is(Lazy) then + if mods.is(Lazy) then DefDef(named.name.asTermName, Nil, tpt, selector(n)) .withMods(mods &~ Lazy) .withSpan(named.span) - else + else valDef( ValDef(named.name.asTermName, tpt, selector(n)) .withMods(mods) @@ -1286,7 +1286,7 @@ object desugar { val ts = tree.trees val arity = ts.length assert(arity <= Definitions.MaxTupleArity) - def tupleTypeRef = defn.TupleType(arity) + def tupleTypeRef = defn.TupleType(arity).nn if (arity == 0) if (ctx.mode is Mode.Type) TypeTree(defn.UnitType) else unitLiteral else if (ctx.mode is Mode.Type) AppliedTypeTree(ref(tupleTypeRef), ts) @@ -1349,7 +1349,7 @@ object desugar { * def $anonfun(params) = body * Closure($anonfun) */ - def makeClosure(params: List[ValDef], body: Tree, tpt: Tree = null, isContextual: Boolean, span: Span)(using Context): Block = + def makeClosure(params: List[ValDef], body: Tree, tpt: Tree | Null = null, isContextual: Boolean, span: Span)(using Context): Block = Block( DefDef(nme.ANON_FUN, params :: Nil, if (tpt == null) TypeTree() else tpt, body) .withSpan(span) diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index ded6db413e55..4de57def853e 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -26,13 +26,13 @@ abstract class Positioned(implicit @constructorOnly src: SourceFile) extends Src * is set, -1 otherwise. */ def uniqueId: Int = - if ids != null && ids.containsKey(this) then ids.get(this) else -1 + if ids != null && ids.nn.containsKey(this) then ids.nn.get(this).nn else -1 private def allocateId() = if ids != null then val ownId = nextId nextId += 1 - ids.put(this, ownId) + ids.nn.put(this, ownId) if ownId == debugId then println(s"Debug tree (id=$debugId) creation \n$this\n") Thread.dumpStack() @@ -160,7 +160,7 @@ abstract class Positioned(implicit @constructorOnly src: SourceFile) extends Src */ def checkPos(nonOverlapping: Boolean)(using Context): Unit = try { import untpd._ - var lastPositioned: Positioned = null + var lastPositioned: Positioned | Null = null var lastSpan = NoSpan def check(p: Any): Unit = p match { case p: Positioned => @@ -234,7 +234,7 @@ abstract class Positioned(implicit @constructorOnly src: SourceFile) extends Src object Positioned { @sharable private var debugId = Int.MinValue - @sharable private var ids: java.util.WeakHashMap[Positioned, Int] = null + @sharable private var ids: java.util.WeakHashMap[Positioned, Int] | Null = null @sharable private var nextId: Int = 0 def init(using Context): Unit = diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index 8592b6d2e647..b9780aca0968 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -823,7 +823,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => * tree must be reachable from come tree stored in an enclosing context. */ def definingStats(sym: Symbol)(using Context): List[Tree] = - if (!sym.span.exists || (ctx eq NoContext) || ctx.compilationUnit == null) Nil + if (!sym.span.exists || (ctx eq NoContext) || (ctx.compilationUnit eq NoCompilationUnit)) Nil else defPath(sym, ctx.compilationUnit.tpdTree) match { case defn :: encl :: _ => def verify(stats: List[Tree]) = diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index cb84f14ccc4d..f65154984f50 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -293,10 +293,10 @@ object Trees { trait DefTree[-T >: Untyped] extends DenotingTree[T] { type ThisTree[-T >: Untyped] <: DefTree[T] - private var myMods: untpd.Modifiers = null + private var myMods: untpd.Modifiers | Null = _ private[dotc] def rawMods: untpd.Modifiers = - if (myMods == null) untpd.EmptyModifiers else myMods + if (myMods == null) untpd.EmptyModifiers else myMods.uncheckedNN def withAnnotations(annots: List[untpd.Tree]): ThisTree[Untyped] = withMods(rawMods.withAnnotations(annots)) @@ -981,7 +981,7 @@ object Trees { } def flatten[T >: Untyped](trees: List[Tree[T]]): List[Tree[T]] = { - def recur(buf: ListBuffer[Tree[T]], remaining: List[Tree[T]]): ListBuffer[Tree[T]] = + def recur(buf: ListBuffer[Tree[T]] | Null, remaining: List[Tree[T]]): ListBuffer[Tree[T]] | Null = remaining match { case Thicket(elems) :: remaining1 => var buf1 = buf diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 684f33a4cad4..37fc7ef1bee4 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -17,6 +17,7 @@ import NameKinds.{TempResultName, OuterSelectName} import typer.ConstFold import scala.annotation.tailrec +import scala.collection.mutable.ListBuffer /** Some creators for typed trees */ object tpd extends Trees.Instance[Type] with TypedTreeInfo { @@ -248,7 +249,10 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { (rtp, tparams :: paramss) case tp: MethodType => val isParamDependent = tp.isParamDependent - val previousParamRefs = if isParamDependent then mutable.ListBuffer[TermRef]() else null + val previousParamRefs: ListBuffer[TermRef] = + // It is ok to assign `null` here. + // If `isParamDependent == false`, the value of `previousParamRefs` is not used. + if isParamDependent then mutable.ListBuffer[TermRef]() else (null: ListBuffer[TermRef] | Null).uncheckedNN def valueParam(name: TermName, origInfo: Type): TermSymbol = val maybeImplicit = @@ -1246,13 +1250,13 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { trait TreeProvider { protected def computeRootTrees(using Context): List[Tree] - private var myTrees: List[Tree] = null + private var myTrees: List[Tree] | Null = _ /** Get trees defined by this provider. Cache them if -Yretain-trees is set. */ def rootTrees(using Context): List[Tree] = if (ctx.settings.YretainTrees.value) { if (myTrees == null) myTrees = computeRootTrees - myTrees + myTrees.uncheckedNN } else computeRootTrees @@ -1475,7 +1479,11 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { /** Creates the tuple type tree repesentation of the type trees in `ts` */ def tupleTypeTree(elems: List[Tree])(using Context): Tree = { val arity = elems.length - if (arity <= Definitions.MaxTupleArity && defn.TupleType(arity) != null) AppliedTypeTree(TypeTree(defn.TupleType(arity)), elems) + if arity <= Definitions.MaxTupleArity then + val tupleTp = defn.TupleType(arity) + if tupleTp != null then + AppliedTypeTree(TypeTree(tupleTp), elems) + else nestedPairsTypeTree(elems) else nestedPairsTypeTree(elems) } diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index 4905290c86b2..7fb0872b4f28 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -511,7 +511,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { vdef.withMods(mods | Param) } - def makeSyntheticParameter(n: Int = 1, tpt: Tree = null, flags: FlagSet = SyntheticTermParam)(using Context): ValDef = + def makeSyntheticParameter(n: Int = 1, tpt: Tree | Null = null, flags: FlagSet = SyntheticTermParam)(using Context): ValDef = ValDef(nme.syntheticParamName(n), if (tpt == null) TypeTree() else tpt, EmptyTree) .withFlags(flags) diff --git a/compiler/src/dotty/tools/dotc/classpath/AggregateClassPath.scala b/compiler/src/dotty/tools/dotc/classpath/AggregateClassPath.scala index 163667a18f44..51b261583feb 100644 --- a/compiler/src/dotty/tools/dotc/classpath/AggregateClassPath.scala +++ b/compiler/src/dotty/tools/dotc/classpath/AggregateClassPath.scala @@ -4,6 +4,8 @@ package dotty.tools package dotc.classpath +import scala.language.unsafeNulls + import java.net.URL import scala.collection.mutable.ArrayBuffer import scala.collection.immutable.ArraySeq diff --git a/compiler/src/dotty/tools/dotc/classpath/DirectoryClassPath.scala b/compiler/src/dotty/tools/dotc/classpath/DirectoryClassPath.scala index b7f848edf543..950f46678fc1 100644 --- a/compiler/src/dotty/tools/dotc/classpath/DirectoryClassPath.scala +++ b/compiler/src/dotty/tools/dotc/classpath/DirectoryClassPath.scala @@ -3,6 +3,8 @@ */ package dotty.tools.dotc.classpath +import scala.language.unsafeNulls + import java.io.{File => JFile} import java.net.URL import java.nio.file.{FileSystems, Files} diff --git a/compiler/src/dotty/tools/dotc/classpath/FileUtils.scala b/compiler/src/dotty/tools/dotc/classpath/FileUtils.scala index 10ca579fc134..d6fa6fb78d07 100644 --- a/compiler/src/dotty/tools/dotc/classpath/FileUtils.scala +++ b/compiler/src/dotty/tools/dotc/classpath/FileUtils.scala @@ -4,6 +4,8 @@ package dotty.tools package dotc.classpath +import scala.language.unsafeNulls + import java.io.{File => JFile, FileFilter} import java.net.URL import dotty.tools.io.AbstractFile diff --git a/compiler/src/dotty/tools/dotc/classpath/PackageNameUtils.scala b/compiler/src/dotty/tools/dotc/classpath/PackageNameUtils.scala index d90de7de2b6b..ea7412f15d8a 100644 --- a/compiler/src/dotty/tools/dotc/classpath/PackageNameUtils.scala +++ b/compiler/src/dotty/tools/dotc/classpath/PackageNameUtils.scala @@ -19,7 +19,7 @@ object PackageNameUtils { if (lastDotIndex == -1) (RootPackage, fullClassName) else - (fullClassName.substring(0, lastDotIndex), fullClassName.substring(lastDotIndex + 1)) + (fullClassName.substring(0, lastDotIndex).nn, fullClassName.substring(lastDotIndex + 1).nn) } def packagePrefix(inPackage: String): String = if (inPackage == RootPackage) "" else inPackage + "." diff --git a/compiler/src/dotty/tools/dotc/classpath/VirtualDirectoryClassPath.scala b/compiler/src/dotty/tools/dotc/classpath/VirtualDirectoryClassPath.scala index 335755406662..0cb0ba59c52e 100644 --- a/compiler/src/dotty/tools/dotc/classpath/VirtualDirectoryClassPath.scala +++ b/compiler/src/dotty/tools/dotc/classpath/VirtualDirectoryClassPath.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.classpath +import scala.language.unsafeNulls + import dotty.tools.io.ClassRepresentation import dotty.tools.io.{AbstractFile, VirtualDirectory} import FileUtils._ diff --git a/compiler/src/dotty/tools/dotc/classpath/ZipAndJarFileLookupFactory.scala b/compiler/src/dotty/tools/dotc/classpath/ZipAndJarFileLookupFactory.scala index 6600a5741808..865f95551a0b 100644 --- a/compiler/src/dotty/tools/dotc/classpath/ZipAndJarFileLookupFactory.scala +++ b/compiler/src/dotty/tools/dotc/classpath/ZipAndJarFileLookupFactory.scala @@ -4,6 +4,8 @@ package dotty.tools.dotc package classpath +import scala.language.unsafeNulls + import java.io.File import java.net.URL import java.nio.file.Files @@ -162,7 +164,7 @@ object ZipAndJarSourcePathFactory extends ZipAndJarFileLookupFactory { private case class ZipArchiveSourcePath(zipFile: File) extends ZipArchiveFileLookup[SourceFileEntryImpl] with NoClassPaths { - + def release: Option[String] = None override def asSourcePathString: String = asClassPathString diff --git a/compiler/src/dotty/tools/dotc/classpath/ZipArchiveFileLookup.scala b/compiler/src/dotty/tools/dotc/classpath/ZipArchiveFileLookup.scala index 7cf21facf02b..e241feee8244 100644 --- a/compiler/src/dotty/tools/dotc/classpath/ZipArchiveFileLookup.scala +++ b/compiler/src/dotty/tools/dotc/classpath/ZipArchiveFileLookup.scala @@ -3,6 +3,8 @@ */ package dotty.tools.dotc.classpath +import scala.language.unsafeNulls + import java.io.File import java.net.URL diff --git a/compiler/src/dotty/tools/dotc/config/CliCommand.scala b/compiler/src/dotty/tools/dotc/config/CliCommand.scala index 0d696722fe4b..68c900e405da 100644 --- a/compiler/src/dotty/tools/dotc/config/CliCommand.scala +++ b/compiler/src/dotty/tools/dotc/config/CliCommand.scala @@ -1,6 +1,8 @@ package dotty.tools.dotc package config +import scala.language.unsafeNulls + import Settings._ import core.Contexts._ import printing.Highlighting diff --git a/compiler/src/dotty/tools/dotc/config/CommandLineParser.scala b/compiler/src/dotty/tools/dotc/config/CommandLineParser.scala index 91017f7fc0c0..7ff93c392425 100644 --- a/compiler/src/dotty/tools/dotc/config/CommandLineParser.scala +++ b/compiler/src/dotty/tools/dotc/config/CommandLineParser.scala @@ -70,7 +70,7 @@ object CommandLineParser: else if qpos(0) == start && qpos(1) == pos then line.substring(start+1, pos-1) else copyText() qpos.clear() - res + res.nn inline def badquote() = errorFn(s"Unmatched quote [${qpos.last}](${line.charAt(qpos.last)})") @@ -103,10 +103,10 @@ object CommandLineParser: def stripComment(s: String) = s takeWhile (_ != '#') val path = Paths.get(arg stripPrefix "@") if (!Files.exists(path)) - System.err.println(s"Argument file ${path.getFileName} could not be found") + System.err.nn.println(s"Argument file ${path.nn.getFileName} could not be found") Nil else - val lines = Files.readAllLines(path) // default to UTF-8 encoding + val lines = Files.readAllLines(path).nn // default to UTF-8 encoding val params = lines.asScala map stripComment mkString " " tokenize(params) diff --git a/compiler/src/dotty/tools/dotc/config/Feature.scala b/compiler/src/dotty/tools/dotc/config/Feature.scala index d72131161d25..8564aa88c499 100644 --- a/compiler/src/dotty/tools/dotc/config/Feature.scala +++ b/compiler/src/dotty/tools/dotc/config/Feature.scala @@ -50,7 +50,8 @@ object Feature: */ def enabledByImport(feature: TermName)(using Context): Boolean = //atPhase(typerPhase) { - ctx.importInfo != null && ctx.importInfo.featureImported(feature) + val info = ctx.importInfo + info != null && info.featureImported(feature) //} /** Is `feature` enabled by either a command line setting or an import? @@ -78,8 +79,7 @@ object Feature: SourceVersion.valueOf(ctx.settings.source.value) def sourceVersion(using Context): SourceVersion = - if ctx.compilationUnit == null then sourceVersionSetting - else ctx.compilationUnit.sourceVersion match + ctx.compilationUnit.sourceVersion match case Some(v) => v case none => sourceVersionSetting diff --git a/compiler/src/dotty/tools/dotc/config/OutputDirs.scala b/compiler/src/dotty/tools/dotc/config/OutputDirs.scala index 283a8bc0aef4..0411c5604768 100644 --- a/compiler/src/dotty/tools/dotc/config/OutputDirs.scala +++ b/compiler/src/dotty/tools/dotc/config/OutputDirs.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package config +import scala.language.unsafeNulls + import io._ /** A class for holding mappings from source directories to diff --git a/compiler/src/dotty/tools/dotc/config/PathResolver.scala b/compiler/src/dotty/tools/dotc/config/PathResolver.scala index 9bd1279ed0e3..e3d912b16ed4 100644 --- a/compiler/src/dotty/tools/dotc/config/PathResolver.scala +++ b/compiler/src/dotty/tools/dotc/config/PathResolver.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package config +import scala.language.unsafeNulls + import WrappedProperties.AccessControl import io.{ClassPath, Directory, Path} import classpath.{AggregateClassPath, ClassPathFactory, JrtClassPath} diff --git a/compiler/src/dotty/tools/dotc/config/Printers.scala b/compiler/src/dotty/tools/dotc/config/Printers.scala index 8e13e50e59b7..458c149723b9 100644 --- a/compiler/src/dotty/tools/dotc/config/Printers.scala +++ b/compiler/src/dotty/tools/dotc/config/Printers.scala @@ -3,7 +3,7 @@ package dotty.tools.dotc.config object Printers { class Printer { - def println(msg: => String): Unit = System.out.println(msg) + def println(msg: => String): Unit = System.out.nn.println(msg) } object noPrinter extends Printer { diff --git a/compiler/src/dotty/tools/dotc/config/Properties.scala b/compiler/src/dotty/tools/dotc/config/Properties.scala index ca5d94977690..1e9cc82112af 100644 --- a/compiler/src/dotty/tools/dotc/config/Properties.scala +++ b/compiler/src/dotty/tools/dotc/config/Properties.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package config +import scala.language.unsafeNulls + import scala.annotation.internal.sharable import java.io.IOException diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index cb8de2a9907f..fa364110b052 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -1,6 +1,8 @@ package dotty.tools.dotc package config +import scala.language.unsafeNulls + import dotty.tools.dotc.config.PathResolver.Defaults import dotty.tools.dotc.config.Settings.{Setting, SettingGroup} import dotty.tools.dotc.core.Contexts._ diff --git a/compiler/src/dotty/tools/dotc/config/ScalaVersion.scala b/compiler/src/dotty/tools/dotc/config/ScalaVersion.scala index 61fb630a8edb..7fdf57478f1a 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaVersion.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaVersion.scala @@ -3,6 +3,8 @@ package dotty.tools package dotc.config +import scala.language.unsafeNulls + import scala.annotation.internal.sharable import scala.util.{Try, Success, Failure} diff --git a/compiler/src/dotty/tools/dotc/config/Settings.scala b/compiler/src/dotty/tools/dotc/config/Settings.scala index dea34bbc263d..3cd7b88b5471 100644 --- a/compiler/src/dotty/tools/dotc/config/Settings.scala +++ b/compiler/src/dotty/tools/dotc/config/Settings.scala @@ -1,6 +1,8 @@ package dotty.tools.dotc package config +import scala.language.unsafeNulls + import core.Contexts._ import dotty.tools.io.{AbstractFile, Directory, JarArchive, PlainDirectory} diff --git a/compiler/src/dotty/tools/dotc/config/WrappedProperties.scala b/compiler/src/dotty/tools/dotc/config/WrappedProperties.scala index 76fac09c8c87..2e4ddff59059 100644 --- a/compiler/src/dotty/tools/dotc/config/WrappedProperties.scala +++ b/compiler/src/dotty/tools/dotc/config/WrappedProperties.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package config +import scala.language.unsafeNulls + /** For placing a wrapper function around property functions. * Motivated by places like google app engine throwing exceptions * on property lookups. diff --git a/compiler/src/dotty/tools/dotc/core/Annotations.scala b/compiler/src/dotty/tools/dotc/core/Annotations.scala index a6c424ef13db..c44d7ebe8e7b 100644 --- a/compiler/src/dotty/tools/dotc/core/Annotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Annotations.scala @@ -89,7 +89,7 @@ object Annotations { def tree(using Context): Tree = t abstract class LazyAnnotation extends Annotation { - protected var mySym: Symbol | (Context ?=> Symbol) + protected var mySym: Symbol | (Context ?=> Symbol) | Null override def symbol(using parentCtx: Context): Symbol = assert(mySym != null) mySym match { @@ -107,7 +107,7 @@ object Annotations { } mySym.asInstanceOf[Symbol] - protected var myTree: Tree | (Context ?=> Tree) + protected var myTree: Tree | (Context ?=> Tree) | Null def tree(using Context): Tree = assert(myTree != null) myTree match { @@ -141,7 +141,7 @@ object Annotations { abstract class LazyBodyAnnotation extends BodyAnnotation { // Copy-pasted from LazyAnnotation to avoid having to turn it into a trait - protected var myTree: Tree | (Context ?=> Tree) + protected var myTree: Tree | (Context ?=> Tree) | Null def tree(using Context): Tree = assert(myTree != null) myTree match { @@ -159,7 +159,7 @@ object Annotations { object LazyBodyAnnotation { def apply(bodyFn: Context ?=> Tree): LazyBodyAnnotation = new LazyBodyAnnotation: - protected var myTree: Tree | (Context ?=> Tree) = ctx ?=> bodyFn(using ctx) + protected var myTree: Tree | (Context ?=> Tree) | Null = ctx ?=> bodyFn(using ctx) } object Annotation { @@ -190,15 +190,15 @@ object Annotations { /** Create an annotation where the tree is computed lazily. */ def deferred(sym: Symbol)(treeFn: Context ?=> Tree)(using Context): Annotation = new LazyAnnotation { - protected var myTree: Tree | (Context ?=> Tree) = ctx ?=> treeFn(using ctx) - protected var mySym: Symbol | (Context ?=> Symbol) = sym + protected var myTree: Tree | (Context ?=> Tree) | Null = ctx ?=> treeFn(using ctx) + protected var mySym: Symbol | (Context ?=> Symbol) | Null = sym } /** Create an annotation where the symbol and the tree are computed lazily. */ def deferredSymAndTree(symFn: Context ?=> Symbol)(treeFn: Context ?=> Tree)(using Context): Annotation = new LazyAnnotation { - protected var mySym: Symbol | (Context ?=> Symbol) = ctx ?=> symFn(using ctx) - protected var myTree: Tree | (Context ?=> Tree) = ctx ?=> treeFn(using ctx) + protected var mySym: Symbol | (Context ?=> Symbol) | Null = ctx ?=> symFn(using ctx) + protected var myTree: Tree | (Context ?=> Tree) | Null = ctx ?=> treeFn(using ctx) } /** Extractor for child annotations */ diff --git a/compiler/src/dotty/tools/dotc/core/Comments.scala b/compiler/src/dotty/tools/dotc/core/Comments.scala index 969cf76dc3fa..1b20b75ad8ac 100644 --- a/compiler/src/dotty/tools/dotc/core/Comments.scala +++ b/compiler/src/dotty/tools/dotc/core/Comments.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package core +import scala.language.unsafeNulls + import ast.{ untpd, tpd } import Symbols._, Contexts._ import util.{SourceFile, ReadOnlyMap} diff --git a/compiler/src/dotty/tools/dotc/core/Constants.scala b/compiler/src/dotty/tools/dotc/core/Constants.scala index 63baf50fae02..f45e9e5217de 100644 --- a/compiler/src/dotty/tools/dotc/core/Constants.scala +++ b/compiler/src/dotty/tools/dotc/core/Constants.scala @@ -148,7 +148,7 @@ object Constants { /** Convert constant value to conform to given type. */ - def convertTo(pt: Type)(using Context): Constant = { + def convertTo(pt: Type)(using Context): Constant | Null = { def classBound(pt: Type): Type = pt.dealias.stripTypeVar match { case tref: TypeRef if !tref.symbol.isClass && tref.info.exists => classBound(tref.info.bounds.lo) diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala index aded1cede9b4..c85056085a68 100644 --- a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala +++ b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala @@ -600,7 +600,8 @@ trait ConstraintHandling { val e = constraint.entry(param) if (e.exists) e.bounds else { - val pinfos = param.binder.paramInfos + // TODO: should we change the type of paramInfos to nullable? + val pinfos: List[param.binder.PInfo] | Null = param.binder.paramInfos if (pinfos != null) pinfos(param.paramNum) // pinfos == null happens in pos/i536.scala else TypeBounds.empty } diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintRunInfo.scala b/compiler/src/dotty/tools/dotc/core/ConstraintRunInfo.scala index 225560585b4b..c1b23888b491 100644 --- a/compiler/src/dotty/tools/dotc/core/ConstraintRunInfo.scala +++ b/compiler/src/dotty/tools/dotc/core/ConstraintRunInfo.scala @@ -6,7 +6,7 @@ import config.Printers.{default, typr} trait ConstraintRunInfo { self: Run => private var maxSize = 0 - private var maxConstraint: Constraint = _ + private var maxConstraint: Constraint | Null = _ def recordConstraintSize(c: Constraint, size: Int): Unit = if (size > maxSize) { maxSize = size @@ -14,7 +14,7 @@ trait ConstraintRunInfo { self: Run => } def printMaxConstraint()(using Context): Unit = { val printer = if (ctx.settings.YdetailedStats.value) default else typr - if (maxSize > 0) printer.println(s"max constraint = ${maxConstraint.show}") + if (maxSize > 0) printer.println(s"max constraint = ${maxConstraint.nn.show}") } protected def reset(): Unit = maxConstraint = null } diff --git a/compiler/src/dotty/tools/dotc/core/ContextOps.scala b/compiler/src/dotty/tools/dotc/core/ContextOps.scala index b7fd43735dd0..aa85f714a8e5 100644 --- a/compiler/src/dotty/tools/dotc/core/ContextOps.scala +++ b/compiler/src/dotty/tools/dotc/core/ContextOps.scala @@ -30,7 +30,7 @@ object ContextOps: if (ctx.owner.isClass) if (ctx.outer.owner == ctx.owner) { // inner class scope; check whether we are referring to self if (ctx.scope.size == 1) { - val elem = ctx.scope.lastEntry + val elem = ctx.scope.lastEntry.nn if (elem.name == name) return elem.sym.denot // return self } val pre = ctx.owner.thisType diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 6415482e50af..19b1a8ac5e11 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -49,10 +49,10 @@ object Contexts { private val (printerFnLoc, store3) = store2.newLocation[Context => Printer](new RefinedPrinter(_)) private val (settingsStateLoc, store4) = store3.newLocation[SettingsState]() private val (compilationUnitLoc, store5) = store4.newLocation[CompilationUnit]() - private val (runLoc, store6) = store5.newLocation[Run]() + private val (runLoc, store6) = store5.newLocation[Run | Null]() private val (profilerLoc, store7) = store6.newLocation[Profiler]() private val (notNullInfosLoc, store8) = store7.newLocation[List[NotNullInfo]]() - private val (importInfoLoc, store9) = store8.newLocation[ImportInfo]() + private val (importInfoLoc, store9) = store8.newLocation[ImportInfo | Null]() private val (typeAssignerLoc, store10) = store9.newLocation[TypeAssigner](TypeAssigner) private val initialStore = store10 @@ -178,7 +178,7 @@ object Contexts { final def gadt: GadtConstraint = _gadt /** The history of implicit searches that are currently active */ - private var _searchHistory: SearchHistory = null + private var _searchHistory: SearchHistory = _ protected def searchHistory_= (searchHistory: SearchHistory): Unit = _searchHistory = searchHistory final def searchHistory: SearchHistory = _searchHistory @@ -227,22 +227,22 @@ object Contexts { def compilationUnit: CompilationUnit = store(compilationUnitLoc) /** The current compiler-run */ - def run: Run = store(runLoc) + def run: Run | Null = store(runLoc) /** The current compiler-run profiler */ def profiler: Profiler = store(profilerLoc) /** The paths currently known to be not null */ - def notNullInfos = store(notNullInfosLoc) + def notNullInfos: List[NotNullInfo] = store(notNullInfosLoc) /** The currently active import info */ - def importInfo = store(importInfoLoc) + def importInfo: ImportInfo | Null = store(importInfoLoc) /** The current type assigner or typer */ def typeAssigner: TypeAssigner = store(typeAssignerLoc) /** The new implicit references that are introduced by this scope */ - protected var implicitsCache: ContextualImplicits = null + protected var implicitsCache: ContextualImplicits | Null = null def implicits: ContextualImplicits = { if (implicitsCache == null) implicitsCache = { @@ -252,30 +252,29 @@ object Contexts { catch { case ex: CyclicReference => Nil } - else if (isImportContext) importInfo.importedImplicits + else if (isImportContext) importInfo.nn.importedImplicits else if (isNonEmptyScopeContext) scope.implicitDecls else Nil val outerImplicits = - if (isImportContext && importInfo.unimported.exists) - outer.implicits exclude importInfo.unimported + if (isImportContext && importInfo.nn.unimported.exists) + outer.implicits exclude importInfo.nn.unimported else outer.implicits if (implicitRefs.isEmpty) outerImplicits else new ContextualImplicits(implicitRefs, outerImplicits, isImportContext)(this) } - implicitsCache + implicitsCache.nn } /** Either the current scope, or, if the current context owner is a class, * the declarations of the current class. */ def effectiveScope(using Context): Scope = - if owner != null && owner.isClass then owner.asClass.unforcedDecls + val myOwner: Symbol | Null = owner + if myOwner != null && myOwner.isClass then myOwner.asClass.unforcedDecls else scope - def nestingLevel: Int = - val sc = effectiveScope - if sc != null then sc.nestingLevel else 0 + def nestingLevel: Int = effectiveScope.nestingLevel /** Sourcefile corresponding to given abstract file, memoized */ def getSource(file: AbstractFile, codec: => Codec = Codec(settings.encoding.value)) = { @@ -309,15 +308,15 @@ object Contexts { def getFile(name: String): AbstractFile = getFile(name.toTermName) - private var related: SimpleIdentityMap[Phase | SourceFile, Context] = null + private var related: SimpleIdentityMap[Phase | SourceFile, Context] | Null = null - private def lookup(key: Phase | SourceFile): Context = + private def lookup(key: Phase | SourceFile): Context | Null = util.Stats.record("Context.related.lookup") if related == null then related = SimpleIdentityMap.empty null else - related(key) + related.nn(key) private def withPhase(phase: Phase, pid: PhaseId): Context = util.Stats.record("Context.withPhase") @@ -329,7 +328,7 @@ object Contexts { if ctx1 == null then util.Stats.record("Context.withPhase.new") ctx1 = fresh.setPhase(pid) - related = related.updated(phase, ctx1) + related = related.nn.updated(phase, ctx1) ctx1 final def withPhase(phase: Phase): Context = withPhase(phase, phase.id) @@ -344,13 +343,13 @@ object Contexts { if ctx1 == null then util.Stats.record("Context.withSource.new") val ctx2 = fresh.setSource(source) - if ctx2.compilationUnit == null then + if ctx2.compilationUnit eq NoCompilationUnit then // `source` might correspond to a file not necessarily // in the current project (e.g. when inlining library code), // so set `mustExist` to false. ctx2.setCompilationUnit(CompilationUnit(source, mustExist = false)) ctx1 = ctx2 - related = related.updated(source, ctx2) + related = related.nn.updated(source, ctx2) ctx1 // `creationTrace`-related code. To enable, uncomment the code below and the @@ -388,11 +387,7 @@ object Contexts { final def erasedTypes = phase.erasedTypes /** Are we in a Java compilation unit? */ - final def isJava: Boolean = - // FIXME: It would be much nicer if compilationUnit was non-nullable, - // perhaps we need to introduce a `NoCompilationUnit` compilation unit - // to be used as a default value. - compilationUnit != null && compilationUnit.isJava + final def isJava: Boolean = compilationUnit.isJava /** Is current phase after TyperPhase? */ final def isAfterTyper = base.isAfterTyper(phase) @@ -406,7 +401,7 @@ object Contexts { def isImportContext: Boolean = (this ne NoContext) && (outer ne NoContext) - && (this.importInfo ne outer.importInfo) + && (this.importInfo nen outer.importInfo) /** Is this a context that introduces a non-empty scope? */ def isNonEmptyScopeContext: Boolean = @@ -568,7 +563,8 @@ object Contexts { override def toString: String = def iinfo(using Context) = - if (ctx.importInfo == null) "" else i"${ctx.importInfo.selectors}%, %" + val info = ctx.importInfo + if (info == null) "" else i"${info.selectors}%, %" def cinfo(using Context) = val core = s" owner = ${ctx.owner}, scope = ${ctx.scope}, import = $iinfo" if (ctx ne NoContext) && (ctx.implicits ne ctx.outer.implicits) then @@ -659,7 +655,7 @@ object Contexts { def setSbtCallback(callback: AnalysisCallback): this.type = updateStore(sbtCallbackLoc, callback) def setPrinterFn(printer: Context => Printer): this.type = updateStore(printerFnLoc, printer) def setSettings(settingsState: SettingsState): this.type = updateStore(settingsStateLoc, settingsState) - def setRun(run: Run): this.type = updateStore(runLoc, run) + def setRun(run: Run | Null): this.type = updateStore(runLoc, run) def setProfiler(profiler: Profiler): this.type = updateStore(profilerLoc, profiler) def setNotNullInfos(notNullInfos: List[NotNullInfo]): this.type = updateStore(notNullInfosLoc, notNullInfos) def setImportInfo(importInfo: ImportInfo): this.type = @@ -828,15 +824,17 @@ object Contexts { owner = NoSymbol tree = untpd.EmptyTree moreProperties = Map(MessageLimiter -> DefaultMessageLimiter()) + scope = EmptyScope source = NoSource store = initialStore .updated(settingsStateLoc, settingsGroup.defaultState) .updated(notNullInfosLoc, Nil) + .updated(compilationUnitLoc, NoCompilationUnit) searchHistory = new SearchRoot gadt = EmptyGadtConstraint } - @sharable object NoContext extends Context(null) { + @sharable object NoContext extends Context((null: ContextBase | Null).uncheckedNN) { source = NoSource override val implicits: ContextualImplicits = new ContextualImplicits(Nil, null, false)(this) } @@ -855,14 +853,15 @@ object Contexts { val initialCtx: Context = new InitialContext(this, settings) /** The platform, initialized by `initPlatform()`. */ - private var _platform: Platform = _ + private var _platform: Platform | Null = _ /** The platform */ def platform: Platform = { - if (_platform == null) + val p = _platform + if p == null then throw new IllegalStateException( "initialize() must be called before accessing platform") - _platform + p } protected def newPlatform(using Context): Platform = @@ -912,8 +911,8 @@ object Contexts { /** A table for hash consing unique named types */ private[core] val uniqueNamedTypes: NamedTypeUniques = NamedTypeUniques() - var emptyTypeBounds: TypeBounds = null - var emptyWildcardBounds: WildcardType = null + var emptyTypeBounds: TypeBounds | Null = null + var emptyWildcardBounds: WildcardType | Null = null /** Number of findMember calls on stack */ private[core] var findMemberCount: Int = 0 @@ -1007,7 +1006,7 @@ object Contexts { // Test that access is single threaded /** The thread on which `checkSingleThreaded was invoked last */ - @sharable private var thread: Thread = null + @sharable private var thread: Thread | Null = null /** Check that we are on the same thread as before */ def checkSingleThreaded(): Unit = diff --git a/compiler/src/dotty/tools/dotc/core/Decorators.scala b/compiler/src/dotty/tools/dotc/core/Decorators.scala index 6f823ba5cc7a..9935311d10c1 100644 --- a/compiler/src/dotty/tools/dotc/core/Decorators.scala +++ b/compiler/src/dotty/tools/dotc/core/Decorators.scala @@ -52,7 +52,7 @@ object Decorators { if name.length != 0 then name.getChars(0, name.length, chars, s.length) termName(chars, 0, len) case name: TypeName => s.concat(name.toTermName) - case _ => termName(s.concat(name.toString)) + case _ => termName(s.concat(name.toString).nn) def indented(width: Int): String = val padding = " " * width @@ -80,9 +80,9 @@ object Decorators { final def mapconserve[U](f: T => U): List[U] = { @tailrec - def loop(mapped: ListBuffer[U], unchanged: List[U], pending: List[T]): List[U] = + def loop(mapped: ListBuffer[U] | Null, unchanged: List[U], pending: List[T]): List[U] = if (pending.isEmpty) - if (mapped eq null) unchanged + if (mapped == null) unchanged else mapped.prependToList(unchanged) else { val head0 = pending.head @@ -91,7 +91,7 @@ object Decorators { if (head1.asInstanceOf[AnyRef] eq head0.asInstanceOf[AnyRef]) loop(mapped, unchanged, pending.tail) else { - val b = if (mapped eq null) new ListBuffer[U] else mapped + val b = if (mapped == null) new ListBuffer[U] else mapped var xc = unchanged while (xc ne pending) { b += xc.head @@ -285,6 +285,6 @@ object Decorators { explained(em(args: _*)) extension [T <: AnyRef](arr: Array[T]) - def binarySearch(x: T): Int = java.util.Arrays.binarySearch(arr.asInstanceOf[Array[Object]], x) + def binarySearch(x: T | Null): Int = java.util.Arrays.binarySearch(arr.asInstanceOf[Array[Object | Null]], x) } diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 6fbced1bd377..8032c5196ea6 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -177,8 +177,8 @@ class Definitions { private def enterT1ParameterlessMethod(cls: ClassSymbol, name: TermName, resultTypeFn: PolyType => Type, flags: FlagSet) = enterPolyMethod(cls, name, 1, resultTypeFn, flags) - private def mkArityArray(name: String, arity: Int, countFrom: Int): Array[TypeRef] = { - val arr = new Array[TypeRef](arity + 1) + private def mkArityArray(name: String, arity: Int, countFrom: Int): Array[TypeRef | Null] = { + val arr = new Array[TypeRef | Null](arity + 1) for (i <- countFrom to arity) arr(i) = requiredClassRef(name + i) arr } @@ -1254,7 +1254,7 @@ class Definitions { @tu lazy val untestableClasses: Set[Symbol] = Set(NothingClass, NullClass, SingletonClass) - @tu lazy val AbstractFunctionType: Array[TypeRef] = mkArityArray("scala.runtime.AbstractFunction", MaxImplementedFunctionArity, 0) + @tu lazy val AbstractFunctionType: Array[TypeRef] = mkArityArray("scala.runtime.AbstractFunction", MaxImplementedFunctionArity, 0).asInstanceOf[Array[TypeRef]] val AbstractFunctionClassPerRun: PerRun[Array[Symbol]] = new PerRun(AbstractFunctionType.map(_.symbol.asClass)) def AbstractFunctionClass(n: Int)(using Context): Symbol = AbstractFunctionClassPerRun()(using ctx)(n) @@ -1277,18 +1277,18 @@ class Definitions { .withDefaultValue(holderImpl("LazyRef")) }) - @tu lazy val TupleType: Array[TypeRef] = mkArityArray("scala.Tuple", MaxTupleArity, 1) + @tu lazy val TupleType: Array[TypeRef | Null] = mkArityArray("scala.Tuple", MaxTupleArity, 1) private class FunType(prefix: String): - private var classRefs: Array[TypeRef] = new Array(22) + private var classRefs: Array[TypeRef | Null] = new Array(22) def apply(n: Int): TypeRef = while n >= classRefs.length do - val classRefs1 = new Array[TypeRef](classRefs.length * 2) + val classRefs1 = new Array[TypeRef | Null](classRefs.length * 2) Array.copy(classRefs, 0, classRefs1, 0, classRefs.length) classRefs = classRefs1 if classRefs(n) == null then classRefs(n) = requiredClassRef(prefix + n.toString) - classRefs(n) + classRefs(n).nn private val erasedContextFunType = FunType("scala.ErasedContextFunction") private val contextFunType = FunType("scala.ContextFunction") @@ -1438,8 +1438,7 @@ class Definitions { /** Are we compiling a java source file? */ private def isJavaContext(using Context): Boolean = - val unit = ctx.compilationUnit - unit != null && unit.isJava + ctx.compilationUnit.isJava private def unqualifiedTypes(refs: List[TermRef]) = val types = refs.toSet[NamedType] @@ -1491,12 +1490,18 @@ class Definitions { */ def isTupleNType(tp: Type)(using Context): Boolean = { val arity = tp.dealias.argInfos.length - arity <= MaxTupleArity && TupleType(arity) != null && tp.isRef(TupleType(arity).symbol) + arity <= MaxTupleArity && { + val tupletp = TupleType(arity) + tupletp != null && tp.isRef(tupletp.symbol) + } } def tupleType(elems: List[Type]): Type = { val arity = elems.length - if (0 < arity && arity <= MaxTupleArity && TupleType(arity) != null) TupleType(arity).appliedTo(elems) + if 0 < arity && arity <= MaxTupleArity then + val tupletp = TupleType(arity) + if tupletp != null then tupletp.appliedTo(elems) + else TypeOps.nestedPairs(elems) else TypeOps.nestedPairs(elems) } diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index a5e1f64d58cb..4c2e629ff112 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -289,7 +289,7 @@ object Denotations { name: Name, site: Denotation = NoDenotation, args: List[Type] = Nil, - source: AbstractFile = null, + source: AbstractFile | Null = null, generateStubs: Boolean = true) (p: Symbol => Boolean) (using Context): Symbol = @@ -1317,8 +1317,10 @@ object Denotations { } recurSimple(path.length, wrap) } - if ctx.run == null then recur(path) - else ctx.run.staticRefs.getOrElseUpdate(path, recur(path)) + + val run = ctx.run + if run == null then recur(path) + else run.staticRefs.getOrElseUpdate(path, recur(path)) } /** If we are looking for a non-existing term name in a package, diff --git a/compiler/src/dotty/tools/dotc/core/GadtConstraint.scala b/compiler/src/dotty/tools/dotc/core/GadtConstraint.scala index c49b5e888904..6861b30fbc00 100644 --- a/compiler/src/dotty/tools/dotc/core/GadtConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/GadtConstraint.scala @@ -15,14 +15,14 @@ import scala.annotation.internal.sharable /** Represents GADT constraints currently in scope */ sealed abstract class GadtConstraint extends Showable { /** Immediate bounds of `sym`. Does not contain lower/upper symbols (see [[fullBounds]]). */ - def bounds(sym: Symbol)(using Context): TypeBounds + def bounds(sym: Symbol)(using Context): TypeBounds | Null /** Full bounds of `sym`, including TypeRefs to other lower/upper symbols. * * @note this performs subtype checks between ordered symbols. * Using this in isSubType can lead to infinite recursion. Consider `bounds` instead. */ - def fullBounds(sym: Symbol)(using Context): TypeBounds + def fullBounds(sym: Symbol)(using Context): TypeBounds | Null /** Is `sym1` ordered to be less than `sym2`? */ def isLess(sym1: Symbol, sym2: Symbol)(using Context): Boolean @@ -153,7 +153,7 @@ final class ProperGadtConstraint private( val internalizedBound = bound match { case nt: NamedType => val ntTvar = mapping(nt.symbol) - if (ntTvar ne null) stripInternalTypeVar(ntTvar) else bound + if (ntTvar != null) stripInternalTypeVar(ntTvar) else bound case _ => bound } @@ -179,22 +179,24 @@ final class ProperGadtConstraint private( override def isLess(sym1: Symbol, sym2: Symbol)(using Context): Boolean = constraint.isLess(tvarOrError(sym1).origin, tvarOrError(sym2).origin) - override def fullBounds(sym: Symbol)(using Context): TypeBounds = + override def fullBounds(sym: Symbol)(using Context): TypeBounds | Null = mapping(sym) match { case null => null - case tv => + // TODO: Improve flow typing so that ascription becomes redundant + case tv: TypeVar => fullBounds(tv.origin) // .ensuring(containsNoInternalTypes(_)) } - override def bounds(sym: Symbol)(using Context): TypeBounds = + override def bounds(sym: Symbol)(using Context): TypeBounds | Null = mapping(sym) match { case null => null - case tv => + // TODO: Improve flow typing so that ascription becomes redundant + case tv: TypeVar => def retrieveBounds: TypeBounds = bounds(tv.origin) match { case TypeAlias(tpr: TypeParamRef) if reverseMapping.contains(tpr) => - TypeAlias(reverseMapping(tpr).typeRef) + TypeAlias(reverseMapping(tpr).nn.typeRef) case tb => tb } retrieveBounds @@ -202,7 +204,7 @@ final class ProperGadtConstraint private( //.ensuring(containsNoInternalTypes(_)) } - override def contains(sym: Symbol)(using Context): Boolean = mapping(sym) ne null + override def contains(sym: Symbol)(using Context): Boolean = mapping(sym) != null def isNarrowing: Boolean = wasConstrained @@ -267,16 +269,16 @@ final class ProperGadtConstraint private( } private def tvarOrError(sym: Symbol)(using Context): TypeVar = - mapping(sym).ensuring(_ ne null, i"not a constrainable symbol: $sym") + mapping(sym).ensuring(_ != null, i"not a constrainable symbol: $sym").uncheckedNN private def containsNoInternalTypes( tp: Type, - acc: TypeAccumulator[Boolean] = null + acc: TypeAccumulator[Boolean] | Null = null )(using Context): Boolean = tp match { case tpr: TypeParamRef => !reverseMapping.contains(tpr) case tv: TypeVar => !reverseMapping.contains(tv.origin) case tp => - (if (acc ne null) acc else new ContainsNoInternalTypesAccumulator()).foldOver(true, tp) + (if (acc != null) acc else new ContainsNoInternalTypesAccumulator()).foldOver(true, tp) } private class ContainsNoInternalTypesAccumulator(using Context) extends TypeAccumulator[Boolean] { @@ -301,8 +303,8 @@ final class ProperGadtConstraint private( } @sharable object EmptyGadtConstraint extends GadtConstraint { - override def bounds(sym: Symbol)(using Context): TypeBounds = null - override def fullBounds(sym: Symbol)(using Context): TypeBounds = null + override def bounds(sym: Symbol)(using Context): TypeBounds | Null = null + override def fullBounds(sym: Symbol)(using Context): TypeBounds | Null = null override def isLess(sym1: Symbol, sym2: Symbol)(using Context): Boolean = unsupported("EmptyGadtConstraint.isLess") diff --git a/compiler/src/dotty/tools/dotc/core/Hashable.scala b/compiler/src/dotty/tools/dotc/core/Hashable.scala index 713555bed517..79da5f1dcd6f 100644 --- a/compiler/src/dotty/tools/dotc/core/Hashable.scala +++ b/compiler/src/dotty/tools/dotc/core/Hashable.scala @@ -8,14 +8,18 @@ import annotation.tailrec object Hashable { /** A null terminated list of BindingTypes. We use `null` here for efficiency */ - class Binders(val tp: BindingType, val next: Binders) + class SomeBinders(val tp: BindingType, val next: Binders) + + type Binders = SomeBinders | Null /** A null terminated list of pairs of BindingTypes. Used for isomorphism tests. */ - class BinderPairs(tp1: BindingType, tp2: BindingType, next: BinderPairs) { + class SomeBinderPairs(tp1: BindingType, tp2: BindingType, next: BinderPairs) { @tailrec final def matches(t1: Type, t2: Type): Boolean = (t1 `eq` tp1) && (t2 `eq` tp2) || next != null && next.matches(t1, t2) } + type BinderPairs = SomeBinderPairs | Null + /** A hash value indicating that the underlying type is not * cached in uniques. */ diff --git a/compiler/src/dotty/tools/dotc/core/MacroClassLoader.scala b/compiler/src/dotty/tools/dotc/core/MacroClassLoader.scala index a65abe56edb9..d8f41ef99b11 100644 --- a/compiler/src/dotty/tools/dotc/core/MacroClassLoader.scala +++ b/compiler/src/dotty/tools/dotc/core/MacroClassLoader.scala @@ -19,6 +19,8 @@ object MacroClassLoader { ctx.setProperty(MacroClassLoaderKey, makeMacroClassLoader(using ctx)) private def makeMacroClassLoader(using Context): ClassLoader = trace("new macro class loader") { + import scala.language.unsafeNulls + val entries = ClassPath.expandPath(ctx.settings.classpath.value, expandStar=true) val urls = entries.map(cp => java.nio.file.Paths.get(cp).toUri.toURL).toArray val out = Option(ctx.settings.outputDir.value.toURL) // to find classes in case of suspended compilation diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala index 21d44d9a4daa..08dd47af56c2 100644 --- a/compiler/src/dotty/tools/dotc/core/NameOps.scala +++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala @@ -14,7 +14,7 @@ import nme._ object NameOps { object compactify { - lazy val md5: MessageDigest = MessageDigest.getInstance("MD5") + lazy val md5: MessageDigest = MessageDigest.getInstance("MD5").nn inline val CLASSFILE_NAME_CHAR_LIMIT = 240 @@ -42,9 +42,9 @@ object NameOps { val suffix = s.takeRight(edge) val cs = s.toArray - val bytes = Codec.toUTF8(CharBuffer.wrap(cs)) + val bytes = Codec.toUTF8(CharBuffer.wrap(cs).nn) md5.update(bytes) - val md5chars = md5.digest().map(b => (b & 0xFF).toHexString).mkString + val md5chars = md5.digest().nn.map(b => (b & 0xFF).toHexString).mkString prefix + marker + md5chars + marker + suffix } diff --git a/compiler/src/dotty/tools/dotc/core/Names.scala b/compiler/src/dotty/tools/dotc/core/Names.scala index 23c2441ba728..a185ad252073 100644 --- a/compiler/src/dotty/tools/dotc/core/Names.scala +++ b/compiler/src/dotty/tools/dotc/core/Names.scala @@ -163,7 +163,7 @@ object Names { override def asTermName: TermName = this @sharable // because it is only modified in the synchronized block of toTypeName. - private var myTypeName: TypeName = null + private var myTypeName: TypeName | Null = null // Note: no @volatile needed since type names are immutable and therefore safely published override def toTypeName: TypeName = @@ -171,7 +171,7 @@ object Names { synchronized { if myTypeName == null then myTypeName = new TypeName(this) } - myTypeName + myTypeName.nn override def likeSpaced(name: Name): TermName = name.toTermName @@ -182,13 +182,13 @@ object Names { private var derivedNames: LinearMap[NameInfo, DerivedName] = LinearMap.empty private def add(info: NameInfo): TermName = synchronized { - derivedNames.lookup(info) match + val dnOpt = derivedNames.lookup(info) + dnOpt match case null => val derivedName = new DerivedName(this, info) derivedNames = derivedNames.updated(info, derivedName) derivedName - case derivedName => - derivedName + case _ => dnOpt } private def rewrap(underlying: TermName) = @@ -225,10 +225,10 @@ object Names { } @sharable // because it's just a cache for performance - private var myMangledString: String = null + private var myMangledString: String | Null = null @sharable // because it's just a cache for performance - private var myMangled: Name = null + private var myMangled: Name | Null = null protected[Names] def mangle: ThisName @@ -240,7 +240,7 @@ object Names { final def mangledString: String = { if (myMangledString == null) myMangledString = qualToString(_.mangledString, _.mangled.toString) - myMangledString + myMangledString.nn } /** If this a qualified name, split it into underlying, last part, and separator @@ -259,11 +259,11 @@ object Names { protected def computeToString: String - @sharable private var myToString: String = null + @sharable private var myToString: String | Null = null - override def toString = + override def toString: String = if myToString == null then myToString = computeToString - myToString + myToString.nn } @@ -386,7 +386,7 @@ object Names { // because asserts are caught in exception handlers which might // cause other failures. In that case the first, important failure // is lost. - System.err.println("Backend should not call Name#toString, Name#mangledString should be used instead.") + System.err.nn.println("Backend should not call Name#toString, Name#mangledString should be used instead.") Thread.dumpStack() assert(false) } @@ -397,8 +397,8 @@ object Names { * from GenBCode or it also contains one of the whitelisted methods below. */ private def toStringOK = { - val trace = Thread.currentThread.getStackTrace - !trace.exists(_.getClassName.endsWith("GenBCode")) || + val trace: Array[StackTraceElement] = Thread.currentThread.nn.getStackTrace.asInstanceOf[Array[StackTraceElement]] + !trace.exists(_.getClassName.nn.endsWith("GenBCode")) || trace.exists(elem => List( "mangledString", @@ -542,13 +542,13 @@ object Names { Stats.record(statsItem("put")) val myTable = currentTable // could be outdated under parallel execution var idx = hashValue(cs, offset, len) & (myTable.length - 1) - var name = myTable(idx).asInstanceOf[SimpleName] + var name: SimpleName | Null = myTable(idx).asInstanceOf[SimpleName | Null] while name != null do - if name.length == len && Names.equals(name.start, cs, offset, len) then - return name + if name.nn.length == len && Names.equals(name.nn.start, cs, offset, len) then + return name.nn Stats.record(statsItem("miss")) idx = (idx + 1) & (myTable.length - 1) - name = myTable(idx).asInstanceOf[SimpleName] + name = myTable(idx).asInstanceOf[SimpleName | Null] Stats.record(statsItem("addEntryAt")) synchronized { if (myTable eq currentTable) && myTable(idx) == null then @@ -563,7 +563,7 @@ object Names { ensureCapacity(nc + len) Array.copy(cs, offset, chrs, nc, len) nc += len - addEntryAt(idx, name) + addEntryAt(idx, name.nn) else enterIfNew(cs, offset, len) } @@ -626,10 +626,10 @@ object Names { * See `sliceToTermName` in `Decorators` for a more efficient version * which however requires a Context for its operation. */ - def termName(s: String): SimpleName = termName(s.toCharArray, 0, s.length) + def termName(s: String): SimpleName = termName(s.toCharArray.nn, 0, s.length) /** Create a type name from a string */ - def typeName(s: String): TypeName = typeName(s.toCharArray, 0, s.length) + def typeName(s: String): TypeName = typeName(s.toCharArray.nn, 0, s.length) /** The type name represented by the empty string */ val EmptyTypeName: TypeName = EmptyTermName.toTypeName diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala index 1f83224cc3e7..d311f3d981d8 100644 --- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -29,12 +29,12 @@ object OrderingConstraint { empty else val result = new OrderingConstraint(boundsMap, lowerMap, upperMap) - ctx.run.recordConstraintSize(result, result.boundsMap.size) + ctx.run.nn.recordConstraintSize(result, result.boundsMap.size) result /** A lens for updating a single entry array in one of the three constraint maps */ abstract class ConstraintLens[T <: AnyRef: ClassTag] { - def entries(c: OrderingConstraint, poly: TypeLambda): Array[T] + def entries(c: OrderingConstraint, poly: TypeLambda): Array[T] | Null def updateEntries(c: OrderingConstraint, poly: TypeLambda, entries: Array[T])(using Context): OrderingConstraint def initial: T @@ -51,20 +51,24 @@ object OrderingConstraint { def update(prev: OrderingConstraint, current: OrderingConstraint, poly: TypeLambda, idx: Int, entry: T)(using Context): OrderingConstraint = { var es = entries(current, poly) - if (es != null && (es(idx) eq entry)) current + // TODO: investigate why flow typing is not working on `es` + if (es != null && (es.nn(idx) eq entry)) current else { val result = if (es == null) { es = Array.fill(poly.paramNames.length)(initial) - updateEntries(current, poly, es) + updateEntries(current, poly, es.nn) } - else if (es ne entries(prev, poly)) - current // can re-use existing entries array. else { - es = es.clone - updateEntries(current, poly, es) + val prev_es = entries(prev, poly) + if (prev_es == null || (es.nn ne prev_es.nn)) + current // can re-use existing entries array. + else { + es = es.nn.clone + updateEntries(current, poly, es.nn) + } } - es(idx) = entry + es.nn(idx) = entry result } } @@ -83,7 +87,7 @@ object OrderingConstraint { } val boundsLens: ConstraintLens[Type] = new ConstraintLens[Type] { - def entries(c: OrderingConstraint, poly: TypeLambda): Array[Type] = + def entries(c: OrderingConstraint, poly: TypeLambda): Array[Type] | Null = c.boundsMap(poly) def updateEntries(c: OrderingConstraint, poly: TypeLambda, entries: Array[Type])(using Context): OrderingConstraint = newConstraint(c.boundsMap.updated(poly, entries), c.lowerMap, c.upperMap) @@ -91,7 +95,7 @@ object OrderingConstraint { } val lowerLens: ConstraintLens[List[TypeParamRef]] = new ConstraintLens[List[TypeParamRef]] { - def entries(c: OrderingConstraint, poly: TypeLambda): Array[List[TypeParamRef]] = + def entries(c: OrderingConstraint, poly: TypeLambda): Array[List[TypeParamRef]] | Null = c.lowerMap(poly) def updateEntries(c: OrderingConstraint, poly: TypeLambda, entries: Array[List[TypeParamRef]])(using Context): OrderingConstraint = newConstraint(c.boundsMap, c.lowerMap.updated(poly, entries), c.upperMap) @@ -99,7 +103,7 @@ object OrderingConstraint { } val upperLens: ConstraintLens[List[TypeParamRef]] = new ConstraintLens[List[TypeParamRef]] { - def entries(c: OrderingConstraint, poly: TypeLambda): Array[List[TypeParamRef]] = + def entries(c: OrderingConstraint, poly: TypeLambda): Array[List[TypeParamRef]] | Null = c.upperMap(poly) def updateEntries(c: OrderingConstraint, poly: TypeLambda, entries: Array[List[TypeParamRef]])(using Context): OrderingConstraint = newConstraint(c.boundsMap, c.lowerMap, c.upperMap.updated(poly, entries)) @@ -201,11 +205,8 @@ class OrderingConstraint(private val boundsMap: ParamBounds, def typeVarOfParam(param: TypeParamRef): Type = { val entries = boundsMap(param.binder) - if (entries == null) NoType - else { - val tvar = typeVar(entries, param.paramNum) - if (tvar != null) tvar else NoType - } + if entries == null then NoType + else typeVar(entries, param.paramNum) } // ---------- Adding TypeLambdas -------------------------------------------------- @@ -470,7 +471,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, } def isRemovable(pt: TypeLambda): Boolean = { - val entries = boundsMap(pt) + val entries = boundsMap(pt).nn @tailrec def allRemovable(last: Int): Boolean = if (last < 0) true else typeVar(entries, last) match { @@ -489,7 +490,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, (this.typeVarOfParam(tl.paramRefs(0)) ne that.typeVarOfParam(tl.paramRefs(0))) def subst(from: TypeLambda, to: TypeLambda)(using Context): OrderingConstraint = - def swapKey[T](m: ArrayValuedMap[T]) = m.remove(from).updated(to, m(from)) + def swapKey[T](m: ArrayValuedMap[T]) = m.remove(from).updated(to, m(from).nn) var current = newConstraint(swapKey(boundsMap), swapKey(lowerMap), swapKey(upperMap)) def subst[T <: Type](x: T): T = x.subst(from, to).asInstanceOf[T] current.foreachParam {(p, i) => @@ -558,21 +559,21 @@ class OrderingConstraint(private val boundsMap: ParamBounds, i += 1 } - private var myUninstVars: mutable.ArrayBuffer[TypeVar] = _ + private var myUninstVars: mutable.ArrayBuffer[TypeVar] | Null = _ /** The uninstantiated typevars of this constraint */ def uninstVars: collection.Seq[TypeVar] = { - if (myUninstVars == null || myUninstVars.exists(_.inst.exists)) { + if (myUninstVars == null || myUninstVars.uncheckedNN.exists(_.inst.exists)) { myUninstVars = new mutable.ArrayBuffer[TypeVar] boundsMap.foreachBinding { (poly, entries) => for (i <- 0 until paramCount(entries)) typeVar(entries, i) match { - case tv: TypeVar if !tv.inst.exists && isBounds(entries(i)) => myUninstVars += tv + case tv: TypeVar if !tv.inst.exists && isBounds(entries(i)) => myUninstVars.uncheckedNN += tv case _ => } } } - myUninstVars + myUninstVars.uncheckedNN } // ---------- Checking ----------------------------------------------- @@ -615,7 +616,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, case TypeParamRef(binder: TypeLambda, _) => !contains(binder) case _ => false - def checkClosedType(tp: Type, where: String) = + def checkClosedType(tp: Type | Null, where: String) = if tp != null then assert(!tp.existsPart(isFreeTypeParamRef), i"unclosed constraint: $this refers to $tp in $where") diff --git a/compiler/src/dotty/tools/dotc/core/PatternTypeConstrainer.scala b/compiler/src/dotty/tools/dotc/core/PatternTypeConstrainer.scala index f928ad785e2c..9aa27919b52d 100644 --- a/compiler/src/dotty/tools/dotc/core/PatternTypeConstrainer.scala +++ b/compiler/src/dotty/tools/dotc/core/PatternTypeConstrainer.scala @@ -249,7 +249,7 @@ trait PatternTypeConstrainer { self: TypeComparer => trace(i"constraining simple pattern type $tp >:< $pt", gadts, res => s"$res\ngadt = ${ctx.gadt.debugBoundsDescription}") { (tp, pt) match { case (AppliedType(tyconS, argsS), AppliedType(tyconP, argsP)) => - val saved = state.constraint + val saved = state.nn.constraint val savedGadt = ctx.gadt.fresh val result = tyconS.typeParams.lazyZip(argsS).lazyZip(argsP).forall { (param, argS, argP) => diff --git a/compiler/src/dotty/tools/dotc/core/Phases.scala b/compiler/src/dotty/tools/dotc/core/Phases.scala index 623286d837b3..e43f617bf965 100644 --- a/compiler/src/dotty/tools/dotc/core/Phases.scala +++ b/compiler/src/dotty/tools/dotc/core/Phases.scala @@ -13,7 +13,7 @@ import scala.collection.mutable.ListBuffer import dotty.tools.dotc.transform.MegaPhase._ import dotty.tools.dotc.transform._ import Periods._ -import parsing.{ Parser} +import parsing.Parser import typer.{TyperPhase, RefChecks} import typer.ImportInfo.withRootImports import ast.tpd @@ -344,7 +344,7 @@ object Phases { def initContext(ctx: FreshContext): Unit = () private var myPeriod: Period = Periods.InvalidPeriod - private var myBase: ContextBase = null + private var myBase: ContextBase = _ private var myErasedTypes = false private var myFlatClasses = false private var myRefChecked = false diff --git a/compiler/src/dotty/tools/dotc/core/Scopes.scala b/compiler/src/dotty/tools/dotc/core/Scopes.scala index 44b97a25503e..863ae4fa6b7f 100644 --- a/compiler/src/dotty/tools/dotc/core/Scopes.scala +++ b/compiler/src/dotty/tools/dotc/core/Scopes.scala @@ -49,11 +49,11 @@ object Scopes { /** the next entry in the hash bucket */ - var tail: ScopeEntry = null + var tail: ScopeEntry | Null = null /** the preceding entry in this scope */ - var prev: ScopeEntry = null + var prev: ScopeEntry | Null = null override def toString: String = sym.toString } @@ -67,7 +67,7 @@ object Scopes { abstract class Scope extends printing.Showable { /** The last scope-entry from which all others are reachable via `prev` */ - private[dotc] def lastEntry: ScopeEntry + private[dotc] def lastEntry: ScopeEntry | Null /** The number of symbols in this scope (including inherited ones * from outer scopes). @@ -87,7 +87,7 @@ object Scopes { def iterator(using Context): Iterator[Symbol] = toList.iterator /** Is the scope empty? */ - def isEmpty: Boolean = lastEntry eq null + def isEmpty: Boolean = lastEntry == null /** Applies a function f to all Symbols of this Scope. */ def foreach[U](f: Symbol => U)(using Context): Unit = toList.foreach(f) @@ -97,7 +97,7 @@ object Scopes { ensureComplete() var syms: List[Symbol] = Nil var e = lastEntry - while ((e ne null) && e.owner == this) { + while ((e != null) && e.owner == this) { val sym = e.sym if (p(sym)) syms = sym :: syms e = e.prev @@ -118,23 +118,23 @@ object Scopes { def cloneScope(using Context): MutableScope /** Lookup a symbol entry matching given name. */ - def lookupEntry(name: Name)(using Context): ScopeEntry + def lookupEntry(name: Name)(using Context): ScopeEntry | Null /** Lookup next entry with same name as this one */ - def lookupNextEntry(entry: ScopeEntry)(using Context): ScopeEntry + def lookupNextEntry(entry: ScopeEntry)(using Context): ScopeEntry | Null /** Lookup a symbol */ final def lookup(name: Name)(using Context): Symbol = { val e = lookupEntry(name) - if (e eq null) NoSymbol else e.sym + if (e == null) NoSymbol else e.sym } /** Returns an iterator yielding every symbol with given name in this scope. */ final def lookupAll(name: Name)(using Context): Iterator[Symbol] = new Iterator[Symbol] { var e = lookupEntry(name) - def hasNext: Boolean = e ne null - def next(): Symbol = { val r = e.sym; e = lookupNextEntry(e); r } + def hasNext: Boolean = e != null + def next(): Symbol = { val r = e.nn.sym; e = lookupNextEntry(e.uncheckedNN); r } } /** Does this scope contain a reference to `sym` when looking up `name`? */ @@ -162,13 +162,14 @@ object Scopes { * a copy with the matching symbols. */ final def filteredScope(p: Symbol => Boolean)(using Context): Scope = { - var result: MutableScope = null + var result: MutableScope | Null = null for (sym <- iterator) if (!p(sym)) { if (result == null) result = cloneScope - result.unlink(sym) + result.nn.unlink(sym) } - if (result == null) this else result + // TODO: improve flow typing to handle this case + if (result == null) this else result.uncheckedNN } def implicitDecls(using Context): List[TermRef] = Nil @@ -192,7 +193,7 @@ object Scopes { * This is necessary because when run from reflection every scope needs to have a * SynchronizedScope as mixin. */ - class MutableScope protected[Scopes](initElems: ScopeEntry, initSize: Int, val nestingLevel: Int) + class MutableScope protected[Scopes](initElems: ScopeEntry | Null, initSize: Int, val nestingLevel: Int) extends Scope { /** Scope shares elements with `base` */ @@ -202,7 +203,7 @@ object Scopes { def this(nestingLevel: Int) = this(null, 0, nestingLevel) - private[dotc] var lastEntry: ScopeEntry = initElems + private[dotc] var lastEntry: ScopeEntry | Null = initElems /** The size of the scope */ private var _size = initSize @@ -212,14 +213,14 @@ object Scopes { /** the hash table */ - private var hashTable: Array[ScopeEntry] = null + private var hashTable: Array[ScopeEntry | Null] | Null = null /** a cache for all elements, to be used by symbol iterator. */ - private var elemsCache: List[Symbol] = null + private var elemsCache: List[Symbol] | Null = null /** The synthesizer to be used, or `null` if no synthesis is done on this scope */ - private var synthesize: SymbolSynthesizer = null + private var synthesize: SymbolSynthesizer | Null = null /** Use specified synthesize for this scope */ def useSynthesizer(s: SymbolSynthesizer): Unit = synthesize = s @@ -231,7 +232,7 @@ object Scopes { def cloneScope(using Context): MutableScope = { val entries = new mutable.ArrayBuffer[ScopeEntry] var e = lastEntry - while ((e ne null) && e.owner == this) { + while ((e != null) && e.owner == this) { entries += e e = e.prev } @@ -246,21 +247,21 @@ object Scopes { /** create and enter a scope entry with given name and symbol */ protected def newScopeEntry(name: Name, sym: Symbol)(using Context): ScopeEntry = { - ensureCapacity(if (hashTable ne null) hashTable.length else MinHashedScopeSize) + ensureCapacity(if (hashTable != null) hashTable.uncheckedNN.length else MinHashedScopeSize) val e = new ScopeEntry(name, sym, this) e.prev = lastEntry lastEntry = e - if (hashTable ne null) enterInHash(e) + if (hashTable != null) enterInHash(e) size += 1 elemsCache = null e } private def enterInHash(e: ScopeEntry)(using Context): Unit = { - val idx = e.name.hashCode & (hashTable.length - 1) - e.tail = hashTable(idx) + val idx = e.name.hashCode & (hashTable.nn.length - 1) + e.tail = hashTable.nn(idx) assert(e.tail != e) - hashTable(idx) = e + hashTable.nn(idx) = e } /** enter a symbol in this scope. */ @@ -288,21 +289,21 @@ object Scopes { private def createHash(tableSize: Int)(using Context): Unit = if (size > tableSize * FillFactor) createHash(tableSize * 2) else { - hashTable = new Array[ScopeEntry](tableSize) + hashTable = new Array[ScopeEntry | Null](tableSize) enterAllInHash(lastEntry) // checkConsistent() // DEBUG } - private def enterAllInHash(e: ScopeEntry, n: Int = 0)(using Context): Unit = - if (e ne null) + private def enterAllInHash(e: ScopeEntry | Null, n: Int = 0)(using Context): Unit = + if (e != null) if (n < MaxRecursions) { enterAllInHash(e.prev, n + 1) enterInHash(e) } else { var entries: List[ScopeEntry] = List() - var ee = e - while (ee ne null) { + var ee: ScopeEntry | Null = e + while (ee != null) { entries = ee :: entries ee = ee.prev } @@ -314,18 +315,18 @@ object Scopes { if (lastEntry == e) lastEntry = e.prev else { - var e1 = lastEntry - while (e1.prev != e) e1 = e1.prev + var e1 = lastEntry.nn + while (e1.prev != e) e1 = e1.prev.nn e1.prev = e.prev } - if (hashTable ne null) { - val index = e.name.hashCode & (hashTable.length - 1) - var e1 = hashTable(index) + if (hashTable != null) { + val index = e.name.hashCode & (hashTable.nn.length - 1) + var e1 = hashTable.nn(index) if (e1 == e) - hashTable(index) = e.tail + hashTable.nn(index) = e.tail else { - while (e1.tail != e) e1 = e1.tail - e1.tail = e.tail + while (e1.nn.tail != e) e1 = e1.nn.tail + e1.nn.tail = e.tail } } elemsCache = null @@ -339,7 +340,7 @@ object Scopes { /** remove symbol from this scope if it is present under the given name */ final def unlink(sym: Symbol, name: Name)(using Context): Unit = { var e = lookupEntry(name) - while (e ne null) { + while (e != null) { if (e.sym == sym) unlink(e) e = lookupNextEntry(e) } @@ -351,7 +352,7 @@ object Scopes { final def replace(prev: Symbol, replacement: Symbol)(using Context): Unit = { require(prev.name == replacement.name) var e = lookupEntry(prev.name) - while (e ne null) { + while (e != null) { if (e.sym == prev) e.sym = replacement e = lookupNextEntry(e) } @@ -360,32 +361,32 @@ object Scopes { /** Lookup a symbol entry matching given name. */ - override def lookupEntry(name: Name)(using Context): ScopeEntry = { - var e: ScopeEntry = null - if (hashTable ne null) { - e = hashTable(name.hashCode & (hashTable.length - 1)) - while ((e ne null) && e.name != name) + override def lookupEntry(name: Name)(using Context): ScopeEntry | Null = { + var e: ScopeEntry | Null = null + if (hashTable != null) { + e = hashTable.nn(name.hashCode & (hashTable.nn.length - 1)) + while ((e != null) && e.name != name) e = e.tail } else { e = lastEntry - while ((e ne null) && e.name != name) + while ((e != null) && e.name != name) e = e.prev } - if ((e eq null) && (synthesize != null)) { - val sym = synthesize(name) + if ((e == null) && (synthesize != null)) { + val sym = synthesize.uncheckedNN(name) if (sym.exists) newScopeEntry(sym.name, sym) else e } else e } /** lookup next entry with same name as this one */ - override final def lookupNextEntry(entry: ScopeEntry)(using Context): ScopeEntry = { - var e = entry - if (hashTable ne null) - while ({ e = e.tail ; (e ne null) && e.name != entry.name }) () + override final def lookupNextEntry(entry: ScopeEntry)(using Context): ScopeEntry | Null = { + var e: ScopeEntry | Null = entry + if (hashTable != null) + while ({ e = e.nn.tail ; (e != null) && e.uncheckedNN.name != entry.name }) () else - while ({ e = e.prev ; (e ne null) && e.name != entry.name }) () + while ({ e = e.nn.prev ; (e != null) && e.uncheckedNN.name != entry.name }) () e } @@ -393,23 +394,23 @@ object Scopes { * Does _not_ include the elements of inherited scopes. */ override final def toList(using Context): List[Symbol] = { - if (elemsCache eq null) { + if (elemsCache == null) { ensureComplete() elemsCache = Nil var e = lastEntry - while ((e ne null) && e.owner == this) { - elemsCache = e.sym :: elemsCache + while ((e != null) && e.owner == this) { + elemsCache = e.sym :: elemsCache.nn e = e.prev } } - elemsCache + elemsCache.nn } override def implicitDecls(using Context): List[TermRef] = { ensureComplete() var irefs = new mutable.ListBuffer[TermRef] var e = lastEntry - while (e ne null) { + while (e != null) { if (e.sym.isOneOf(GivenOrImplicitVal)) { val d = e.sym.denot irefs += TermRef(NoPrefix, d.symbol.asTerm).withDenot(d) @@ -432,7 +433,7 @@ object Scopes { while (e != null) { var e1 = lookupEntry(e.name) while (e1 != e && e1 != null) e1 = lookupNextEntry(e1) - assert(e1 == e, s"PANIC: Entry ${e.name} is badly linked") + assert(e1 == e, s"PANIC: Entry ${e.nn.name} is badly linked") e = e.prev } } @@ -462,12 +463,12 @@ object Scopes { /** The empty scope (immutable). */ object EmptyScope extends Scope { - override private[dotc] def lastEntry: ScopeEntry = null + override private[dotc] def lastEntry: ScopeEntry | Null = null override def size: Int = 0 override def nestingLevel: Int = 0 override def toList(using Context): List[Symbol] = Nil override def cloneScope(using Context): MutableScope = unsupported("cloneScope") - override def lookupEntry(name: Name)(using Context): ScopeEntry = null - override def lookupNextEntry(entry: ScopeEntry)(using Context): ScopeEntry = null + override def lookupEntry(name: Name)(using Context): ScopeEntry | Null = null + override def lookupNextEntry(entry: ScopeEntry)(using Context): ScopeEntry | Null = null } } diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index 01a3306b8fe8..c631cdd35251 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -40,7 +40,7 @@ object StdNames { inline val Tuple = "Tuple" inline val Product = "Product" - def sanitize(str: String): String = str.replaceAll("""[<>]""", """\$""") + def sanitize(str: String): String = str.replaceAll("""[<>]""", """\$""").nn } abstract class DefinedNames[N <: Name] { diff --git a/compiler/src/dotty/tools/dotc/core/Substituters.scala b/compiler/src/dotty/tools/dotc/core/Substituters.scala index bc292d4724a6..0db49855bfda 100644 --- a/compiler/src/dotty/tools/dotc/core/Substituters.scala +++ b/compiler/src/dotty/tools/dotc/core/Substituters.scala @@ -7,7 +7,7 @@ import Types._, Symbols._, Contexts._ */ object Substituters: - final def subst(tp: Type, from: BindingType, to: BindingType, theMap: SubstBindingMap)(using Context): Type = + final def subst(tp: Type, from: BindingType, to: BindingType, theMap: SubstBindingMap | Null)(using Context): Type = tp match { case tp: BoundType => if (tp.binder eq from) tp.copyBoundType(to.asInstanceOf[tp.BT]) else tp @@ -23,7 +23,7 @@ object Substituters: .mapOver(tp) } - final def subst1(tp: Type, from: Symbol, to: Type, theMap: Subst1Map)(using Context): Type = + final def subst1(tp: Type, from: Symbol, to: Type, theMap: Subst1Map | Null)(using Context): Type = tp match { case tp: NamedType => val sym = tp.symbol @@ -37,7 +37,7 @@ object Substituters: .mapOver(tp) } - final def subst2(tp: Type, from1: Symbol, to1: Type, from2: Symbol, to2: Type, theMap: Subst2Map)(using Context): Type = + final def subst2(tp: Type, from1: Symbol, to1: Type, from2: Symbol, to2: Type, theMap: Subst2Map | Null)(using Context): Type = tp match { case tp: NamedType => val sym = tp.symbol @@ -52,7 +52,7 @@ object Substituters: .mapOver(tp) } - final def subst(tp: Type, from: List[Symbol], to: List[Type], theMap: SubstMap)(using Context): Type = + final def subst(tp: Type, from: List[Symbol], to: List[Type], theMap: SubstMap | Null)(using Context): Type = tp match { case tp: NamedType => val sym = tp.symbol @@ -72,7 +72,7 @@ object Substituters: .mapOver(tp) } - final def substSym(tp: Type, from: List[Symbol], to: List[Symbol], theMap: SubstSymMap)(using Context): Type = + final def substSym(tp: Type, from: List[Symbol], to: List[Symbol], theMap: SubstSymMap | Null)(using Context): Type = tp match { case tp: NamedType => val sym = tp.symbol @@ -103,7 +103,7 @@ object Substituters: .mapOver(tp) } - final def substThis(tp: Type, from: ClassSymbol, to: Type, theMap: SubstThisMap)(using Context): Type = + final def substThis(tp: Type, from: ClassSymbol, to: Type, theMap: SubstThisMap | Null)(using Context): Type = tp match { case tp: ThisType => if (tp.cls eq from) to else tp @@ -117,7 +117,7 @@ object Substituters: .mapOver(tp) } - final def substRecThis(tp: Type, from: Type, to: Type, theMap: SubstRecThisMap)(using Context): Type = + final def substRecThis(tp: Type, from: Type, to: Type, theMap: SubstRecThisMap | Null)(using Context): Type = tp match { case tp @ RecThis(binder) => if (binder eq from) to else tp @@ -131,7 +131,7 @@ object Substituters: .mapOver(tp) } - final def substParam(tp: Type, from: ParamRef, to: Type, theMap: SubstParamMap)(using Context): Type = + final def substParam(tp: Type, from: ParamRef, to: Type, theMap: SubstParamMap | Null)(using Context): Type = tp match { case tp: BoundType => if (tp == from) to else tp @@ -145,7 +145,7 @@ object Substituters: .mapOver(tp) } - final def substParams(tp: Type, from: BindingType, to: List[Type], theMap: SubstParamsMap)(using Context): Type = + final def substParams(tp: Type, from: BindingType, to: List[Type], theMap: SubstParamsMap | Null)(using Context): Type = tp match { case tp: ParamRef => if (tp.binder == from) to(tp.paramNum) else tp diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 96c629517719..7be005ea4b8a 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -495,7 +495,7 @@ object SymDenotations { /** `fullName` where `.' is the separator character */ def fullName(using Context): Name = fullNameSeparated(QualifiedName) - private var myTargetName: Name = null + private var myTargetName: Name | Null = null private def computeTargetName(targetNameAnnot: Option[Annotation])(using Context): Name = targetNameAnnot match @@ -526,9 +526,9 @@ object SymDenotations { else carrier.getAnnotation(defn.TargetNameAnnot) myTargetName = computeTargetName(targetNameAnnot) if name.is(SuperAccessorName) then - myTargetName = myTargetName.unmangle(List(ExpandedName, SuperAccessorName, ExpandPrefixName)) + myTargetName = myTargetName.nn.unmangle(List(ExpandedName, SuperAccessorName, ExpandPrefixName)) - myTargetName + myTargetName.nn // ----- Tests ------------------------------------------------- @@ -831,7 +831,7 @@ object SymDenotations { * As a side effect, drop Local flags of members that are not accessed via the ThisType * of their owner. */ - final def isAccessibleFrom(pre: Type, superAccess: Boolean = false, whyNot: StringBuffer = null)(using Context): Boolean = { + final def isAccessibleFrom(pre: Type, superAccess: Boolean = false, whyNot: StringBuffer | Null = null)(using Context): Boolean = { /** Are we inside definition of `boundary`? * If this symbol is Java defined, package structure is interpreted to be flat. @@ -861,7 +861,7 @@ object SymDenotations { /** Is protected access to target symbol permitted? */ def isProtectedAccessOK: Boolean = inline def fail(str: String): false = - if whyNot != null then whyNot.append(str) + if whyNot != null then whyNot.nn.append(str) false val cls = owner.enclosingSubClass if !cls.exists then @@ -1227,16 +1227,17 @@ object SymDenotations { * lookup its companion in the same scope. */ private def companionNamed(name: TypeName)(using Context): Symbol = + val unit = ctx.compilationUnit if (owner.isClass) owner.unforcedDecls.lookup(name).suchThat(_.isCoDefinedWith(symbol)).symbol - else if (!owner.exists || ctx.compilationUnit == null) + else if (!owner.exists || (unit eq NoCompilationUnit)) NoSymbol - else if (!ctx.compilationUnit.tpdTree.isEmpty) + else if (!unit.tpdTree.isEmpty) tpd.definingStats(symbol).iterator .map(tpd.definedSym) .find(_.name == name) .getOrElse(NoSymbol) - else if (ctx.scope == null) + else if (ctx.scope eq EmptyScope) NoSymbol else if (ctx.scope.lookup(this.name) == symbol) ctx.scope.lookup(name) @@ -1530,10 +1531,10 @@ object SymDenotations { owner: Symbol = this.owner, name: Name = this.name, initFlags: FlagSet = UndefinedFlags, - info: Type = null, - privateWithin: Symbol = null, - annotations: List[Annotation] = null, - rawParamss: List[List[Symbol]] = null)( + info: Type | Null = null, + privateWithin: Symbol | Null = null, + annotations: List[Annotation] | Null = null, + rawParamss: List[List[Symbol]] | Null = null)( using Context): SymDenotation = { // simulate default parameters, while also passing implicit context ctx to the default values val initFlags1 = (if (initFlags != UndefinedFlags) initFlags else this.flags) @@ -1558,7 +1559,7 @@ object SymDenotations { /** Are `info1` and `info2` ClassInfo types with different parents? * @param completersMatter if `true`, consider parents changed if `info1` or `info2 `is a type completer */ - protected def changedClassParents(info1: Type, info2: Type, completersMatter: Boolean): Boolean = + protected def changedClassParents(info1: Type | Null, info2: Type | Null, completersMatter: Boolean): Boolean = info2 match { case info2: ClassInfo => info1 match { @@ -1700,15 +1701,15 @@ object SymDenotations { // ----- caches ------------------------------------------------------- - private var myTypeParams: List[TypeSymbol] = null + private var myTypeParams: List[TypeSymbol] | Null = null private var fullNameCache: SimpleIdentityMap[QualifiedNameKind, Name] = SimpleIdentityMap.empty - private var myMemberCache: EqHashMap[Name, PreDenotation] = null + private var myMemberCache: EqHashMap[Name, PreDenotation] | Null = null private var myMemberCachePeriod: Period = Nowhere /** A cache from types T to baseType(T, C) */ type BaseTypeMap = EqHashMap[CachedType, Type] - private var myBaseTypeCache: BaseTypeMap = null + private var myBaseTypeCache: BaseTypeMap | Null = null private var myBaseTypeCachePeriod: Period = Nowhere private var baseDataCache: BaseData = BaseData.None @@ -1719,14 +1720,14 @@ object SymDenotations { myMemberCache = EqHashMap() myMemberCachePeriod = ctx.period } - myMemberCache + myMemberCache.nn } private def baseTypeCache(using Context): BaseTypeMap = { if !currentHasSameBaseTypesAs(myBaseTypeCachePeriod) then myBaseTypeCache = new BaseTypeMap() myBaseTypeCachePeriod = ctx.period - myBaseTypeCache + myBaseTypeCache.nn } private def invalidateBaseDataCache() = { @@ -1749,7 +1750,7 @@ object SymDenotations { invalidateMemberNamesCache() def invalidateMemberCachesFor(sym: Symbol)(using Context): Unit = - if myMemberCache != null then myMemberCache.remove(sym.name) + if myMemberCache != null then myMemberCache.uncheckedNN.remove(sym.name) if !sym.flagsUNSAFE.is(Private) then invalidateMemberNamesCache() if sym.isWrappedToplevelDef then @@ -1802,7 +1803,7 @@ object SymDenotations { case _ => typeParamsFromDecls } } - myTypeParams + myTypeParams.nn } override protected[dotc] final def info_=(tp: Type): Unit = { @@ -1837,7 +1838,7 @@ object SymDenotations { // ------ class-specific operations ----------------------------------- - private var myThisType: Type = null + private var myThisType: Type | Null = null /** The this-type depends on the kind of class: * - for a package class `p`: ThisType(TypeRef(Noprefix, p)) @@ -1846,7 +1847,7 @@ object SymDenotations { */ override def thisType(using Context): Type = { if (myThisType == null) myThisType = computeThisType - myThisType + myThisType.nn } private def computeThisType(using Context): Type = { @@ -1855,11 +1856,11 @@ object SymDenotations { ThisType.raw(TypeRef(pre, cls)) } - private var myTypeRef: TypeRef = null + private var myTypeRef: TypeRef | Null = null override def typeRef(using Context): TypeRef = { if (myTypeRef == null) myTypeRef = super.typeRef - myTypeRef + myTypeRef.nn } override def appliedRef(using Context): Type = classInfo.appliedRef @@ -1967,7 +1968,7 @@ object SymDenotations { */ def replace(prev: Symbol, replacement: Symbol)(using Context): Unit = { unforcedDecls.openForMutations.replace(prev, replacement) - if (myMemberCache != null) myMemberCache.remove(replacement.name) + if (myMemberCache != null) myMemberCache.uncheckedNN.remove(replacement.name) } /** Delete symbol from current scope. @@ -1978,7 +1979,7 @@ object SymDenotations { val scope = info.decls.openForMutations scope.unlink(sym, sym.name) if sym.name != sym.originalName then scope.unlink(sym, sym.originalName) - if (myMemberCache != null) myMemberCache.remove(sym.name) + if (myMemberCache != null) myMemberCache.uncheckedNN.remove(sym.name) if (!sym.flagsUNSAFE.is(Private)) invalidateMemberNamesCache() } @@ -2004,7 +2005,7 @@ object SymDenotations { final def membersNamed(name: Name)(using Context): PreDenotation = Stats.record("membersNamed") if Config.cacheMembersNamed then - var denots: PreDenotation = memberCache.lookup(name) + var denots: PreDenotation | Null = memberCache.lookup(name) if denots == null then denots = computeMembersNamed(name) memberCache(name) = denots @@ -2412,7 +2413,7 @@ object SymDenotations { ) if compiledNow.exists then compiledNow else - val assocFiles = multi.aggregate(d => Set(d.symbol.associatedFile), _ union _) + val assocFiles = multi.aggregate(d => Set(d.symbol.associatedFile.nn), _ union _) if assocFiles.size == 1 then multi // they are all overloaded variants from the same file else @@ -2437,7 +2438,7 @@ object SymDenotations { try f.container == chosen.container catch case NonFatal(ex) => true if !ambiguityWarningIssued then for conflicting <- assocFiles.find(!sameContainer(_)) do - report.warning(i"""${ambiguousFilesMsg(conflicting)} + report.warning(i"""${ambiguousFilesMsg(conflicting.nn)} |Keeping only the definition in $chosen""") ambiguityWarningIssued = true multi.filterWithPredicate(_.symbol.associatedFile == chosen) @@ -2627,8 +2628,8 @@ object SymDenotations { def apply(module: TermSymbol, modcls: ClassSymbol): LazyType = this private var myDecls: Scope = EmptyScope - private var mySourceModule: Symbol = null - private var myModuleClass: Symbol = null + private var mySourceModule: Symbol | Null = null + private var myModuleClass: Symbol | Null = null private var mySourceModuleFn: Context ?=> Symbol = LazyType.NoSymbolFn private var myModuleClassFn: Context ?=> Symbol = LazyType.NoSymbolFn @@ -2640,10 +2641,10 @@ object SymDenotations { def decls: Scope = myDecls def sourceModule(using Context): Symbol = if mySourceModule == null then mySourceModule = mySourceModuleFn - mySourceModule + mySourceModule.nn def moduleClass(using Context): Symbol = if myModuleClass == null then myModuleClass = myModuleClassFn - myModuleClass + myModuleClass.nn def withDecls(decls: Scope): this.type = { myDecls = decls; this } def withSourceModule(sourceModuleFn: Context ?=> Symbol): this.type = { mySourceModuleFn = sourceModuleFn; this } @@ -2767,10 +2768,11 @@ object SymDenotations { private abstract class InheritedCacheImpl(val createdAt: Period) extends InheritedCache { protected def sameGroup(p1: Phase, p2: Phase): Boolean - private var dependent: WeakHashMap[InheritedCache, Unit] = null + private var dependent: WeakHashMap[InheritedCache, Unit] | Null = null private var checkedPeriod: Period = Nowhere protected def invalidateDependents() = { + import scala.language.unsafeNulls if (dependent != null) { val it = dependent.keySet.iterator() while (it.hasNext()) it.next().invalidate() @@ -2780,7 +2782,7 @@ object SymDenotations { protected def addDependent(dep: InheritedCache) = { if (dependent == null) dependent = new WeakHashMap - dependent.put(dep, ()) + dependent.nn.put(dep, ()) } def isValidAt(phase: Phase)(using Context) = @@ -2798,7 +2800,7 @@ object SymDenotations { } private class MemberNamesImpl(createdAt: Period) extends InheritedCacheImpl(createdAt) with MemberNames { - private var cache: SimpleIdentityMap[NameFilter, Set[Name]] = SimpleIdentityMap.empty + private var cache: SimpleIdentityMap[NameFilter, Set[Name]] | Null = SimpleIdentityMap.empty final def isValid(using Context): Boolean = cache != null && isValidAt(ctx.phase) @@ -2819,7 +2821,7 @@ object SymDenotations { def apply(keepOnly: NameFilter, clsd: ClassDenotation)(implicit onBehalf: MemberNames, ctx: Context) = { assert(isValid) - val cached = cache(keepOnly) + val cached = cache.nn(keepOnly) try if (cached != null) cached else { @@ -2827,7 +2829,7 @@ object SymDenotations { val computed = try clsd.computeMemberNames(keepOnly)(this, ctx) finally locked = false - cache = cache.updated(keepOnly, computed) + cache = cache.nn.updated(keepOnly, computed) computed } finally addDependent(onBehalf) @@ -2837,7 +2839,7 @@ object SymDenotations { } private class BaseDataImpl(createdAt: Period) extends InheritedCacheImpl(createdAt) with BaseData { - private var cache: (List[ClassSymbol], BaseClassSet) = null + private var cache: (List[ClassSymbol], BaseClassSet) | Null = null private var valid = true private var locked = false @@ -2862,7 +2864,7 @@ object SymDenotations { : (List[ClassSymbol], BaseClassSet) = { assert(isValid) try - if (cache != null) cache + if (cache != null) cache.uncheckedNN else { if (locked) throw CyclicReference(clsd) locked = true diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index 597cf1dc76b0..c5ae98853061 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -135,7 +135,7 @@ object SymbolLoaders { if (!ok) report.warning(i"""$what ${tree.name} is in the wrong directory. |It was declared to be in package ${path.reverse.mkString(".")} - |But it is found in directory ${filePath.reverse.mkString(File.separator)}""", + |But it is found in directory ${filePath.reverse.mkString(File.separator.nn)}""", tree.srcPos.focus) ok } @@ -207,7 +207,7 @@ object SymbolLoaders { /** Load contents of a package */ class PackageLoader(_sourceModule: TermSymbol, classPath: ClassPath) extends SymbolLoader { - override def sourceFileOrNull: AbstractFile = null + override def sourceFileOrNull: AbstractFile | Null = null override def sourceModule(using Context): TermSymbol = _sourceModule def description(using Context): String = "package loader " + sourceModule.fullName @@ -222,7 +222,7 @@ object SymbolLoaders { override def newScopeEntry(name: Name, sym: Symbol)(using Context): ScopeEntry = super.newScopeEntry(name.mangled, sym) - override def lookupEntry(name: Name)(using Context): ScopeEntry = { + override def lookupEntry(name: Name)(using Context): ScopeEntry | Null = { val mangled = name.mangled val e = super.lookupEntry(mangled) if (e != null) e @@ -295,7 +295,7 @@ object SymbolLoaders { val fullName = pkg.name val name = if (packageName.isEmpty) fullName - else fullName.substring(packageName.length + 1) + else fullName.substring(packageName.length + 1).nn enterPackage(root.symbol, name.toTermName, (module, modcls) => new PackageLoader(module, classPath)) @@ -311,7 +311,7 @@ abstract class SymbolLoader extends LazyType { self => /** Load source or class file for `root`, return */ def doComplete(root: SymDenotation)(using Context): Unit - def sourceFileOrNull: AbstractFile + def sourceFileOrNull: AbstractFile | Null /** Description of the resource (ClassPath, AbstractFile) * being processed by this loader @@ -331,7 +331,7 @@ abstract class SymbolLoader extends LazyType { self => if (ctx.debug) ex.printStackTrace() val msg = ex.getMessage() report.error( - if (msg eq null) "i/o error while loading " + root.name + if (msg == null) "i/o error while loading " + root.name else "error while loading " + root.name + ",\n" + msg) } try { @@ -398,7 +398,7 @@ abstract class SymbolLoader extends LazyType { self => class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader { - override def sourceFileOrNull: AbstractFile = classfile + override def sourceFileOrNull: AbstractFile | Null = classfile def description(using Context): String = "class file " + classfile.toString @@ -424,15 +424,15 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader { class SourcefileLoader(val srcfile: AbstractFile) extends SymbolLoader { def description(using Context): String = "source file " + srcfile.toString - override def sourceFileOrNull: AbstractFile = srcfile + override def sourceFileOrNull: AbstractFile | Null = srcfile def doComplete(root: SymDenotation)(using Context): Unit = - ctx.run.lateCompile(srcfile, typeCheck = ctx.settings.YretainTrees.value) + ctx.run.nn.lateCompile(srcfile, typeCheck = ctx.settings.YretainTrees.value) } /** A NoCompleter which is also a SymbolLoader. */ class NoLoader extends SymbolLoader with NoCompleter { def description(using Context): String = "NoLoader" - override def sourceFileOrNull: AbstractFile = null + override def sourceFileOrNull: AbstractFile | Null = null override def complete(root: SymDenotation)(using Context): Unit = super[NoCompleter].complete(root) def doComplete(root: SymDenotation)(using Context): Unit = diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index b19c8cae3105..15b46f6c9cb9 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -65,11 +65,11 @@ object Symbols { myCoord = c } - private var myDefTree: Tree = null + private var myDefTree: Tree | Null = null /** The tree defining the symbol at pickler time, EmptyTree if none was retained */ def defTree: Tree = - if (myDefTree == null) tpd.EmptyTree else myDefTree + if (myDefTree == null) tpd.EmptyTree else myDefTree.nn /** Set defining tree if this symbol retains its definition tree */ def defTree_=(tree: Tree)(using Context): Unit = @@ -91,7 +91,9 @@ object Symbols { private[core] def invalidateDenotCache(): Unit = { checkedPeriod = Nowhere } - /** Set the denotation of this symbol */ + /** Set the denotation of this symbol + * `denot` should always be initialized when a new Symbol is created. + */ private[core] def denot_=(d: SymDenotation): Unit = { util.Stats.record("Symbol.denot_=") lastDenot = d @@ -101,9 +103,8 @@ object Symbols { /** The current denotation of this symbol */ final def denot(using Context): SymDenotation = { util.Stats.record("Symbol.denot") - val lastd = lastDenot - if (checkedPeriod == ctx.period) lastd - else computeDenot(lastd) + if (checkedPeriod == ctx.period) lastDenot + else computeDenot(lastDenot) } private def computeDenot(lastd: SymDenotation)(using Context): SymDenotation = { @@ -130,7 +131,7 @@ object Symbols { lastDenot private[core] def defRunId: RunId = - if (lastDenot == null) NoRunId else lastDenot.validFor.runId + lastDenot.validFor.runId private inline def associatedFileMatches(inline filter: AbstractFile => Boolean)(using Context): Boolean = try @@ -142,7 +143,7 @@ object Symbols { /** Does this symbol come from a currently compiled source file? */ final def isDefinedInCurrentRun(using Context): Boolean = - span.exists && defRunId == ctx.runId && associatedFileMatches(ctx.run.files.contains) + span.exists && defRunId == ctx.runId && associatedFileMatches(ctx.run.nn.files.contains) /** Is this symbol valid in the current run and has an associated file that is * not a binary file. e.g. This will return true for @@ -180,10 +181,8 @@ object Symbols { * conservatively returns `false` if symbol does not yet have a denotation, or denotation * is a class that is not yet read. */ - final def isPrivate(using Context): Boolean = { - val d = lastDenot - d != null && d.flagsUNSAFE.is(Private) - } + final def isPrivate(using Context): Boolean = + lastDenot.flagsUNSAFE.is(Private) /** Is the symbol a pattern bound symbol? */ @@ -192,14 +191,14 @@ object Symbols { /** The symbol's signature if it is completed or a method, NotAMethod otherwise. */ final def signature(using Context): Signature = - if (lastDenot != null && (lastDenot.isCompleted || lastDenot.is(Method))) + if lastDenot.uncheckedNN.isCompleted || lastDenot.uncheckedNN.is(Method) then denot.signature else Signature.NotAMethod /** Special cased here, because it may be used on naked symbols in substituters */ final def isStatic(using Context): Boolean = - lastDenot != null && lastDenot.initial.isStatic + lastDenot.initial.isStatic /** This symbol entered into owner's scope (owner must be a class). */ final def entered(using Context): this.type = { @@ -266,11 +265,11 @@ object Symbols { * containing this symbol instead of the directly enclosing class. * Overridden in ClassSymbol */ - def associatedFile(using Context): AbstractFile = - if (lastDenot == null) null else lastDenot.topLevelClass.associatedFile + def associatedFile(using Context): AbstractFile | Null = + lastDenot.topLevelClass.associatedFile /** The class file from which this class was generated, null if not applicable. */ - final def binaryFile(using Context): AbstractFile = { + final def binaryFile(using Context): AbstractFile | Null = { val file = associatedFile if (file != null && file.extension == "class") file else null } @@ -355,8 +354,7 @@ object Symbols { protected def prefixString: String = "Symbol" override def toString: String = - if (lastDenot == null) s"Naked$prefixString#$id" - else lastDenot.toString// + "#" + id // !!! DEBUG + lastDenot.toString // + "#" + id // !!! DEBUG def toText(printer: Printer): Text = printer.toText(this) @@ -373,7 +371,7 @@ object Symbols { type TermSymbol = Symbol { type ThisName = TermName } type TypeSymbol = Symbol { type ThisName = TypeName } - class ClassSymbol private[Symbols] (coord: Coord, val assocFile: AbstractFile, id: Int, nestingLevel: Int) + class ClassSymbol private[Symbols] (coord: Coord, val assocFile: AbstractFile | Null, id: Int, nestingLevel: Int) extends Symbol(coord, id, nestingLevel) { type ThisName = TypeName @@ -433,7 +431,7 @@ object Symbols { } /** The source or class file from which this class was generated, null if not applicable. */ - override def associatedFile(using Context): AbstractFile = + override def associatedFile(using Context): AbstractFile | Null = if assocFile != null || this.is(Package) || this.owner.is(Package) then assocFile else super.associatedFile @@ -465,7 +463,7 @@ object Symbols { } @sharable object NoSymbol extends Symbol(NoCoord, 0, 0) { - override def associatedFile(using Context): AbstractFile = NoSource.file + override def associatedFile(using Context): AbstractFile | Null = NoSource.file override def recomputeDenot(lastd: SymDenotation)(using Context): SymDenotation = NoDenotation } @@ -483,7 +481,7 @@ object Symbols { info: Type = sym.info, privateWithin: Symbol = sym.privateWithin, coord: Coord = NoCoord, // Can be `= owner.coord` once we bootstrap - associatedFile: AbstractFile = null // Can be `= owner.associatedFile` once we bootstrap + associatedFile: AbstractFile | Null = null // Can be `= owner.associatedFile` once we bootstrap ): Symbol = { val coord1 = if (coord == NoCoord) owner.coord else coord val associatedFile1 = if (associatedFile == null) owner.associatedFile else associatedFile @@ -537,7 +535,7 @@ object Symbols { infoFn: ClassSymbol => Type, privateWithin: Symbol = NoSymbol, coord: Coord = NoCoord, - assocFile: AbstractFile = null)(using Context): ClassSymbol + assocFile: AbstractFile | Null = null)(using Context): ClassSymbol = { val cls = new ClassSymbol(coord, assocFile, ctx.base.nextSymId, ctx.nestingLevel) val denot = SymDenotation(cls, owner, name, flags, infoFn(cls), privateWithin) @@ -555,7 +553,7 @@ object Symbols { selfInfo: Type = NoType, privateWithin: Symbol = NoSymbol, coord: Coord = NoCoord, - assocFile: AbstractFile = null)(using Context): ClassSymbol = + assocFile: AbstractFile | Null = null)(using Context): ClassSymbol = newClassSymbol( owner, name, flags, ClassInfo(owner.thisType, _, parents, decls, selfInfo), @@ -572,7 +570,7 @@ object Symbols { selfInfo: Type = NoType, privateWithin: Symbol = NoSymbol, coord: Coord = NoCoord, - assocFile: AbstractFile = null)(using Context): ClassSymbol = { + assocFile: AbstractFile | Null = null)(using Context): ClassSymbol = { def completer = new LazyType { def complete(denot: SymDenotation)(using Context): Unit = { val cls = denot.asClass.classSymbol @@ -598,7 +596,7 @@ object Symbols { infoFn: (TermSymbol, ClassSymbol) => Type, // typically a ModuleClassCompleterWithDecls privateWithin: Symbol = NoSymbol, coord: Coord = NoCoord, - assocFile: AbstractFile = null)(using Context): TermSymbol + assocFile: AbstractFile | Null = null)(using Context): TermSymbol = { val base = owner.thisType val modclsFlags = clsFlags | ModuleClassCreationFlags @@ -627,7 +625,7 @@ object Symbols { decls: Scope, privateWithin: Symbol = NoSymbol, coord: Coord = NoCoord, - assocFile: AbstractFile = null)(using Context): TermSymbol = + assocFile: AbstractFile | Null = null)(using Context): TermSymbol = newModuleSymbol( owner, name, modFlags, clsFlags, (module, modcls) => ClassInfo( @@ -671,7 +669,7 @@ object Symbols { /** Create a stub symbol that will issue a missing reference error * when attempted to be completed. */ - def newStubSymbol(owner: Symbol, name: Name, file: AbstractFile = null)(using Context): Symbol = { + def newStubSymbol(owner: Symbol, name: Name, file: AbstractFile | Null = null)(using Context): Symbol = { def stubCompleter = new StubInfo() val normalizedOwner = if (owner.is(ModuleVal)) owner.moduleClass else owner typr.println(s"creating stub for ${name.show}, owner = ${normalizedOwner.denot.debugString}, file = $file") diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 777a569e8d36..a79b1bd940f3 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -9,6 +9,7 @@ import StdNames.nme import TypeOps.refineUsingParent import collection.mutable import util.Stats +import util.NoSourcePosition import config.Config import config.Feature.migrateTo3 import config.Printers.{subtyping, gadts, matchTypes, noPrinter} @@ -35,7 +36,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling protected given [DummySoItsADef]: Context = myContext - protected var state: TyperState = null + protected var state: TyperState = compiletime.uninitialized def constraint: Constraint = state.constraint def constraint_=(c: Constraint): Unit = state.constraint = c @@ -48,7 +49,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling needsGc = false if Config.checkTypeComparerReset then checkReset() - private var pendingSubTypes: util.MutableSet[(Type, Type)] = null + private var pendingSubTypes: util.MutableSet[(Type, Type)] | Null = null private var recCount = 0 private var monitored = false @@ -91,7 +92,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling override def checkReset() = super.checkReset() - assert(pendingSubTypes == null || pendingSubTypes.isEmpty) + assert(pendingSubTypes == null || pendingSubTypes.uncheckedNN.isEmpty) assert(canCompareAtoms == true) assert(successCount == 0) assert(totalCount == 0) @@ -150,7 +151,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling * every time we compare components of the previous pair of types. * This type is used for capture conversion in `isSubArgs`. */ - private [this] var leftRoot: Type = null + private [this] var leftRoot: Type | Null = null /** Are we forbidden from recording GADT constraints? */ private var frozenGadt = false @@ -247,13 +248,13 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling } } val p = (normalize(tp1), normalize(tp2)) - !pendingSubTypes.contains(p) && { + !pendingSubTypes.nn.contains(p) && { try { - pendingSubTypes += p + pendingSubTypes.nn += p firstTry } finally - pendingSubTypes -= p + pendingSubTypes.nn -= p } } @@ -782,7 +783,6 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling case AndType(tp1, tp2) => isNullable(tp1) && isNullable(tp2) case OrType(tp1, tp2) => isNullable(tp1) || isNullable(tp2) case _ => false - val sym1 = tp1.symbol (sym1 eq NothingClass) && tp2.isValueTypeOrLambda || (sym1 eq NullClass) && isNullable(tp2) @@ -1488,11 +1488,12 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling */ def compareCaptured(arg1: TypeBounds, arg2: Type) = tparam match { case tparam: Symbol => - if (leftRoot.isStable || ctx.isAfterTyper || ctx.mode.is(Mode.TypevarsMissContext)) - && leftRoot.isValueType - && leftRoot.member(tparam.name).exists + val leftr = leftRoot.nn + if (leftr.isStable || ctx.isAfterTyper || ctx.mode.is(Mode.TypevarsMissContext)) + && leftr.isValueType + && leftr.member(tparam.name).exists then - val captured = TypeRef(leftRoot, tparam) + val captured = TypeRef(leftr, tparam) try isSubArg(captured, arg2) catch case ex: TypeError => // The captured reference could be illegal and cause a @@ -2473,7 +2474,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling /** Does `tycon` have a field with type `tparam`? Special cased for `scala.*:` * as that type is artificially added to tuples. */ private def typeparamCorrespondsToField(tycon: Type, tparam: TypeParamInfo): Boolean = - productSelectorTypes(tycon, null).exists { + productSelectorTypes(tycon, NoSourcePosition).exists { case tp: TypeRef => tp.designator.eq(tparam) // Bingo! case _ => @@ -2630,9 +2631,9 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling !(tp2 <:< tp1) && (provablyDisjoint(tp1, tp2.tp2) || provablyDisjoint(tp1, tp2.tp1)) case (tp1: NamedType, _) if gadtBounds(tp1.symbol) != null => - provablyDisjoint(gadtBounds(tp1.symbol).hi, tp2) || provablyDisjoint(tp1.superType, tp2) + provablyDisjoint(gadtBounds(tp1.symbol).uncheckedNN.hi, tp2) || provablyDisjoint(tp1.superType, tp2) case (_, tp2: NamedType) if gadtBounds(tp2.symbol) != null => - provablyDisjoint(tp1, gadtBounds(tp2.symbol).hi) || provablyDisjoint(tp1, tp2.superType) + provablyDisjoint(tp1, gadtBounds(tp2.symbol).uncheckedNN.hi) || provablyDisjoint(tp1, tp2.superType) case (tp1: TermRef, tp2: TermRef) if isEnumValueOrModule(tp1) && isEnumValueOrModule(tp2) => tp1.termSymbol != tp2.termSymbol case (tp1: TermRef, tp2: TypeRef) if isEnumValue(tp1) => @@ -2684,12 +2685,12 @@ object TypeComparer { } private[core] def show(res: Any)(using Context): String = - if ctx.settings.YexplainLowlevel.value then String.valueOf(res) + if ctx.settings.YexplainLowlevel.value then String.valueOf(res).nn else res match case ClassInfo(_, cls, _, _, _) => cls.showLocated case bounds: TypeBounds => i"type bounds [$bounds]" case res: printing.Showable => res.show - case _ => String.valueOf(res) + case _ => String.valueOf(res).nn /** The approximation state indicates how the pair of types currently compared * relates to the types compared originally. @@ -2843,7 +2844,7 @@ class TrackingTypeComparer(initctx: Context) extends TypeComparer(initctx) { super.addOneBound(param, bound, isUpper) } - override def gadtBounds(sym: Symbol)(using Context): TypeBounds = { + override def gadtBounds(sym: Symbol)(using Context): TypeBounds | Null = { if (sym.exists) footprint += sym.typeRef super.gadtBounds(sym) } diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala index 1473bcc559e2..a8ce6039db18 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala @@ -77,7 +77,7 @@ object TypeErasure { def normalizeClass(cls: ClassSymbol)(using Context): ClassSymbol = { if (cls.owner == defn.ScalaPackageClass) { if (defn.specialErasure.contains(cls)) - return defn.specialErasure(cls) + return defn.specialErasure(cls).uncheckedNN if (cls == defn.UnitClass) return defn.BoxedUnitClass } @@ -688,7 +688,7 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst private def erasePair(tp: Type)(using Context): Type = { val arity = tp.tupleArity if (arity < 0) defn.ProductClass.typeRef - else if (arity <= Definitions.MaxTupleArity) defn.TupleType(arity) + else if (arity <= Definitions.MaxTupleArity) defn.TupleType(arity).nn else defn.TupleXXLClass.typeRef } diff --git a/compiler/src/dotty/tools/dotc/core/TypeErrors.scala b/compiler/src/dotty/tools/dotc/core/TypeErrors.scala index c9ca98f65f5e..2954ce7da916 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErrors.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErrors.scala @@ -18,8 +18,8 @@ class TypeError(msg: String) extends Exception(msg) { def this() = this("") final def toMessage(using Context): Message = withMode(Mode.Printing)(produceMessage) - def produceMessage(using Context): Message = super.getMessage - override def getMessage: String = super.getMessage + def produceMessage(using Context): Message = super.getMessage.nn + override def getMessage: String = super.getMessage.nn } class MalformedType(pre: Type, denot: Denotation, absMembers: Set[Name]) extends TypeError { @@ -78,7 +78,7 @@ class RecursionOverflow(val op: String, details: => String, val previous: Throwa } override def fillInStackTrace(): Throwable = this - override def getStackTrace(): Array[StackTraceElement] = previous.getStackTrace() + override def getStackTrace(): Array[StackTraceElement] = previous.getStackTrace().asInstanceOf } /** Post-process exceptions that might result from StackOverflow to add @@ -95,7 +95,7 @@ object handleRecursive { case _: RecursionOverflow => throw new RecursionOverflow(op, details, exc, weight) case _ => - var e = exc + var e: Throwable | Null = exc while (e != null && !e.isInstanceOf[StackOverflowError]) e = e.getCause if (e != null) throw new RecursionOverflow(op, details, e, weight) else throw exc @@ -155,7 +155,8 @@ object CyclicReference { val ex = new CyclicReference(denot) if (!(ctx.mode is Mode.CheckCyclic) || ctx.settings.Ydebug.value) { cyclicErrors.println(s"Cyclic reference involving! $denot") - for (elem <- ex.getStackTrace take 200) + val sts = ex.getStackTrace.asInstanceOf[Array[StackTraceElement]] + for (elem <- sts take 200) cyclicErrors.println(elem.toString) } ex diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index cd570b57d3b3..c13d005fa5ac 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -122,7 +122,7 @@ object TypeOps: pre.isStable || !ctx.phase.isTyper /** Implementation of Types#simplified */ - def simplify(tp: Type, theMap: SimplifyMap)(using Context): Type = { + def simplify(tp: Type, theMap: SimplifyMap | Null)(using Context): Type = { def mapOver = (if (theMap != null) theMap else new SimplifyMap).mapOver(tp) tp match { case tp: NamedType => @@ -796,7 +796,7 @@ object TypeOps: // // See tests/patmat/i3938.scala class InferPrefixMap extends TypeMap { - var prefixTVar: Type = null + var prefixTVar: Type | Null = null def apply(tp: Type): Type = tp match { case ThisType(tref: TypeRef) if !tref.symbol.isStaticOwner => if (tref.symbol.is(Module)) @@ -807,7 +807,7 @@ object TypeOps: prefixTVar = WildcardType // prevent recursive call from assigning it val tref2 = this(tref.applyIfParameterized(tref.typeParams.map(_ => TypeBounds.empty))) prefixTVar = newTypeVar(TypeBounds.upper(tref2)) - prefixTVar + prefixTVar.uncheckedNN } case tp => mapOver(tp) } diff --git a/compiler/src/dotty/tools/dotc/core/TyperState.scala b/compiler/src/dotty/tools/dotc/core/TyperState.scala index a537234208a1..3a6169b75c6b 100644 --- a/compiler/src/dotty/tools/dotc/core/TyperState.scala +++ b/compiler/src/dotty/tools/dotc/core/TyperState.scala @@ -45,7 +45,7 @@ class TyperState() { private var myId: Int = _ def id: Int = myId - private var previous: TyperState /* | Null */ = _ + private var previous: TyperState | Null = _ private var myReporter: Reporter = _ @@ -75,7 +75,7 @@ class TyperState() { this def isGlobalCommittable: Boolean = - isCommittable && (previous == null || previous.isGlobalCommittable) + isCommittable && (previous == null || previous.uncheckedNN.isGlobalCommittable) private var isCommitted: Boolean = _ @@ -92,7 +92,7 @@ class TyperState() { /** Initializes all fields except reporter, isCommittable, which need to be * set separately. */ - private[core] def init(previous: TyperState /* | Null */, constraint: Constraint): this.type = + private[core] def init(previous: TyperState | Null, constraint: Constraint): this.type = this.myId = TyperState.nextId TyperState.nextId += 1 this.previous = previous @@ -117,7 +117,7 @@ class TyperState() { * which is not yet committed, or which does not have a parent. */ def uncommittedAncestor: TyperState = - if (isCommitted) previous.uncommittedAncestor else this + if (isCommitted && previous != null) previous.uncheckedNN.uncommittedAncestor else this /** Commit typer state so that its information is copied into current typer state * In addition (1) the owning state of undetermined or temporarily instantiated @@ -179,7 +179,7 @@ class TyperState() { var ts = this while ts.constraint.domainLambdas.contains(tl) do ts.constraint = ts.constraint.subst(tl, tl1) - ts = ts.previous + ts = ts.previous.nn /** Integrate the constraints from `that` into this TyperState. * @@ -235,14 +235,14 @@ class TyperState() { * each tvar can only be instantiated by one TyperState. */ private def includeVar(tvar: TypeVar)(using Context): Unit = - val oldState = tvar.owningState.get + val oldState = tvar.owningState.nn.get assert(oldState == null || !oldState.isCommittable, i"$this attempted to take ownership of $tvar which is already owned by committable $oldState") tvar.owningState = new WeakReference(this) ownedVars += tvar private def isOwnedAnywhere(ts: TyperState, tvar: TypeVar): Boolean = - ts.ownedVars.contains(tvar) || ts.previous != null && isOwnedAnywhere(ts.previous, tvar) + ts.ownedVars.contains(tvar) || ts.previous != null && isOwnedAnywhere(ts.previous.uncheckedNN, tvar) /** Make type variable instances permanent by assigning to `inst` field if * type variable instantiation cannot be retracted anymore. Then, remove @@ -253,7 +253,8 @@ class TyperState() { Stats.record("typerState.gc") val toCollect = new mutable.ListBuffer[TypeLambda] for tvar <- ownedVars do - assert(tvar.owningState.get eq this, s"Inconsistent state in $this: it owns $tvar whose owningState is ${tvar.owningState.get}") + val tvarState = tvar.owningState.nn.get + assert(tvarState eqn this, s"Inconsistent state in $this: it owns $tvar whose owningState is ${tvarState}") assert(!tvar.inst.exists, s"Inconsistent state in $this: it owns $tvar which is already instantiated") val inst = constraint.instType(tvar) if inst.exists then @@ -266,9 +267,9 @@ class TyperState() { override def toString: String = { def ids(state: TyperState): List[String] = s"${state.id}${if (state.isCommittable) "" else "X"}" :: - (if (state.previous == null) Nil else ids(state.previous)) + (if (state.previous == null) Nil else ids(state.previous.uncheckedNN)) s"TS[${ids(this).mkString(", ")}]" } - def stateChainStr: String = s"$this${if (previous == null) "" else previous.stateChainStr}" + def stateChainStr: String = s"$this${if (previous == null) "" else previous.uncheckedNN.stateChainStr}" } diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 4fd3e6770194..4198c0a49797 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -111,7 +111,7 @@ object Types { private def testProvisional(using Context): Boolean = class ProAcc extends TypeAccumulator[Boolean]: override def apply(x: Boolean, t: Type) = x || test(t, this) - def test(t: Type, theAcc: TypeAccumulator[Boolean]): Boolean = + def test(t: Type, theAcc: TypeAccumulator[Boolean] | Null): Boolean = if t.mightBeProvisional then t.mightBeProvisional = t match case t: TypeRef => @@ -725,7 +725,8 @@ object Types { NoDenotation } def goRec(tp: RecType) = - if (tp.parent == null) NoDenotation + // TODO: change tp.parent to nullable or other values + if ((tp.parent: Type | Null) == null) NoDenotation else if (tp eq pre) go(tp.parent) else { //println(s"find member $pre . $name in $tp") @@ -2064,10 +2065,10 @@ object Types { /** Implementations of this trait cache the results of `narrow`. */ trait NarrowCached extends Type { - private var myNarrow: TermRef = null + private var myNarrow: TermRef | Null = null override def narrow(using Context): TermRef = { - if (myNarrow eq null) myNarrow = super.narrow - myNarrow + if (myNarrow == null) myNarrow = super.narrow + myNarrow.nn } } @@ -2084,9 +2085,9 @@ object Types { assert(prefix.isValueType || (prefix eq NoPrefix), s"invalid prefix $prefix") - private var myName: Name = null - private var lastDenotation: Denotation = null - private var lastSymbol: Symbol = null + private var myName: Name | Null = null + private var lastDenotation: Denotation | Null = null + private var lastSymbol: Symbol | Null = null private var checkedPeriod: Period = Nowhere private var myStableHash: Byte = 0 private var mySignature: Signature = _ @@ -2157,21 +2158,21 @@ object Types { final def symbol(using Context): Symbol = // We can rely on checkedPeriod (unlike in the definition of `denot` below) // because SymDenotation#installAfter never changes the symbol - if (checkedPeriod == ctx.period) lastSymbol else computeSymbol + if (checkedPeriod == ctx.period) lastSymbol.nn else computeSymbol private def computeSymbol(using Context): Symbol = designator match { case sym: Symbol => if (sym.isValidInCurrentRun) sym else denot.symbol case name => - (if (denotationIsCurrent) lastDenotation else denot).symbol + (if (denotationIsCurrent) lastDenotation.nn else denot).symbol } /** There is a denotation computed which is valid (somewhere in) the * current run. */ def denotationIsCurrent(using Context): Boolean = - lastDenotation != null && lastDenotation.validFor.runId == ctx.runId + lastDenotation != null && lastDenotation.uncheckedNN.validFor.runId == ctx.runId /** If the reference is symbolic or the denotation is current, its symbol, otherwise NoDenotation. * @@ -2184,7 +2185,7 @@ object Types { */ final def currentSymbol(using Context): Symbol = designator match { case sym: Symbol => sym - case _ => if (denotationIsCurrent) lastDenotation.symbol else NoSymbol + case _ => if (denotationIsCurrent) lastDenotation.nn.symbol else NoSymbol } /** Retrieves currently valid symbol without necessarily updating denotation. @@ -2192,7 +2193,7 @@ object Types { * Used to get the class underlying a ThisType. */ private[Types] def stableInRunSymbol(using Context): Symbol = - if (checkedPeriod.runId == ctx.runId) lastSymbol + if (checkedPeriod.runId == ctx.runId) lastSymbol.nn else symbol def info(using Context): Type = denot.info @@ -2203,9 +2204,9 @@ object Types { val now = ctx.period // Even if checkedPeriod == now we still need to recheck lastDenotation.validFor // as it may have been mutated by SymDenotation#installAfter - if (checkedPeriod != Nowhere && lastDenotation.validFor.contains(now)) { + if (checkedPeriod != Nowhere && lastDenotation.nn.validFor.contains(now)) { checkedPeriod = now - lastDenotation + lastDenotation.nn } else computeDenot } @@ -2259,7 +2260,7 @@ object Types { private def disambiguate(d: Denotation)(using Context): Denotation = disambiguate(d, currentSignature, currentSymbol.targetName) - private def disambiguate(d: Denotation, sig: Signature, target: Name)(using Context): Denotation = + private def disambiguate(d: Denotation, sig: Signature | Null, target: Name)(using Context): Denotation = if (sig != null) d.atSignature(sig, target, relaxed = !ctx.erasedTypes) match { case d1: SingleDenotation => d1 @@ -2340,7 +2341,7 @@ object Types { lastSymbol = denot.symbol checkedPeriod = if (prefix.isProvisional) Nowhere else ctx.period designator match { - case sym: Symbol if designator ne lastSymbol => + case sym: Symbol if designator ne lastSymbol.nn => designator = lastSymbol.asInstanceOf[Designator{ type ThisName = self.ThisName }] case _ => } @@ -2352,34 +2353,39 @@ object Types { private def checkSymAssign(sym: Symbol)(using Context) = { def selfTypeOf(sym: Symbol) = if (sym.isClass) sym.asClass.givenSelfType else NoType + val lastSym = lastSymbol assert( - (lastSymbol eq sym) + (lastSym == null) || - (lastSymbol eq null) + (lastSym eq sym) || !denotationIsCurrent || - lastSymbol.infoOrCompleter.isInstanceOf[ErrorType] + lastSym.infoOrCompleter.isInstanceOf[ErrorType] || !sym.exists || - !lastSymbol.exists + !lastSym.exists || sym.isPackageObject // package objects can be visited before we get around to index them || - sym.owner != lastSymbol.owner && - (sym.owner.derivesFrom(lastSymbol.owner) + sym.owner != lastSym.owner && + (sym.owner.derivesFrom(lastSym.owner) || - selfTypeOf(sym).derivesFrom(lastSymbol.owner) + selfTypeOf(sym).derivesFrom(lastSym.owner) || - selfTypeOf(lastSymbol).derivesFrom(sym.owner) + selfTypeOf(lastSym).derivesFrom(sym.owner) ) || - sym == defn.AnyClass.primaryConstructor, - s"""data race? overwriting $lastSymbol with $sym in type $this, - |last sym id = ${lastSymbol.id}, new sym id = ${sym.id}, - |last owner = ${lastSymbol.owner}, new owner = ${sym.owner}, - |period = ${ctx.phase} at run ${ctx.runId}""") + sym == defn.AnyClass.primaryConstructor, { + if lastSym == null then + s"""data race? overwriting $lastSym with $sym in type $this, + |period = ${ctx.phase} at run ${ctx.runId}""" + else + s"""data race? overwriting $lastSym with $sym in type $this, + |last sym id = ${lastSym.id}, new sym id = ${sym.id}, + |last owner = ${lastSym.owner}, new owner = ${sym.owner}, + |period = ${ctx.phase} at run ${ctx.runId}""" }) } /** A reference with the initial symbol in `symd` has an info that @@ -2565,13 +2571,14 @@ object Types { /** A reference like this one, but with the given prefix. */ final def withPrefix(prefix: Type)(using Context): NamedType = { def reload(): NamedType = { - val allowPrivate = !lastSymbol.exists || lastSymbol.is(Private) + val lastSym = lastSymbol.nn + val allowPrivate = !lastSym.exists || lastSym.is(Private) var d = memberDenot(prefix, name, allowPrivate) - if (d.isOverloaded && lastSymbol.exists) + if (d.isOverloaded && lastSym.exists) d = disambiguate(d, - if (lastSymbol.signature == Signature.NotAMethod) Signature.NotAMethod - else lastSymbol.asSeenFrom(prefix).signature, - lastSymbol.targetName) + if (lastSym.signature == Signature.NotAMethod) Signature.NotAMethod + else lastSym.asSeenFrom(prefix).signature, + lastSym.targetName) NamedType(prefix, name, d) } if (prefix eq this.prefix) this @@ -2864,8 +2871,9 @@ object Types { } } - case class LazyRef(private var refFn: Context => Type) extends UncachedProxyType with ValueType { - private var myRef: Type = null + // `refFn` can be null only if `computed` is true. + case class LazyRef(private var refFn: (Context => (Type | Null)) | Null) extends UncachedProxyType with ValueType { + private var myRef: Type | Null = null private var computed = false override def tryNormalize(using Context): Type = ref.tryNormalize @@ -2881,11 +2889,11 @@ object Types { throw CyclicReference(NoDenotation) else computed = true - val result = refFn(ctx) + val result = refFn.nn(ctx) refFn = null if result != null then myRef = result else assert(myRef != null) // must have been `update`d - myRef + myRef.nn /** Update the value of the lazyref, discarding the compute function `refFn` * Can be called only as long as the ref is still undefined. @@ -2904,7 +2912,7 @@ object Types { override def hashCode: Int = System.identityHashCode(this) } object LazyRef: - def of(refFn: Context ?=> Type): LazyRef = LazyRef(refFn(using _)) + def of(refFn: Context ?=> (Type | Null)): LazyRef = LazyRef(refFn(using _)) // --- Refined Type and RecType ------------------------------------------------ @@ -3008,11 +3016,11 @@ object Types { val parent: Type = parentExp(this) - private var myRecThis: RecThis = null + private var myRecThis: RecThis | Null = null def recThis: RecThis = { if (myRecThis == null) myRecThis = new RecThisImpl(this) - myRecThis + myRecThis.nn } override def underlying(using Context): Type = parent @@ -3039,7 +3047,7 @@ object Types { refacc.apply(false, tp) } - override def computeHash(bs: Binders): Int = doHash(new Binders(this, bs), parent) + override def computeHash(bs: Binders): Int = doHash(new SomeBinders(this, bs), parent) override def hashIsStable: Boolean = false // this is a conservative observation. By construction RecTypes contain at least @@ -3052,7 +3060,7 @@ object Types { override def iso(that: Any, bs: BinderPairs): Boolean = that match { case that: RecType => - parent.equals(that.parent, new BinderPairs(this, that, bs)) + parent.equals(that.parent, new SomeBinderPairs(this, that, bs)) case _ => false } @@ -3425,7 +3433,7 @@ object Types { final def isTypeLambda: Boolean = isInstanceOf[TypeLambda] final def isHigherKinded: Boolean = isInstanceOf[TypeProxy] - private var myParamRefs: List[ParamRefType] = null + private var myParamRefs: List[ParamRefType] | Null = null def paramRefs: List[ParamRefType] = { if myParamRefs == null then @@ -3434,7 +3442,7 @@ object Types { case _ :: rest => newParamRef(i) :: recur(rest, i + 1) case _ => Nil myParamRefs = recur(paramNames, 0) - myParamRefs + myParamRefs.nn } /** Like `paramInfos` but substitute parameter references with the given arguments */ @@ -3562,7 +3570,7 @@ object Types { case that: MethodOrPoly => paramNames.eqElements(that.paramNames) && companion.eq(that.companion) && { - val bs1 = new BinderPairs(this, that, bs) + val bs1 = new SomeBinderPairs(this, that, bs) paramInfos.equalElements(that.paramInfos, bs1) && resType.equals(that.resType, bs1) } @@ -3605,7 +3613,7 @@ object Types { val status = (x & StatusMask) max (y & StatusMask) val provisional = (x | y) & Provisional (if status == TrueDeps then status else status | provisional).toByte - def compute(status: DependencyStatus, tp: Type, theAcc: TypeAccumulator[DependencyStatus]): DependencyStatus = + def compute(status: DependencyStatus, tp: Type, theAcc: TypeAccumulator[DependencyStatus] | Null): DependencyStatus = def applyPrefix(tp: NamedType) = if tp.currentSymbol.isStatic then status else compute(status, tp.prefix, theAcc) @@ -3887,7 +3895,7 @@ object Types { else Nil override def computeHash(bs: Binders): Int = - doHash(new Binders(this, bs), declaredVariances ::: paramNames, resType, paramInfos) + doHash(new SomeBinders(this, bs), declaredVariances ::: paramNames, resType, paramInfos) // No definition of `eql` --> fall back on equals, which calls iso @@ -3899,9 +3907,9 @@ object Types { || typeParams.corresponds(that.typeParams)((x, y) => x.declaredVariance == y.declaredVariance)) && { - val bs1 = new BinderPairs(this, that, bs) + val bs1 = new SomeBinderPairs(this, that, bs) // `paramInfos` and `resType` might still be uninstantiated at this point - paramInfos != null && resType != null && + (paramInfos: List[TypeBounds] | Null) != null && (resType: Type | Null) != null && paramInfos.equalElements(that.paramInfos, bs1) && resType.equals(that.resType, bs1) } @@ -4282,7 +4290,7 @@ object Types { op } catch { case e: Throwable => - throw new TypeError(e.getMessage) + throw new TypeError(e.getMessage.nn) } ConstantType(Constant(result)) @@ -4503,7 +4511,8 @@ object Types { def paramName: binder.ThisName = binder.paramNames(paramNum) override def underlying(using Context): Type = { - val infos = binder.paramInfos + // TODO: update paramInfos's type to nullable + val infos: List[Type] | Null = binder.paramInfos if (infos == null) NoType // this can happen if the referenced generic type is not initialized yet else infos(paramNum) } @@ -4615,10 +4624,10 @@ object Types { //val id = skid //assert(id != 10) - private var myRepr: Name = null + private var myRepr: Name | Null = null def repr(using Context): Name = { if (myRepr == null) myRepr = SkolemName.fresh() - myRepr + myRepr.nn } override def toString: String = s"Skolem($hashCode)" @@ -4664,7 +4673,7 @@ object Types { * - On instantiation, replacing any param in the param bound * with a level greater than nestingLevel (see `fullLowerBound`). */ - final class TypeVar private(initOrigin: TypeParamRef, creatorState: TyperState, val nestingLevel: Int) extends CachedProxyType with ValueType { + final class TypeVar private(initOrigin: TypeParamRef, creatorState: TyperState | Null, val nestingLevel: Int) extends CachedProxyType with ValueType { private var currentOrigin = initOrigin def origin: TypeParamRef = currentOrigin @@ -4681,7 +4690,7 @@ object Types { private[core] def setInst(tp: Type): Unit = myInst = tp if tp.exists && owningState != null then - val owningState1 = owningState.get + val owningState1 = owningState.uncheckedNN.get if owningState1 != null then owningState1.ownedVars -= this owningState = null // no longer needed; null out to avoid a memory leak @@ -4693,7 +4702,7 @@ object Types { /** The state owning the variable. This is at first `creatorState`, but it can * be changed to an enclosing state on a commit. */ - private[core] var owningState: WeakReference[TyperState] = + private[core] var owningState: WeakReference[TyperState] | Null = if (creatorState == null) null else new WeakReference(creatorState) /** The instance type of this variable, or NoType if the variable is currently @@ -4715,7 +4724,7 @@ object Types { assert(currentEntry.bounds.contains(tp), i"$origin is constrained to be $currentEntry but attempted to instantiate it to $tp") - if ((ctx.typerState eq owningState.get) && !TypeComparer.subtypeCheckInProgress) + if ((ctx.typerState eq owningState.nn.get.uncheckedNN) && !TypeComparer.subtypeCheckInProgress) setInst(tp) ctx.typerState.constraint = ctx.typerState.constraint.replace(origin, tp) tp @@ -4771,7 +4780,7 @@ object Types { } } object TypeVar: - def apply(using Context)(initOrigin: TypeParamRef, creatorState: TyperState, nestingLevel: Int = ctx.nestingLevel) = + def apply(using Context)(initOrigin: TypeParamRef, creatorState: TyperState | Null, nestingLevel: Int = ctx.nestingLevel) = new TypeVar(initOrigin, creatorState, nestingLevel) type TypeVars = SimpleIdentitySet[TypeVar] @@ -4799,8 +4808,8 @@ object Types { def alternatives(using Context): List[Type] = cases.map(caseType) def underlying(using Context): Type = bound - private var myReduced: Type = null - private var reductionContext: util.MutableMap[Type, Type] = null + private var myReduced: Type | Null = null + private var reductionContext: util.MutableMap[Type, Type] = _ override def tryNormalize(using Context): Type = try @@ -4857,7 +4866,7 @@ object Types { TypeComparer.tracked(matchCases) } - myReduced + myReduced.nn } override def computeHash(bs: Binders): Int = doHash(bs, scrutinee, bound :: cases) @@ -4899,8 +4908,8 @@ object Types { decls: Scope, selfInfo: TypeOrSymbol) extends CachedGroundType with TypeType { - private var selfTypeCache: Type = null - private var appliedRefCache: Type = null + private var selfTypeCache: Type | Null = null + private var appliedRefCache: Type | Null = null /** The self type of a class is the conjunction of * - the explicit self type if given (or the info of a given self symbol), and @@ -4916,23 +4925,23 @@ object Types { else if (ctx.erasedTypes) appliedRef else AndType(givenSelf, appliedRef) } - selfTypeCache + selfTypeCache.nn } def appliedRef(using Context): Type = { if (appliedRefCache == null) appliedRefCache = TypeRef(prefix, cls).appliedTo(cls.classDenot.typeParams.map(_.typeRef)) - appliedRefCache + appliedRefCache.nn } // cached because baseType needs parents - private var parentsCache: List[Type] = null + private var parentsCache: List[Type] | Null = null override def parents(using Context): List[Type] = { if (parentsCache == null) parentsCache = declaredParents.mapConserve(_.asSeenFrom(prefix, cls.owner)) - parentsCache + parentsCache.nn } protected def newLikeThis(prefix: Type, declaredParents: List[Type], decls: Scope, selfInfo: TypeOrSymbol)(using Context): ClassInfo = @@ -4979,7 +4988,7 @@ object Types { else cinfo } - override def computeHash(bs: Binders): Int = doHash(bs, cls, prefix) + override def computeHash(bs: Binders | Null): Int = doHash(bs, cls, prefix) override def hashIsStable: Boolean = prefix.hashIsStable && declaredParents.hashIsStable override def eql(that: Type): Boolean = that match { diff --git a/compiler/src/dotty/tools/dotc/core/Uniques.scala b/compiler/src/dotty/tools/dotc/core/Uniques.scala index d706875f58dd..4078a2b1051a 100644 --- a/compiler/src/dotty/tools/dotc/core/Uniques.scala +++ b/compiler/src/dotty/tools/dotc/core/Uniques.scala @@ -52,7 +52,7 @@ object Uniques: val oldHead = table(bucket) @tailrec - def linkedListLoop(entry: Entry[NamedType]): NamedType = entry match + def linkedListLoop(entry: Entry[NamedType] | Null): NamedType = entry match case null => addEntryAt(bucket, newType, h, oldHead) case _ => val e = entry.get @@ -79,7 +79,7 @@ object Uniques: val oldHead = table(bucket) @tailrec - def linkedListLoop(entry: Entry[AppliedType]): AppliedType = entry match + def linkedListLoop(entry: Entry[AppliedType] | Null): AppliedType = entry match case null => addEntryAt(bucket, newType, h, oldHead) case _ => val e = entry.get diff --git a/compiler/src/dotty/tools/dotc/core/classfile/AbstractFileReader.scala b/compiler/src/dotty/tools/dotc/core/classfile/AbstractFileReader.scala index d4f781e22126..46581d00714e 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/AbstractFileReader.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/AbstractFileReader.scala @@ -3,6 +3,8 @@ package dotc package core package classfile +import scala.language.unsafeNulls + import java.lang.Float.intBitsToFloat import java.lang.Double.longBitsToDouble import java.io.{ByteArrayInputStream, DataInputStream} diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index c96141a73676..48ba560360dd 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -3,6 +3,8 @@ package dotc package core package classfile +import scala.language.unsafeNulls + import dotty.tools.tasty.{ TastyReader, TastyHeaderUnpickler } import Contexts._, Symbols._, Types._, Names._, StdNames._, NameOps._, Scopes._, Decorators._ diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ReusableDataReader.scala b/compiler/src/dotty/tools/dotc/core/classfile/ReusableDataReader.scala index c9a04c392242..eb1649091f77 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ReusableDataReader.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ReusableDataReader.scala @@ -3,6 +3,8 @@ package dotc package core package classfile +import scala.language.unsafeNulls + import java.io.{DataInputStream, InputStream} import java.nio.{BufferUnderflowException, ByteBuffer} diff --git a/compiler/src/dotty/tools/dotc/core/tasty/CommentPickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/CommentPickler.scala index 2fd75516ad70..df3e4df497f8 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/CommentPickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/CommentPickler.scala @@ -17,7 +17,7 @@ class CommentPickler(pickler: TastyPickler, addrOfTree: tpd.Tree => Addr, docStr private def pickleComment(addr: Addr, comment: Comment): Unit = if addr != NoAddr then - val bytes = comment.raw.getBytes(StandardCharsets.UTF_8) + val bytes = comment.raw.getBytes(StandardCharsets.UTF_8).nn val length = bytes.length buf.writeAddr(addr) buf.writeNat(length) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/CommentUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/CommentUnpickler.scala index d59b1e581b49..eb0d140df51e 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/CommentUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/CommentUnpickler.scala @@ -1,6 +1,8 @@ package dotty.tools.dotc package core.tasty +import scala.language.unsafeNulls + import core.Comments.Comment import util.Spans.Span import util.HashMap diff --git a/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala index 7396adf76991..f80f9688073e 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala @@ -3,6 +3,8 @@ package dotc package core package tasty +import scala.language.unsafeNulls + import Contexts._, SymDenotations._, Decorators._ import dotty.tools.dotc.ast.tpd import TastyUnpickler._ diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyPickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyPickler.scala index f4654022f38c..1c77d84af3af 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyPickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyPickler.scala @@ -3,6 +3,8 @@ package dotc package core package tasty +import scala.language.unsafeNulls + import dotty.tools.tasty.{TastyBuffer, TastyFormat, TastyHash} import TastyFormat._ import TastyBuffer._ diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala index f8c93c27c086..f2650ee714ab 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala @@ -39,7 +39,7 @@ object TastyPrinter: else if arg.startsWith("-") then println(s"bad option '$arg' was ignored") else if arg.endsWith(".tasty") then { val path = Paths.get(arg) - if Files.exists(path) then printTasty(arg, Files.readAllBytes(path)) + if Files.exists(path) then printTasty(arg, Files.readAllBytes(path).nn) else println("File not found: " + arg) } else if arg.endsWith(".jar") then { diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala index 1a7e1d50c981..7752df9c3dd7 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala @@ -2,6 +2,8 @@ package dotty.tools.dotc package core package tasty +import scala.language.unsafeNulls + import dotty.tools.tasty.{TastyFormat, TastyBuffer, TastyReader, TastyHeaderUnpickler} import TastyFormat.NameTags._, TastyFormat.nameTagToString import TastyBuffer.NameRef diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index c8bffbc17252..dd2cc46c406d 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -3,6 +3,8 @@ package dotc package core package tasty +import scala.language.unsafeNulls + import dotty.tools.tasty.TastyFormat._ import dotty.tools.tasty.TastyBuffer._ diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 475e8dccd997..06dc4872c7f3 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -3,6 +3,8 @@ package dotc package core package tasty +import scala.language.unsafeNulls + import Comments.CommentsContext import Contexts._ import Symbols._ diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index b5b8c4715ebc..dbd3e15dcc2d 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -3,6 +3,8 @@ package dotc package core package unpickleScala2 +import scala.language.unsafeNulls + import java.io.IOException import java.lang.Float.intBitsToFloat import java.lang.Double.longBitsToDouble @@ -511,7 +513,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas // can also show up before initialization, if that's the case // we'll need to study more closely how Scala 2 handles type // parameter unpickling and try to emulate it. - !completer.isInitialized + !completer.areParamsInitialized case _ => true) @@ -660,11 +662,11 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas atReadPos(index(infoRef), () => readTypeParams()(using ctx)) /** Have the type params of this class already been unpickled? */ - def isInitialized: Boolean = myTypeParams ne null + def areParamsInitialized: Boolean = myTypeParams ne null /** Force reading type params early, we need them in setClassInfo of subclasses. */ def init()(using Context): List[TypeSymbol] = - if !isInitialized then loadTypeParams() + if !areParamsInitialized then loadTypeParams() myTypeParams override def completerTypeParams(sym: Symbol)(using Context): List[TypeSymbol] = diff --git a/compiler/src/dotty/tools/dotc/decompiler/DecompilationPrinter.scala b/compiler/src/dotty/tools/dotc/decompiler/DecompilationPrinter.scala index c66a16dbb7b5..85a56b9f1d15 100644 --- a/compiler/src/dotty/tools/dotc/decompiler/DecompilationPrinter.scala +++ b/compiler/src/dotty/tools/dotc/decompiler/DecompilationPrinter.scala @@ -1,6 +1,8 @@ package dotty.tools.dotc package decompiler +import scala.language.unsafeNulls + import java.io.{OutputStream, PrintStream} import java.nio.charset.StandardCharsets diff --git a/compiler/src/dotty/tools/dotc/decompiler/IDEDecompilerDriver.scala b/compiler/src/dotty/tools/dotc/decompiler/IDEDecompilerDriver.scala index 2e3c67150d11..c148ff5f9bca 100644 --- a/compiler/src/dotty/tools/dotc/decompiler/IDEDecompilerDriver.scala +++ b/compiler/src/dotty/tools/dotc/decompiler/IDEDecompilerDriver.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package decompiler +import scala.language.unsafeNulls + import dotty.tools.dotc.core.Contexts._ import dotty.tools.dotc.core._ import dotty.tools.dotc.core.tasty.TastyHTMLPrinter @@ -35,7 +37,7 @@ class IDEDecompilerDriver(val settings: List[String]) extends dotc.Driver { inContext(run.runContext) { run.compile(List(tastyFile)) run.printSummary() - val unit = ctx.run.units.head + val unit = ctx.run.nn.units.head val decompiled = QuotesImpl.showDecompiledTree(unit.tpdTree) val tree = new TastyHTMLPrinter(unit.pickled.head._2()).showContents() diff --git a/compiler/src/dotty/tools/dotc/fromtasty/Debug.scala b/compiler/src/dotty/tools/dotc/fromtasty/Debug.scala index c5102acaff3b..979fae239e59 100644 --- a/compiler/src/dotty/tools/dotc/fromtasty/Debug.scala +++ b/compiler/src/dotty/tools/dotc/fromtasty/Debug.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package fromtasty +import scala.language.unsafeNulls + import scala.util.control.NonFatal import dotty.tools.io.Directory diff --git a/compiler/src/dotty/tools/dotc/fromtasty/TASTYRun.scala b/compiler/src/dotty/tools/dotc/fromtasty/TASTYRun.scala index 1c8ba2359623..04c65a3d3882 100644 --- a/compiler/src/dotty/tools/dotc/fromtasty/TASTYRun.scala +++ b/compiler/src/dotty/tools/dotc/fromtasty/TASTYRun.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package fromtasty +import scala.language.unsafeNulls + import io.{JarArchive, AbstractFile, Path} import core.Contexts._ import java.io.File diff --git a/compiler/src/dotty/tools/dotc/fromtasty/TastyFileUtil.scala b/compiler/src/dotty/tools/dotc/fromtasty/TastyFileUtil.scala index fa926371f562..bc04cc648a65 100644 --- a/compiler/src/dotty/tools/dotc/fromtasty/TastyFileUtil.scala +++ b/compiler/src/dotty/tools/dotc/fromtasty/TastyFileUtil.scala @@ -1,6 +1,8 @@ package dotty.tools.dotc package fromtasty +import scala.language.unsafeNulls + import dotty.tools.dotc.core.tasty.TastyClassName import dotty.tools.dotc.core.StdNames.nme.EMPTY_PACKAGE import dotty.tools.io.AbstractFile diff --git a/compiler/src/dotty/tools/dotc/interactive/Completion.scala b/compiler/src/dotty/tools/dotc/interactive/Completion.scala index 1192bead245c..81860862040c 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Completion.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Completion.scala @@ -1,5 +1,6 @@ package dotty.tools.dotc.interactive +import scala.language.unsafeNulls import dotty.tools.dotc.ast.untpd import dotty.tools.dotc.config.Printers.interactiv @@ -10,6 +11,7 @@ import dotty.tools.dotc.core.Flags._ import dotty.tools.dotc.core.Names.{Name, TermName} import dotty.tools.dotc.core.NameKinds.SimpleNameKind import dotty.tools.dotc.core.NameOps._ +import dotty.tools.dotc.core.Scopes._ import dotty.tools.dotc.core.Symbols.{Symbol, defn} import dotty.tools.dotc.core.StdNames.nme import dotty.tools.dotc.core.SymDenotations.SymDenotation @@ -184,7 +186,7 @@ object Completion { .groupByName.foreach { (name, denots) => addMapping(name, ScopedDenotations(denots, ctx)) } - else if ctx.scope != null then + else if ctx.scope ne EmptyScope then ctx.scope.toList.filter(symbol => include(symbol, symbol.name)) .flatMap(_.alternatives) .groupByName.foreach { (name, denots) => @@ -351,7 +353,7 @@ object Completion { val extMethodsFromGivensInScope = extractMemberExtensionMethods(givensInScope) // 3. The reference is of the form r.m and the extension method is defined in the implicit scope of the type of r. - val implicitScopeCompanions = ctx.run.implicitScope(qual.tpe).companionRefs.showAsList + val implicitScopeCompanions = ctx.run.nn.implicitScope(qual.tpe).companionRefs.showAsList val extMethodsFromImplicitScope = extractMemberExtensionMethods(implicitScopeCompanions) // 4. The reference is of the form r.m and the extension method is defined in some given instance in the implicit scope of the type of r. diff --git a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala index 219d9f5384ba..8ee950707296 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package interactive +import scala.language.unsafeNulls + import scala.collection._ import ast.{NavigateAST, Trees, tpd, untpd} diff --git a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala index e17866130e3d..a0f8231b7b36 100644 --- a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala +++ b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package interactive +import scala.language.unsafeNulls + import java.net.URI import java.io._ import java.nio.file._ @@ -162,7 +164,8 @@ class InteractiveDriver(val settings: List[String]) extends Driver { run.compileSources(List(source)) run.printSummary() - val unit = if ctx.run.units.nonEmpty then ctx.run.units.head else ctx.run.suspendedUnits.head + val ctxRun = ctx.run.nn + val unit = if ctxRun.units.nonEmpty then ctxRun.units.head else ctxRun.suspendedUnits.head val t = unit.tpdTree cleanup(t) myOpenedTrees(uri) = topLevelTrees(t, source) diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaScanners.scala b/compiler/src/dotty/tools/dotc/parsing/JavaScanners.scala index 3c3a601e0e1b..d7178bd411e7 100644 --- a/compiler/src/dotty/tools/dotc/parsing/JavaScanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/JavaScanners.scala @@ -518,7 +518,7 @@ object JavaScanners { val limit: Double = if (token == DOUBLELIT) Double.MaxValue else Float.MaxValue try { - val value: Double = java.lang.Double.valueOf(strVal.toString).doubleValue() + val value: Double = java.lang.Double.valueOf(strVal.toString).nn.doubleValue() if (value > limit) error("floating point number too large") if (negated) -value else value diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 0c3df1b1957a..5d3e97159c17 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package parsing +import scala.language.unsafeNulls + import scala.annotation.internal.sharable import scala.collection.mutable.ListBuffer import scala.collection.immutable.BitSet diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index fa9aa67e8088..f36176083792 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package parsing +import scala.language.unsafeNulls + import core.Names._, core.Contexts._, core.Decorators._, util.Spans._ import core.StdNames._, core.Comments._ import util.SourceFile diff --git a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala index 55f428cef5a4..46bb43170bde 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package parsing +import scala.language.unsafeNulls + import collection.immutable.BitSet import core.Decorators._ import core.StdNames.nme diff --git a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala index 72e507722b2e..591042961dbb 100644 --- a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala @@ -3,6 +3,8 @@ package dotc package parsing package xml +import scala.language.unsafeNulls + import scala.collection.mutable import mutable.{ Buffer, ArrayBuffer, ListBuffer } import scala.util.control.ControlThrowable diff --git a/compiler/src/dotty/tools/dotc/parsing/xml/SymbolicXMLBuilder.scala b/compiler/src/dotty/tools/dotc/parsing/xml/SymbolicXMLBuilder.scala index 1dc4505cf9fc..0e70cc077fa4 100644 --- a/compiler/src/dotty/tools/dotc/parsing/xml/SymbolicXMLBuilder.scala +++ b/compiler/src/dotty/tools/dotc/parsing/xml/SymbolicXMLBuilder.scala @@ -3,6 +3,8 @@ package dotc package parsing package xml +import scala.language.unsafeNulls + import scala.collection.mutable import core._ import Decorators._ diff --git a/compiler/src/dotty/tools/dotc/parsing/xml/Utility.scala b/compiler/src/dotty/tools/dotc/parsing/xml/Utility.scala index 50cee13c9e1a..87412cf6d69c 100644 --- a/compiler/src/dotty/tools/dotc/parsing/xml/Utility.scala +++ b/compiler/src/dotty/tools/dotc/parsing/xml/Utility.scala @@ -2,8 +2,9 @@ package dotty.tools.dotc package parsing package xml -import scala.collection.mutable +import scala.language.unsafeNulls +import scala.collection.mutable /** * The `Utility` object provides utility functions for processing instances diff --git a/compiler/src/dotty/tools/dotc/plugins/Plugin.scala b/compiler/src/dotty/tools/dotc/plugins/Plugin.scala index f7391a1b711b..21bb0fa2be54 100644 --- a/compiler/src/dotty/tools/dotc/plugins/Plugin.scala +++ b/compiler/src/dotty/tools/dotc/plugins/Plugin.scala @@ -1,6 +1,8 @@ package dotty.tools.dotc package plugins +import scala.language.unsafeNulls + import core._ import Contexts._ import Phases._ diff --git a/compiler/src/dotty/tools/dotc/plugins/Plugins.scala b/compiler/src/dotty/tools/dotc/plugins/Plugins.scala index 14cb83fb6c6c..85acc22ecdef 100644 --- a/compiler/src/dotty/tools/dotc/plugins/Plugins.scala +++ b/compiler/src/dotty/tools/dotc/plugins/Plugins.scala @@ -1,6 +1,8 @@ package dotty.tools.dotc package plugins +import scala.language.unsafeNulls + import core._ import Contexts._ import config.{ PathResolver, Feature } @@ -34,8 +36,8 @@ trait Plugins { // Explicit parameterization of recover to avoid -Xlint warning about inferred Any errors foreach (_.recover[Any] { // legacy behavior ignores altogether, so at least warn devs - case e: MissingPluginException => report.warning(e.getMessage) - case e: Exception => report.inform(e.getMessage) + case e: MissingPluginException => report.warning(e.getMessage.nn) + case e: Exception => report.inform(e.getMessage.nn) }) goods map (_.get) diff --git a/compiler/src/dotty/tools/dotc/printing/Formatting.scala b/compiler/src/dotty/tools/dotc/printing/Formatting.scala index 845283f69a0f..50e18d5587b9 100644 --- a/compiler/src/dotty/tools/dotc/printing/Formatting.scala +++ b/compiler/src/dotty/tools/dotc/printing/Formatting.scala @@ -1,6 +1,8 @@ package dotty.tools.dotc package printing +import scala.language.unsafeNulls + import core._ import Texts._, Types._, Flags._, Symbols._, Contexts._ import collection.mutable diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 157b424b6251..1d516cdd40a4 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -319,7 +319,7 @@ class PlainPrinter(_ctx: Context) extends Printer { case tp: ThisType => nameString(tp.cls) + ".this" case SuperType(thistpe: SingletonType, _) => - toTextRef(thistpe).map(_.replaceAll("""\bthis$""", "super")) + toTextRef(thistpe).map(_.replaceAll("""\bthis$""", "super").nn) case SuperType(thistpe, _) => "Super(" ~ toTextGlobal(thistpe) ~ ")" case tp @ ConstantType(value) => @@ -542,7 +542,7 @@ class PlainPrinter(_ctx: Context) extends Printer { case '"' => "\\\"" case '\'' => "\\\'" case '\\' => "\\\\" - case _ => if ch.isControl then f"${"\\"}u${ch.toInt}%04x" else String.valueOf(ch) + case _ => if ch.isControl then f"${"\\"}u${ch.toInt}%04x" else String.valueOf(ch).nn } def toText(const: Constant): Text = const.tag match { @@ -552,7 +552,7 @@ class PlainPrinter(_ctx: Context) extends Printer { case LongTag => literalText(const.longValue.toString + "L") case DoubleTag => literalText(const.doubleValue.toString + "d") case FloatTag => literalText(const.floatValue.toString + "f") - case _ => literalText(String.valueOf(const.value)) + case _ => literalText(String.valueOf(const.value).nn) } /** Usual target for `Annotation#toText`, overridden in RefinedPrinter */ diff --git a/compiler/src/dotty/tools/dotc/printing/Showable.scala b/compiler/src/dotty/tools/dotc/printing/Showable.scala index 7b9496f7586f..4a0e68861a1a 100644 --- a/compiler/src/dotty/tools/dotc/printing/Showable.scala +++ b/compiler/src/dotty/tools/dotc/printing/Showable.scala @@ -25,7 +25,7 @@ trait Showable extends Any { /** The string representation with each line after the first one indented * by the given given margin (in spaces). */ - def showIndented(margin: Int)(using Context): String = show.replace("\n", "\n" + " " * margin) + def showIndented(margin: Int)(using Context): String = show.replace("\n", "\n" + " " * margin).nn /** The summarized string representation of this showable element. * Recursion depth is limited to some smallish value. Default is diff --git a/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala b/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala index 787caf81cd07..f2ac42c773eb 100644 --- a/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala +++ b/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala @@ -1,6 +1,8 @@ package dotty.tools.dotc package printing +import scala.language.unsafeNulls + import dotty.tools.dotc.ast.untpd import dotty.tools.dotc.core.Contexts._ import dotty.tools.dotc.core.StdNames._ diff --git a/compiler/src/dotty/tools/dotc/printing/Texts.scala b/compiler/src/dotty/tools/dotc/printing/Texts.scala index 0cab82a76a6d..17f86e766869 100644 --- a/compiler/src/dotty/tools/dotc/printing/Texts.scala +++ b/compiler/src/dotty/tools/dotc/printing/Texts.scala @@ -65,7 +65,7 @@ object Texts { else appendIndented(that)(width) private def lengthWithoutAnsi(str: String): Int = - str.replaceAll("\u001b\\[\\d+m", "").length + str.replaceAll("\u001b\\[\\d+m", "").nn.length def layout(width: Int): Text = this match { case Str(s, _) => diff --git a/compiler/src/dotty/tools/dotc/profile/AsyncHelper.scala b/compiler/src/dotty/tools/dotc/profile/AsyncHelper.scala index 977dd596f031..61bee4d9f32a 100644 --- a/compiler/src/dotty/tools/dotc/profile/AsyncHelper.scala +++ b/compiler/src/dotty/tools/dotc/profile/AsyncHelper.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.profile +import scala.language.unsafeNulls + import java.util.concurrent.ThreadPoolExecutor.AbortPolicy import java.util.concurrent._ import java.util.concurrent.atomic.AtomicInteger diff --git a/compiler/src/dotty/tools/dotc/profile/Profiler.scala b/compiler/src/dotty/tools/dotc/profile/Profiler.scala index 0a4c3dd4d691..ae86713a378c 100644 --- a/compiler/src/dotty/tools/dotc/profile/Profiler.scala +++ b/compiler/src/dotty/tools/dotc/profile/Profiler.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.profile +import scala.language.unsafeNulls + import java.io.{FileWriter, PrintWriter} import java.lang.management.{ManagementFactory, GarbageCollectorMXBean, RuntimeMXBean, MemoryMXBean, ClassLoadingMXBean, CompilationMXBean} import java.util.concurrent.TimeUnit diff --git a/compiler/src/dotty/tools/dotc/quoted/TastyString.scala b/compiler/src/dotty/tools/dotc/quoted/TastyString.scala index 528414654969..369e646e883e 100644 --- a/compiler/src/dotty/tools/dotc/quoted/TastyString.scala +++ b/compiler/src/dotty/tools/dotc/quoted/TastyString.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.quoted +import scala.language.unsafeNulls + import java.util.Base64 import java.nio.charset.StandardCharsets.UTF_8 diff --git a/compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala b/compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala index 3f498b432f98..dec13a4f5925 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package reporting +import scala.language.unsafeNulls + import dotty.tools.dotc.config.Settings.Setting import dotty.tools.dotc.core.Contexts._ import dotty.tools.dotc.interfaces.Diagnostic.{ERROR, INFO, WARNING} diff --git a/compiler/src/dotty/tools/dotc/reporting/ExploringReporter.scala b/compiler/src/dotty/tools/dotc/reporting/ExploringReporter.scala index 9255820140d8..a2062bd1b2c7 100644 --- a/compiler/src/dotty/tools/dotc/reporting/ExploringReporter.scala +++ b/compiler/src/dotty/tools/dotc/reporting/ExploringReporter.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package reporting +import scala.language.unsafeNulls + import collection.mutable import core.Contexts.Context import Diagnostic._ diff --git a/compiler/src/dotty/tools/dotc/reporting/Message.scala b/compiler/src/dotty/tools/dotc/reporting/Message.scala index f309dc0f1477..84078cebe91f 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Message.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Message.scala @@ -1,6 +1,9 @@ package dotty.tools package dotc package reporting + +import scala.language.unsafeNulls + import scala.annotation.threadUnsafe object Message { diff --git a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala index c2ddd535b728..4e68743802b1 100644 --- a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala +++ b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package reporting +import scala.language.unsafeNulls + import java.lang.System.{lineSeparator => EOL} import core.Contexts._ diff --git a/compiler/src/dotty/tools/dotc/reporting/Reporter.scala b/compiler/src/dotty/tools/dotc/reporting/Reporter.scala index 39ece915ca83..ad51087a3bbd 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Reporter.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Reporter.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package reporting +import scala.language.unsafeNulls + import dotty.tools.dotc.core.Contexts._ import dotty.tools.dotc.core.Mode import dotty.tools.dotc.core.Symbols.{NoSymbol, Symbol} @@ -179,9 +181,10 @@ abstract class Reporter extends interfaces.ReporterResult { // `ctx.run` can be null in test, also in the repl when parsing the first line. The parser runs early, the Run is // only created in ReplDriver.compile when a line is submitted. This means that `@nowarn` doesnt work on parser // warnings in the first line. + val run = ctx.run dia match - case w: Warning if ctx.run != null => - val sup = ctx.run.suppressions + case w: Warning if run != null => + val sup = run.suppressions if sup.suppressionsComplete(w.pos.source) then sup.nowarnAction(w) match case Action.Warning => go() case Action.Verbose => w.setVerbose(); go() diff --git a/compiler/src/dotty/tools/dotc/reporting/StoreReporter.scala b/compiler/src/dotty/tools/dotc/reporting/StoreReporter.scala index db39ed6527d1..9783a3208a60 100644 --- a/compiler/src/dotty/tools/dotc/reporting/StoreReporter.scala +++ b/compiler/src/dotty/tools/dotc/reporting/StoreReporter.scala @@ -17,27 +17,28 @@ import Diagnostic._ * - The reporter is not flushed and the message containers capture a * `Context` (about 4MB) */ -class StoreReporter(outer: Reporter = Reporter.NoReporter, fromTyperState: Boolean = false) extends Reporter { +class StoreReporter(outer: Reporter | Null = Reporter.NoReporter, fromTyperState: Boolean = false) extends Reporter { - protected var infos: mutable.ListBuffer[Diagnostic] = null + protected var infos: mutable.ListBuffer[Diagnostic] | Null = null def doReport(dia: Diagnostic)(using Context): Unit = { typr.println(s">>>> StoredError: ${dia.message}") // !!! DEBUG if (infos == null) infos = new mutable.ListBuffer - infos += dia + infos.uncheckedNN += dia } override def hasUnreportedErrors: Boolean = - outer != null && infos != null && infos.exists(_.isInstanceOf[Error]) + outer != null && infos != null && infos.uncheckedNN.exists(_.isInstanceOf[Error]) override def hasStickyErrors: Boolean = - infos != null && infos.exists(_.isInstanceOf[StickyError]) + infos != null && infos.uncheckedNN.exists(_.isInstanceOf[StickyError]) override def removeBufferedMessages(using Context): List[Diagnostic] = - if (infos != null) try infos.toList finally infos = null + if (infos != null) try infos.uncheckedNN.toList finally infos = null else Nil - override def pendingMessages(using Context): List[Diagnostic] = if (infos != null) infos.toList else Nil + override def pendingMessages(using Context): List[Diagnostic] = + if (infos != null) infos.uncheckedNN.toList else Nil override def errorsReported: Boolean = hasErrors || (outer != null && outer.errorsReported) diff --git a/compiler/src/dotty/tools/dotc/reporting/TestReporter.scala b/compiler/src/dotty/tools/dotc/reporting/TestReporter.scala index a3d84e462bf0..8d7204a93fa2 100644 --- a/compiler/src/dotty/tools/dotc/reporting/TestReporter.scala +++ b/compiler/src/dotty/tools/dotc/reporting/TestReporter.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package reporting +import scala.language.unsafeNulls + import collection.mutable import Diagnostic._ diff --git a/compiler/src/dotty/tools/dotc/reporting/WConf.scala b/compiler/src/dotty/tools/dotc/reporting/WConf.scala index 01c2e79389c6..d8aabc94c97d 100644 --- a/compiler/src/dotty/tools/dotc/reporting/WConf.scala +++ b/compiler/src/dotty/tools/dotc/reporting/WConf.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package reporting +import scala.language.unsafeNulls + import dotty.tools.dotc.core.Contexts._ import dotty.tools.dotc.util.SourcePosition diff --git a/compiler/src/dotty/tools/dotc/reporting/trace.scala b/compiler/src/dotty/tools/dotc/reporting/trace.scala index 10179f9d3789..7c114b51ed21 100644 --- a/compiler/src/dotty/tools/dotc/reporting/trace.scala +++ b/compiler/src/dotty/tools/dotc/reporting/trace.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package reporting +import scala.language.unsafeNulls + import core.Contexts._ import config.Config import config.Printers diff --git a/compiler/src/dotty/tools/dotc/sbt/APIUtils.scala b/compiler/src/dotty/tools/dotc/sbt/APIUtils.scala index 9ddb8aa9116c..aa98f79c8e3b 100644 --- a/compiler/src/dotty/tools/dotc/sbt/APIUtils.scala +++ b/compiler/src/dotty/tools/dotc/sbt/APIUtils.scala @@ -1,6 +1,8 @@ package dotty.tools.dotc package sbt +import scala.language.unsafeNulls + import core._ import Contexts._ import Flags._ diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index feef706d3c15..1120b279b2e2 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -1,6 +1,8 @@ package dotty.tools.dotc package sbt +import scala.language.unsafeNulls + import ExtractDependencies.internalError import ast.{Positioned, Trees, tpd} import core._ diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 83fb4fd40215..f7b15dc21eb0 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -1,6 +1,8 @@ package dotty.tools.dotc package sbt +import scala.language.unsafeNulls + import java.io.File import java.util.{Arrays, EnumSet} diff --git a/compiler/src/dotty/tools/dotc/sbt/ShowAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ShowAPI.scala index 89a652c0172a..cacb10cf98bc 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ShowAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ShowAPI.scala @@ -9,6 +9,8 @@ package dotty.tools.dotc package sbt +import scala.language.unsafeNulls + import xsbti.api._ import scala.util.Try diff --git a/compiler/src/dotty/tools/dotc/sbt/ThunkHolder.scala b/compiler/src/dotty/tools/dotc/sbt/ThunkHolder.scala index 858cc2f1157d..60aa76c91ed4 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ThunkHolder.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ThunkHolder.scala @@ -25,7 +25,7 @@ private[sbt] trait ThunkHolder { * It will be forced by the next call to `forceThunks()` */ def lzy[T <: AnyRef](t: => T): api.Lazy[T] = { - val l = api.SafeLazy.apply(() => t) + val l = api.SafeLazy.apply(() => t).nn thunks += l l } diff --git a/compiler/src/dotty/tools/dotc/semanticdb/Descriptor.scala b/compiler/src/dotty/tools/dotc/semanticdb/Descriptor.scala index a93b99df602c..2743e37cb79f 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/Descriptor.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/Descriptor.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.semanticdb +import scala.language.unsafeNulls + import java.lang.System.{lineSeparator => EOL} import dotty.tools.dotc.semanticdb.{Descriptor => d} diff --git a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala index 140d2fe5b766..5e658b992fde 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package semanticdb +import scala.language.unsafeNulls + import core._ import Phases._ import ast.tpd._ diff --git a/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala b/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala index 45af208b3e36..5d89a3463391 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala @@ -402,7 +402,7 @@ object Scala3: else Descriptor.None def unescapeUnicode = - unicodeEscape.replaceAllIn(symbol, m => String.valueOf(Integer.parseInt(m.group(1), 16).toChar)) + unicodeEscape.replaceAllIn(symbol, m => String.valueOf(Integer.parseInt(m.group(1), 16).toChar).nn) def isJavaIdent = isJavaIdentifierStart(symbol.head) && symbol.tail.forall(isJavaIdentifierPart) diff --git a/compiler/src/dotty/tools/dotc/semanticdb/Tools.scala b/compiler/src/dotty/tools/dotc/semanticdb/Tools.scala index d7d3324549b7..b611de678c13 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/Tools.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/Tools.scala @@ -48,7 +48,7 @@ object Tools: /** Parses SemanticDB text documents from an absolute path to a `*.semanticdb` file. */ private def parseTextDocuments(path: Path): TextDocuments = - val bytes = Files.readAllBytes(path) // NOTE: a semanticdb file is a TextDocuments message, not TextDocument + val bytes = Files.readAllBytes(path).nn // NOTE: a semanticdb file is a TextDocuments message, not TextDocument TextDocuments.parseFrom(bytes) def metac(doc: TextDocument, realPath: Path)(using sb: StringBuilder): StringBuilder = diff --git a/compiler/src/dotty/tools/dotc/semanticdb/internal/MD5.scala b/compiler/src/dotty/tools/dotc/semanticdb/internal/MD5.scala index 01bcc36467f4..dc10df6a5bba 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/internal/MD5.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/internal/MD5.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.semanticdb.internal +import scala.language.unsafeNulls + import java.nio.ByteBuffer import java.nio.charset.StandardCharsets import java.security.MessageDigest diff --git a/compiler/src/dotty/tools/dotc/semanticdb/internal/SemanticdbInputStream.scala b/compiler/src/dotty/tools/dotc/semanticdb/internal/SemanticdbInputStream.scala index 3a2b616477c3..99a4da63128a 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/internal/SemanticdbInputStream.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/internal/SemanticdbInputStream.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.semanticdb.internal +import scala.language.unsafeNulls + import java.io.IOException import java.io.InputStream import java.util.Arrays diff --git a/compiler/src/dotty/tools/dotc/semanticdb/internal/SemanticdbOutputStream.scala b/compiler/src/dotty/tools/dotc/semanticdb/internal/SemanticdbOutputStream.scala index da39949f09fc..37da7f868e25 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/internal/SemanticdbOutputStream.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/internal/SemanticdbOutputStream.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.semanticdb.internal +import scala.language.unsafeNulls + import java.io.IOException import java.io.OutputStream import java.nio.ByteBuffer diff --git a/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala b/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala index d3efa6c60d5c..32bcc53184b1 100644 --- a/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala +++ b/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala @@ -12,6 +12,7 @@ import core.Names._ import core.NameKinds.TempResultName import core.Constants._ import util.Store +import dotty.tools.uncheckedNN /** This phase translates variables that are captured in closures to * heap-allocated refs. @@ -51,10 +52,10 @@ class CapturedVars extends MiniPhase with IdentityDenotTransformer: Set(refClass(defn.ObjectClass), volatileRefClass(defn.ObjectClass)) } - private var myRefInfo: RefInfo = null - private def refInfo(using Context) = { + private var myRefInfo: RefInfo | Null = null + private def refInfo(using Context): RefInfo = { if (myRefInfo == null) myRefInfo = new RefInfo() - myRefInfo + myRefInfo.uncheckedNN } private class CollectCaptured extends TreeTraverser { diff --git a/compiler/src/dotty/tools/dotc/transform/CheckLoopingImplicits.scala b/compiler/src/dotty/tools/dotc/transform/CheckLoopingImplicits.scala index 70c8c0314658..758e5d7f5cc6 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckLoopingImplicits.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckLoopingImplicits.scala @@ -21,7 +21,7 @@ class CheckLoopingImplicits extends MiniPhase: override def description: String = CheckLoopingImplicits.description - override def transformValDef(mdef: ValDef)(using Context): Tree = + override def transformValDef(mdef: ValDef)(using Context): Tree = transform(mdef) override def transformDefDef(mdef: DefDef)(using Context): Tree = @@ -80,7 +80,7 @@ class CheckLoopingImplicits extends MiniPhase: checkNotLooping(finalizer) case SeqLiteral(elems, _) => elems.foreach(checkNotLooping) - case t: ValDef => + case t: ValDef => checkNotLooping(t.rhs) case _ => diff --git a/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala index b4544b2225dd..179625759b10 100644 --- a/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala +++ b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala @@ -1,11 +1,9 @@ -package dotty.tools.dotc.transform +package dotty.tools.dotc +package transform -import dotty.tools.dotc.ast.tpd -import dotty.tools.dotc.core.Contexts.Context -import dotty.tools.dotc.transform.MegaPhase._ -import java.io.{File => _} - -import dotty.tools.dotc.core._ +import core._ +import ast.tpd +import MegaPhase._ import Contexts._ import Symbols._ import Phases._ @@ -38,7 +36,7 @@ class CollectEntryPoints extends MiniPhase: private def getEntryPoint(tree: tpd.TypeDef)(using Context): Option[String] = val sym = tree.symbol - import dotty.tools.dotc.core.NameOps.stripModuleClassSuffix + import core.NameOps.stripModuleClassSuffix val name = sym.fullName.stripModuleClassSuffix.toString Option.when(sym.isStatic && !sym.is(Flags.Trait) && ctx.platform.hasMainMethod(sym))(name) diff --git a/compiler/src/dotty/tools/dotc/transform/CollectNullableFields.scala b/compiler/src/dotty/tools/dotc/transform/CollectNullableFields.scala index cf575e84975d..7b89c8785e05 100644 --- a/compiler/src/dotty/tools/dotc/transform/CollectNullableFields.scala +++ b/compiler/src/dotty/tools/dotc/transform/CollectNullableFields.scala @@ -100,7 +100,7 @@ class CollectNullableFields extends MiniPhase { nullability.foreach { case (sym, Nullable(from)) => - val bldr = result.computeIfAbsent(from, _ => new mutable.ListBuffer) + val bldr = result.computeIfAbsent(from, _ => new mutable.ListBuffer).nn bldr += sym case _ => } diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index d19084ac3d8c..cd3b29d7e256 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -683,7 +683,7 @@ object Erasure { val owner = sym.maybeOwner if defn.specialErasure.contains(owner) then assert(sym.isConstructor, s"${sym.showLocated}") - defn.specialErasure(owner) + defn.specialErasure(owner).nn else if defn.isSyntheticFunctionClass(owner) then defn.functionTypeErasure(owner).typeSymbol else diff --git a/compiler/src/dotty/tools/dotc/transform/Flatten.scala b/compiler/src/dotty/tools/dotc/transform/Flatten.scala index 678a202709e0..25df51d0916d 100644 --- a/compiler/src/dotty/tools/dotc/transform/Flatten.scala +++ b/compiler/src/dotty/tools/dotc/transform/Flatten.scala @@ -24,11 +24,11 @@ class Flatten extends MiniPhase with SymTransformer { override def changesMembers: Boolean = true // the phase removes inner classes - private var LiftedDefs: Store.Location[mutable.ListBuffer[Tree]] = _ + private var LiftedDefs: Store.Location[mutable.ListBuffer[Tree] | Null] = _ private def liftedDefs(using Context) = ctx.store(LiftedDefs) override def initContext(ctx: FreshContext): Unit = - LiftedDefs = ctx.addLocation[mutable.ListBuffer[Tree]](null) + LiftedDefs = ctx.addLocation[mutable.ListBuffer[Tree] | Null](null) def transformSym(ref: SymDenotation)(using Context): SymDenotation = if (ref.isClass && !ref.is(Package) && !ref.owner.is(Package)) @@ -43,16 +43,18 @@ class Flatten extends MiniPhase with SymTransformer { private def liftIfNested(tree: Tree)(using Context) = if (ctx.owner.is(Package)) tree else { - transformFollowing(tree).foreachInThicket(liftedDefs += _) + transformFollowing(tree).foreachInThicket(t => liftedDefs.nn += t) EmptyTree } override def transformStats(stats: List[Tree])(using Context): List[Tree] = - if (ctx.owner.is(Package)) { - val liftedStats = stats ++ liftedDefs - liftedDefs.clear() - liftedStats - } + if ctx.owner.is(Package) then + val defs = liftedDefs + if defs != null then + val liftedStats = stats ++ defs + defs.clear() + liftedStats + else stats else stats override def transformTypeDef(tree: TypeDef)(using Context): Tree = diff --git a/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala b/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala index fae5f79d51b2..6ce708068393 100644 --- a/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala +++ b/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala @@ -167,7 +167,7 @@ object GenericSignatures { // likely to end up with Foo.Empty where it needs Foo.Empty$. def fullNameInSig(sym: Symbol): Unit = { val name = atPhase(genBCodePhase) { sanitizeName(sym.fullName).replace('.', '/') } - builder.append('L').append(name) + builder.append('L').nn.append(name) } def classSig(sym: Symbol, pre: Type = NoType, args: List[Type] = Nil): Unit = { @@ -211,7 +211,7 @@ object GenericSignatures { // TODO revisit this. Does it align with javac for code that can be expressed in both languages? val delimiter = if (builder.charAt(builder.length() - 1) == '>') '.' else '$' - builder.append(delimiter).append(sanitizeName(sym.name)) + builder.append(delimiter).nn.append(sanitizeName(sym.name)) } else fullNameInSig(sym) } @@ -253,7 +253,7 @@ object GenericSignatures { typeParamSig(sym.name.lastPart) } else if (defn.specialErasure.contains(sym)) - jsig(defn.specialErasure(sym).typeRef) + jsig(defn.specialErasure(sym).nn.typeRef) else if (sym == defn.UnitClass || sym == defn.BoxedUnitModule) jsig(defn.BoxedUnitClass.typeRef) else if (sym == defn.NothingClass) diff --git a/compiler/src/dotty/tools/dotc/transform/Inlining.scala b/compiler/src/dotty/tools/dotc/transform/Inlining.scala index f9aefdd95bfc..ca17cf607641 100644 --- a/compiler/src/dotty/tools/dotc/transform/Inlining.scala +++ b/compiler/src/dotty/tools/dotc/transform/Inlining.scala @@ -30,7 +30,7 @@ class Inlining extends MacroTransform { override def runOn(units: List[CompilationUnit])(using Context): List[CompilationUnit] = val newUnits = super.runOn(units).filterNot(_.suspended) - ctx.run.checkSuspendedUnits(newUnits) + ctx.run.nn.checkSuspendedUnits(newUnits) newUnits override def checkPostCondition(tree: Tree)(using Context): Unit = diff --git a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala index aabf8cf9a680..e72874dfaadd 100644 --- a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala @@ -44,10 +44,10 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer { val containerFlagsMask: FlagSet = Method | Lazy | Accessor | Module /** A map of lazy values to the fields they should null after initialization. */ - private var lazyValNullables: IdentityHashMap[Symbol, mutable.ListBuffer[Symbol]] = _ + private var lazyValNullables: IdentityHashMap[Symbol, mutable.ListBuffer[Symbol]] | Null = _ private def nullableFor(sym: Symbol)(using Context) = { // optimisation: value only used once, we can remove the value from the map - val nullables = lazyValNullables.remove(sym) + val nullables = lazyValNullables.nn.remove(sym) if (nullables == null) Nil else nullables.toList } @@ -382,7 +382,7 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer { val thizClass = Literal(Constant(claz.info)) val helperModule = requiredModule("scala.runtime.LazyVals") val getOffset = Select(ref(helperModule), lazyNme.RLazyVals.getOffset) - var offsetSymbol: TermSymbol = null + var offsetSymbol: TermSymbol | Null = null var flag: Tree = EmptyTree var ord = 0 @@ -402,21 +402,21 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer { .symbol.asTerm else { // need to create a new flag offsetSymbol = newSymbol(claz, offsetById, Synthetic, defn.LongType).enteredAfter(this) - offsetSymbol.addAnnotation(Annotation(defn.ScalaStaticAnnot)) + offsetSymbol.nn.addAnnotation(Annotation(defn.ScalaStaticAnnot)) val flagName = LazyBitMapName.fresh(id.toString.toTermName) val flagSymbol = newSymbol(claz, flagName, containerFlags, defn.LongType).enteredAfter(this) flag = ValDef(flagSymbol, Literal(Constant(0L))) - val offsetTree = ValDef(offsetSymbol, getOffset.appliedTo(thizClass, Literal(Constant(flagName.toString)))) + val offsetTree = ValDef(offsetSymbol.nn, getOffset.appliedTo(thizClass, Literal(Constant(flagName.toString)))) info.defs = offsetTree :: info.defs } case None => offsetSymbol = newSymbol(claz, offsetName(0), Synthetic, defn.LongType).enteredAfter(this) - offsetSymbol.addAnnotation(Annotation(defn.ScalaStaticAnnot)) + offsetSymbol.nn.addAnnotation(Annotation(defn.ScalaStaticAnnot)) val flagName = LazyBitMapName.fresh("0".toTermName) val flagSymbol = newSymbol(claz, flagName, containerFlags, defn.LongType).enteredAfter(this) flag = ValDef(flagSymbol, Literal(Constant(0L))) - val offsetTree = ValDef(offsetSymbol, getOffset.appliedTo(thizClass, Literal(Constant(flagName.toString)))) + val offsetTree = ValDef(offsetSymbol.nn, getOffset.appliedTo(thizClass, Literal(Constant(flagName.toString)))) appendOffsetDefs += (claz -> new OffsetInfo(List(offsetTree), ord)) } @@ -425,7 +425,7 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer { val containerTree = ValDef(containerSymbol, defaultValue(tpe)) - val offset = ref(offsetSymbol) + val offset = ref(offsetSymbol.nn) val getFlag = Select(ref(helperModule), lazyNme.RLazyVals.get) val setFlag = Select(ref(helperModule), lazyNme.RLazyVals.setFlag) val wait = Select(ref(helperModule), lazyNme.RLazyVals.wait4Notification) diff --git a/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala b/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala index c3fc28bb0157..e4a78616e4eb 100644 --- a/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala +++ b/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala @@ -464,7 +464,7 @@ class MegaPhase(val miniPhases: Array[MiniPhase]) extends Phase { // Initialization code /** Class#getDeclaredMethods is slow, so we cache its output */ - private val clsMethodsCache = new java.util.IdentityHashMap[Class[?], Array[java.lang.reflect.Method]] + private val clsMethodsCache = new java.util.IdentityHashMap[Class[?], Array[java.lang.reflect.Method | Null]] /** Does `phase` contain a redefinition of method `name`? * (which is a method of MiniPhase) @@ -474,21 +474,21 @@ class MegaPhase(val miniPhases: Array[MiniPhase]) extends Phase { if (cls.eq(classOf[MiniPhase])) false else { var clsMethods = clsMethodsCache.get(cls) - if (clsMethods eq null) { + if (clsMethods == null) { clsMethods = cls.getDeclaredMethods clsMethodsCache.put(cls, clsMethods) } - clsMethods.exists(_.getName == name) || - hasRedefinedMethod(cls.getSuperclass) + clsMethods.nn.exists(_.nn.getName == name) || + hasRedefinedMethod(cls.getSuperclass.nn) } hasRedefinedMethod(phase.getClass) } - private def newNxArray = new Array[MiniPhase](miniPhases.length + 1) + private def newNxArray = new Array[MiniPhase | Null](miniPhases.length + 1) private val emptyNxArray = newNxArray - private def init(methName: String): Array[MiniPhase] = { - var nx: Array[MiniPhase] = emptyNxArray + private def init(methName: String): Array[MiniPhase | Null] = { + var nx: Array[MiniPhase | Null] = emptyNxArray for (idx <- miniPhases.length - 1 to 0 by -1) { val subPhase = miniPhases(idx) if (defines(subPhase, methName)) { diff --git a/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala b/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala index d733359a5dcd..4044034cb5ea 100644 --- a/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala +++ b/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala @@ -121,7 +121,7 @@ object OverridingPairs: var overridden: Symbol = _ //@M: note that next is called once during object initialization - final def hasNext: Boolean = nextEntry ne null + final def hasNext: Boolean = nextEntry != null /** @post * curEntry = the next candidate that may override something else @@ -130,10 +130,10 @@ object OverridingPairs: */ private def nextOverriding(): Unit = { @tailrec def loop(): Unit = - if (curEntry ne null) { - overriding = curEntry.sym + if (curEntry != null) { + overriding = curEntry.uncheckedNN.sym if (visited.contains(overriding)) { - curEntry = curEntry.prev + curEntry = curEntry.uncheckedNN.prev loop() } } @@ -148,10 +148,10 @@ object OverridingPairs: */ @tailrec final def next(): Unit = if nextEntry != null then - nextEntry = decls.lookupNextEntry(nextEntry) + nextEntry = decls.lookupNextEntry(nextEntry.uncheckedNN) if nextEntry != null then try - overridden = nextEntry.sym + overridden = nextEntry.uncheckedNN.sym if overriding.owner != overridden.owner && matches(overriding, overridden) then visited += overridden if !isHandledByParent(overriding, overridden) then return @@ -160,7 +160,7 @@ object OverridingPairs: // The root cause in this example is an illegal "override" of an inner trait report.error(ex, base.srcPos) else - curEntry = curEntry.prev + curEntry = curEntry.nn.prev nextOverriding() next() diff --git a/compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala b/compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala index 78640ed6163a..82a187f57109 100644 --- a/compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala @@ -108,7 +108,7 @@ class PickleQuotes extends MacroTransform { * This transformation is only applied to definitions at staging level 1. * See `isCaptured`. */ - private class QuoteReifier(outer: QuoteReifier, capturers: mutable.HashMap[Symbol, Tree => Tree], + private class QuoteReifier(outer: QuoteReifier | Null, capturers: mutable.HashMap[Symbol, Tree => Tree], val embedded: Embedded, val owner: Symbol)(@constructorOnly ictx: Context) extends TreeMapWithStages(ictx) { self => import StagingContext._ @@ -312,13 +312,13 @@ class PickleQuotes extends MacroTransform { else { assert(level == 1, "unexpected top splice outside quote") val (body1, quotes) = nested(isQuote = false).splitSplice(body)(using spliceContext) - val tpe = outer.embedded.getHoleType(body, splice) + val tpe = outer.nn.embedded.getHoleType(body, splice) val hole = makeHole(splice.isTerm, body1, quotes, tpe).withSpan(splice.span) // We do not place add the inline marker for trees that where lifted as they come from the same file as their // enclosing quote. Any intemediate splice will add it's own Inlined node and cancel it before splicig the lifted tree. // Note that lifted trees are not necessarily expressions and that Inlined nodes are expected to be expressions. // For example we can have a lifted tree containing the LHS of an assignment (see tests/run-with-compiler/quote-var.scala). - if (outer.embedded.isLiftedSymbol(body.symbol)) hole + if (outer.nn.embedded.isLiftedSymbol(body.symbol)) hole else Inlined(EmptyTree, Nil, hole).withSpan(splice.span) } @@ -332,7 +332,7 @@ class PickleQuotes extends MacroTransform { cpy.Select(splice)(body1, splice.name) else if level == 1 then val (body1, quotes) = nested(isQuote = false).splitSplice(body)(using spliceContext) - val tpe = outer.embedded.getHoleType(body, splice) + val tpe = outer.nn.embedded.getHoleType(body, splice) makeHole(splice.isTerm, body1, quotes, tpe).withSpan(splice.span) else splice @@ -395,7 +395,7 @@ class PickleQuotes extends MacroTransform { * In case the case that level == -1 the code is not in a quote, it is in an inline method, * hence we should take that as owner directly. */ - val lambdaOwner = if (level == -1) ctx.owner else outer.owner + val lambdaOwner = if (level == -1) ctx.owner else outer.nn.owner val tpe = MethodType(defn.SeqType.appliedTo(defn.AnyType) :: Nil, tree.tpe.widen) val meth = newSymbol(lambdaOwner, UniqueName.fresh(nme.ANON_FUN), Synthetic | Method, tpe) @@ -406,10 +406,10 @@ class PickleQuotes extends MacroTransform { val captured = mutable.LinkedHashMap.empty[Symbol, Tree] val captured2 = capturer(captured) - outer.localSymbols.foreach(sym => if (!sym.isInlineMethod) capturers.put(sym, captured2)) + outer.nn.localSymbols.foreach(sym => if (!sym.isInlineMethod) capturers.put(sym, captured2)) val tree2 = transform(tree) - capturers --= outer.localSymbols + capturers --= outer.nn.localSymbols val captures = captured.result().valuesIterator.toList if (captures.isEmpty) tree2 diff --git a/compiler/src/dotty/tools/dotc/transform/SpecializeFunctions.scala b/compiler/src/dotty/tools/dotc/transform/SpecializeFunctions.scala index 84145742ed90..c1f891d6293a 100644 --- a/compiler/src/dotty/tools/dotc/transform/SpecializeFunctions.scala +++ b/compiler/src/dotty/tools/dotc/transform/SpecializeFunctions.scala @@ -35,7 +35,7 @@ class SpecializeFunctions extends MiniPhase { val sym = ddef.symbol val cls = ctx.owner.asClass - var specName: Name = null + var specName: Name | Null = null def isSpecializable = { val paramTypes = ddef.termParamss.head.map(_.symbol.info) @@ -48,7 +48,7 @@ class SpecializeFunctions extends MiniPhase { val specializedApply = newSymbol( cls, - specName, + specName.nn, sym.flags | Flags.Synthetic, sym.info ).entered diff --git a/compiler/src/dotty/tools/dotc/transform/Splicer.scala b/compiler/src/dotty/tools/dotc/transform/Splicer.scala index 8c34d5f3186d..3a2c1792dfa4 100644 --- a/compiler/src/dotty/tools/dotc/transform/Splicer.scala +++ b/compiler/src/dotty/tools/dotc/transform/Splicer.scala @@ -1,6 +1,8 @@ package dotty.tools.dotc package transform +import scala.language.unsafeNulls + import java.io.{PrintWriter, StringWriter} import java.lang.reflect.{InvocationTargetException, Method => JLRMethod} @@ -472,7 +474,7 @@ object Splicer { private object MissingClassDefinedInCurrentRun { def unapply(targetException: NoClassDefFoundError)(using Context): Option[Symbol] = { val className = targetException.getMessage - if (className eq null) None + if (className == null) None else { val sym = staticRef(className.toTypeName).symbol if (sym.isDefinedInCurrentRun) Some(sym) else None diff --git a/compiler/src/dotty/tools/dotc/transform/TailRec.scala b/compiler/src/dotty/tools/dotc/transform/TailRec.scala index bde4fbfbdaca..cb1119ea71f1 100644 --- a/compiler/src/dotty/tools/dotc/transform/TailRec.scala +++ b/compiler/src/dotty/tools/dotc/transform/TailRec.scala @@ -12,6 +12,7 @@ import core.Symbols._ import reporting._ import transform.MegaPhase.MiniPhase import util.LinearSet +import dotty.tools.uncheckedNN /** A Tail Rec Transformer. @@ -222,11 +223,11 @@ class TailRec extends MiniPhase { var failureReported: Boolean = false /** The `tailLabelN` label symbol, used to encode a `continue` from the infinite `while` loop. */ - private var myContinueLabel: Symbol = _ + private var myContinueLabel: Symbol | Null = _ def continueLabel(using Context): Symbol = { if (myContinueLabel == null) myContinueLabel = newSymbol(method, TailLabelName.fresh(), Label, defn.UnitType) - myContinueLabel + myContinueLabel.uncheckedNN } /** The local `var` that replaces `this`, if it is modified in at least one recursive call. */ diff --git a/compiler/src/dotty/tools/dotc/transform/TupleOptimizations.scala b/compiler/src/dotty/tools/dotc/transform/TupleOptimizations.scala index 6370bb51afb9..33341995d5b6 100644 --- a/compiler/src/dotty/tools/dotc/transform/TupleOptimizations.scala +++ b/compiler/src/dotty/tools/dotc/transform/TupleOptimizations.scala @@ -189,7 +189,7 @@ class TupleOptimizations extends MiniPhase with IdentityDenotTransformer { private def knownTupleFromElements(tpes: List[Type], elements: List[Tree])(using Context) = { val size = elements.size assert(0 < size && size <= MaxTupleArity) - val tupleModule = defn.TupleType(size).classSymbol.companionModule + val tupleModule = defn.TupleType(size).nn.classSymbol.companionModule ref(tupleModule).select(nme.apply).appliedToTypes(tpes).appliedToTermArgs(elements) } diff --git a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index c467e2dbd8f3..0b880afdd995 100644 --- a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package transform +import scala.language.unsafeNulls as _ + import core._ import Contexts._, Symbols._, Types._, Constants._, StdNames._, Decorators._ import ast.untpd diff --git a/compiler/src/dotty/tools/dotc/transform/init/Checker.scala b/compiler/src/dotty/tools/dotc/transform/init/Checker.scala index e77abbb99549..533c20afb99a 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Checker.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Checker.scala @@ -2,7 +2,6 @@ package dotty.tools.dotc package transform package init - import dotty.tools.dotc._ import ast.tpd import tpd._ diff --git a/compiler/src/dotty/tools/dotc/transform/init/Errors.scala b/compiler/src/dotty/tools/dotc/transform/init/Errors.scala index 9f3e0d1fcc47..c2224f6c4567 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Errors.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Errors.scala @@ -4,7 +4,6 @@ package transform package init import ast.tpd._ - import core._ import Decorators._, printing.SyntaxHighlighting import Types._, Symbols._, Contexts._ @@ -37,7 +36,7 @@ object Errors { val line = if pos.source.exists then val loc = "[ " + pos.source.file.name + ":" + (pos.line + 1) + " ]" - val code = SyntaxHighlighting.highlight(pos.lineContent.trim) + val code = SyntaxHighlighting.highlight(pos.lineContent.trim.nn) i"$code\t$loc" else tree.show @@ -56,7 +55,7 @@ object Errors { case _ => this :: Nil } - override def toString() = this.getClass.getName + override def toString() = this.getClass.getName.nn } /** Access non-initialized field */ diff --git a/compiler/src/dotty/tools/dotc/transform/localopt/FormatChecker.scala b/compiler/src/dotty/tools/dotc/transform/localopt/FormatChecker.scala index bc5219a33883..ff8d89920791 100644 --- a/compiler/src/dotty/tools/dotc/transform/localopt/FormatChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/localopt/FormatChecker.scala @@ -74,7 +74,7 @@ class TypedFormatChecker(partsElems: List[Tree], parts: List[String], args: List def loop(remaining: List[String], n: Int): Unit = remaining match case part0 :: more => - def badPart(t: Throwable): String = "".tap(_ => report.partError(t.getMessage, index = n, offset = 0)) + def badPart(t: Throwable): String = "".tap(_ => report.partError(t.getMessage.nn, index = n, offset = 0)) val part = try StringContext.processEscapes(part0) catch badPart val matches = formatPattern.findAllMatchIn(part) diff --git a/compiler/src/dotty/tools/dotc/transform/localopt/StringInterpolatorOpt.scala b/compiler/src/dotty/tools/dotc/transform/localopt/StringInterpolatorOpt.scala index 667f9fdb2779..681641853b10 100644 --- a/compiler/src/dotty/tools/dotc/transform/localopt/StringInterpolatorOpt.scala +++ b/compiler/src/dotty/tools/dotc/transform/localopt/StringInterpolatorOpt.scala @@ -1,6 +1,8 @@ package dotty.tools.dotc package transform.localopt +import scala.language.unsafeNulls + import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Decorators._ import dotty.tools.dotc.core.Constants.Constant diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index e957f11d009b..de07fec74acb 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -270,15 +270,15 @@ trait SpaceLogic { if (fun1.symbol.name == nme.unapply && ss1.length != ss2.length) return a val range = (0 until ss1.size).toList - val cache = Array.fill[Space](ss2.length)(null) + val cache = Array.fill[Space | Null](ss2.length)(null) def sub(i: Int) = if cache(i) == null then cache(i) = minus(ss1(i), ss2(i)) - cache(i) + cache(i).nn end sub if range.exists(i => isSubspace(ss1(i), sub(i))) then a - else if cache.forall(sub => isSubspace(sub, Empty)) then Empty + else if cache.forall(sub => isSubspace(sub.nn, Empty)) then Empty else // `(_, _, _) - (Some, None, _)` becomes `(None, _, _) | (_, Some, _) | (_, _, Empty)` val spaces = LazyList(range: _*).flatMap { i => diff --git a/compiler/src/dotty/tools/dotc/transform/sjs/JSExportUtils.scala b/compiler/src/dotty/tools/dotc/transform/sjs/JSExportUtils.scala index 90e5d2dffbed..9abf9a919d6d 100644 --- a/compiler/src/dotty/tools/dotc/transform/sjs/JSExportUtils.scala +++ b/compiler/src/dotty/tools/dotc/transform/sjs/JSExportUtils.scala @@ -2,6 +2,8 @@ package dotty.tools.dotc package transform package sjs +import scala.language.unsafeNulls + import core._ import NameKinds.DefaultGetterName import Names._ diff --git a/compiler/src/dotty/tools/dotc/transform/sjs/PrepJSInterop.scala b/compiler/src/dotty/tools/dotc/transform/sjs/PrepJSInterop.scala index e97585735eb7..2d9934d5526c 100644 --- a/compiler/src/dotty/tools/dotc/transform/sjs/PrepJSInterop.scala +++ b/compiler/src/dotty/tools/dotc/transform/sjs/PrepJSInterop.scala @@ -544,7 +544,7 @@ class PrepJSInterop extends MacroTransform with IdentityDenotTransformer { thisP val dotIndex = pathName.indexOf('.') val globalRef = if (dotIndex < 0) pathName - else pathName.substring(0, dotIndex) + else pathName.substring(0, dotIndex).nn checkGlobalRefName(globalRef) } diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 0681c8ee2481..43154022e3a0 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -207,7 +207,7 @@ object Applications { end tupleFold tupleFold(Nil, tp).reverse - def wrapDefs(defs: mutable.ListBuffer[Tree], tree: Tree)(using Context): Tree = + def wrapDefs(defs: mutable.ListBuffer[Tree] | Null, tree: Tree)(using Context): Tree = if (defs != null && defs.nonEmpty) tpd.Block(defs.toList, tree) else tree /** Find reference to default parameter getter for parameter #n in current @@ -743,7 +743,7 @@ trait Applications extends Compatibility { type TypedArg = Tree def isVarArg(arg: Trees.Tree[T]): Boolean = untpd.isWildcardStarArg(arg) private var typedArgBuf = new mutable.ListBuffer[Tree] - private var liftedDefs: mutable.ListBuffer[Tree] = null + private var liftedDefs: mutable.ListBuffer[Tree] | Null = null private var myNormalizedFun: Tree = fun init() @@ -782,7 +782,7 @@ trait Applications extends Compatibility { override def liftFun(): Unit = if (liftedDefs == null) { liftedDefs = new mutable.ListBuffer[Tree] - myNormalizedFun = lifter.liftApp(liftedDefs, myNormalizedFun) + myNormalizedFun = lifter.liftApp(liftedDefs.uncheckedNN, myNormalizedFun) } /** The index of the first difference between lists of trees `xs` and `ys` @@ -848,7 +848,7 @@ trait Applications extends Compatibility { scala.util.Sorting.stableSort[(Tree, Int), Int]( argDefBuf.zip(impureArgIndices), (arg, idx) => originalIndex(idx)).map(_._1) } - liftedDefs ++= orderedArgDefs + liftedDefs.nn ++= orderedArgDefs end if if (sameSeq(typedArgs, args)) // trick to cut down on tree copying typedArgs = args.asInstanceOf[List[Tree]] diff --git a/compiler/src/dotty/tools/dotc/typer/ConstFold.scala b/compiler/src/dotty/tools/dotc/typer/ConstFold.scala index 1710d7ceff3c..81b1de67b707 100644 --- a/compiler/src/dotty/tools/dotc/typer/ConstFold.scala +++ b/compiler/src/dotty/tools/dotc/typer/ConstFold.scala @@ -73,7 +73,7 @@ object ConstFold: private def withFoldedType(c: Constant | Null): T = if c == null then tree else tree.withType(ConstantType(c)).asInstanceOf[T] - private def foldUnop(op: Name, x: Constant): Constant = (op, x.tag) match { + private def foldUnop(op: Name, x: Constant): Constant | Null = (op, x.tag) match { case (nme.UNARY_!, BooleanTag) => Constant(!x.booleanValue) case (nme.UNARY_~ , IntTag ) => Constant(~x.intValue) @@ -95,7 +95,7 @@ object ConstFold: /** These are local helpers to keep foldBinop from overly taxing the * optimizer. */ - private def foldBooleanOp(op: Name, x: Constant, y: Constant): Constant = op match { + private def foldBooleanOp(op: Name, x: Constant, y: Constant): Constant | Null = op match { case nme.ZOR => Constant(x.booleanValue | y.booleanValue) case nme.OR => Constant(x.booleanValue | y.booleanValue) case nme.XOR => Constant(x.booleanValue ^ y.booleanValue) @@ -105,7 +105,7 @@ object ConstFold: case nme.NE => Constant(x.booleanValue != y.booleanValue) case _ => null } - private def foldSubrangeOp(op: Name, x: Constant, y: Constant): Constant = op match { + private def foldSubrangeOp(op: Name, x: Constant, y: Constant): Constant | Null = op match { case nme.OR => Constant(x.intValue | y.intValue) case nme.XOR => Constant(x.intValue ^ y.intValue) case nme.AND => Constant(x.intValue & y.intValue) @@ -125,7 +125,7 @@ object ConstFold: case nme.MOD => Constant(x.intValue % y.intValue) case _ => null } - private def foldLongOp(op: Name, x: Constant, y: Constant): Constant = op match { + private def foldLongOp(op: Name, x: Constant, y: Constant): Constant | Null = op match { case nme.OR => Constant(x.longValue | y.longValue) case nme.XOR => Constant(x.longValue ^ y.longValue) case nme.AND => Constant(x.longValue & y.longValue) @@ -145,7 +145,7 @@ object ConstFold: case nme.MOD => Constant(x.longValue % y.longValue) case _ => null } - private def foldFloatOp(op: Name, x: Constant, y: Constant): Constant = op match { + private def foldFloatOp(op: Name, x: Constant, y: Constant): Constant | Null = op match { case nme.EQ => Constant(x.floatValue == y.floatValue) case nme.NE => Constant(x.floatValue != y.floatValue) case nme.LT => Constant(x.floatValue < y.floatValue) @@ -159,7 +159,7 @@ object ConstFold: case nme.MOD => Constant(x.floatValue % y.floatValue) case _ => null } - private def foldDoubleOp(op: Name, x: Constant, y: Constant): Constant = op match { + private def foldDoubleOp(op: Name, x: Constant, y: Constant): Constant | Null = op match { case nme.EQ => Constant(x.doubleValue == y.doubleValue) case nme.NE => Constant(x.doubleValue != y.doubleValue) case nme.LT => Constant(x.doubleValue < y.doubleValue) @@ -173,21 +173,21 @@ object ConstFold: case nme.MOD => Constant(x.doubleValue % y.doubleValue) case _ => null } - private def foldStringOp(op: Name, x: Constant, y: Constant): Constant = op match { + private def foldStringOp(op: Name, x: Constant, y: Constant): Constant | Null = op match { case nme.ADD => Constant(x.stringValue + y.stringValue) case nme.EQ => Constant(x.stringValue == y.stringValue) case nme.NE => Constant(x.stringValue != y.stringValue) case _ => null } - private def foldNullOp(op: Name, x: Constant, y: Constant): Constant = + private def foldNullOp(op: Name, x: Constant, y: Constant): Constant | Null= assert(x.tag == NullTag || y.tag == NullTag) op match case nme.EQ => Constant(x.tag == y.tag) case nme.NE => Constant(x.tag != y.tag) case _ => null - private def foldBinop(op: Name, x: Constant, y: Constant): Constant = + private def foldBinop(op: Name, x: Constant, y: Constant): Constant | Null = val optag = if (x.tag == y.tag) x.tag else if (x.isNumeric && y.isNumeric) math.max(x.tag, y.tag) diff --git a/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala b/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala index 970b771623f6..c2b8c79666f4 100644 --- a/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala @@ -122,7 +122,7 @@ class CrossVersionChecks extends MiniPhase: val msg = annot.argumentConstant(0).get.stringValue report.warning(SymbolChangedSemanticsInVersion(sym, symVersion, msg), pos) case Failure(ex) => - report.warning(SymbolHasUnparsableVersionNumber(sym, ex.getMessage), pos) + report.warning(SymbolHasUnparsableVersionNumber(sym, ex.getMessage.nn), pos) case _ => /** Check that a deprecated val or def does not override a diff --git a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala index b7a9a901f34c..73ceda9223fd 100644 --- a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala +++ b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala @@ -292,7 +292,7 @@ class ImplicitSearchError( } """\$\{\s*([^}\s]+)\s*\}""".r.replaceAllIn(raw, (_: Regex.Match) match { - case Regex.Groups(v) => quoteReplacement(translate(v).getOrElse("")) + case Regex.Groups(v) => quoteReplacement(translate(v).getOrElse("")).nn }) } diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index d61728e53819..fc1fd57c7bd8 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -100,13 +100,13 @@ object Implicits: */ def companionRefs: TermRefSet = TermRefSet.empty - private var mySingletonClass: ClassSymbol = null + private var mySingletonClass: ClassSymbol | Null = null /** Widen type so that it is neither a singleton type nor a type that inherits from scala.Singleton. */ private def widenSingleton(tp: Type)(using Context): Type = { if (mySingletonClass == null) mySingletonClass = defn.SingletonClass val wtp = tp.widenSingleton - if (wtp.derivesFrom(mySingletonClass)) defn.AnyType else wtp + if (wtp.derivesFrom(mySingletonClass.uncheckedNN)) defn.AnyType else wtp } protected def isAccessible(ref: TermRef)(using Context): Boolean @@ -267,7 +267,6 @@ object Implicits: * @param companionRefs the companion objects in the implicit scope. */ class OfTypeImplicits(tp: Type, override val companionRefs: TermRefSet)(initctx: Context) extends ImplicitRefs(initctx) { - assert(initctx.typer != null) implicits.println(i"implicit scope of type $tp = ${companionRefs.showAsList}%, %") @threadUnsafe lazy val refs: List[ImplicitRef] = { val buf = new mutable.ListBuffer[TermRef] @@ -298,7 +297,7 @@ object Implicits: */ class ContextualImplicits( val refs: List[ImplicitRef], - val outerImplicits: ContextualImplicits, + val outerImplicits: ContextualImplicits | Null, isImport: Boolean)(initctx: Context) extends ImplicitRefs(initctx) { private val eligibleCache = EqHashMap[Type, List[Candidate]]() @@ -307,15 +306,15 @@ object Implicits: * Scala2 mode, since we do not want to change the implicit disambiguation then. */ override val level: Int = - def isSameOwner = irefCtx.owner eq outerImplicits.irefCtx.owner - def isSameScope = irefCtx.scope eq outerImplicits.irefCtx.scope + def isSameOwner = irefCtx.owner eq outerImplicits.uncheckedNN.irefCtx.owner + def isSameScope = irefCtx.scope eq outerImplicits.uncheckedNN.irefCtx.scope def isLazyImplicit = refs.head.implicitName.is(LazyImplicitName) if outerImplicits == null then 1 else if migrateTo3(using irefCtx) || isSameOwner && (isImport || isSameScope && !isLazyImplicit) - then outerImplicits.level - else outerImplicits.level + 1 + then outerImplicits.uncheckedNN.level + else outerImplicits.uncheckedNN.level + 1 end level /** Is this the outermost implicits? This is the case if it either the implicits @@ -323,7 +322,7 @@ object Implicits: */ private def isOuterMost = { val finalImplicits = NoContext.implicits - (this eq finalImplicits) || (outerImplicits eq finalImplicits) + (this eq finalImplicits) || (outerImplicits eqn finalImplicits) } private def combineEligibles(ownEligible: List[Candidate], outerEligible: List[Candidate]): List[Candidate] = @@ -338,7 +337,7 @@ object Implicits: if monitored then record(s"check uncached eligible refs in irefCtx", refs.length) val ownEligible = filterMatching(tp) if isOuterMost then ownEligible - else combineEligibles(ownEligible, outerImplicits.uncachedEligible(tp)) + else combineEligibles(ownEligible, outerImplicits.nn.uncachedEligible(tp)) /** The implicit references that are eligible for type `tp`. */ def eligible(tp: Type): List[Candidate] = @@ -365,7 +364,7 @@ object Implicits: if (monitored) record(s"check eligible refs in irefCtx", refs.length) val ownEligible = filterMatching(tp) if isOuterMost then ownEligible - else combineEligibles(ownEligible, outerImplicits.eligible(tp)) + else combineEligibles(ownEligible, outerImplicits.nn.eligible(tp)) } override def isAccessible(ref: TermRef)(using Context): Boolean = @@ -382,9 +381,9 @@ object Implicits: def exclude(root: Symbol): ContextualImplicits = if (this == NoContext.implicits) this else { - val outerExcluded = outerImplicits exclude root - if (irefCtx.importInfo.site.termSymbol == root) outerExcluded - else if (outerExcluded eq outerImplicits) this + val outerExcluded = outerImplicits.nn exclude root + if (irefCtx.importInfo.nn.site.termSymbol == root) outerExcluded + else if (outerExcluded eqn outerImplicits) this else new ContextualImplicits(refs, outerExcluded, isImport)(irefCtx) } } @@ -843,7 +842,7 @@ trait Implicits: } } - private var synthesizer: Synthesizer = null + private var synthesizer: Synthesizer | Null = null /** Find an implicit argument for parameter `formal`. * Return a failure as a SearchFailureType in the type of the returned tree. @@ -855,7 +854,7 @@ trait Implicits: if fail.isAmbiguous then failed else if synthesizer == null then synthesizer = Synthesizer(this) - synthesizer.tryAll(formal, span).orElse(failed) + synthesizer.uncheckedNN.tryAll(formal, span).orElse(failed) /** Search an implicit argument and report error if not found */ def implicitArgTree(formal: Type, span: Span)(using Context): Tree = { @@ -1038,7 +1037,7 @@ trait Implicits: /** Try to typecheck an implicit reference */ def typedImplicit(cand: Candidate, pt: Type, argument: Tree, span: Span)(using Context): SearchResult = trace(i"typed implicit ${cand.ref}, pt = $pt, implicitsEnabled == ${ctx.mode is ImplicitsEnabled}", implicits, show = true) { - if ctx.run.isCancelled then NoMatchingImplicitsFailure + if ctx.run.nn.isCancelled then NoMatchingImplicitsFailure else record("typedImplicit") val ref = cand.ref @@ -1502,7 +1501,7 @@ trait Implicits: searchImplicit(contextual = true) end bestImplicit - def implicitScope(tp: Type): OfTypeImplicits = ctx.run.implicitScope(tp) + def implicitScope(tp: Type): OfTypeImplicits = ctx.run.nn.implicitScope(tp) /** All available implicits, without ranking */ def allImplicits: Set[TermRef] = { @@ -1673,11 +1672,11 @@ final class SearchRoot extends SearchHistory: var nestedSearches: Int = 0 /** The dictionary of recursive implicit types and corresponding terms for this search. */ - var myImplicitDictionary: mutable.Map[Type, (TermRef, tpd.Tree)] = null + var myImplicitDictionary: mutable.Map[Type, (TermRef, tpd.Tree)] | Null = null private def implicitDictionary = if myImplicitDictionary == null then myImplicitDictionary = mutable.Map.empty[Type, (TermRef, tpd.Tree)] - myImplicitDictionary + myImplicitDictionary.uncheckedNN /** * Link a reference to an under-construction implicit for the provided type to its @@ -1856,10 +1855,13 @@ sealed class TermRefSet(using Context): if !that.isEmpty then that.foreach(+=) def foreach[U](f: TermRef => U): Unit = - elems.forEach((sym: TermSymbol, prefixes: Type | List[Type]) => - prefixes match - case prefix: Type => f(TermRef(prefix, sym)) - case prefixes: List[Type] => prefixes.foreach(pre => f(TermRef(pre, sym)))) + def handle(sym: TermSymbol | Null, prefixes: Type | List[Type] | Null): Unit = + // We cannot use `.nn` here due to inference issue. + val prefixes0: Type | List[Type] = prefixes.uncheckedNN + prefixes0 match + case prefix: Type => f(TermRef(prefix, sym.uncheckedNN)) + case prefixes: List[Type] => prefixes.foreach(pre => f(TermRef(pre, sym.uncheckedNN))) + elems.forEach(handle) // used only for debugging def showAsList: List[TermRef] = { diff --git a/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala b/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala index 264ff78c8c8f..b5be2daf873b 100644 --- a/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala +++ b/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala @@ -64,9 +64,9 @@ class ImportInfo(symf: Context ?=> Symbol, mySym = symf assert(mySym != null) } - mySym + mySym.uncheckedNN } - private var mySym: Symbol = _ + private var mySym: Symbol | Null = _ /** The (TermRef) type of the qualifier of the import clause */ def site(using Context): Type = importSym.info match { @@ -75,13 +75,13 @@ class ImportInfo(symf: Context ?=> Symbol, } /** The names that are excluded from any wildcard import */ - def excluded: Set[TermName] = { ensureInitialized(); myExcluded } + def excluded: Set[TermName] = { ensureInitialized(); myExcluded.nn } /** A mapping from original to renamed names */ - def forwardMapping: SimpleIdentityMap[TermName, TermName] = { ensureInitialized(); myForwardMapping } + def forwardMapping: SimpleIdentityMap[TermName, TermName] = { ensureInitialized(); myForwardMapping.nn } /** A mapping from renamed to original names */ - def reverseMapping: SimpleIdentityMap[TermName, TermName] = { ensureInitialized(); myReverseMapping } + def reverseMapping: SimpleIdentityMap[TermName, TermName] = { ensureInitialized(); myReverseMapping.nn } /** Does the import clause contain wildcard selectors (both `_` and `given` count)? */ def isWildcardImport: Boolean = { ensureInitialized(); myWildcardImport } @@ -89,9 +89,9 @@ class ImportInfo(symf: Context ?=> Symbol, /** Does the import clause have at least one `given` selector? */ def isGivenImport: Boolean = { ensureInitialized(); myGivenImport } - private var myExcluded: Set[TermName] = null - private var myForwardMapping: SimpleIdentityMap[TermName, TermName] = null - private var myReverseMapping: SimpleIdentityMap[TermName, TermName] = null + private var myExcluded: Set[TermName] | Null = null + private var myForwardMapping: SimpleIdentityMap[TermName, TermName] | Null = null + private var myReverseMapping: SimpleIdentityMap[TermName, TermName] | Null = null private var myWildcardImport: Boolean = false private var myGivenImport: Boolean = false private var myWildcardBound: Type = NoType @@ -108,10 +108,10 @@ class ImportInfo(symf: Context ?=> Symbol, if sel.isGiven then myGivenImport = true else if sel.rename != sel.name then - myExcluded += sel.name + myExcluded = myExcluded.nn + sel.name if sel.rename != nme.WILDCARD then - myForwardMapping = myForwardMapping.updated(sel.name, sel.rename) - myReverseMapping = myReverseMapping.updated(sel.rename, sel.name) + myForwardMapping = myForwardMapping.uncheckedNN.updated(sel.name, sel.rename) + myReverseMapping = myReverseMapping.uncheckedNN.updated(sel.rename, sel.name) /** The upper bound for `given` wildcards, or `Nothing` if there are none */ def givenBound(using Context) = @@ -148,9 +148,9 @@ class ImportInfo(symf: Context ?=> Symbol, else for renamed <- reverseMapping.keys - denot <- pre.member(reverseMapping(renamed)).altsWith(_.isOneOf(GivenOrImplicitVal)) + denot <- pre.member(reverseMapping(renamed).nn).altsWith(_.isOneOf(GivenOrImplicitVal)) yield - val original = reverseMapping(renamed) + val original = reverseMapping(renamed).nn val ref = TermRef(pre, original, denot) if renamed == original then ref else RenamedImplicitRef(ref, renamed) @@ -176,11 +176,11 @@ class ImportInfo(symf: Context ?=> Symbol, if maybeShadowsRoot && defn.rootImportTypes.exists(_.symbol == sym) then sym else NoSymbol assert(myUnimported != null) - myUnimported + myUnimported.uncheckedNN private val isLanguageImport: Boolean = untpd.languageImport(qualifier).isDefined - private var myUnimported: Symbol = _ + private var myUnimported: Symbol | Null = _ private var featureCache: SimpleIdentityMap[TermName, java.lang.Boolean] = SimpleIdentityMap.empty @@ -218,10 +218,11 @@ class ImportInfo(symf: Context ?=> Symbol, case Some(bv) => bv case None => var c = ctx.outer - while c.importInfo eq ctx.importInfo do c = c.outer - (c.importInfo != null) && c.importInfo.featureImported(feature)(using c) + while c.importInfo eqn ctx.importInfo do c = c.outer + val cinfo = c.importInfo + (cinfo != null) && cinfo.featureImported(feature)(using c) ) - featureCache(feature) + featureCache(feature).nn def toText(printer: Printer): Text = printer.toText(this) } diff --git a/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala b/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala index a1a33482877c..88e8568dfcb9 100644 --- a/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala +++ b/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala @@ -123,8 +123,8 @@ trait ImportSuggestions: .filter(lookInside(_)) .flatMap(sym => rootsIn(sym.termRef)) val imported = - if ctx.importInfo eq ctx.outer.importInfo then Nil - else ctx.importInfo.importSym.info match + if ctx.importInfo eqn ctx.outer.importInfo then Nil + else ctx.importInfo.nn.importSym.info match case ImportType(expr) => rootsOnPath(expr.tpe) case _ => Nil defined ++ imported ++ recur(using ctx.outer) @@ -148,7 +148,7 @@ trait ImportSuggestions: */ private def importSuggestions(pt: Type)(using Context): (List[TermRef], List[TermRef]) = val timer = new Timer() - val allotted = ctx.run.importSuggestionBudget + val allotted = ctx.run.nn.importSuggestionBudget if allotted <= 1 then return (Nil, Nil) implicits.println(i"looking for import suggestions, timeout = ${allotted}ms") val start = System.currentTimeMillis() @@ -160,7 +160,7 @@ trait ImportSuggestions: val alreadyAvailableCandidates: Set[Symbol] = { val wildProto = wildApprox(pt) val contextualCandidates = ctx.implicits.eligible(wildProto) - val implicitScopeCandidates = ctx.run.implicitScope(wildProto).eligible + val implicitScopeCandidates = ctx.run.nn.implicitScope(wildProto).eligible val allCandidates = contextualCandidates ++ implicitScopeCandidates allCandidates.map(_.implicitRef.underlyingRef.symbol).toSet } @@ -196,7 +196,7 @@ trait ImportSuggestions: val task = new TimerTask: def run() = println(i"Cancelling test of $ref when making suggestions for error in ${ctx.source}") - ctx.run.isCancelled = true + ctx.run.nn.isCancelled = true val span = ctx.owner.srcPos.span val (expectedType, argument, kind) = pt match case ViewProto(argType, resType) => @@ -212,11 +212,12 @@ trait ImportSuggestions: typedImplicit(candidate, expectedType, argument, span)( using testContext()).isSuccess finally + val run = ctx.run.nn if task.cancel() then // timer task has not run yet - assert(!ctx.run.isCancelled) + assert(!run.isCancelled) else - while !ctx.run.isCancelled do () // wait until timer task has run to completion - ctx.run.isCancelled = false + while !run.isCancelled do () // wait until timer task has run to completion + run.isCancelled = false } end deepTest @@ -265,8 +266,9 @@ trait ImportSuggestions: * for current search, but but never less than to half of the previous budget. */ private def reduceTimeBudget(used: Int)(using Context) = - ctx.run.importSuggestionBudget = - (ctx.run.importSuggestionBudget - used) max (ctx.run.importSuggestionBudget / 2) + val run = ctx.run.nn + run.importSuggestionBudget = + (run.importSuggestionBudget - used) max (run.importSuggestionBudget / 2) /** The `ref` parts of this list of pairs, discarding subsequent elements that * have the same String part. Elements are sorted by their String parts. diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 095b7f21be92..e7836d647bfc 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -1366,7 +1366,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) { // the binding is to be maximized iff it only occurs contravariantly in the type val wasToBeMinimized: Boolean = { val v = syms(trSym) - if (v ne null) v else false + if (v != null) v else false } syms.updated(trSym, wasToBeMinimized || variance >= 0 : java.lang.Boolean) case _ => diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index ef3d844fb570..67f69b69fda8 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -526,7 +526,7 @@ class Namer { typer: Typer => * body and derived clause of the synthetic module class `fromCls`. */ def mergeModuleClass(mdef: Tree, modCls: TypeDef, fromCls: TypeDef): TypeDef = { - var res: TypeDef = null + var res: TypeDef | Null = null val Thicket(trees) = expanded(mdef) val merged = trees.map { tree => if (tree == modCls) { @@ -539,16 +539,17 @@ class Namer { typer: Typer => if (fromTempl.derived.nonEmpty) { if (modTempl.derived.nonEmpty) report.error(em"a class and its companion cannot both have `derives` clauses", mdef.srcPos) - res.putAttachment(desugar.DerivingCompanion, fromTempl.srcPos.startPos) + // `res` is inside a closure, so the flow-typing doesn't work here. + res.uncheckedNN.putAttachment(desugar.DerivingCompanion, fromTempl.srcPos.startPos) } - res + res.uncheckedNN } else tree } mdef.putAttachment(ExpandedTree, Thicket(merged)) - res + res.nn } /** Merge `fromCls` of `fromStat` into `toCls` of `toStat` @@ -790,7 +791,6 @@ class Namer { typer: Typer => if (Config.showCompletions && ctx.typerState != creationContext.typerState) { def levels(c: Context): Int = if (c.typerState eq creationContext.typerState) 0 - else if (c.typerState == null) -1 else if (c.outer.typerState == c.typerState) levels(c.outer) else levels(c.outer) + 1 println(s"!!!completing ${denot.symbol.showLocated} in buried typerState, gap = ${levels(ctx)}") @@ -810,13 +810,13 @@ class Namer { typer: Typer => completer.complete(denot) } - private var completedTypeParamSyms: List[TypeSymbol] = null + private var completedTypeParamSyms: List[TypeSymbol] | Null = null def setCompletedTypeParams(tparams: List[TypeSymbol]) = completedTypeParamSyms = tparams override def completerTypeParams(sym: Symbol)(using Context): List[TypeSymbol] = - if completedTypeParamSyms != null then completedTypeParamSyms + if completedTypeParamSyms != null then completedTypeParamSyms.uncheckedNN else Nil protected def addAnnotations(sym: Symbol): Unit = original match { @@ -918,8 +918,8 @@ class Namer { typer: Typer => class TypeDefCompleter(original: TypeDef)(ictx: Context) extends Completer(original)(ictx) with TypeParamsCompleter { - private var myTypeParams: List[TypeSymbol] = null - private var nestedCtx: Context = null + private var myTypeParams: List[TypeSymbol] | Null = null + private var nestedCtx: Context | Null = null assert(!original.isClassDef) /** If completion of the owner of the to be completed symbol has not yet started, @@ -940,7 +940,7 @@ class Namer { typer: Typer => if myTypeParams == null then //println(i"completing type params of $sym in ${sym.owner}") nestedCtx = localContext(sym).setNewScope - given Context = nestedCtx + given Context = nestedCtx.uncheckedNN def typeParamTrees(tdef: Tree): List[TypeDef] = tdef match case TypeDef(_, original) => @@ -955,12 +955,12 @@ class Namer { typer: Typer => myTypeParams = tparams.map(symbolOfTree(_).asType) for param <- tparams do typedAheadExpr(param) end if - myTypeParams + myTypeParams.uncheckedNN end completerTypeParams override final def typeSig(sym: Symbol): Type = val tparamSyms = completerTypeParams(sym)(using ictx) - given ctx: Context = nestedCtx + given ctx: Context = nestedCtx.nn def abstracted(tp: TypeBounds): TypeBounds = HKTypeLambda.boundsFromParams(tparamSyms, tp) @@ -1049,7 +1049,7 @@ class Namer { typer: Typer => private var localCtx: Context = _ /** info to be used temporarily while completing the class, to avoid cyclic references. */ - private var tempInfo: TempClassInfo = _ + private var tempInfo: TempClassInfo | Null = null val TypeDef(name, impl @ Template(constr, _, self, _)) = original @@ -1399,7 +1399,7 @@ class Namer { typer: Typer => end addUsingTraits completeConstructor(denot) - denot.info = tempInfo + denot.info = tempInfo.nn val parentTypes = defn.adjustForTuple(cls, cls.typeParams, defn.adjustForBoxedUnit(cls, @@ -1420,7 +1420,7 @@ class Namer { typer: Typer => original.putAttachment(AttachedDeriver, deriver) } - denot.info = tempInfo.finalized(parentTypes) + denot.info = tempInfo.nn.finalized(parentTypes) tempInfo = null // The temporary info can now be garbage-collected Checking.checkWellFormed(cls) diff --git a/compiler/src/dotty/tools/dotc/typer/Nullables.scala b/compiler/src/dotty/tools/dotc/typer/Nullables.scala index 0ea7207c7b2b..08ab428e7203 100644 --- a/compiler/src/dotty/tools/dotc/typer/Nullables.scala +++ b/compiler/src/dotty/tools/dotc/typer/Nullables.scala @@ -158,10 +158,11 @@ object Nullables: def isTracked(ref: TermRef)(using Context) = ref.isStable || { val sym = ref.symbol + val unit = ctx.compilationUnit !ref.usedOutOfOrder && sym.span.exists - && ctx.compilationUnit != null // could be null under -Ytest-pickler - && ctx.compilationUnit.assignmentSpans.contains(sym.span.start) + && (unit ne NoCompilationUnit) // could be null under -Ytest-pickler + && unit.assignmentSpans.contains(sym.span.start) } /** The nullability context to be used after a case that matches pattern `pat`. diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index 9bfc66a70be6..1da11ca71992 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -383,14 +383,15 @@ object ProtoTypes { targ = arg.withType(WildcardType) case _ => targ = typerFn(arg) + // TODO: investigate why flow typing is not working on `targ` if ctx.reporter.hasUnreportedErrors then - if hasInnerErrors(targ) then + if hasInnerErrors(targ.nn) then state.errorArgs += arg else - state.typedArg = state.typedArg.updated(arg, targ) + state.typedArg = state.typedArg.updated(arg, targ.nn) state.errorArgs -= arg } - targ + targ.nn } /** The typed arguments. This takes any arguments already typed using @@ -800,7 +801,7 @@ object ProtoTypes { /** Approximate occurrences of parameter types and uninstantiated typevars * by wildcard types. */ - private def wildApprox(tp: Type, theMap: WildApproxMap, seen: Set[TypeParamRef], internal: Set[TypeLambda])(using Context): Type = tp match { + private def wildApprox(tp: Type, theMap: WildApproxMap | Null, seen: Set[TypeParamRef], internal: Set[TypeLambda])(using Context): Type = tp match { case tp: NamedType => // default case, inlined for speed val isPatternBoundTypeRef = tp.isInstanceOf[TypeRef] && tp.symbol.isPatternBound if (isPatternBoundTypeRef) WildcardType(tp.underlying.bounds) diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index d7fe9dc1916a..5c079ae05b83 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -1050,9 +1050,9 @@ object RefChecks { val matches = referencePattern.findAllIn(s) for reference <- matches do val referenceOffset = matches.start - val prefixlessReference = reference.replaceFirst("""\$\{\s*""", "") + val prefixlessReference = reference.replaceFirst("""\$\{\s*""", "").nn val variableOffset = referenceOffset + reference.length - prefixlessReference.length - val variableName = prefixlessReference.replaceFirst("""\s*\}""", "") + val variableName = prefixlessReference.replaceFirst("""\s*\}""", "").nn f(variableName, variableOffset) end checkImplicitNotFoundAnnotation diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index fe6e2f07f4fb..e5aefd8a13d9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -309,7 +309,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer */ def isDefinedInCurrentUnit(denot: Denotation)(using Context): Boolean = denot match { case MultiDenotation(d1, d2) => isDefinedInCurrentUnit(d1) || isDefinedInCurrentUnit(d2) - case denot: SingleDenotation => ctx.compilationUnit != null && denot.symbol.source == ctx.compilationUnit.source + case denot: SingleDenotation => (ctx.compilationUnit ne NoCompilationUnit) && denot.symbol.source == ctx.compilationUnit.source } /** Is `denot` the denotation of a self symbol? */ @@ -324,7 +324,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer (prevPrec.ordinal < prec.ordinal || prevPrec == prec && (prevCtx.scope eq ctx.scope)) @tailrec def loop(lastCtx: Context)(using Context): Type = - if (ctx.scope == null) previous + if (ctx.scope eq EmptyScope) previous else { var result: Type = NoType @@ -431,15 +431,15 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer val outer = ctx.outer val curImport = ctx.importInfo def updateUnimported() = - if (curImport.unimported ne NoSymbol) unimported += curImport.unimported + if (curImport.nn.unimported ne NoSymbol) unimported += curImport.nn.unimported if (curOwner.is(Package) && curImport != null && curImport.isRootImport && previous.exists) previous // no more conflicts possible in this case - else if (isPossibleImport(NamedImport) && (curImport ne outer.importInfo)) { - val namedImp = namedImportRef(curImport) + else if (isPossibleImport(NamedImport) && (curImport nen outer.importInfo)) { + val namedImp = namedImportRef(curImport.uncheckedNN) if (namedImp.exists) recurAndCheckNewOrShadowed(namedImp, NamedImport, ctx)(using outer) - else if (isPossibleImport(WildImport) && !curImport.importSym.isCompleting) { - val wildImp = wildImportRef(curImport) + else if (isPossibleImport(WildImport) && !curImport.nn.importSym.isCompleting) { + val wildImp = wildImportRef(curImport.uncheckedNN) if (wildImp.exists) recurAndCheckNewOrShadowed(wildImp, WildImport, ctx)(using outer) else { @@ -780,7 +780,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer } catch { case ex: FromDigitsException => - report.error(ex.getMessage, tree.srcPos) + report.error(ex.getMessage.nn, tree.srcPos) tree.kind match { case Whole(_) => lit(0) case _ => lit(0.0) @@ -1227,7 +1227,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer if pos < mtpe.paramInfos.length then mtpe.paramInfos(pos) // This works only if vararg annotations match up. - // See neg/i14367.scala for an example where the inferred type is mispredicted. + // See neg/i14367.scala for an example where the inferred type is mispredicted. // Nevertheless, the alternative would be to give up completely, so this is // defensible. else NoType @@ -2184,7 +2184,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer val sup = Suppression(tree.sourcePos, filters, range.start, range.end, verbose) // invalid suppressions, don't report as unused if filters == List(MessageFilter.None) then sup.markUsed() - ctx.run.suppressions.addSuppression(sup) + ctx.run.nn.suppressions.addSuppression(sup) def typedValDef(vdef: untpd.ValDef, sym: Symbol)(using Context): Tree = { val ValDef(name, tpt, _) = vdef @@ -2937,7 +2937,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer assertPositioned(tree) if tree.source != ctx.source && tree.source.exists then typed(tree, pt, locked)(using ctx.withSource(tree.source)) - else if ctx.run.isCancelled then + else if ctx.run.nn.isCancelled then tree.withType(WildcardType) else adapt(typedUnadapted(tree, pt, locked), pt, locked) } diff --git a/compiler/src/dotty/tools/dotc/typer/TyperPhase.scala b/compiler/src/dotty/tools/dotc/typer/TyperPhase.scala index cf2a1c1d1379..71e1dc961c00 100644 --- a/compiler/src/dotty/tools/dotc/typer/TyperPhase.scala +++ b/compiler/src/dotty/tools/dotc/typer/TyperPhase.scala @@ -44,7 +44,7 @@ class TyperPhase(addRootImports: Boolean = true) extends Phase { typr.println("typed: " + unit.source) record("retained untyped trees", unit.untpdTree.treeSize) record("retained typed trees after typer", unit.tpdTree.treeSize) - ctx.run.suppressions.reportSuspendedMessages(unit.source) + ctx.run.nn.suppressions.reportSuspendedMessages(unit.source) catch case ex: CompilationUnit.SuspendException => } @@ -86,7 +86,7 @@ class TyperPhase(addRootImports: Boolean = true) extends Phase { unitContexts.foreach(javaCheck(using _)) // after typechecking to avoid cycles val newUnits = unitContexts.map(_.compilationUnit).filterNot(discardAfterTyper) - ctx.run.checkSuspendedUnits(newUnits) + ctx.run.nn.checkSuspendedUnits(newUnits) newUnits def run(using Context): Unit = unsupported("run") diff --git a/compiler/src/dotty/tools/dotc/util/Attachment.scala b/compiler/src/dotty/tools/dotc/util/Attachment.scala index 8f0e5dd97dfe..d545c3631f20 100644 --- a/compiler/src/dotty/tools/dotc/util/Attachment.scala +++ b/compiler/src/dotty/tools/dotc/util/Attachment.scala @@ -1,6 +1,7 @@ -package dotty.tools.dotc.util +package dotty.tools.dotc +package util -import dotty.tools.dotc.core.Contexts.Context +import core.Contexts.Context /** A class inheriting from Attachment.Container supports * adding, removing and lookup of attachments. Attachments are typed key/value pairs. @@ -15,7 +16,7 @@ object Attachment { * Clients should inherit from Container instead. */ trait LinkSource { - private[Attachment] var next: Link[?] + private[Attachment] var next: Link[?] | Null /** Optionally get attachment corresponding to `key` */ final def getAttachment[V](key: Key[V]): Option[V] = { @@ -94,16 +95,16 @@ object Attachment { /** A private, concrete implementation class linking attachments. */ - private[Attachment] class Link[+V](val key: Key[V], val value: V, var next: Link[?]) + private[Attachment] class Link[+V](val key: Key[V], val value: V, var next: Link[?] | Null) extends LinkSource /** A trait for objects that can contain attachments */ trait Container extends LinkSource { - private[Attachment] var next: Link[?] = null + private[Attachment] var next: Link[?] | Null = null /** Copy the sticky attachments from `container` to this container. */ final def withAttachmentsFrom(container: Container): this.type = { - var current: Link[?] = container.next + var current: Link[?] | Null = container.next while (current != null) { if (current.key.isInstanceOf[StickyKey[?]]) putAttachment(current.key, current.value) current = current.next diff --git a/compiler/src/dotty/tools/dotc/util/ClasspathFromClassloader.scala b/compiler/src/dotty/tools/dotc/util/ClasspathFromClassloader.scala index 7094cf589af7..25def103083d 100644 --- a/compiler/src/dotty/tools/dotc/util/ClasspathFromClassloader.scala +++ b/compiler/src/dotty/tools/dotc/util/ClasspathFromClassloader.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.util +import scala.language.unsafeNulls + import java.net.URLClassLoader import java.nio.file.Paths diff --git a/compiler/src/dotty/tools/dotc/util/CommentParsing.scala b/compiler/src/dotty/tools/dotc/util/CommentParsing.scala index c25660a6225a..b4af59c09310 100644 --- a/compiler/src/dotty/tools/dotc/util/CommentParsing.scala +++ b/compiler/src/dotty/tools/dotc/util/CommentParsing.scala @@ -5,6 +5,8 @@ */ package dotty.tools.dotc.util +import scala.language.unsafeNulls + import scala.collection.mutable /** The comment parsing in `dotc` is used by both the comment cooking and the diff --git a/compiler/src/dotty/tools/dotc/util/DiffUtil.scala b/compiler/src/dotty/tools/dotc/util/DiffUtil.scala index 93532a0709a9..cec86fa84443 100644 --- a/compiler/src/dotty/tools/dotc/util/DiffUtil.scala +++ b/compiler/src/dotty/tools/dotc/util/DiffUtil.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.util +import scala.language.unsafeNulls + import scala.annotation.tailrec import scala.collection.mutable diff --git a/compiler/src/dotty/tools/dotc/util/EqHashMap.scala b/compiler/src/dotty/tools/dotc/util/EqHashMap.scala index 39027e2d716d..ea049acba02b 100644 --- a/compiler/src/dotty/tools/dotc/util/EqHashMap.scala +++ b/compiler/src/dotty/tools/dotc/util/EqHashMap.scala @@ -68,7 +68,7 @@ extends GenericHashMap[Key, Value](initialCapacity, capacityMultiple): setKey(idx, key) setValue(idx, value) - override def copyFrom(oldTable: Array[AnyRef]): Unit = + override def copyFrom(oldTable: Array[AnyRef | Null]): Unit = if isDense then Array.copy(oldTable, 0, table, 0, oldTable.length) else diff --git a/compiler/src/dotty/tools/dotc/util/GenericHashMap.scala b/compiler/src/dotty/tools/dotc/util/GenericHashMap.scala index f2a3f012f76c..fd6518fcc15c 100644 --- a/compiler/src/dotty/tools/dotc/util/GenericHashMap.scala +++ b/compiler/src/dotty/tools/dotc/util/GenericHashMap.scala @@ -29,11 +29,11 @@ abstract class GenericHashMap[Key, Value] protected var used: Int = _ protected var limit: Int = _ - protected var table: Array[AnyRef] = _ + protected var table: Array[AnyRef | Null] = _ clear() private def allocate(capacity: Int) = - table = new Array[AnyRef](capacity * 2) + table = new Array[AnyRef | Null](capacity * 2) limit = if capacity <= DenseLimit then capacity - 1 else capacity / capacityMultiple private def roundToPower(n: Int) = @@ -145,14 +145,14 @@ abstract class GenericHashMap[Key, Value] setKey(idx, key) setValue(idx, value) - def copyFrom(oldTable: Array[AnyRef]): Unit = + def copyFrom(oldTable: Array[AnyRef | Null]): Unit = if isDense then Array.copy(oldTable, 0, table, 0, oldTable.length) else var idx = 0 while idx < oldTable.length do - val key = oldTable(idx).asInstanceOf[Key] - if key != null then addOld(key, oldTable(idx + 1).asInstanceOf[Value]) + val key = oldTable(idx) + if key != null then addOld(key.asInstanceOf[Key], oldTable(idx + 1).asInstanceOf[Value]) idx += 2 protected def growTable(): Unit = diff --git a/compiler/src/dotty/tools/dotc/util/HashMap.scala b/compiler/src/dotty/tools/dotc/util/HashMap.scala index 75d84301122f..aaae781c310a 100644 --- a/compiler/src/dotty/tools/dotc/util/HashMap.scala +++ b/compiler/src/dotty/tools/dotc/util/HashMap.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.util +import scala.language.unsafeNulls + /** A specialized implementation of GenericHashMap with standard hashCode and equals * as comparison */ @@ -71,7 +73,7 @@ extends GenericHashMap[Key, Value](initialCapacity, capacityMultiple): setKey(idx, key) setValue(idx, value) - override def copyFrom(oldTable: Array[AnyRef]): Unit = + override def copyFrom(oldTable: Array[AnyRef | Null]): Unit = if isDense then Array.copy(oldTable, 0, table, 0, oldTable.length) else diff --git a/compiler/src/dotty/tools/dotc/util/HashSet.scala b/compiler/src/dotty/tools/dotc/util/HashSet.scala index e99754c7267b..a524dd39a594 100644 --- a/compiler/src/dotty/tools/dotc/util/HashSet.scala +++ b/compiler/src/dotty/tools/dotc/util/HashSet.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.util +import dotty.tools.uncheckedNN + object HashSet: /** The number of elements up to which dense packing is used. @@ -29,12 +31,12 @@ class HashSet[T](initialCapacity: Int = 8, capacityMultiple: Int = 2) extends Mu private var used: Int = _ private var limit: Int = _ - private var table: Array[AnyRef] = _ + private var table: Array[AnyRef | Null] = _ clear() private def allocate(capacity: Int) = - table = new Array[AnyRef](capacity) + table = new Array[AnyRef | Null](capacity) limit = if capacity <= DenseLimit then capacity - 1 else capacity / capacityMultiple private def roundToPower(n: Int) = @@ -67,27 +69,27 @@ class HashSet[T](initialCapacity: Int = 8, capacityMultiple: Int = 2) extends Mu /** Turn hashcode `x` into a table index */ protected def index(x: Int): Int = x & (table.length - 1) - protected def currentTable: Array[AnyRef] = table + protected def currentTable: Array[AnyRef | Null] = table protected def firstIndex(x: T) = if isDense then 0 else index(hash(x)) protected def nextIndex(idx: Int) = Stats.record(statsItem("miss")) index(idx + 1) - protected def entryAt(idx: Int) = table(idx).asInstanceOf[T] - protected def setEntry(idx: Int, x: T) = table(idx) = x.asInstanceOf[AnyRef] + protected def entryAt(idx: Int): T | Null = table(idx).asInstanceOf[T | Null] + protected def setEntry(idx: Int, x: T) = table(idx) = x.asInstanceOf[AnyRef | Null] def lookup(x: T): T | Null = Stats.record(statsItem("lookup")) var idx = firstIndex(x) - var e = entryAt(idx) + var e: T | Null = entryAt(idx) while e != null do - if isEqual(e, x) then return e + if isEqual(e.uncheckedNN, x) then return e idx = nextIndex(idx) e = entryAt(idx) null -/** Add entry at `x` at index `idx` */ + /** Add entry at `x` at index `idx` */ protected def addEntryAt(idx: Int, x: T): T = Stats.record(statsItem("addEntryAt")) setEntry(idx, x) @@ -98,9 +100,10 @@ class HashSet[T](initialCapacity: Int = 8, capacityMultiple: Int = 2) extends Mu def put(x: T): T = Stats.record(statsItem("put")) var idx = firstIndex(x) - var e = entryAt(idx) + var e: T | Null = entryAt(idx) while e != null do - if isEqual(e, x) then return e + // TODO: remove uncheckedNN when explicit-nulls is enabled for regule compiling + if isEqual(e.uncheckedNN, x) then return e.uncheckedNN idx = nextIndex(idx) e = entryAt(idx) addEntryAt(idx, x) @@ -110,22 +113,22 @@ class HashSet[T](initialCapacity: Int = 8, capacityMultiple: Int = 2) extends Mu def remove(x: T): Boolean = Stats.record(statsItem("remove")) var idx = firstIndex(x) - var e = entryAt(idx) + var e: T | Null = entryAt(idx) while e != null do - if isEqual(e, x) then + if isEqual(e.uncheckedNN, x) then var hole = idx while idx = nextIndex(idx) e = entryAt(idx) e != null do - val eidx = index(hash(e)) + val eidx = index(hash(e.uncheckedNN)) if isDense || index(eidx - (hole + 1)) > index(idx - (hole + 1)) // entry `e` at `idx` can move unless `index(hash(e))` is in // the (ring-)interval [hole + 1 .. idx] then - setEntry(hole, e) + setEntry(hole, e.uncheckedNN) hole = idx table(hole) = null used -= 1 @@ -146,14 +149,14 @@ class HashSet[T](initialCapacity: Int = 8, capacityMultiple: Int = 2) extends Mu e = entryAt(idx) setEntry(idx, x) - def copyFrom(oldTable: Array[AnyRef]): Unit = + def copyFrom(oldTable: Array[AnyRef | Null]): Unit = if isDense then Array.copy(oldTable, 0, table, 0, oldTable.length) else var idx = 0 while idx < oldTable.length do - val e = oldTable(idx).asInstanceOf[T] - if e != null then addOld(e) + val e: T | Null = oldTable(idx).asInstanceOf[T | Null] + if e != null then addOld(e.uncheckedNN) idx += 1 protected def growTable(): Unit = @@ -165,14 +168,14 @@ class HashSet[T](initialCapacity: Int = 8, capacityMultiple: Int = 2) extends Mu copyFrom(oldTable) abstract class EntryIterator extends Iterator[T]: - def entry(idx: Int): T + def entry(idx: Int): T | Null private var idx = 0 def hasNext = while idx < table.length && table(idx) == null do idx += 1 idx < table.length def next() = require(hasNext) - try entry(idx) finally idx += 1 + try entry(idx).uncheckedNN finally idx += 1 def iterator: Iterator[T] = new EntryIterator(): def entry(idx: Int) = entryAt(idx) diff --git a/compiler/src/dotty/tools/dotc/util/LRUCache.scala b/compiler/src/dotty/tools/dotc/util/LRUCache.scala index d57e59827ce0..99ee8a80227b 100644 --- a/compiler/src/dotty/tools/dotc/util/LRUCache.scala +++ b/compiler/src/dotty/tools/dotc/util/LRUCache.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.util +import scala.language.unsafeNulls + import reflect.ClassTag import annotation.tailrec diff --git a/compiler/src/dotty/tools/dotc/util/LinearMap.scala b/compiler/src/dotty/tools/dotc/util/LinearMap.scala index 1e5754c34f3e..28a5daaefdba 100644 --- a/compiler/src/dotty/tools/dotc/util/LinearMap.scala +++ b/compiler/src/dotty/tools/dotc/util/LinearMap.scala @@ -7,17 +7,17 @@ import collection.immutable * map for sizes <= 4 (where immutable maps have specialized, compact * representations) and as a HashMap for larger sizes. */ -opaque type LinearMap[K <: AnyRef, V >: Null <: AnyRef] = +opaque type LinearMap[K <: AnyRef, V <: AnyRef | Null] = immutable.Map[K, V] | HashMap[K, V] object LinearMap: - def empty[K <: AnyRef, V >: Null <: AnyRef]: LinearMap[K, V] = + def empty[K <: AnyRef, V <: AnyRef | Null]: LinearMap[K, V] = immutable.Map.empty[K, V] - extension [K <: AnyRef, V >: Null <: AnyRef](m: LinearMap[K, V]) + extension [K <: AnyRef, V <: AnyRef | Null](m: LinearMap[K, V]) - def lookup(key: K): V /*| Null*/ = (m: @unchecked) match + def lookup(key: K): V | Null = (m: @unchecked) match case m: immutable.AbstractMap[K, V] @unchecked => if m.contains(key) then m(key) else null case m: HashMap[K, V] @unchecked => diff --git a/compiler/src/dotty/tools/dotc/util/LinearSet.scala b/compiler/src/dotty/tools/dotc/util/LinearSet.scala index 80507ef8bedb..d057c4ebeda9 100644 --- a/compiler/src/dotty/tools/dotc/util/LinearSet.scala +++ b/compiler/src/dotty/tools/dotc/util/LinearSet.scala @@ -1,18 +1,19 @@ package dotty.tools.dotc.util + import collection.immutable /** A linear set is a set where after a `+` the previous set value cannot be * used anymore. The set is implemented as an immutable set for sizes <= 4 * and as a HashSet for larger sizes. */ -opaque type LinearSet[Elem >: Null <: AnyRef] = +opaque type LinearSet[Elem <: AnyRef | Null] = immutable.Set[Elem] | HashSet[Elem] object LinearSet: - def empty[Elem >: Null <: AnyRef]: LinearSet[Elem] = immutable.Set.empty[Elem] + def empty[Elem <: AnyRef | Null]: LinearSet[Elem] = immutable.Set.empty[Elem] - extension [Elem >: Null <: AnyRef](s: LinearSet[Elem]) + extension [Elem <: AnyRef | Null](s: LinearSet[Elem]) def contains(elem: Elem): Boolean = (s: @unchecked) match case s: immutable.AbstractSet[Elem] @unchecked => s.contains(elem) diff --git a/compiler/src/dotty/tools/dotc/util/NameTransformer.scala b/compiler/src/dotty/tools/dotc/util/NameTransformer.scala index 8b68836c068b..61cf238fbc7f 100644 --- a/compiler/src/dotty/tools/dotc/util/NameTransformer.scala +++ b/compiler/src/dotty/tools/dotc/util/NameTransformer.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package util +import scala.language.unsafeNulls + import core.Names._ import scala.annotation.internal.sharable diff --git a/compiler/src/dotty/tools/dotc/util/ParsedComment.scala b/compiler/src/dotty/tools/dotc/util/ParsedComment.scala index b7afe1aec2a4..0aefd4e43981 100644 --- a/compiler/src/dotty/tools/dotc/util/ParsedComment.scala +++ b/compiler/src/dotty/tools/dotc/util/ParsedComment.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.util +import scala.language.unsafeNulls + import dotty.tools.dotc.core.Comments.{Comment, CommentsContext} import dotty.tools.dotc.core.Contexts._ import dotty.tools.dotc.core.Names.TermName diff --git a/compiler/src/dotty/tools/dotc/util/ShowPickled.scala b/compiler/src/dotty/tools/dotc/util/ShowPickled.scala index e744cc3c1e5e..f85a57a8f812 100644 --- a/compiler/src/dotty/tools/dotc/util/ShowPickled.scala +++ b/compiler/src/dotty/tools/dotc/util/ShowPickled.scala @@ -113,7 +113,7 @@ object ShowPickled { result.toInt } - def printFile(buf: PickleBuffer, out: PrintStream = System.out): Unit = { + def printFile(buf: PickleBuffer, out: PrintStream = System.out.nn): Unit = { out.println("Version " + buf.readNat() + "." + buf.readNat()) val index = buf.createIndex val entryList = makeEntryList(buf, index) diff --git a/compiler/src/dotty/tools/dotc/util/SimpleIdentityMap.scala b/compiler/src/dotty/tools/dotc/util/SimpleIdentityMap.scala index c7dc8632f194..2f202bc05921 100644 --- a/compiler/src/dotty/tools/dotc/util/SimpleIdentityMap.scala +++ b/compiler/src/dotty/tools/dotc/util/SimpleIdentityMap.scala @@ -5,10 +5,10 @@ import collection.mutable.ListBuffer /** A simple linked map with `eq` as the key comparison, optimized for small maps. * It has linear complexity for `apply`, `updated`, and `remove`. */ -abstract class SimpleIdentityMap[K <: AnyRef, +V >: Null <: AnyRef] extends (K => V) { +abstract class SimpleIdentityMap[K <: AnyRef, +V <: AnyRef] extends (K => V | Null) { final def isEmpty: Boolean = this eq SimpleIdentityMap.myEmpty def size: Int - def apply(k: K): V + def apply(k: K): V | Null def remove(k: K): SimpleIdentityMap[K, V] def updated[V1 >: V <: AnyRef](k: K, v: V1): SimpleIdentityMap[K, V1] def contains(k: K): Boolean = apply(k) != null @@ -32,25 +32,25 @@ object SimpleIdentityMap { private val CompactifyThreshold = 4 - private object myEmpty extends SimpleIdentityMap[AnyRef, Null] { + private object myEmpty extends SimpleIdentityMap[AnyRef, Nothing] { def size = 0 def apply(k: AnyRef) = null def remove(k: AnyRef) = this - def updated[V1 >: Null <: AnyRef](k: AnyRef, v: V1) = new Map1(k, v) - def mapValuesNow[V1 >: Null <: AnyRef](f: (AnyRef, V1) => V1) = this - def foreachBinding(f: (AnyRef, Null) => Unit) = () - def forallBinding(f: (AnyRef, Null) => Boolean) = true + def updated[V1 <: AnyRef](k: AnyRef, v: V1) = new Map1(k, v) + def mapValuesNow[V1 <: AnyRef](f: (AnyRef, V1) => V1) = this + def foreachBinding(f: (AnyRef, Nothing) => Unit) = () + def forallBinding(f: (AnyRef, Nothing) => Boolean) = true } - def empty[K <: AnyRef]: SimpleIdentityMap[K, Null] = myEmpty.asInstanceOf[SimpleIdentityMap[K, Null]] + def empty[K <: AnyRef]: SimpleIdentityMap[K, Nothing] = myEmpty.asInstanceOf[SimpleIdentityMap[K, Nothing]] - class Map1[K <: AnyRef, +V >: Null <: AnyRef] (k1: K, v1: V) extends SimpleIdentityMap[K, V] { + class Map1[K <: AnyRef, +V <: AnyRef] (k1: K, v1: V) extends SimpleIdentityMap[K, V] { def size: Int = 1 - def apply(k: K): V = + def apply(k: K): V | Null = if (k eq k1) v1 else null def remove(k: K): SimpleIdentityMap[K, V] = - if (k eq k1) empty.asInstanceOf[SimpleIdentityMap[K, V]] + if (k eq k1) empty else this def updated[V1 >: V <: AnyRef](k: K, v: V1): SimpleIdentityMap[K, V1] = if (k eq k1) new Map1(k, v) @@ -63,9 +63,9 @@ object SimpleIdentityMap { def forallBinding(f: (K, V) => Boolean): Boolean = f(k1, v1) } - class Map2[K <: AnyRef, +V >: Null <: AnyRef] (k1: K, v1: V, k2: K, v2: V) extends SimpleIdentityMap[K, V] { + class Map2[K <: AnyRef, +V <: AnyRef] (k1: K, v1: V, k2: K, v2: V) extends SimpleIdentityMap[K, V] { def size: Int = 2 - def apply(k: K): V = + def apply(k: K): V | Null = if (k eq k1) v1 else if (k eq k2) v2 else null @@ -86,9 +86,9 @@ object SimpleIdentityMap { def forallBinding(f: (K, V) => Boolean): Boolean = f(k1, v1) && f(k2, v2) } - class Map3[K <: AnyRef, +V >: Null <: AnyRef] (k1: K, v1: V, k2: K, v2: V, k3: K, v3: V) extends SimpleIdentityMap[K, V] { + class Map3[K <: AnyRef, +V <: AnyRef] (k1: K, v1: V, k2: K, v2: V, k3: K, v3: V) extends SimpleIdentityMap[K, V] { def size: Int = 3 - def apply(k: K): V = + def apply(k: K): V | Null = if (k eq k1) v1 else if (k eq k2) v2 else if (k eq k3) v3 @@ -112,9 +112,9 @@ object SimpleIdentityMap { def forallBinding(f: (K, V) => Boolean): Boolean = f(k1, v1) && f(k2, v2) && f(k3, v3) } - class Map4[K <: AnyRef, +V >: Null <: AnyRef] (k1: K, v1: V, k2: K, v2: V, k3: K, v3: V, k4: K, v4: V) extends SimpleIdentityMap[K, V] { + class Map4[K <: AnyRef, +V <: AnyRef] (k1: K, v1: V, k2: K, v2: V, k3: K, v3: V, k4: K, v4: V) extends SimpleIdentityMap[K, V] { def size: Int = 4 - def apply(k: K): V = + def apply(k: K): V | Null = if (k eq k1) v1 else if (k eq k2) v2 else if (k eq k3) v3 @@ -141,14 +141,14 @@ object SimpleIdentityMap { def forallBinding(f: (K, V) => Boolean): Boolean = f(k1, v1) && f(k2, v2) && f(k3, v3) && f(k4, v4) } - class MapMore[K <: AnyRef, +V >: Null <: AnyRef](bindings: Array[AnyRef]) extends SimpleIdentityMap[K, V] { + class MapMore[K <: AnyRef, +V <: AnyRef](bindings: Array[AnyRef]) extends SimpleIdentityMap[K, V] { private def key(i: Int): K = bindings(i).asInstanceOf[K] private def value(i: Int): V = bindings(i + 1).asInstanceOf[V] def size: Int = bindings.length / 2 Stats.record(s"SimpleIdentityMap/$size") - def apply(k: K): V = { + def apply(k: K): V | Null = { var i = 0 while (i < bindings.length) { if (bindings(i) eq k) return value(i) diff --git a/compiler/src/dotty/tools/dotc/util/SimpleIdentitySet.scala b/compiler/src/dotty/tools/dotc/util/SimpleIdentitySet.scala index 45ee3652fe16..ed49699b633a 100644 --- a/compiler/src/dotty/tools/dotc/util/SimpleIdentitySet.scala +++ b/compiler/src/dotty/tools/dotc/util/SimpleIdentitySet.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.util +import scala.language.unsafeNulls + import collection.mutable /** A simple linked set with `eq` as the comparison, optimized for small sets. diff --git a/compiler/src/dotty/tools/dotc/util/SourceFile.scala b/compiler/src/dotty/tools/dotc/util/SourceFile.scala index bddcd02e7ab9..6df6c42b59b2 100644 --- a/compiler/src/dotty/tools/dotc/util/SourceFile.scala +++ b/compiler/src/dotty/tools/dotc/util/SourceFile.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package util +import scala.language.unsafeNulls + import dotty.tools.io._ import Spans._ import core.Contexts._ @@ -58,7 +60,7 @@ object ScriptSourceFile { class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends interfaces.SourceFile { import SourceFile._ - private var myContent: Array[Char] = null + private var myContent: Array[Char] | Null = null def content(): Array[Char] = { if (myContent == null) myContent = computeContent @@ -267,10 +269,10 @@ object SourceFile { /** Return true if file is a script: * if filename extension is not .scala and has a script header. */ - def isScript(file: AbstractFile, content: Array[Char]): Boolean = + def isScript(file: AbstractFile | Null, content: Array[Char]): Boolean = ScriptSourceFile.hasScriptHeader(content) - def apply(file: AbstractFile, codec: Codec): SourceFile = + def apply(file: AbstractFile | Null, codec: Codec): SourceFile = // see note above re: Files.exists is remarkably slow val chars = try diff --git a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala index 7808c9a57acd..29f9a34d2292 100644 --- a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala +++ b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package util +import scala.language.unsafeNulls + import printing.{Showable, Printer} import printing.Texts._ import core.Contexts.Context diff --git a/compiler/src/dotty/tools/dotc/util/Spans.scala b/compiler/src/dotty/tools/dotc/util/Spans.scala index 0a28c367ff29..baf2cfa121b0 100644 --- a/compiler/src/dotty/tools/dotc/util/Spans.scala +++ b/compiler/src/dotty/tools/dotc/util/Spans.scala @@ -1,5 +1,6 @@ package dotty.tools.dotc package util + import language.implicitConversions /** The offsets part of a full position, consisting of 2 or 3 entries: diff --git a/compiler/src/dotty/tools/dotc/util/StackTraceOps.scala b/compiler/src/dotty/tools/dotc/util/StackTraceOps.scala index 071fc22afa3d..7fa54606c572 100644 --- a/compiler/src/dotty/tools/dotc/util/StackTraceOps.scala +++ b/compiler/src/dotty/tools/dotc/util/StackTraceOps.scala @@ -12,6 +12,8 @@ package dotty.tools.dotc.util +import scala.language.unsafeNulls + import collection.mutable, mutable.ListBuffer import scala.util.chaining.given import java.lang.System.lineSeparator diff --git a/compiler/src/dotty/tools/dotc/util/Store.scala b/compiler/src/dotty/tools/dotc/util/Store.scala index 72e6da0faa49..d8c9230b9272 100644 --- a/compiler/src/dotty/tools/dotc/util/Store.scala +++ b/compiler/src/dotty/tools/dotc/util/Store.scala @@ -7,24 +7,24 @@ object Store { val empty: Store = new Store(Array()) } -class Store(private val elems: Array[AnyRef]) extends AnyVal { +class Store(private val elems: Array[AnyRef | Null]) extends AnyVal { import Store._ def newLocation[T](): (Location[T], Store) = { - val elems1 = new Array[AnyRef](elems.length + 1) + val elems1 = new Array[AnyRef | Null](elems.length + 1) System.arraycopy(elems, 0, elems1, 0, elems.length) (new Location(elems.length), new Store(elems1)) } def newLocation[T](initial: T): (Location[T], Store) = { val (loc, store) = newLocation[T]() - store.elems(loc.idx) = initial.asInstanceOf[AnyRef] + store.elems(loc.idx) = initial.asInstanceOf[AnyRef | Null] (loc, store) } def updated[T](loc: Location[T], value: T): Store = { val elems1 = elems.clone - elems1(loc.idx) = value.asInstanceOf[AnyRef] + elems1(loc.idx) = value.asInstanceOf[AnyRef | Null] new Store(elems1) } diff --git a/compiler/src/dotty/tools/dotc/util/WeakHashSet.scala b/compiler/src/dotty/tools/dotc/util/WeakHashSet.scala index 37931463ec32..3c23b181a041 100644 --- a/compiler/src/dotty/tools/dotc/util/WeakHashSet.scala +++ b/compiler/src/dotty/tools/dotc/util/WeakHashSet.scala @@ -6,6 +6,8 @@ import java.lang.ref.{ReferenceQueue, WeakReference} import scala.annotation.{ constructorOnly, tailrec } +import dotty.tools._ + /** * A HashSet where the elements are stored weakly. Elements in this set are eligible for GC if no other * hard references are associated with them. Its primary use case is as a canonical reference @@ -49,7 +51,7 @@ abstract class WeakHashSet[A <: AnyRef](initialCapacity: Int = 8, loadFactor: Do /** * the underlying table of entries which is an array of Entry linked lists */ - protected var table = new Array[Entry[A]](computeCapacity) + protected var table = new Array[Entry[A] | Null](computeCapacity) /** * the limit at which we'll increase the size of the hash table @@ -67,7 +69,7 @@ abstract class WeakHashSet[A <: AnyRef](initialCapacity: Int = 8, loadFactor: Do /** * remove a single entry from a linked list in a given bucket */ - private def remove(bucket: Int, prevEntry: Entry[A], entry: Entry[A]): Unit = { + private def remove(bucket: Int, prevEntry: Entry[A] | Null, entry: Entry[A]): Unit = { Stats.record(statsItem("remove")) prevEntry match { case null => table(bucket) = entry.tail @@ -80,7 +82,7 @@ abstract class WeakHashSet[A <: AnyRef](initialCapacity: Int = 8, loadFactor: Do * remove entries associated with elements that have been gc'ed */ protected def removeStaleEntries(): Unit = { - def poll(): Entry[A] = queue.poll().asInstanceOf[Entry[A]] + def poll(): Entry[A] | Null = queue.poll().asInstanceOf @tailrec def queueLoop(): Unit = { @@ -89,8 +91,10 @@ abstract class WeakHashSet[A <: AnyRef](initialCapacity: Int = 8, loadFactor: Do val bucket = index(stale.hash) @tailrec - def linkedListLoop(prevEntry: Entry[A], entry: Entry[A]): Unit = if (stale eq entry) remove(bucket, prevEntry, entry) - else if (entry != null) linkedListLoop(entry, entry.tail) + def linkedListLoop(prevEntry: Entry[A] | Null, entry: Entry[A] | Null): Unit = + if entry != null then + if stale eq entry then remove(bucket, prevEntry, entry) + else linkedListLoop(entry, entry.tail) linkedListLoop(null, table(bucket)) @@ -107,13 +111,13 @@ abstract class WeakHashSet[A <: AnyRef](initialCapacity: Int = 8, loadFactor: Do protected def resize(): Unit = { Stats.record(statsItem("resize")) val oldTable = table - table = new Array[Entry[A]](oldTable.size * 2) + table = new Array[Entry[A] | Null](oldTable.size * 2) threshold = computeThreshold @tailrec def tableLoop(oldBucket: Int): Unit = if (oldBucket < oldTable.size) { @tailrec - def linkedListLoop(entry: Entry[A]): Unit = entry match { + def linkedListLoop(entry: Entry[A] | Null): Unit = entry match { case null => () case _ => val bucket = index(entry.hash) @@ -129,26 +133,28 @@ abstract class WeakHashSet[A <: AnyRef](initialCapacity: Int = 8, loadFactor: Do tableLoop(0) } - def lookup(elem: A): A | Null = elem match { + // TODO: remove the `case null` when we can enable explicit nulls in regular compiling, + // since the type `A <: AnyRef` of `elem` can ensure the value is not null. + def lookup(elem: A): A | Null = (elem: A | Null) match { case null => throw new NullPointerException("WeakHashSet cannot hold nulls") - case _ => + case _ => Stats.record(statsItem("lookup")) removeStaleEntries() val bucket = index(hash(elem)) @tailrec - def linkedListLoop(entry: Entry[A]): A = entry match { - case null => null.asInstanceOf[A] + def linkedListLoop(entry: Entry[A] | Null): A | Null = entry match { + case null => null case _ => val entryElem = entry.get - if (isEqual(elem, entryElem)) entryElem + if entryElem != null && isEqual(elem, entryElem) then entryElem else linkedListLoop(entry.tail) } linkedListLoop(table(bucket)) } - protected def addEntryAt(bucket: Int, elem: A, elemHash: Int, oldHead: Entry[A]): A = { + protected def addEntryAt(bucket: Int, elem: A, elemHash: Int, oldHead: Entry[A] | Null): A = { Stats.record(statsItem("addEntryAt")) table(bucket) = new Entry(elem, elemHash, oldHead, queue) count += 1 @@ -156,7 +162,9 @@ abstract class WeakHashSet[A <: AnyRef](initialCapacity: Int = 8, loadFactor: Do elem } - def put(elem: A): A = elem match { + // TODO: remove the `case null` when we can enable explicit nulls in regular compiling, + // since the type `A <: AnyRef` of `elem` can ensure the value is not null. + def put(elem: A): A = (elem: A | Null) match { case null => throw new NullPointerException("WeakHashSet cannot hold nulls") case _ => Stats.record(statsItem("put")) @@ -166,11 +174,11 @@ abstract class WeakHashSet[A <: AnyRef](initialCapacity: Int = 8, loadFactor: Do val oldHead = table(bucket) @tailrec - def linkedListLoop(entry: Entry[A]): A = entry match { + def linkedListLoop(entry: Entry[A] | Null): A = entry match { case null => addEntryAt(bucket, elem, h, oldHead) case _ => val entryElem = entry.get - if (isEqual(elem, entryElem)) entryElem + if entryElem != null && isEqual(elem, entryElem) then entryElem.uncheckedNN else linkedListLoop(entry.tail) } @@ -179,27 +187,25 @@ abstract class WeakHashSet[A <: AnyRef](initialCapacity: Int = 8, loadFactor: Do def +=(elem: A): Unit = put(elem) - def -=(elem: A): Unit = elem match { + def -=(elem: A): Unit = (elem: A | Null) match { case null => case _ => Stats.record(statsItem("-=")) removeStaleEntries() val bucket = index(hash(elem)) - - @tailrec - def linkedListLoop(prevEntry: Entry[A], entry: Entry[A]): Unit = entry match { - case null => () - case _ if isEqual(elem, entry.get) => remove(bucket, prevEntry, entry) - case _ => linkedListLoop(entry, entry.tail) - } + def linkedListLoop(prevEntry: Entry[A] | Null, entry: Entry[A] | Null): Unit = + if entry != null then + val entryElem = entry.get + if entryElem != null && isEqual(elem, entryElem) then remove(bucket, prevEntry, entry) + else linkedListLoop(entry, entry.tail) linkedListLoop(null, table(bucket)) } def clear(): Unit = { - table = new Array[Entry[A]](table.size) + table = new Array[Entry[A] | Null](table.size) threshold = computeThreshold count = 0 @@ -227,12 +233,12 @@ abstract class WeakHashSet[A <: AnyRef](initialCapacity: Int = 8, loadFactor: Do /** * the entry that was last examined */ - private var entry: Entry[A] = null + private var entry: Entry[A] | Null = null /** * the element that will be the result of the next call to next() */ - private var lookaheadelement: A = null.asInstanceOf[A] + private var lookaheadelement: A | Null = null @tailrec def hasNext: Boolean = { @@ -241,27 +247,26 @@ abstract class WeakHashSet[A <: AnyRef](initialCapacity: Int = 8, loadFactor: Do entry = table(currentBucket) } - if (entry == null) false + val e = entry + if (e == null) false else { - lookaheadelement = entry.get - if (lookaheadelement == null) { + lookaheadelement = e.get + if lookaheadelement == null then // element null means the weakref has been cleared since we last did a removeStaleEntries(), move to the next entry - entry = entry.tail + entry = e.tail hasNext - } - else - true + else true } } - def next(): A = if (lookaheadelement == null) - throw new IndexOutOfBoundsException("next on an empty iterator") - else { - val result = lookaheadelement - lookaheadelement = null.asInstanceOf[A] - entry = entry.tail - result - } + def next(): A = + if lookaheadelement == null then + throw new IndexOutOfBoundsException("next on an empty iterator") + else + val result = lookaheadelement.nn + lookaheadelement = null + entry = entry.nn.tail + result } } @@ -291,7 +296,7 @@ abstract class WeakHashSet[A <: AnyRef](initialCapacity: Int = 8, loadFactor: Do assert(entry.get != null, s"$entry had a null value indicated that gc activity was happening during diagnostic validation or that a null value was inserted") computedCount += 1 val cachedHash = entry.hash - val realHash = hash(entry.get) + val realHash = hash(entry.get.uncheckedNN) assert(cachedHash == realHash, s"for $entry cached hash was $cachedHash but should have been $realHash") val computedBucket = index(realHash) assert(computedBucket == bucket, s"for $entry the computed bucket was $computedBucket but should have been $bucket") @@ -308,7 +313,7 @@ abstract class WeakHashSet[A <: AnyRef](initialCapacity: Int = 8, loadFactor: Do /** * Produces a diagnostic dump of the table that underlies this hash set. */ - def dump: String = java.util.Arrays.toString(table.asInstanceOf[Array[AnyRef]]) + def dump: String = java.util.Arrays.toString(table.asInstanceOf[Array[AnyRef | Null]]) /** * Number of buckets that hold collisions. Useful for diagnosing performance issues. @@ -339,6 +344,6 @@ object WeakHashSet { * A single entry in a WeakHashSet. It's a WeakReference plus a cached hash code and * a link to the next Entry in the same bucket */ - class Entry[A](@constructorOnly element: A, val hash:Int, var tail: Entry[A], @constructorOnly queue: ReferenceQueue[A]) extends WeakReference[A](element, queue) + class Entry[A](@constructorOnly element: A, val hash:Int, var tail: Entry[A] | Null, @constructorOnly queue: ReferenceQueue[A]) extends WeakReference[A](element, queue) } diff --git a/compiler/src/dotty/tools/io/AbstractFile.scala b/compiler/src/dotty/tools/io/AbstractFile.scala index c260ede89930..29bc764dcd7b 100644 --- a/compiler/src/dotty/tools/io/AbstractFile.scala +++ b/compiler/src/dotty/tools/io/AbstractFile.scala @@ -5,6 +5,8 @@ package dotty.tools.io +import scala.language.unsafeNulls + import java.io.{ IOException, InputStream, OutputStream, BufferedOutputStream, ByteArrayOutputStream diff --git a/compiler/src/dotty/tools/io/ClassPath.scala b/compiler/src/dotty/tools/io/ClassPath.scala index eeefabddd19f..754c2bae3597 100644 --- a/compiler/src/dotty/tools/io/ClassPath.scala +++ b/compiler/src/dotty/tools/io/ClassPath.scala @@ -7,6 +7,8 @@ package dotty.tools package io +import scala.language.unsafeNulls + import java.net.MalformedURLException import java.net.URL import java.util.regex.PatternSyntaxException diff --git a/compiler/src/dotty/tools/io/Directory.scala b/compiler/src/dotty/tools/io/Directory.scala index 5a4a93d1c045..7c2067390a09 100644 --- a/compiler/src/dotty/tools/io/Directory.scala +++ b/compiler/src/dotty/tools/io/Directory.scala @@ -8,6 +8,8 @@ package dotty.tools.io +import scala.language.unsafeNulls + import java.nio.file.{Files, Paths} diff --git a/compiler/src/dotty/tools/io/File.scala b/compiler/src/dotty/tools/io/File.scala index 284e8989a1f5..27f2c077dd6a 100644 --- a/compiler/src/dotty/tools/io/File.scala +++ b/compiler/src/dotty/tools/io/File.scala @@ -8,6 +8,8 @@ package dotty.tools.io +import scala.language.unsafeNulls + import java.io.{File => JavaIoFile, _} import java.nio.file.{Files, Paths} import java.nio.file.StandardOpenOption._ diff --git a/compiler/src/dotty/tools/io/Jar.scala b/compiler/src/dotty/tools/io/Jar.scala index 99997ef2de67..9979a9ca9379 100644 --- a/compiler/src/dotty/tools/io/Jar.scala +++ b/compiler/src/dotty/tools/io/Jar.scala @@ -7,6 +7,8 @@ package dotty.tools package io +import scala.language.unsafeNulls + import java.io.{ InputStream, OutputStream, DataOutputStream } import java.util.jar._ import scala.jdk.CollectionConverters._ diff --git a/compiler/src/dotty/tools/io/JarArchive.scala b/compiler/src/dotty/tools/io/JarArchive.scala index 80af5ef390b5..8f3b5d8010e4 100644 --- a/compiler/src/dotty/tools/io/JarArchive.scala +++ b/compiler/src/dotty/tools/io/JarArchive.scala @@ -1,5 +1,7 @@ package dotty.tools.io +import scala.language.unsafeNulls + import java.nio.file.{FileSystemAlreadyExistsException, FileSystems} import scala.jdk.CollectionConverters._ @@ -10,7 +12,7 @@ import scala.jdk.CollectionConverters._ */ class JarArchive private (root: Directory) extends PlainDirectory(root) { def close(): Unit = jpath.getFileSystem().close() - def allFileNames(): Iterator[String] = + def allFileNames(): Iterator[String] = java.nio.file.Files.walk(jpath).iterator().asScala.map(_.toString) } diff --git a/compiler/src/dotty/tools/io/NoAbstractFile.scala b/compiler/src/dotty/tools/io/NoAbstractFile.scala index e6022ea40633..13c2c6851d2b 100644 --- a/compiler/src/dotty/tools/io/NoAbstractFile.scala +++ b/compiler/src/dotty/tools/io/NoAbstractFile.scala @@ -5,6 +5,8 @@ package dotty.tools.io +import scala.language.unsafeNulls + import java.io.InputStream /** A distinguished object so you can avoid both null diff --git a/compiler/src/dotty/tools/io/Path.scala b/compiler/src/dotty/tools/io/Path.scala index 208b18078b7e..7ed0bc515b82 100644 --- a/compiler/src/dotty/tools/io/Path.scala +++ b/compiler/src/dotty/tools/io/Path.scala @@ -5,6 +5,8 @@ package dotty.tools.io +import scala.language.unsafeNulls + import java.io.RandomAccessFile import java.nio.file._ import java.net.{URI, URL} diff --git a/compiler/src/dotty/tools/io/PlainFile.scala b/compiler/src/dotty/tools/io/PlainFile.scala index 608e661fdd07..898e037488f7 100644 --- a/compiler/src/dotty/tools/io/PlainFile.scala +++ b/compiler/src/dotty/tools/io/PlainFile.scala @@ -6,6 +6,8 @@ package dotty.tools package io +import scala.language.unsafeNulls + import java.io.{InputStream, OutputStream} import java.nio.file.{InvalidPathException, Paths} @@ -26,7 +28,7 @@ class PlainFile(val givenPath: Path) extends AbstractFile { dotc.util.Stats.record("new PlainFile") def jpath: JPath = givenPath.jpath - + override def underlyingSource = { val fileSystem = jpath.getFileSystem fileSystem.provider().getScheme match { diff --git a/compiler/src/dotty/tools/io/Streamable.scala b/compiler/src/dotty/tools/io/Streamable.scala index 68e3f9cc7d28..328ce03f7853 100644 --- a/compiler/src/dotty/tools/io/Streamable.scala +++ b/compiler/src/dotty/tools/io/Streamable.scala @@ -5,6 +5,8 @@ package dotty.tools.io +import scala.language.unsafeNulls + import java.net.URL import java.io.{ BufferedInputStream, InputStream } import java.io.{ BufferedReader, InputStreamReader, Closeable => JCloseable } diff --git a/compiler/src/dotty/tools/io/VirtualDirectory.scala b/compiler/src/dotty/tools/io/VirtualDirectory.scala index 6648569fb99a..c66e28011821 100644 --- a/compiler/src/dotty/tools/io/VirtualDirectory.scala +++ b/compiler/src/dotty/tools/io/VirtualDirectory.scala @@ -4,6 +4,8 @@ package dotty.tools.io +import scala.language.unsafeNulls + import scala.collection.mutable import java.io.{InputStream, OutputStream} /** diff --git a/compiler/src/dotty/tools/io/VirtualFile.scala b/compiler/src/dotty/tools/io/VirtualFile.scala index a957ed974dee..a9d03308f97a 100644 --- a/compiler/src/dotty/tools/io/VirtualFile.scala +++ b/compiler/src/dotty/tools/io/VirtualFile.scala @@ -5,6 +5,8 @@ package dotty.tools.io +import scala.language.unsafeNulls + import java.io.{ ByteArrayInputStream, ByteArrayOutputStream, InputStream, OutputStream } /** This class implements an in-memory file. diff --git a/compiler/src/dotty/tools/io/ZipArchive.scala b/compiler/src/dotty/tools/io/ZipArchive.scala index 23e66d17ea88..4383bc187979 100644 --- a/compiler/src/dotty/tools/io/ZipArchive.scala +++ b/compiler/src/dotty/tools/io/ZipArchive.scala @@ -5,6 +5,8 @@ package dotty.tools.io +import scala.language.unsafeNulls + import java.net.URL import java.io.{ IOException, InputStream, OutputStream, FilterInputStream } import java.nio.file.Files diff --git a/compiler/src/dotty/tools/package.scala b/compiler/src/dotty/tools/package.scala index e07cb42d1179..f6bf4314e262 100644 --- a/compiler/src/dotty/tools/package.scala +++ b/compiler/src/dotty/tools/package.scala @@ -26,12 +26,6 @@ package object tools { /** Forward-ported from the explicit-nulls branch. */ extension [T](x: T | Null) - - /** Assert `x` is non null and strip `Null` from type */ - inline def nn: T = - assert(x != null) - x.asInstanceOf[T] - /** Should be used when we know from the context that `x` is not null. * Flow-typing under explicit nulls will automatically insert many necessary * occurrences of uncheckedNN. @@ -42,6 +36,13 @@ package object tools { if x == null then None else Some(x.asInstanceOf[T]) end extension + /** Nullable eq and ne. */ + extension [T <: AnyRef](x: T | Null) + inline def eqn (y: T | Null) = + x.asInstanceOf[AnyRef] eq y.asInstanceOf[AnyRef] + + inline def nen(y: T | Null): Boolean = !eqn(y) + object resultWrapper { opaque type WrappedResult[T] = T private[tools] def unwrap[T](x: WrappedResult[T]): T = x diff --git a/compiler/src/dotty/tools/repl/AbstractFileClassLoader.scala b/compiler/src/dotty/tools/repl/AbstractFileClassLoader.scala index 7263758b60c5..89fd290f7286 100644 --- a/compiler/src/dotty/tools/repl/AbstractFileClassLoader.scala +++ b/compiler/src/dotty/tools/repl/AbstractFileClassLoader.scala @@ -13,6 +13,8 @@ package dotty.tools package repl +import scala.language.unsafeNulls + import io.AbstractFile import java.net.{URL, URLConnection, URLStreamHandler} diff --git a/compiler/src/dotty/tools/repl/JLineTerminal.scala b/compiler/src/dotty/tools/repl/JLineTerminal.scala index 807ae2bf5eec..d2f4c4589f17 100644 --- a/compiler/src/dotty/tools/repl/JLineTerminal.scala +++ b/compiler/src/dotty/tools/repl/JLineTerminal.scala @@ -1,5 +1,7 @@ package dotty.tools.repl +import scala.language.unsafeNulls + import dotty.tools.dotc.core.Contexts._ import dotty.tools.dotc.parsing.Scanners.Scanner import dotty.tools.dotc.parsing.Tokens._ diff --git a/compiler/src/dotty/tools/repl/Rendering.scala b/compiler/src/dotty/tools/repl/Rendering.scala index 53198678dd80..5a0355570663 100644 --- a/compiler/src/dotty/tools/repl/Rendering.scala +++ b/compiler/src/dotty/tools/repl/Rendering.scala @@ -1,6 +1,8 @@ package dotty.tools package repl +import scala.language.unsafeNulls + import java.lang.{ ClassLoader, ExceptionInInitializerError } import java.lang.reflect.InvocationTargetException diff --git a/compiler/src/dotty/tools/repl/ReplCompiler.scala b/compiler/src/dotty/tools/repl/ReplCompiler.scala index ed097ac1277a..205d1acf3805 100644 --- a/compiler/src/dotty/tools/repl/ReplCompiler.scala +++ b/compiler/src/dotty/tools/repl/ReplCompiler.scala @@ -163,8 +163,8 @@ class ReplCompiler extends Compiler { private def runCompilationUnit(unit: CompilationUnit, state: State): Result[(CompilationUnit, State)] = { val ctx = state.context - ctx.run.compileUnits(unit :: Nil) - ctx.run.printSummary() // this outputs "2 errors found" like normal - but we might decide that's needlessly noisy for the REPL + ctx.run.nn.compileUnits(unit :: Nil) + ctx.run.nn.printSummary() // this outputs "2 errors found" like normal - but we might decide that's needlessly noisy for the REPL if (!ctx.reporter.hasErrors) (unit, state).result else ctx.reporter.removeBufferedMessages(using ctx).errors @@ -291,7 +291,7 @@ class ReplCompiler extends Compiler { wrapped(expr, src, state).flatMap { pkg => val unit = CompilationUnit(src) unit.untpdTree = pkg - ctx.run.compileUnits(unit :: Nil, ctx) + ctx.run.nn.compileUnits(unit :: Nil, ctx) if (errorsAllowed || !ctx.reporter.hasErrors) unwrapped(unit.tpdTree, src) diff --git a/compiler/src/dotty/tools/repl/ReplDriver.scala b/compiler/src/dotty/tools/repl/ReplDriver.scala index 06d91c789d1b..708e0efdc726 100644 --- a/compiler/src/dotty/tools/repl/ReplDriver.scala +++ b/compiler/src/dotty/tools/repl/ReplDriver.scala @@ -1,5 +1,7 @@ package dotty.tools.repl +import scala.language.unsafeNulls + import java.io.{File => JFile, PrintStream} import java.nio.charset.StandardCharsets diff --git a/compiler/src/dotty/tools/repl/ScriptEngine.scala b/compiler/src/dotty/tools/repl/ScriptEngine.scala index 27369a94b516..6be76e0fa369 100644 --- a/compiler/src/dotty/tools/repl/ScriptEngine.scala +++ b/compiler/src/dotty/tools/repl/ScriptEngine.scala @@ -1,6 +1,8 @@ package dotty.tools package repl +import scala.language.unsafeNulls + import java.io.{Reader, StringWriter} import javax.script.{AbstractScriptEngine, Bindings, ScriptContext, ScriptEngine => JScriptEngine, ScriptEngineFactory, ScriptException, SimpleBindings} import dotc.core.StdNames.str diff --git a/compiler/src/dotty/tools/runner/ObjectRunner.scala b/compiler/src/dotty/tools/runner/ObjectRunner.scala index 112b55f2e464..cb8f9d791dfa 100644 --- a/compiler/src/dotty/tools/runner/ObjectRunner.scala +++ b/compiler/src/dotty/tools/runner/ObjectRunner.scala @@ -36,7 +36,7 @@ trait CommonRunner { _: UndeclaredThrowableException | _: ExecutionException if x.getCause != null => - rootCause(x.getCause) + rootCause(x.getCause.nn) case _ => x } } diff --git a/compiler/src/dotty/tools/runner/ScalaClassLoader.scala b/compiler/src/dotty/tools/runner/ScalaClassLoader.scala index c7d58de05dfd..bbc028b217c1 100644 --- a/compiler/src/dotty/tools/runner/ScalaClassLoader.scala +++ b/compiler/src/dotty/tools/runner/ScalaClassLoader.scala @@ -1,6 +1,7 @@ package dotty.tools package runner +import scala.language.unsafeNulls import java.lang.ClassLoader import java.lang.invoke.{MethodHandles, MethodType} @@ -60,7 +61,7 @@ object RichClassLoader { object ScalaClassLoader { def setContext(cl: ClassLoader) = Thread.currentThread.setContextClassLoader(cl) - def fromURLsParallelCapable(urls: Seq[URL], parent: ClassLoader = null): URLClassLoader = + def fromURLsParallelCapable(urls: Seq[URL], parent: ClassLoader | Null = null): URLClassLoader = new URLClassLoader(urls.toArray, if parent == null then bootClassLoader else parent) @sharable private[this] val bootClassLoader: ClassLoader = diff --git a/compiler/src/dotty/tools/scripting/Main.scala b/compiler/src/dotty/tools/scripting/Main.scala index 3a86155f1fe9..f5259974f16f 100755 --- a/compiler/src/dotty/tools/scripting/Main.scala +++ b/compiler/src/dotty/tools/scripting/Main.scala @@ -1,5 +1,7 @@ package dotty.tools.scripting +import scala.language.unsafeNulls + import java.io.File import java.nio.file.{Path, Paths} import dotty.tools.dotc.config.Properties.isWin diff --git a/compiler/src/dotty/tools/scripting/ScriptingDriver.scala b/compiler/src/dotty/tools/scripting/ScriptingDriver.scala index 9abe5f81c4cd..38765ac6dafa 100755 --- a/compiler/src/dotty/tools/scripting/ScriptingDriver.scala +++ b/compiler/src/dotty/tools/scripting/ScriptingDriver.scala @@ -1,5 +1,7 @@ package dotty.tools.scripting +import scala.language.unsafeNulls + import java.nio.file.{ Files, Paths, Path } import java.io.File diff --git a/compiler/src/dotty/tools/scripting/StringDriver.scala b/compiler/src/dotty/tools/scripting/StringDriver.scala index 6ac0bce9766a..b8b64994f285 100755 --- a/compiler/src/dotty/tools/scripting/StringDriver.scala +++ b/compiler/src/dotty/tools/scripting/StringDriver.scala @@ -1,5 +1,7 @@ package dotty.tools.scripting +import scala.language.unsafeNulls + import java.nio.file.{ Files, Paths, Path } import dotty.tools.dotc.Driver diff --git a/compiler/src/dotty/tools/scripting/Util.scala b/compiler/src/dotty/tools/scripting/Util.scala index 9529eb9ad791..71ae4413de55 100755 --- a/compiler/src/dotty/tools/scripting/Util.scala +++ b/compiler/src/dotty/tools/scripting/Util.scala @@ -1,5 +1,7 @@ package dotty.tools.scripting +import scala.language.unsafeNulls + import java.nio.file.{ Path } import java.io.File import java.net.{ URLClassLoader } diff --git a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala index e97aa061c3f5..48a75d77965b 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala @@ -1,6 +1,8 @@ package scala.quoted package runtime.impl +import scala.language.unsafeNulls + import dotty.tools.dotc import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.ast.untpd @@ -12,6 +14,7 @@ import dotty.tools.dotc.core.NameKinds import dotty.tools.dotc.core.StdNames._ import dotty.tools.dotc.quoted.reflect._ import dotty.tools.dotc.core.Decorators._ +import dotty.tools.dotc.NoCompilationUnit import dotty.tools.dotc.quoted.{MacroExpansion, PickledQuotes} @@ -2699,7 +2702,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler def FunctionClass(arity: Int, isImplicit: Boolean = false, isErased: Boolean = false): Symbol = dotc.core.Symbols.defn.FunctionClass(arity, isImplicit, isErased) def TupleClass(arity: Int): Symbol = - dotc.core.Symbols.defn.TupleType(arity).classSymbol.asClass + dotc.core.Symbols.defn.TupleType(arity).nn.classSymbol.asClass def isTupleClass(sym: Symbol): Boolean = dotc.core.Symbols.defn.isTupleClass(sym) def ScalaPrimitiveValueClasses: List[Symbol] = @@ -2795,10 +2798,11 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler object SourceFile extends SourceFileModule { def current: SourceFile = - if ctx.compilationUnit == null then + val unit = ctx.compilationUnit + if unit eq NoCompilationUnit then throw new java.lang.UnsupportedOperationException( "`reflect.SourceFile.current` cannot be called within the TASTy ispector") - ctx.compilationUnit.source + else unit.source } given SourceFileMethods: SourceFileMethods with diff --git a/compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala b/compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala index 7f77f8fa5eb2..1d50af5ab7f2 100644 --- a/compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala +++ b/compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala @@ -1423,7 +1423,7 @@ object SourceCode { case '"' => "\\\"" case '\'' => "\\\'" case '\\' => "\\\\" - case _ => if ch.isControl then f"${"\\"}u${ch.toInt}%04x" else String.valueOf(ch) + case _ => if ch.isControl then f"${"\\"}u${ch.toInt}%04x" else String.valueOf(ch).nn } private def escapedString(str: String): String = str flatMap escapedChar @@ -1439,7 +1439,7 @@ object SourceCode { namesIndex(name0) = index + 1 val name = if index == 1 then name0 - else s"`$name0${index.toString.toCharArray.map {x => (x - '0' + '₀').toChar}.mkString}`" + else s"`$name0${index.toString.toCharArray.nn.map {x => (x - '0' + '₀').toChar}.mkString}`" names(sym) = name Some(name) } diff --git a/compiler/test-coursier/dotty/tools/coursier/CoursierScalaTests.scala b/compiler/test-coursier/dotty/tools/coursier/CoursierScalaTests.scala index d8a14f72ebfa..979fea0684b2 100644 --- a/compiler/test-coursier/dotty/tools/coursier/CoursierScalaTests.scala +++ b/compiler/test-coursier/dotty/tools/coursier/CoursierScalaTests.scala @@ -2,6 +2,8 @@ package dotty package tools package coursier +import scala.language.unsafeNulls + import java.io.File import java.nio.file.{Path, Paths, Files} import scala.sys.process._ diff --git a/compiler/test/debug/Gen.scala b/compiler/test/debug/Gen.scala index 4818176275f5..646dec189f10 100755 --- a/compiler/test/debug/Gen.scala +++ b/compiler/test/debug/Gen.scala @@ -1,3 +1,5 @@ +import scala.language.unsafeNulls + import scala.io.Source import scala.collection.mutable.ListBuffer import scala.util.Using diff --git a/compiler/test/dotty/Properties.scala b/compiler/test/dotty/Properties.scala index 4ef2ad7a61c9..8d40a54c31d6 100644 --- a/compiler/test/dotty/Properties.scala +++ b/compiler/test/dotty/Properties.scala @@ -1,5 +1,7 @@ package dotty +import scala.language.unsafeNulls + import java.nio.file._ /** Runtime properties from defines or environmnent */ diff --git a/compiler/test/dotty/tools/DottyTest.scala b/compiler/test/dotty/tools/DottyTest.scala index b138b446d67f..54cf0e0c177c 100644 --- a/compiler/test/dotty/tools/DottyTest.scala +++ b/compiler/test/dotty/tools/DottyTest.scala @@ -1,6 +1,8 @@ package dotty package tools +import scala.language.unsafeNulls + import vulpix.TestConfiguration import dotc.core._ diff --git a/compiler/test/dotty/tools/DottyTypeStealer.scala b/compiler/test/dotty/tools/DottyTypeStealer.scala index 6477396679c2..7f73fc0bbd90 100644 --- a/compiler/test/dotty/tools/DottyTypeStealer.scala +++ b/compiler/test/dotty/tools/DottyTypeStealer.scala @@ -1,5 +1,7 @@ package dotty.tools +import scala.language.unsafeNulls + import dotc.ast.tpd import dotc.ast.tpd._ import dotc.core.Contexts.{Context, atPhase} diff --git a/compiler/test/dotty/tools/TestSources.scala b/compiler/test/dotty/tools/TestSources.scala index 4fbf0e9fc5dd..76cf1d92e2bf 100644 --- a/compiler/test/dotty/tools/TestSources.scala +++ b/compiler/test/dotty/tools/TestSources.scala @@ -1,5 +1,7 @@ package dotty.tools +import scala.language.unsafeNulls + import java.io.File import java.nio.file._ diff --git a/compiler/test/dotty/tools/backend/jvm/AsmConverters.scala b/compiler/test/dotty/tools/backend/jvm/AsmConverters.scala index 17b5e892ae0f..675e0c2014c3 100644 --- a/compiler/test/dotty/tools/backend/jvm/AsmConverters.scala +++ b/compiler/test/dotty/tools/backend/jvm/AsmConverters.scala @@ -1,5 +1,7 @@ package dotty.tools.backend.jvm +import scala.language.unsafeNulls + import scala.tools.asm import asm._ import asm.tree._ diff --git a/compiler/test/dotty/tools/backend/jvm/AsmNode.scala b/compiler/test/dotty/tools/backend/jvm/AsmNode.scala index 1100c9054b4d..5918e1ecf198 100644 --- a/compiler/test/dotty/tools/backend/jvm/AsmNode.scala +++ b/compiler/test/dotty/tools/backend/jvm/AsmNode.scala @@ -1,5 +1,7 @@ package dotty.tools.backend.jvm +import scala.language.unsafeNulls + import java.lang.reflect.Modifier import scala.tools.asm import asm._ diff --git a/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTest.scala b/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTest.scala index 228f657457b8..6c796c280723 100644 --- a/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTest.scala +++ b/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTest.scala @@ -2,6 +2,8 @@ package dotty package tools package backend.jvm +import scala.language.unsafeNulls + import vulpix.TestConfiguration import dotc.core.Contexts.{Context, ContextBase, ctx} diff --git a/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala b/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala index 9d6ff413f8a2..051dd414e28f 100644 --- a/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala +++ b/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala @@ -1,5 +1,7 @@ package dotty.tools.backend.jvm +import scala.language.unsafeNulls + import org.junit.Assert._ import org.junit.Test diff --git a/compiler/test/dotty/tools/backend/jvm/InlineBytecodeTests.scala b/compiler/test/dotty/tools/backend/jvm/InlineBytecodeTests.scala index 741928203d77..92379379bdaa 100644 --- a/compiler/test/dotty/tools/backend/jvm/InlineBytecodeTests.scala +++ b/compiler/test/dotty/tools/backend/jvm/InlineBytecodeTests.scala @@ -1,5 +1,7 @@ package dotty.tools.backend.jvm +import scala.language.unsafeNulls + import org.junit.Assert._ import org.junit.Test diff --git a/compiler/test/dotty/tools/backend/jvm/StringConcatTest.scala b/compiler/test/dotty/tools/backend/jvm/StringConcatTest.scala index 613e72b32e52..14352106c5e8 100644 --- a/compiler/test/dotty/tools/backend/jvm/StringConcatTest.scala +++ b/compiler/test/dotty/tools/backend/jvm/StringConcatTest.scala @@ -122,7 +122,7 @@ class StringConcatTest extends DottyBytecodeTest { chsq: java.lang.CharSequence, chrs: Array[Char]) = { val s1 = str + obj + v + z + c + b + s + i + f + l + d + sbuf + chsq + chrs - val s2 = String.valueOf(obj) + str + v + z + c + b + s + i + f + l + d + sbuf + chsq + chrs + val s2 = String.valueOf(obj).nn + str + v + z + c + b + s + i + f + l + d + sbuf + chsq + chrs s1 + "//" + s2 } def sbuf = { val r = new java.lang.StringBuffer(); r.append("sbuf"); r } diff --git a/compiler/test/dotty/tools/compilerSupport.scala b/compiler/test/dotty/tools/compilerSupport.scala index 487a10bd216c..e67b74a55492 100644 --- a/compiler/test/dotty/tools/compilerSupport.scala +++ b/compiler/test/dotty/tools/compilerSupport.scala @@ -1,5 +1,7 @@ package dotty.tools +import scala.language.unsafeNulls + import javax.tools._ import java.io._ import java.nio.file._ diff --git a/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala b/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala index 9a6da578348c..cce23cb5c9a6 100644 --- a/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala @@ -2,6 +2,8 @@ package dotty package tools package dotc +import scala.language.unsafeNulls + import org.junit.{ Test, BeforeClass, AfterClass } import org.junit.Assert._ import org.junit.Assume._ diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 4ea8db553f54..7305914d18ae 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -2,6 +2,8 @@ package dotty package tools package dotc +import scala.language.unsafeNulls + import org.junit.{ Test, BeforeClass, AfterClass } import org.junit.Assert._ import org.junit.Assume._ diff --git a/compiler/test/dotty/tools/dotc/ConstantFoldingTests.scala b/compiler/test/dotty/tools/dotc/ConstantFoldingTests.scala index 176d31559291..fca82bf7a813 100644 --- a/compiler/test/dotty/tools/dotc/ConstantFoldingTests.scala +++ b/compiler/test/dotty/tools/dotc/ConstantFoldingTests.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc +import scala.language.unsafeNulls + import org.junit.Assert._ import org.junit.Test import dotty.tools.backend.jvm._ diff --git a/compiler/test/dotty/tools/dotc/FromTastyTests.scala b/compiler/test/dotty/tools/dotc/FromTastyTests.scala index e6bb7190a3fa..2684a47b870c 100644 --- a/compiler/test/dotty/tools/dotc/FromTastyTests.scala +++ b/compiler/test/dotty/tools/dotc/FromTastyTests.scala @@ -2,6 +2,8 @@ package dotty package tools package dotc +import scala.language.unsafeNulls + import org.junit.{AfterClass, Test} import vulpix._ diff --git a/compiler/test/dotty/tools/dotc/IdempotencyTests.scala b/compiler/test/dotty/tools/dotc/IdempotencyTests.scala index 38f8c02ee375..84b3f1f8a48f 100644 --- a/compiler/test/dotty/tools/dotc/IdempotencyTests.scala +++ b/compiler/test/dotty/tools/dotc/IdempotencyTests.scala @@ -2,6 +2,8 @@ package dotty package tools package dotc +import scala.language.unsafeNulls + import java.io.{File => JFile} import java.nio.file.{Files, Path, Paths} diff --git a/compiler/test/dotty/tools/dotc/InterfaceEntryPointTest.scala b/compiler/test/dotty/tools/dotc/InterfaceEntryPointTest.scala index a23ca77707ee..f5d27737dbef 100644 --- a/compiler/test/dotty/tools/dotc/InterfaceEntryPointTest.scala +++ b/compiler/test/dotty/tools/dotc/InterfaceEntryPointTest.scala @@ -1,6 +1,8 @@ package dotty package tools.dotc +import scala.language.unsafeNulls + import org.junit.Test import org.junit.Assert._ import org.junit.experimental.categories.Category diff --git a/compiler/test/dotty/tools/dotc/ScalaCommandTest.scala b/compiler/test/dotty/tools/dotc/ScalaCommandTest.scala index f3d12d7b7bba..53f063a9e767 100644 --- a/compiler/test/dotty/tools/dotc/ScalaCommandTest.scala +++ b/compiler/test/dotty/tools/dotc/ScalaCommandTest.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc +import scala.language.unsafeNulls + import org.junit.Test import org.junit.Assert._ import org.junit.Rule diff --git a/compiler/test/dotty/tools/dotc/SettingsTests.scala b/compiler/test/dotty/tools/dotc/SettingsTests.scala index 4625f4f34f72..dcee1ebde4f2 100644 --- a/compiler/test/dotty/tools/dotc/SettingsTests.scala +++ b/compiler/test/dotty/tools/dotc/SettingsTests.scala @@ -1,6 +1,8 @@ package dotty.tools package dotc +import scala.language.unsafeNulls + import reporting.StoreReporter import vulpix.TestConfiguration diff --git a/compiler/test/dotty/tools/dotc/TastyBootstrapTests.scala b/compiler/test/dotty/tools/dotc/TastyBootstrapTests.scala index 7b1629c426d6..3164e11e9b2f 100644 --- a/compiler/test/dotty/tools/dotc/TastyBootstrapTests.scala +++ b/compiler/test/dotty/tools/dotc/TastyBootstrapTests.scala @@ -2,6 +2,8 @@ package dotty package tools package dotc +import scala.language.unsafeNulls + import org.junit.{ Test, BeforeClass, AfterClass } import org.junit.Assert._ import org.junit.Assume._ diff --git a/compiler/test/dotty/tools/dotc/TastyHashTest.scala b/compiler/test/dotty/tools/dotc/TastyHashTest.scala index 09d631d97377..066c9127e8b8 100644 --- a/compiler/test/dotty/tools/dotc/TastyHashTest.scala +++ b/compiler/test/dotty/tools/dotc/TastyHashTest.scala @@ -19,7 +19,7 @@ class TastyHashTest { testHash(0X202020202L, Array(2, 2, 2, 2, 2)) testHash(0X1010101L, Array.fill(1024)(1)) testHash(0xaafefeaaab54ffL, Array.tabulate(1024)(_.toByte)) - testHash(0x34545c16020230L, "abcdefghijklmnopqrstuvwxyz1234567890".getBytes) + testHash(0x34545c16020230L, "abcdefghijklmnopqrstuvwxyz1234567890".getBytes.nn) } def testHash(expected: Long, arr: Array[Byte]): Unit = { diff --git a/compiler/test/dotty/tools/dotc/classpath/MultiReleaseJarTest.scala b/compiler/test/dotty/tools/dotc/classpath/MultiReleaseJarTest.scala index f4849258d283..a878a25cf199 100644 --- a/compiler/test/dotty/tools/dotc/classpath/MultiReleaseJarTest.scala +++ b/compiler/test/dotty/tools/dotc/classpath/MultiReleaseJarTest.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.classpath +import scala.language.unsafeNulls + import dotty.tools.dotc.core.Contexts.Context import java.io.{ByteArrayOutputStream, IOException} diff --git a/compiler/test/dotty/tools/dotc/classpath/ZipAndJarFileLookupFactoryTest.scala b/compiler/test/dotty/tools/dotc/classpath/ZipAndJarFileLookupFactoryTest.scala index 439f5ed6a019..84973b8d3d71 100644 --- a/compiler/test/dotty/tools/dotc/classpath/ZipAndJarFileLookupFactoryTest.scala +++ b/compiler/test/dotty/tools/dotc/classpath/ZipAndJarFileLookupFactoryTest.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.classpath +import scala.language.unsafeNulls + import org.junit.Test import java.nio.file._ import java.nio.file.attribute.FileTime diff --git a/compiler/test/dotty/tools/dotc/config/CommandLineParserTest.scala b/compiler/test/dotty/tools/dotc/config/CommandLineParserTest.scala index 431fb37b8a07..35f8382293c1 100644 --- a/compiler/test/dotty/tools/dotc/config/CommandLineParserTest.scala +++ b/compiler/test/dotty/tools/dotc/config/CommandLineParserTest.scala @@ -1,6 +1,8 @@ package dotty.tools.dotc.config +import scala.language.unsafeNulls + import org.junit.Assert.{assertEquals, assertTrue} import org.junit.Test diff --git a/compiler/test/dotty/tools/dotc/core/tasty/CommentPicklingTest.scala b/compiler/test/dotty/tools/dotc/core/tasty/CommentPicklingTest.scala index 064eedd6dceb..fc6731652ada 100644 --- a/compiler/test/dotty/tools/dotc/core/tasty/CommentPicklingTest.scala +++ b/compiler/test/dotty/tools/dotc/core/tasty/CommentPicklingTest.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.core.tasty +import scala.language.unsafeNulls + import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.ast.tpd.TreeOps import dotty.tools.dotc.{Driver, Main} diff --git a/compiler/test/dotty/tools/dotc/core/tasty/PathPicklingTest.scala b/compiler/test/dotty/tools/dotc/core/tasty/PathPicklingTest.scala index 927cbe838e6e..438c6034f8b3 100644 --- a/compiler/test/dotty/tools/dotc/core/tasty/PathPicklingTest.scala +++ b/compiler/test/dotty/tools/dotc/core/tasty/PathPicklingTest.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.core.tasty +import scala.language.unsafeNulls + import java.io.{File => JFile, ByteArrayOutputStream, IOException} import java.nio.file.{Files, NoSuchFileException, Paths} diff --git a/compiler/test/dotty/tools/dotc/interactive/CustomCompletionTests.scala b/compiler/test/dotty/tools/dotc/interactive/CustomCompletionTests.scala index 7e247b51dff6..a43a5cafce21 100644 --- a/compiler/test/dotty/tools/dotc/interactive/CustomCompletionTests.scala +++ b/compiler/test/dotty/tools/dotc/interactive/CustomCompletionTests.scala @@ -43,7 +43,7 @@ class CustomCompletionTests extends DottyTest: given ctx: Context = run.runContext.withSource(file) val unit = CompilationUnit(file) ctx - .run + .run.nn .compileUnits(unit :: Nil, ctx) // ignoring compilation errors here - the input code diff --git a/compiler/test/dotty/tools/dotc/plugins/PluginsTest.scala b/compiler/test/dotty/tools/dotc/plugins/PluginsTest.scala index e8e7c87c9b37..dfca8783f324 100644 --- a/compiler/test/dotty/tools/dotc/plugins/PluginsTest.scala +++ b/compiler/test/dotty/tools/dotc/plugins/PluginsTest.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.plugins +import scala.language.unsafeNulls + import org.junit.Test import dotty.tools.dotc._ diff --git a/compiler/test/dotty/tools/dotc/printing/PrintingTest.scala b/compiler/test/dotty/tools/dotc/printing/PrintingTest.scala index 9c260cb75cc8..710ceee0a7c0 100644 --- a/compiler/test/dotty/tools/dotc/printing/PrintingTest.scala +++ b/compiler/test/dotty/tools/dotc/printing/PrintingTest.scala @@ -2,6 +2,8 @@ package dotty package tools package dotc +import scala.language.unsafeNulls + import vulpix.FileDiff import vulpix.TestConfiguration import vulpix.TestConfiguration diff --git a/compiler/test/dotty/tools/dotc/printing/SyntaxHighlightingTests.scala b/compiler/test/dotty/tools/dotc/printing/SyntaxHighlightingTests.scala index 35355fd20828..4dc991a0bfe4 100644 --- a/compiler/test/dotty/tools/dotc/printing/SyntaxHighlightingTests.scala +++ b/compiler/test/dotty/tools/dotc/printing/SyntaxHighlightingTests.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.printing +import scala.language.unsafeNulls + import dotty.tools.DottyTest import org.junit.Assert._ import org.junit.{Ignore, Test} diff --git a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTest.scala b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTest.scala index fff29edfa670..5d3a7994cc47 100644 --- a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTest.scala +++ b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTest.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package reporting +import scala.language.unsafeNulls + import core.Contexts.Context import org.junit.Assert._ diff --git a/compiler/test/dotty/tools/dotc/reporting/TestReporter.scala b/compiler/test/dotty/tools/dotc/reporting/TestReporter.scala index ed25f7f8d6c6..dcbbcc015d41 100644 --- a/compiler/test/dotty/tools/dotc/reporting/TestReporter.scala +++ b/compiler/test/dotty/tools/dotc/reporting/TestReporter.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package reporting +import scala.language.unsafeNulls + import java.io.{ PrintStream, PrintWriter, File => JFile, FileOutputStream, StringWriter } import java.text.SimpleDateFormat import java.util.Date diff --git a/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala b/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala index d1f58bf52a91..a85cc9ad80f9 100644 --- a/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala +++ b/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.semanticdb +import scala.language.unsafeNulls + import java.net.URLClassLoader import java.util.regex.Pattern import java.io.File diff --git a/compiler/test/dotty/tools/dotc/transform/PatmatExhaustivityTest.scala b/compiler/test/dotty/tools/dotc/transform/PatmatExhaustivityTest.scala index 0c895d436238..5b846b6daf21 100644 --- a/compiler/test/dotty/tools/dotc/transform/PatmatExhaustivityTest.scala +++ b/compiler/test/dotty/tools/dotc/transform/PatmatExhaustivityTest.scala @@ -3,6 +3,8 @@ package tools package dotc package transform +import scala.language.unsafeNulls + import vulpix.FileDiff import vulpix.TestConfiguration import reporting.TestReporter @@ -33,7 +35,7 @@ class PatmatExhaustivityTest { e.printStackTrace(printWriter) } - stringBuffer.toString.trim.replaceAll("\\s+\n", "\n") match { + stringBuffer.toString.trim.nn.replaceAll("\\s+\n", "\n") match { case "" => Nil case s => s.linesIterator.toSeq } diff --git a/compiler/test/dotty/tools/dotc/transform/SpecializeFunctionsTests.scala b/compiler/test/dotty/tools/dotc/transform/SpecializeFunctionsTests.scala index b74e6c0012dc..5e095796551f 100644 --- a/compiler/test/dotty/tools/dotc/transform/SpecializeFunctionsTests.scala +++ b/compiler/test/dotty/tools/dotc/transform/SpecializeFunctionsTests.scala @@ -2,6 +2,8 @@ package dotty.tools package dotc package transform +import scala.language.unsafeNulls + import org.junit.Test import dotty.tools.backend.jvm.DottyBytecodeTest diff --git a/compiler/test/dotty/tools/dotc/util/DiffUtilTests.scala b/compiler/test/dotty/tools/dotc/util/DiffUtilTests.scala index 5b380e5605e6..53379db6c512 100644 --- a/compiler/test/dotty/tools/dotc/util/DiffUtilTests.scala +++ b/compiler/test/dotty/tools/dotc/util/DiffUtilTests.scala @@ -1,5 +1,7 @@ package dotty.tools.dotc.util +import scala.language.unsafeNulls + import org.junit.Assert._ import org.junit.Test diff --git a/compiler/test/dotty/tools/dotc/util/StackTraceTest.scala b/compiler/test/dotty/tools/dotc/util/StackTraceTest.scala index ef5f1b813030..7e49fd64c146 100644 --- a/compiler/test/dotty/tools/dotc/util/StackTraceTest.scala +++ b/compiler/test/dotty/tools/dotc/util/StackTraceTest.scala @@ -1,6 +1,8 @@ package dotty.tools.dotc.util +import scala.language.unsafeNulls + import scala.util.{Failure, Success, Try} import scala.util.chaining.given diff --git a/compiler/test/dotty/tools/io/AbstractFileTest.scala b/compiler/test/dotty/tools/io/AbstractFileTest.scala index b8ac74a0835a..1814370d41fe 100644 --- a/compiler/test/dotty/tools/io/AbstractFileTest.scala +++ b/compiler/test/dotty/tools/io/AbstractFileTest.scala @@ -1,5 +1,7 @@ package dotty.tools.io +import scala.language.unsafeNulls + import org.junit.Test import dotty.tools.io.AbstractFile diff --git a/compiler/test/dotty/tools/io/ClasspathTest.scala b/compiler/test/dotty/tools/io/ClasspathTest.scala index 35437ef17390..a0fef65afdec 100755 --- a/compiler/test/dotty/tools/io/ClasspathTest.scala +++ b/compiler/test/dotty/tools/io/ClasspathTest.scala @@ -1,5 +1,7 @@ package dotty.tools.io +import scala.language.unsafeNulls + import org.junit.Test import java.io.File @@ -29,9 +31,9 @@ class ClasspathTest { for src <- libjarFiles do val dest = Paths.get(s"$outDir/${src.getName}") printf("copy: %s\n", Files.copy(src.toPath, dest)) - + val cp = Seq(s"$outDir/*", "not-a-real-directory/*").mkString(pathsep).replace('\\', '/') - + val libjars = libjarFiles.map { _.getName }.toSet // expand wildcard classpath entries, ignoring invalid entries diff --git a/compiler/test/dotty/tools/io/ZipArchiveTest.scala b/compiler/test/dotty/tools/io/ZipArchiveTest.scala index d10027070c69..4959eb2986fd 100644 --- a/compiler/test/dotty/tools/io/ZipArchiveTest.scala +++ b/compiler/test/dotty/tools/io/ZipArchiveTest.scala @@ -1,5 +1,7 @@ package dotty.tools.io +import scala.language.unsafeNulls + import java.io.IOException import java.net.{URI, URL, URLClassLoader} import java.nio.file.{Files, Path, Paths} diff --git a/compiler/test/dotty/tools/repl/AbstractFileClassLoaderTest.scala b/compiler/test/dotty/tools/repl/AbstractFileClassLoaderTest.scala index 3a2be3587f05..27796feb819b 100644 --- a/compiler/test/dotty/tools/repl/AbstractFileClassLoaderTest.scala +++ b/compiler/test/dotty/tools/repl/AbstractFileClassLoaderTest.scala @@ -1,5 +1,7 @@ package dotty.tools.repl +import scala.language.unsafeNulls + import org.junit.Assert.* import org.junit.Test diff --git a/compiler/test/dotty/tools/repl/DocTests.scala b/compiler/test/dotty/tools/repl/DocTests.scala index ea900e866119..cd037ea8ba8f 100644 --- a/compiler/test/dotty/tools/repl/DocTests.scala +++ b/compiler/test/dotty/tools/repl/DocTests.scala @@ -1,6 +1,8 @@ package dotty.tools package repl +import scala.language.unsafeNulls + import org.junit.Test import org.junit.Assert.assertEquals diff --git a/compiler/test/dotty/tools/repl/LoadTests.scala b/compiler/test/dotty/tools/repl/LoadTests.scala index c4f1f9f0781d..520aeee86197 100644 --- a/compiler/test/dotty/tools/repl/LoadTests.scala +++ b/compiler/test/dotty/tools/repl/LoadTests.scala @@ -1,5 +1,7 @@ package dotty.tools.repl +import scala.language.unsafeNulls + import java.nio.file.{Path, Files} import java.util.Comparator import java.util.regex.Pattern diff --git a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala index 69b3df423c5b..e1c25937ecf8 100644 --- a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala +++ b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala @@ -1,5 +1,7 @@ package dotty.tools.repl +import scala.language.unsafeNulls + import java.util.regex.Pattern import org.junit.Assert.{assertTrue => assert, _} diff --git a/compiler/test/dotty/tools/repl/ReplTest.scala b/compiler/test/dotty/tools/repl/ReplTest.scala index d5256986f874..b4f69d4e9b11 100644 --- a/compiler/test/dotty/tools/repl/ReplTest.scala +++ b/compiler/test/dotty/tools/repl/ReplTest.scala @@ -1,6 +1,8 @@ package dotty.tools package repl +import scala.language.unsafeNulls + import vulpix.TestConfiguration import vulpix.FileDiff diff --git a/compiler/test/dotty/tools/repl/ShadowingBatchTests.scala b/compiler/test/dotty/tools/repl/ShadowingBatchTests.scala index e891f0eff696..5a96976bd867 100644 --- a/compiler/test/dotty/tools/repl/ShadowingBatchTests.scala +++ b/compiler/test/dotty/tools/repl/ShadowingBatchTests.scala @@ -1,6 +1,8 @@ package dotty.tools package repl +import scala.language.unsafeNulls + import java.io.File import java.nio.file.Files diff --git a/compiler/test/dotty/tools/repl/ShadowingTests.scala b/compiler/test/dotty/tools/repl/ShadowingTests.scala index 43c182b9ae5b..564ac6258633 100644 --- a/compiler/test/dotty/tools/repl/ShadowingTests.scala +++ b/compiler/test/dotty/tools/repl/ShadowingTests.scala @@ -1,6 +1,8 @@ package dotty.tools package repl +import scala.language.unsafeNulls + import java.io.File import java.nio.file.{Path, Files} import java.util.Comparator diff --git a/compiler/test/dotty/tools/repl/TabcompleteTests.scala b/compiler/test/dotty/tools/repl/TabcompleteTests.scala index ab581d664629..6593d03838a7 100644 --- a/compiler/test/dotty/tools/repl/TabcompleteTests.scala +++ b/compiler/test/dotty/tools/repl/TabcompleteTests.scala @@ -1,5 +1,7 @@ package dotty.tools.repl +import scala.language.unsafeNulls + import org.junit.Assert._ import org.junit.Test diff --git a/compiler/test/dotty/tools/scripting/BashScriptsTests.scala b/compiler/test/dotty/tools/scripting/BashScriptsTests.scala index b83b16e01e1f..6fa009428bb1 100644 --- a/compiler/test/dotty/tools/scripting/BashScriptsTests.scala +++ b/compiler/test/dotty/tools/scripting/BashScriptsTests.scala @@ -2,6 +2,8 @@ package dotty package tools package scripting +import scala.language.unsafeNulls + import java.nio.file.Paths import org.junit.{Test, AfterClass} import org.junit.Assert.assertEquals @@ -48,7 +50,7 @@ object BashScriptsTests: ) val showArgsScript = testFiles.find(_.getName == "showArgs.sc").get.absPath - def testFile(name: String): String = + def testFile(name: String): String = val file = testFiles.find(_.getName == name) match { case Some(f) => val ff = f.absPath @@ -78,7 +80,7 @@ class BashScriptsTests: // classpath tests managed by scripting.ClasspathTests.scala ////////////////////////// begin tests ////////////////////// - + /* verify that `dist/bin/scala` correctly passes args to the jvm via -J-D for script envtest.sc */ @Test def verifyScJProperty = val tag = "World1" diff --git a/compiler/test/dotty/tools/scripting/ClasspathTests.scala b/compiler/test/dotty/tools/scripting/ClasspathTests.scala index 767c30e60ad6..0f3ada041538 100755 --- a/compiler/test/dotty/tools/scripting/ClasspathTests.scala +++ b/compiler/test/dotty/tools/scripting/ClasspathTests.scala @@ -2,6 +2,8 @@ package dotty package tools package scripting +import scala.language.unsafeNulls + import java.io.File import java.nio.file.Path @@ -40,7 +42,7 @@ class ClasspathTests: // classpathReport.sc is expected to produce two lines: // cwd: // classpath: - + val scriptOutput: Seq[String] = exec(cmd:_*) val scriptCwd: String = findTaggedLine("cwd", scriptOutput) // the value tagged "cwd: " printf("script ran in directory [%s]\n", scriptCwd) @@ -49,7 +51,7 @@ class ClasspathTests: // convert scriptCp to a list of files val hashbangJars: List[File] = scriptCp.split(psep).map { _.toFile }.toList val hashbangClasspathJars = hashbangJars.map { _.name }.sorted.distinct // get jar basenames, remove duplicates - val packlibDir = s"$scriptCwd/$packLibDir" // classpathReport.sc specifies a wildcard classpath in this directory + val packlibDir = s"$scriptCwd/$packLibDir" // classpathReport.sc specifies a wildcard classpath in this directory val packlibJars: List[File] = listJars(packlibDir) // classpath entries expected to have been reported by the script printf("%d jar files in dist/target/pack/lib\n", packlibJars.size) diff --git a/compiler/test/dotty/tools/scripting/ExpressionTest.scala b/compiler/test/dotty/tools/scripting/ExpressionTest.scala index 136007af835d..803baf30e6d8 100755 --- a/compiler/test/dotty/tools/scripting/ExpressionTest.scala +++ b/compiler/test/dotty/tools/scripting/ExpressionTest.scala @@ -2,6 +2,8 @@ package dotty package tools package scripting +import scala.language.unsafeNulls + import java.nio.file.Paths import org.junit.{Test, AfterClass} import org.junit.Assert.assertEquals @@ -10,7 +12,7 @@ import vulpix.TestConfiguration import ScriptTestEnv.* -/** +/** * +. test scala -e */ class ExpressionTest: @@ -41,7 +43,7 @@ class ExpressionTest: printf("stdout: %s\n", stdout.mkString("|")) printf("stderr: %s\n", stderr.mkString("\n", "\n", "")) stdout.filter(_.nonEmpty).mkString("") - + def testExpression(expression: String)(check: (result: String) => Boolean): Boolean = val result = getResult(expression) check(result) diff --git a/compiler/test/dotty/tools/scripting/ScriptTestEnv.scala b/compiler/test/dotty/tools/scripting/ScriptTestEnv.scala index 15bcf4034a5f..ebae5bfca6be 100644 --- a/compiler/test/dotty/tools/scripting/ScriptTestEnv.scala +++ b/compiler/test/dotty/tools/scripting/ScriptTestEnv.scala @@ -2,6 +2,8 @@ package dotty package tools package scripting +import scala.language.unsafeNulls + import java.io.File import java.nio.file.{Path, Paths, Files} @@ -30,7 +32,7 @@ object ScriptTestEnv { val dirstr = if testCwd.nonEmpty then if verbose then printf("TEST_CWD set to [%s]\n", testCwd) testCwd - else + else userDir // userDir, if TEST_CWD not set // issue warning if things don't look right @@ -82,7 +84,7 @@ object ScriptTestEnv { } out - def whichExe(basename: String): String = + def whichExe(basename: String): String = val exeName = if (osname.toLowerCase.startsWith("windows")) s"$basename.exe" else basename which(exeName) @@ -149,7 +151,7 @@ object ScriptTestEnv { def exec(cmd: String *): Seq[String] = Process(cmd).lazyLines_!.toList - def script2jar(scriptFile: File) = + def script2jar(scriptFile: File) = val jarName = s"${scriptFile.getName.dropExtension}.jar" File(scriptFile.getParent, jarName) @@ -235,7 +237,7 @@ object ScriptTestEnv { val scala = s"$workingDirectory/dist/target/pack/bin/scala".toPath.normalize (scalac.norm, scala.norm) } - + // use optional TEST_BASH if defined, otherwise, bash must be in PATH diff --git a/compiler/test/dotty/tools/scripting/ScriptingTests.scala b/compiler/test/dotty/tools/scripting/ScriptingTests.scala index 7ddab2b55424..2fb12b401754 100644 --- a/compiler/test/dotty/tools/scripting/ScriptingTests.scala +++ b/compiler/test/dotty/tools/scripting/ScriptingTests.scala @@ -2,6 +2,8 @@ package dotty package tools package scripting +import scala.language.unsafeNulls + import java.io.File import java.nio.file.Path @@ -116,7 +118,7 @@ class ScriptingTests: printf("success: script created file %s\n", touchedFile) if touchedFile.exists then printf("success: created file %s\n", touchedFile) assert( touchedFile.exists, s"expected to find file ${touchedFile}" ) - + /* * Compile touchFile.sc to create executable jar, verify jar execution succeeds. */ @@ -150,7 +152,7 @@ class ScriptingTests: def touchedFile = File("touchedFile.out") - def script2jar(scriptFile: File) = + def script2jar(scriptFile: File) = val jarName = s"${scriptFile.getName.dropExtension}.jar" File(scriptFile.getParent, jarName) diff --git a/compiler/test/dotty/tools/utils.scala b/compiler/test/dotty/tools/utils.scala index 388715f45cc2..f51747bbf54d 100644 --- a/compiler/test/dotty/tools/utils.scala +++ b/compiler/test/dotty/tools/utils.scala @@ -1,6 +1,8 @@ package dotty package tools +import scala.language.unsafeNulls + import java.io.File import java.nio.charset.Charset import java.nio.charset.StandardCharsets.UTF_8 diff --git a/compiler/test/dotty/tools/vulpix/FileDiff.scala b/compiler/test/dotty/tools/vulpix/FileDiff.scala index 4cb68005ecb7..c060c4d3938c 100644 --- a/compiler/test/dotty/tools/vulpix/FileDiff.scala +++ b/compiler/test/dotty/tools/vulpix/FileDiff.scala @@ -1,5 +1,7 @@ package dotty.tools.vulpix +import scala.language.unsafeNulls + import scala.io.Source import scala.util.Using diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala index ddb65ac84b1a..6df8c734ad3e 100644 --- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala +++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala @@ -2,6 +2,8 @@ package dotty package tools package vulpix +import scala.language.unsafeNulls + import java.io.{File => JFile, IOException, PrintStream, ByteArrayOutputStream} import java.lang.System.{lineSeparator => EOL} import java.net.URL diff --git a/compiler/test/dotty/tools/vulpix/RunnerOrchestration.scala b/compiler/test/dotty/tools/vulpix/RunnerOrchestration.scala index c6be1856564a..e95f48e3ecd7 100644 --- a/compiler/test/dotty/tools/vulpix/RunnerOrchestration.scala +++ b/compiler/test/dotty/tools/vulpix/RunnerOrchestration.scala @@ -2,6 +2,8 @@ package dotty package tools package vulpix +import scala.language.unsafeNulls + import java.io.{ File => JFile, InputStreamReader, BufferedReader, PrintStream } import java.nio.file.Paths import java.nio.charset.StandardCharsets diff --git a/compiler/test/dotty/tools/vulpix/SummaryReport.scala b/compiler/test/dotty/tools/vulpix/SummaryReport.scala index a4b59ab091f2..7043906e329d 100644 --- a/compiler/test/dotty/tools/vulpix/SummaryReport.scala +++ b/compiler/test/dotty/tools/vulpix/SummaryReport.scala @@ -2,6 +2,8 @@ package dotty package tools package vulpix +import scala.language.unsafeNulls + import scala.collection.mutable import dotc.reporting.TestReporter diff --git a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala index b43dcbdd6046..fb04b91b29d9 100644 --- a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala +++ b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala @@ -2,6 +2,8 @@ package dotty package tools package vulpix +import scala.language.unsafeNulls + import java.io.File object TestConfiguration { diff --git a/compiler/test/dotty/tools/vulpix/TestFlags.scala b/compiler/test/dotty/tools/vulpix/TestFlags.scala index b6726e4b8862..acf1c9ae167c 100644 --- a/compiler/test/dotty/tools/vulpix/TestFlags.scala +++ b/compiler/test/dotty/tools/vulpix/TestFlags.scala @@ -1,5 +1,7 @@ package dotty.tools.vulpix +import scala.language.unsafeNulls + import java.io.{File => JFile} final case class TestFlags( diff --git a/compiler/test/dotty/tools/vulpix/VulpixUnitTests.scala b/compiler/test/dotty/tools/vulpix/VulpixUnitTests.scala index 432bb64bc1cf..8a32fd636e76 100644 --- a/compiler/test/dotty/tools/vulpix/VulpixUnitTests.scala +++ b/compiler/test/dotty/tools/vulpix/VulpixUnitTests.scala @@ -1,6 +1,8 @@ package dotty.tools package vulpix +import scala.language.unsafeNulls + import java.io.{File => JFile} import org.junit.Assert._ import org.junit.{ Test, AfterClass } diff --git a/project/Build.scala b/project/Build.scala index 7c6f5e5953a5..928aa5e1b67d 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -475,6 +475,24 @@ object Build { def findArtifactPath(classpath: Def.Classpath, name: String): String = findArtifact(classpath, name).getAbsolutePath + /** Insert UnsafeNulls Import after package */ + def insertUnsafeNullsImport(lines: Seq[String]): Seq[String] = { + def recur(ls: Seq[String], foundPackage: Boolean): Seq[String] = ls match { + case Seq(l, rest @ _*) => + val lt = l.trim() + if (foundPackage) { + if (!(lt.isEmpty || lt.startsWith("package "))) + "import scala.language.unsafeNulls" +: ls + else l +: recur(rest, foundPackage) + } else { + if (lt.startsWith("package ")) l +: recur(rest, true) + else l +: recur(rest, foundPackage) + } + case _ => ls + } + recur(lines, false) + } + // Settings shared between scala3-compiler and scala3-compiler-bootstrapped lazy val commonDottyCompilerSettings = Seq( // Generate compiler.properties, used by sbt @@ -691,7 +709,12 @@ object Build { IO.createDirectory(trgDir) IO.unzip(scalaJSIRSourcesJar, trgDir) - (trgDir ** "*.scala").get.toSet + val sjsSources = (trgDir ** "*.scala").get.toSet + sjsSources.foreach(f => { + val lines = IO.readLines(f) + IO.writeLines(f, insertUnsafeNullsImport(lines)) + }) + sjsSources } (Set(scalaJSIRSourcesJar)).toSeq }.taskValue, ) @@ -745,6 +768,9 @@ object Build { "tasty-core" -> (LocalProject("tasty-core-bootstrapped") / Compile / packageBin).value.getAbsolutePath, ) }, + + Compile / scalacOptions ++= Seq("-Yexplicit-nulls"), + repl := (Compile / console).value, Compile / console / scalacOptions := Nil, // reset so that we get stock REPL behaviour! E.g. avoid -unchecked being enabled ) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala index 6d7dade3d8c7..76416c793b1d 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala @@ -37,7 +37,7 @@ case class ScaladocTastyInspector()(using ctx: DocContext) extends DocTastyInspe // however, path-dependent types disallow doing so w/o using casts inline def hackForeachTree(thunk: reflect.Tree => Unit): Unit = given dctx: dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx - dctx.run.units.foreach { compilationUnit => + dctx.run.nn.units.foreach { compilationUnit => // mirrors code from TastyInspector thunk(compilationUnit.tpdTree.asInstanceOf[reflect.Tree]) } diff --git a/tests/explicit-nulls/neg/unsafe-scope.scala b/tests/explicit-nulls/neg/unsafe-scope.scala index ab9a121f50a5..cff0dc5f9090 100644 --- a/tests/explicit-nulls/neg/unsafe-scope.scala +++ b/tests/explicit-nulls/neg/unsafe-scope.scala @@ -17,7 +17,7 @@ class S { { // disable unsafeNulls here - import scala.language.{unsafeNulls => _} + import scala.language.unsafeNulls as _ val z: String = s // error val zl = s.length // error val zs: Array[String | Null] | Null = s // error