@@ -286,7 +286,7 @@ object Contexts {
286
286
* contexts are created only on request and cached in this array
287
287
*/
288
288
private var phasedCtx : Context = this
289
- private var phasedCtxs : Array [Context ] = _
289
+ private var phasedCtxs : Array [Context ] = null
290
290
291
291
/** This context at given phase.
292
292
* This method will always return a phase period equal to phaseId, thus will never return squashed phases
@@ -340,11 +340,6 @@ object Contexts {
340
340
/** The current reporter */
341
341
def reporter : Reporter = typerState.reporter
342
342
343
- /** Run `op` as if it was run in a fresh explore typer state, but possibly
344
- * optimized to re-use the current typer state.
345
- */
346
- final def test [T ](op : Context ?=> T ): T = typerState.test(op)(using this )
347
-
348
343
/** Is this a context for the members of a class definition? */
349
344
def isClassDefContext : Boolean =
350
345
owner.isClass && (owner ne outer.owner)
@@ -453,15 +448,17 @@ object Contexts {
453
448
/** Is the explicit nulls option set? */
454
449
def explicitNulls : Boolean = base.settings.YexplicitNulls .value
455
450
456
- protected def init (outer : Context , origin : Context ): this .type = {
457
- util.Stats .record(" Context.fresh" )
451
+ /** Initialize all context fields, except typerState, which has to be set separately
452
+ * @param outer The outer context
453
+ * @param origin The context from which fields are copied
454
+ */
455
+ private [Contexts ] def init (outer : Context , origin : Context ): this .type = {
458
456
_outer = outer
459
457
_period = origin.period
460
458
_mode = origin.mode
461
459
_owner = origin.owner
462
460
_tree = origin.tree
463
461
_scope = origin.scope
464
- _typerState = origin.typerState
465
462
_typeAssigner = origin.typeAssigner
466
463
_gadt = origin.gadt
467
464
_searchHistory = origin.searchHistory
@@ -472,11 +469,19 @@ object Contexts {
472
469
this
473
470
}
474
471
472
+ def reuseIn (outer : Context ): this .type =
473
+ implicitsCache = null
474
+ phasedCtxs = null
475
+ sourceCtx = null
476
+ init(outer, outer)
477
+
475
478
/** A fresh clone of this context embedded in this context. */
476
479
def fresh : FreshContext = freshOver(this )
477
480
478
481
/** A fresh clone of this context embedded in the specified `outer` context. */
479
- def freshOver (outer : Context ): FreshContext = new FreshContext (base).init(outer, this )
482
+ def freshOver (outer : Context ): FreshContext =
483
+ util.Stats .record(" Context.fresh" )
484
+ FreshContext (base).init(outer, this ).setTyperState(this .typerState)
480
485
481
486
final def withOwner (owner : Symbol ): Context =
482
487
if (owner ne this .owner) fresh.setOwner(owner) else this
@@ -539,25 +544,59 @@ object Contexts {
539
544
* of its attributes using the with... methods.
540
545
*/
541
546
class FreshContext (base : ContextBase ) extends Context (base) {
542
- def setPeriod (period : Period ): this .type = { this .period = period; this }
543
- def setMode (mode : Mode ): this .type = { this .mode = mode; this }
544
- def setOwner (owner : Symbol ): this .type = { assert(owner != NoSymbol ); this .owner = owner; this }
545
- def setTree (tree : Tree [? >: Untyped ]): this .type = { this .tree = tree; this }
547
+ def setPeriod (period : Period ): this .type =
548
+ util.Stats .record(" Context.setPeriod" )
549
+ this .period = period
550
+ this
551
+ def setMode (mode : Mode ): this .type =
552
+ util.Stats .record(" Context.setMode" )
553
+ this .mode = mode
554
+ this
555
+ def setOwner (owner : Symbol ): this .type =
556
+ util.Stats .record(" Context.setOwner" )
557
+ assert(owner != NoSymbol )
558
+ this .owner = owner
559
+ this
560
+ def setTree (tree : Tree [? >: Untyped ]): this .type =
561
+ util.Stats .record(" Context.setTree" )
562
+ this .tree = tree
563
+ this
546
564
def setScope (scope : Scope ): this .type = { this .scope = scope; this }
547
- def setNewScope : this .type = { this .scope = newScope; this }
565
+ def setNewScope : this .type =
566
+ util.Stats .record(" Context.setScope" )
567
+ this .scope = newScope
568
+ this
548
569
def setTyperState (typerState : TyperState ): this .type = { this .typerState = typerState; this }
549
570
def setNewTyperState (): this .type = setTyperState(typerState.fresh().setCommittable(true ))
550
571
def setExploreTyperState (): this .type = setTyperState(typerState.fresh().setCommittable(false ))
551
572
def setReporter (reporter : Reporter ): this .type = setTyperState(typerState.fresh().setReporter(reporter))
552
- def setTypeAssigner (typeAssigner : TypeAssigner ): this .type = { this .typeAssigner = typeAssigner; this }
573
+ def setTypeAssigner (typeAssigner : TypeAssigner ): this .type =
574
+ util.Stats .record(" Context.setTypeAssigner" )
575
+ this .typeAssigner = typeAssigner
576
+ this
553
577
def setTyper (typer : Typer ): this .type = { this .scope = typer.scope; setTypeAssigner(typer) }
554
- def setGadt (gadt : GadtConstraint ): this .type = { this .gadt = gadt; this }
578
+ def setGadt (gadt : GadtConstraint ): this .type =
579
+ util.Stats .record(" Context.setGadt" )
580
+ this .gadt = gadt
581
+ this
555
582
def setFreshGADTBounds : this .type = setGadt(gadt.fresh)
556
- def setSearchHistory (searchHistory : SearchHistory ): this .type = { this .searchHistory = searchHistory; this }
557
- def setSource (source : SourceFile ): this .type = { this .source = source; this }
583
+ def setSearchHistory (searchHistory : SearchHistory ): this .type =
584
+ util.Stats .record(" Context.setSearchHistory" )
585
+ this .searchHistory = searchHistory
586
+ this
587
+ def setSource (source : SourceFile ): this .type =
588
+ util.Stats .record(" Context.setSource" )
589
+ this .source = source
590
+ this
558
591
def setTypeComparerFn (tcfn : Context => TypeComparer ): this .type = { this .typeComparer = tcfn(this ); this }
559
- private def setMoreProperties (moreProperties : Map [Key [Any ], Any ]): this .type = { this .moreProperties = moreProperties; this }
560
- private def setStore (store : Store ): this .type = { this .store = store; this }
592
+ private def setMoreProperties (moreProperties : Map [Key [Any ], Any ]): this .type =
593
+ util.Stats .record(" Context.setMoreProperties" )
594
+ this .moreProperties = moreProperties
595
+ this
596
+ private def setStore (store : Store ): this .type =
597
+ util.Stats .record(" Context.setStore" )
598
+ this .store = store
599
+ this
561
600
def setImplicits (implicits : ContextualImplicits ): this .type = { this .implicitsCache = implicits; this }
562
601
563
602
def setCompilationUnit (compilationUnit : CompilationUnit ): this .type = {
@@ -632,14 +671,42 @@ object Contexts {
632
671
final def retractMode (mode : Mode ): c.type = c.setMode(c.mode &~ mode)
633
672
}
634
673
674
+ /** Test `op` in a fresh context with a typerstate that is not committable.
675
+ * The passed context may not survive the operation.
676
+ */
677
+ def explore [T ](op : Context ?=> T )(using Context ): T =
678
+ util.Stats .record(" Context.test" )
679
+ val base = ctx.base
680
+ import base ._
681
+ val nestedCtx =
682
+ if testsInUse < testContexts.size then
683
+ testContexts(testsInUse).reuseIn(ctx)
684
+ else
685
+ val ts = TyperState ()
686
+ .setReporter(TestingReporter ())
687
+ .setCommittable(false )
688
+ val c = FreshContext (ctx.base).init(ctx, ctx).setTyperState(ts)
689
+ testContexts += c
690
+ c
691
+ testsInUse += 1
692
+ val nestedTS = nestedCtx.typerState
693
+ nestedTS.init(ctx.typerState, ctx.typerState.constraint)
694
+ val result =
695
+ try op(using nestedCtx)
696
+ finally
697
+ nestedTS.reporter.asInstanceOf [TestingReporter ].reset()
698
+ testsInUse -= 1
699
+ result
700
+ end explore
701
+
635
702
/** A class defining the initial context with given context base
636
703
* and set of possible settings.
637
704
*/
638
705
private class InitialContext (base : ContextBase , settingsGroup : SettingGroup ) extends FreshContext (base) {
639
706
outer = NoContext
640
707
period = InitialPeriod
641
708
mode = Mode .None
642
- typerState = new TyperState ( null )
709
+ typerState = TyperState .initialState( )
643
710
owner = NoSymbol
644
711
tree = untpd.EmptyTree
645
712
typeAssigner = TypeAssigner
@@ -785,6 +852,9 @@ object Contexts {
785
852
786
853
protected [dotc] val indentTab : String = " "
787
854
855
+ private [dotc] val testContexts = new mutable.ArrayBuffer [FreshContext ]
856
+ private [dotc] var testsInUse : Int = 0
857
+
788
858
def reset (): Unit = {
789
859
for ((_, set) <- uniqueSets) set.clear()
790
860
errorTypeMsg.clear()
0 commit comments