From 3138600345e041fe4637ecf6daa0c161619d0e4e Mon Sep 17 00:00:00 2001 From: Xavientois Date: Sun, 13 Feb 2022 09:14:05 -0500 Subject: [PATCH] Supress safe initialization warning in Run class Due to the `this` pointer being passed to `start.setRun` in a function called during initialization, the initialization checker cannot prove that `this` is fully initialized. We would get the following error: ``` [error] -- Error: /*******/dotty/compiler/src/dotty/tools/dotc/Run.scala:84:17 [error] 84 | start.setRun(this) [error] | ^^^^ [error] |Cannot prove that the value is fully initialized. Only initialized values may be used as arguments. Calling trace: [error] | -> val run = new Run(this, initCtx) { [ ReplCompiler.scala:42 ] [error] | -> class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with ConstraintRunInfo {iler-b[ Run.scala:38 ] [error] | -> private var myCtx = rootContext(using ictx) [ Run.scala:89 ] [error] | -> val rootCtx = super.rootContext.fresh [ ReplCompiler.scala:62 ] ``` The call to `start.setRun` stores the reference to `this` in a store without accessing any of its fields. The instance of `Run` referrred to by `this` will be fully initialized immediately after that function call. Thus, we are able to safely mark `this` as `@unchecked` without worrying about uninitialized members of the `Run` instance being accessed. Review by @liufengyun --- compiler/src/dotty/tools/dotc/Run.scala | 69 +++++++++++++------------ 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala index 9f7036f64255..a258036466ff 100644 --- a/compiler/src/dotty/tools/dotc/Run.scala +++ b/compiler/src/dotty/tools/dotc/Run.scala @@ -57,41 +57,8 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint */ @volatile var isCancelled = false - /** Produces the following contexts, from outermost to innermost - * - * bootStrap: A context with next available runId and a scope consisting of - * the RootPackage _root_ - * start A context with RootClass as owner and the necessary initializations - * for type checking. - * imports For each element of RootImports, an import context - */ - protected def rootContext(using Context): Context = { - ctx.initialize() - ctx.base.setPhasePlan(comp.phases) - val rootScope = new MutableScope(0) - val bootstrap = ctx.fresh - .setPeriod(Period(comp.nextRunId, FirstPhaseId)) - .setScope(rootScope) - rootScope.enter(ctx.definitions.RootPackage)(using bootstrap) - var start = bootstrap.fresh - .setOwner(defn.RootClass) - .setTyper(new Typer) - .addMode(Mode.ImplicitsEnabled) - .setTyperState(ctx.typerState.fresh(ctx.reporter)) - if ctx.settings.YexplicitNulls.value && !Feature.enabledBySetting(nme.unsafeNulls) then - start = start.addMode(Mode.SafeNulls) - ctx.initialize()(using start) // re-initialize the base context with start - start.setRun(this) - } - private var compiling = false - private var myCtx = rootContext(using ictx) - - /** The context created for this run */ - given runContext[Dummy_so_its_a_def]: Context = myCtx - assert(runContext.runId <= Periods.MaxPossibleRunId) - private var myUnits: List[CompilationUnit] = _ private var myUnitsCached: List[CompilationUnit] = _ private var myFiles: Set[AbstractFile] = _ @@ -369,4 +336,40 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint myUnits = null myUnitsCached = null } + + /** Produces the following contexts, from outermost to innermost + * + * bootStrap: A context with next available runId and a scope consisting of + * the RootPackage _root_ + * start A context with RootClass as owner and the necessary initializations + * for type checking. + * imports For each element of RootImports, an import context + */ + protected def rootContext(using Context): Context = { + ctx.initialize() + ctx.base.setPhasePlan(comp.phases) + val rootScope = new MutableScope(0) + val bootstrap = ctx.fresh + .setPeriod(Period(comp.nextRunId, FirstPhaseId)) + .setScope(rootScope) + rootScope.enter(ctx.definitions.RootPackage)(using bootstrap) + var start = bootstrap.fresh + .setOwner(defn.RootClass) + .setTyper(new Typer) + .addMode(Mode.ImplicitsEnabled) + .setTyperState(ctx.typerState.fresh(ctx.reporter)) + if ctx.settings.YexplicitNulls.value && !Feature.enabledBySetting(nme.unsafeNulls) then + start = start.addMode(Mode.SafeNulls) + ctx.initialize()(using start) // re-initialize the base context with start + + // `this` must be unchecked for safe initialization because by being passed to setRun during + // initialization, it is not yet considered fully initialized by the initialization checker + start.setRun(this: @unchecked) + } + + private var myCtx = rootContext(using ictx) + + /** The context created for this run */ + given runContext[Dummy_so_its_a_def]: Context = myCtx + assert(runContext.runId <= Periods.MaxPossibleRunId) }