@@ -172,19 +172,66 @@ object Contexts {
172172 def uniqueNamedTypes : Uniques .NamedTypeUniques
173173 def uniques : util.HashSet [Type ]
174174
175- def fresh : FreshContext
176- def freshOver (outer : Context ): FreshContext
175+ def fresh : FreshCtx
176+ def freshOver (outer : Ctx ): FreshCtx
177177
178178 def withPeriod (pd : Period ): Context
179179 def withPhase (phaseId : PhaseId ): Context
180180 def withPhase (phase : Phase ): Context
181181 def withOwner (owner : Symbol ): Ctx
182182 def withSource (source : SourceFile ): Ctx
183183 def withProperty [T ](key : Key [T ], value : Option [T ]): Ctx
184+ def withAddedMode (mode : Mode ): Ctx
185+ def withRetractedMode (mode : Mode ): Ctx
186+
187+ def toContext (using cs : CState ) = withPeriod(cs)
188+
189+ private [Contexts ] def storedSourceCtx (source : SourceFile ): Ctx
184190
185191 def toContextUNSAFE = asInstanceOf [Context ]
186192 end Ctx
187193
194+ trait FreshCtx extends Ctx :
195+ def setPeriod (period : Period ): this .type
196+ def setMode (mode : Mode ): this .type
197+ def addMode (mode : Mode ): this .type
198+ def retractMode (mode : Mode ): this .type
199+ def setOwner (owner : Symbol ): this .type
200+ def setTree (tree : Tree [? >: Untyped ]): this .type
201+ def setScope (scope : Scope ): this .type
202+ def setNewScope : this .type
203+ def setTyperState (typerState : TyperState ): this .type
204+ def setNewTyperState (): this .type
205+ def setExploreTyperState (): this .type
206+ def setReporter (reporter : Reporter ): this .type
207+ def setTypeAssigner (typeAssigner : TypeAssigner ): this .type
208+ def setTyper (typer : Typer ): this .type
209+ def setGadt (gadt : GadtConstraint ): this .type
210+ def setFreshGADTBounds : this .type
211+ def setSearchHistory (searchHistory : SearchHistory ): this .type
212+ def setSource (source : SourceFile ): this .type
213+ def setTypeComparerFn (tcfn : Context => TypeComparer ): this .type
214+ def setImplicits (implicits : ContextualImplicits ): this .type
215+ def setCompilationUnit (compilationUnit : CompilationUnit ): this .type
216+ def setCompilerCallback (callback : CompilerCallback ): this .type
217+ def setSbtCallback (callback : AnalysisCallback ): this .type
218+ def setPrinterFn (printer : Context => Printer ): this .type
219+ def setSettings (settingsState : SettingsState ): this .type
220+ def setRun (run : Run ): this .type
221+ def setProfiler (profiler : Profiler ): this .type
222+ def setNotNullInfos (notNullInfos : List [NotNullInfo ]): this .type
223+ def setImportInfo (importInfo : ImportInfo ): this .type
224+ def setProperty [T ](key : Key [T ], value : T ): this .type
225+ def dropProperty (key : Key [? ]): this .type
226+ def addLocation [T ](initial : T ): Store .Location [T ]
227+ def addLocation [T ](): Store .Location [T ]
228+ def updateStore [T ](loc : Store .Location [T ], value : T ): this .type
229+ def setPhase (pid : PhaseId ): this .type
230+ def setPhase (phase : Phase ): this .type
231+ def setSetting [T ](setting : Setting [T ], value : T ): this .type
232+ def setDebug : this .type
233+ end FreshCtx
234+
188235 /** A context is passed basically everywhere in dotc.
189236 * This is convenient but carries the risk of captured contexts in
190237 * objects that turn into space leaks. To combat this risk, here are some
@@ -210,16 +257,16 @@ object Contexts {
210257 protected given CState = cstate
211258
212259 /** All outer contexts, ending in `base.initialCtx` and then `NoContext` */
213- def outersIterator : Iterator [Context ] = new Iterator [Context ] {
214- var current = thiscontext
260+ def outersIterator : Iterator [Ctx ] = new Iterator [Ctx ] {
261+ var current : Ctx = thiscontext
215262 def hasNext = current != NoContext
216263 def next = { val c = current; current = current.outer; c }
217264 }
218265
219266 /** The outer context */
220- private var _outer : Context = _
221- protected def outer_= (outer : Context ): Unit = _outer = outer
222- final def outer : Context = _outer
267+ private var _outer : Ctx = _
268+ protected def outer_= (outer : Ctx ): Unit = _outer = outer
269+ final def outer : Ctx = _outer
223270
224271 /** The current context */
225272 private var _period : Period = _
@@ -487,9 +534,12 @@ object Contexts {
487534 * @param outer The outer context
488535 * @param origin The context from which fields are copied
489536 */
490- private [Contexts ] def init (outer : Context , origin : Context ): this .type = {
537+ private [Contexts ] def init (outer : Ctx , origin : Context ): this .type =
538+ init(outer, origin, origin.cstate)
539+
540+ private [Contexts ] def init (outer : Ctx , origin : Ctx , cstate : CState ): this .type = {
491541 _outer = outer
492- _period = origin.period
542+ _period = cstate
493543 _mode = origin.mode
494544 _owner = origin.owner
495545 _tree = origin.tree
@@ -514,20 +564,23 @@ object Contexts {
514564 def fresh : FreshContext = freshOver(this )
515565
516566 /** A fresh clone of this context embedded in the specified `outer` context. */
517- def freshOver (outer : Context ): FreshContext =
567+ def freshOver (outer : Ctx ): FreshContext =
518568 util.Stats .record(" Context.fresh" )
519569 FreshContext (base).init(outer, this ).setTyperState(this .typerState)
520570
521571 final def withOwner (owner : Symbol ): Context =
522572 if (owner ne this .owner) fresh.setOwner(owner) else this
523573
524- private var sourceCtx : SimpleIdentityMap [SourceFile , Context ] = null
574+ private var sourceCtx : SimpleIdentityMap [SourceFile , Ctx ] = null
575+
576+ private [Contexts ] def storedSourceCtx (source : SourceFile ): Ctx =
577+ if sourceCtx == null then null
578+ else sourceCtx(source)
525579
526- final def withSource (source : SourceFile ): Context =
527- if (source `eq` this .source) this
528- else if ((source `eq` outer.source) &&
529- outer.sourceCtx != null &&
530- (outer.sourceCtx(this .source) `eq` this )) outer
580+ final def withSource (source : SourceFile ): Ctx =
581+ if source eq this .source then this
582+ else if (source eq outer.source)
583+ && (outer.storedSourceCtx(this .source) eq this ) then outer
531584 else {
532585 if (sourceCtx == null ) sourceCtx = SimpleIdentityMap .Empty
533586 val prev = sourceCtx(source)
@@ -551,6 +604,12 @@ object Contexts {
551604 case None => fresh.dropProperty(key)
552605 }
553606
607+ private def withModeBits (mode : Mode ): Context =
608+ if (mode != this .mode) fresh.setMode(mode) else this
609+
610+ def withAddedMode (mode : Mode ): Context = withModeBits(this .mode | mode)
611+ def withRetractedMode (mode : Mode ): Context = withModeBits(this .mode &~ mode)
612+
554613 def typer : Typer = this .typeAssigner match {
555614 case typer : Typer => typer
556615 case _ => new Typer
@@ -585,7 +644,7 @@ object Contexts {
585644 /** A fresh context allows selective modification
586645 * of its attributes using the with... methods.
587646 */
588- class FreshContext (base : ContextBase ) extends Context (base) {
647+ class FreshContext (base : ContextBase ) extends Context (base), FreshCtx {
589648 def setPeriod (period : Period ): this .type =
590649 util.Stats .record(" Context.setPeriod" )
591650 this .period = period
@@ -594,6 +653,8 @@ object Contexts {
594653 util.Stats .record(" Context.setMode" )
595654 this .mode = mode
596655 this
656+ final def addMode (mode : Mode ): this .type = setMode(this .mode | mode)
657+ final def retractMode (mode : Mode ): this .type = setMode(this .mode &~ mode)
597658 def setOwner (owner : Symbol ): this .type =
598659 util.Stats .record(" Context.setOwner" )
599660 assert(owner != NoSymbol )
@@ -696,7 +757,7 @@ object Contexts {
696757 def withNotNullInfos (infos : List [NotNullInfo ])(using CState ): Ctx =
697758 if c.notNullInfos eq infos then c else c.fresh.setNotNullInfos(infos)
698759 end ops
699-
760+ /*
700761 // TODO: Fix issue when converting ModeChanges and FreshModeChanges to extension givens
701762 implicit class ModeChanges(val c: Context) extends AnyVal {
702763 final def withModeBits(mode: Mode): Context =
@@ -710,7 +771,7 @@ object Contexts {
710771 final def addMode(mode: Mode): c.type = c.setMode(c.mode | mode)
711772 final def retractMode(mode: Mode): c.type = c.setMode(c.mode &~ mode)
712773 }
713-
774+ */
714775 /** Test `op` in a fresh context with a typerstate that is not committable.
715776 * The passed context may not survive the operation.
716777 */
@@ -725,7 +786,7 @@ object Contexts {
725786 val ts = TyperState ()
726787 .setReporter(TestingReporter ())
727788 .setCommittable(false )
728- val c = FreshContext (ctx.base).init(ctx.toContextUNSAFE , ctx.toContextUNSAFE ).setTyperState(ts)
789+ val c = FreshContext (ctx.base).init(ctx, ctx, currentPeriod ).setTyperState(ts)
729790 testContexts += c
730791 c
731792 testsInUse += 1
0 commit comments