aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/core/Contexts.scala
diff options
context:
space:
mode:
authorFelix Mulder <felix.mulder@gmail.com>2016-11-02 11:08:28 +0100
committerGuillaume Martres <smarter@ubuntu.com>2016-11-22 01:35:07 +0100
commit8a61ff432543a29234193cd1f7c14abd3f3d31a0 (patch)
treea8147561d307af862c295cfc8100d271063bb0dd /compiler/src/dotty/tools/dotc/core/Contexts.scala
parent6a455fe6da5ff9c741d91279a2dc6fe2fb1b472f (diff)
downloaddotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.tar.gz
dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.tar.bz2
dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.zip
Move compiler and compiler tests to compiler dir
Diffstat (limited to 'compiler/src/dotty/tools/dotc/core/Contexts.scala')
-rw-r--r--compiler/src/dotty/tools/dotc/core/Contexts.scala709
1 files changed, 709 insertions, 0 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala
new file mode 100644
index 000000000..639c4d111
--- /dev/null
+++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala
@@ -0,0 +1,709 @@
+package dotty.tools
+package dotc
+package core
+
+import interfaces.CompilerCallback
+import Decorators._
+import Periods._
+import Names._
+import Phases._
+import Types._
+import Symbols._
+import Scopes._
+import NameOps._
+import Uniques._
+import SymDenotations._
+import Comments._
+import Flags.ParamAccessor
+import util.Positions._
+import ast.Trees._
+import ast.untpd
+import util.{FreshNameCreator, SimpleMap, SourceFile, NoSource}
+import typer.{Implicits, ImplicitRunInfo, ImportInfo, Inliner, NamerContextOps, SearchHistory, TypeAssigner, Typer}
+import Implicits.ContextualImplicits
+import config.Settings._
+import config.Config
+import reporting._
+import collection.mutable
+import collection.immutable.BitSet
+import printing._
+import config.{Settings, ScalaSettings, Platform, JavaPlatform}
+import language.implicitConversions
+import DenotTransformers.DenotTransformer
+import util.Property.Key
+import xsbti.AnalysisCallback
+
+object Contexts {
+
+ /** A context is passed basically everywhere in dotc.
+ * This is convenient but carries the risk of captured contexts in
+ * objects that turn into space leaks. To combat this risk, here are some
+ * conventions to follow:
+ *
+ * - Never let an implicit context be an argument of a class whose instances
+ * live longer than the context.
+ * - Classes that need contexts for their initialization take an explicit parameter
+ * named `initctx`. They pass initctx to all positions where it is needed
+ * (and these positions should all be part of the intialization sequence of the class).
+ * - Classes that need contexts that survive initialization are instead passed
+ * a "condensed context", typically named `cctx` (or they create one). Condensed contexts
+ * just add some basic information to the context base without the
+ * risk of capturing complete trees.
+ * - To make sure these rules are kept, it would be good to do a sanity
+ * check using bytecode inspection with javap or scalap: Keep track
+ * of all class fields of type context; allow them only in whitelisted
+ * classes (which should be short-lived).
+ */
+ abstract class Context extends Periods
+ with Substituters
+ with TypeOps
+ with Phases
+ with Printers
+ with Symbols
+ with SymDenotations
+ with Reporting
+ with NamerContextOps
+ with Cloneable { thiscontext =>
+ implicit def ctx: Context = this
+
+ /** The context base at the root */
+ val base: ContextBase
+
+ /** All outer contexts, ending in `base.initialCtx` and then `NoContext` */
+ def outersIterator = new Iterator[Context] {
+ var current = thiscontext
+ def hasNext = current != NoContext
+ def next = { val c = current; current = current.outer; c }
+ }
+
+ /** The outer context */
+ private[this] var _outer: Context = _
+ protected def outer_=(outer: Context) = _outer = outer
+ def outer: Context = _outer
+
+ /** The compiler callback implementation, or null if no callback will be called. */
+ private[this] var _compilerCallback: CompilerCallback = _
+ protected def compilerCallback_=(callback: CompilerCallback) =
+ _compilerCallback = callback
+ def compilerCallback: CompilerCallback = _compilerCallback
+
+ /** The sbt callback implementation if we are run from sbt, null otherwise */
+ private[this] var _sbtCallback: AnalysisCallback = _
+ protected def sbtCallback_=(callback: AnalysisCallback) =
+ _sbtCallback = callback
+ def sbtCallback: AnalysisCallback = _sbtCallback
+
+ /** The current context */
+ private[this] var _period: Period = _
+ protected def period_=(period: Period) = {
+ assert(period.firstPhaseId == period.lastPhaseId, period)
+ _period = period
+ }
+ def period: Period = _period
+
+ /** The scope nesting level */
+ private[this] var _mode: Mode = _
+ protected def mode_=(mode: Mode) = _mode = mode
+ def mode: Mode = _mode
+
+ /** The current type comparer */
+ private[this] var _typerState: TyperState = _
+ protected def typerState_=(typerState: TyperState) = _typerState = typerState
+ def typerState: TyperState = _typerState
+
+ /** The current plain printer */
+ private[this] var _printerFn: Context => Printer = _
+ protected def printerFn_=(printerFn: Context => Printer) = _printerFn = printerFn
+ def printerFn: Context => Printer = _printerFn
+
+ /** The current owner symbol */
+ private[this] var _owner: Symbol = _
+ protected def owner_=(owner: Symbol) = _owner = owner
+ def owner: Symbol = _owner
+
+ /** The current settings values */
+ private[this] var _sstate: SettingsState = _
+ protected def sstate_=(sstate: SettingsState) = _sstate = sstate
+ def sstate: SettingsState = _sstate
+
+ /** The current tree */
+ private[this] var _compilationUnit: CompilationUnit = _
+ protected def compilationUnit_=(compilationUnit: CompilationUnit) = _compilationUnit = compilationUnit
+ def compilationUnit: CompilationUnit = _compilationUnit
+
+ /** The current tree */
+ private[this] var _tree: Tree[_ >: Untyped]= _
+ protected def tree_=(tree: Tree[_ >: Untyped]) = _tree = tree
+ def tree: Tree[_ >: Untyped] = _tree
+
+ /** The current scope */
+ private[this] var _scope: Scope = _
+ protected def scope_=(scope: Scope) = _scope = scope
+ def scope: Scope = _scope
+
+ /** The current type assigner or typer */
+ private[this] var _typeAssigner: TypeAssigner = _
+ protected def typeAssigner_=(typeAssigner: TypeAssigner) = _typeAssigner = typeAssigner
+ def typeAssigner: TypeAssigner = _typeAssigner
+ def typer: Typer = _typeAssigner.asInstanceOf[Typer]
+
+ /** The currently active import info */
+ private[this] var _importInfo: ImportInfo = _
+ protected def importInfo_=(importInfo: ImportInfo) = _importInfo = importInfo
+ def importInfo: ImportInfo = _importInfo
+
+ /** The current compiler-run specific Info */
+ private[this] var _runInfo: RunInfo = _
+ protected def runInfo_=(runInfo: RunInfo) = _runInfo = runInfo
+ def runInfo: RunInfo = _runInfo
+
+ /** An optional diagostics buffer than is used by some checking code
+ * to provide more information in the buffer if it exists.
+ */
+ private var _diagnostics: Option[StringBuilder] = _
+ protected def diagnostics_=(diagnostics: Option[StringBuilder]) = _diagnostics = diagnostics
+ def diagnostics: Option[StringBuilder] = _diagnostics
+
+ /** The current bounds in force for type parameters appearing in a GADT */
+ private var _gadt: GADTMap = _
+ protected def gadt_=(gadt: GADTMap) = _gadt = gadt
+ def gadt: GADTMap = _gadt
+
+ /**The current fresh name creator */
+ private[this] var _freshNames: FreshNameCreator = _
+ protected def freshNames_=(freshNames: FreshNameCreator) = _freshNames = freshNames
+ def freshNames: FreshNameCreator = _freshNames
+
+ def freshName(prefix: String = ""): String = freshNames.newName(prefix)
+ def freshName(prefix: Name): String = freshName(prefix.toString)
+
+ /** A map in which more contextual properties can be stored */
+ private var _moreProperties: Map[Key[Any], Any] = _
+ protected def moreProperties_=(moreProperties: Map[Key[Any], Any]) = _moreProperties = moreProperties
+ def moreProperties: Map[Key[Any], Any] = _moreProperties
+
+ def property[T](key: Key[T]): Option[T] =
+ moreProperties.get(key).asInstanceOf[Option[T]]
+
+ private var _typeComparer: TypeComparer = _
+ protected def typeComparer_=(typeComparer: TypeComparer) = _typeComparer = typeComparer
+ def typeComparer: TypeComparer = {
+ if (_typeComparer.ctx ne this)
+ _typeComparer = _typeComparer.copyIn(this)
+ _typeComparer
+ }
+
+ /** Number of findMember calls on stack */
+ private[core] var findMemberCount: Int = 0
+
+ /** List of names which have a findMemberCall on stack,
+ * after Config.LogPendingFindMemberThreshold is reached.
+ */
+ private[core] var pendingMemberSearches: List[Name] = Nil
+
+ /** The new implicit references that are introduced by this scope */
+ private var implicitsCache: ContextualImplicits = null
+ def implicits: ContextualImplicits = {
+ if (implicitsCache == null )
+ implicitsCache = {
+ val implicitRefs: List[TermRef] =
+ if (isClassDefContext)
+ try owner.thisType.implicitMembers
+ catch {
+ case ex: CyclicReference => Nil
+ }
+ else if (isImportContext) importInfo.importedImplicits
+ else if (isNonEmptyScopeContext) scope.implicitDecls
+ else Nil
+ val outerImplicits =
+ if (isImportContext && importInfo.hiddenRoot.exists)
+ outer.implicits exclude importInfo.hiddenRoot
+ else
+ outer.implicits
+ if (implicitRefs.isEmpty) outerImplicits
+ else new ContextualImplicits(implicitRefs, outerImplicits)(this)
+ }
+ implicitsCache
+ }
+
+ /** The history of implicit searches that are currently active */
+ private var _searchHistory: SearchHistory = null
+ protected def searchHistory_= (searchHistory: SearchHistory) = _searchHistory = searchHistory
+ def searchHistory: SearchHistory = _searchHistory
+
+ /** Those fields are used to cache phases created in withPhase.
+ * phasedCtx is first phase with altered phase ever requested.
+ * phasedCtxs is array that uses phaseId's as indexes,
+ * contexts are created only on request and cached in this array
+ */
+ private var phasedCtx: Context = _
+ private var phasedCtxs: Array[Context] = _
+
+ /** This context at given phase.
+ * This method will always return a phase period equal to phaseId, thus will never return squashed phases
+ */
+ final def withPhase(phaseId: PhaseId): Context =
+ if (this.phaseId == phaseId) this
+ else if (phasedCtx.phaseId == phaseId) phasedCtx
+ else if (phasedCtxs != null && phasedCtxs(phaseId) != null) phasedCtxs(phaseId)
+ else {
+ val ctx1 = fresh.setPhase(phaseId)
+ if (phasedCtx eq this) phasedCtx = ctx1
+ else {
+ if (phasedCtxs == null) phasedCtxs = new Array[Context](base.phases.length)
+ phasedCtxs(phaseId) = ctx1
+ }
+ ctx1
+ }
+
+ final def withPhase(phase: Phase): Context =
+ withPhase(phase.id)
+
+ final def withPhaseNoLater(phase: Phase) =
+ if (phase.exists && ctx.phase.id > phase.id) withPhase(phase) else ctx
+
+ /** If -Ydebug is on, the top of the stack trace where this context
+ * was created, otherwise `null`.
+ */
+ private var creationTrace: Array[StackTraceElement] = _
+
+ private def setCreationTrace() =
+ if (this.settings.YtraceContextCreation.value)
+ creationTrace = (new Throwable).getStackTrace().take(20)
+
+ /** Print all enclosing context's creation stacktraces */
+ def printCreationTraces() = {
+ println("=== context creation trace =======")
+ for (ctx <- outersIterator) {
+ println(s">>>>>>>>> $ctx")
+ if (ctx.creationTrace != null) println(ctx.creationTrace.mkString("\n"))
+ }
+ println("=== end context creation trace ===")
+ }
+
+ /** The current reporter */
+ def reporter: Reporter = typerState.reporter
+
+ /** Is this a context for the members of a class definition? */
+ def isClassDefContext: Boolean =
+ owner.isClass && (owner ne outer.owner)
+
+ /** Is this a context that introduces an import clause? */
+ def isImportContext: Boolean =
+ (this ne NoContext) && (this.importInfo ne outer.importInfo)
+
+ /** Is this a context that introduces a non-empty scope? */
+ def isNonEmptyScopeContext: Boolean =
+ (this.scope ne outer.scope) && this.scope.nonEmpty
+
+ /** Leave message in diagnostics buffer if it exists */
+ def diagnose(str: => String) =
+ for (sb <- diagnostics) {
+ sb.setLength(0)
+ sb.append(str)
+ }
+
+ /** The next outer context whose tree is a template or package definition */
+ def enclTemplate: Context = {
+ var c = this
+ while (c != NoContext && !c.tree.isInstanceOf[Template[_]] && !c.tree.isInstanceOf[PackageDef[_]])
+ c = c.outer
+ c
+ }
+
+ /** The context for a supercall. This context is used for elaborating
+ * the parents of a class and their arguments.
+ * The context is computed from the current class context. It has
+ *
+ * - as owner: The primary constructor of the class
+ * - as outer context: The context enclosing the class context
+ * - as scope: The parameter accessors in the class context
+ * - with additional mode: InSuperCall
+ *
+ * The reasons for this peculiar choice of attributes are as follows:
+ *
+ * - The constructor must be the owner, because that's where any local methods or closures
+ * should go.
+ * - The context may not see any class members (inherited or defined), and should
+ * instead see definitions defined in the outer context which might be shadowed by
+ * such class members. That's why the outer context must be the outer context of the class.
+ * - At the same time the context should see the parameter accessors of the current class,
+ * that's why they get added to the local scope. An alternative would have been to have the
+ * context see the constructor parameters instead, but then we'd need a final substitution step
+ * from constructor parameters to class parameter accessors.
+ */
+ def superCallContext: Context = {
+ val locals = newScopeWith(owner.asClass.paramAccessors: _*)
+ superOrThisCallContext(owner.primaryConstructor, locals)
+ }
+
+ /** The context for the arguments of a this(...) constructor call.
+ * The context is computed from the local auxiliary constructor context.
+ * It has
+ *
+ * - as owner: The auxiliary constructor
+ * - as outer context: The context enclosing the enclosing class context
+ * - as scope: The parameters of the auxiliary constructor.
+ */
+ def thisCallArgContext: Context = {
+ assert(owner.isClassConstructor)
+ val constrCtx = outersIterator.dropWhile(_.outer.owner == owner).next
+ superOrThisCallContext(owner, constrCtx.scope)
+ .setTyperState(typerState)
+ .setGadt(gadt)
+ }
+
+ /** The super- or this-call context with given owner and locals. */
+ private def superOrThisCallContext(owner: Symbol, locals: Scope): FreshContext = {
+ var classCtx = outersIterator.dropWhile(!_.isClassDefContext).next
+ classCtx.outer.fresh.setOwner(owner)
+ .setScope(locals)
+ .setMode(classCtx.mode | Mode.InSuperCall)
+ }
+
+ /** The context of expression `expr` seen as a member of a statement sequence */
+ def exprContext(stat: Tree[_ >: Untyped], exprOwner: Symbol) =
+ if (exprOwner == this.owner) this
+ else if (untpd.isSuperConstrCall(stat) && this.owner.isClass) superCallContext
+ else ctx.fresh.setOwner(exprOwner)
+
+ /** The current source file; will be derived from current
+ * compilation unit.
+ */
+ def source: SourceFile =
+ if (compilationUnit == null) NoSource else compilationUnit.source
+
+ /** Does current phase use an erased types interpretation? */
+ def erasedTypes: Boolean = phase.erasedTypes
+
+ /** Is the debug option set? */
+ def debug: Boolean = base.settings.debug.value
+
+ /** Is the verbose option set? */
+ def verbose: Boolean = base.settings.verbose.value
+
+ /** Should use colors when printing? */
+ def useColors: Boolean =
+ base.settings.color.value == "always"
+
+ /** A condensed context containing essential information of this but
+ * no outer contexts except the initial context.
+ private var _condensed: CondensedContext = null
+ def condensed: CondensedContext = {
+ if (_condensed eq outer.condensed)
+ _condensed = base.initialCtx.fresh
+ .withPeriod(period)
+ .withNewMode(mode)
+ // typerState and its constraint is not preserved in condensed
+ // reporter is always ThrowingReporter
+ .withPrinterFn(printerFn)
+ .withOwner(owner)
+ .withSettings(sstate)
+ // tree is not preserved in condensed
+ .withRunInfo(runInfo)
+ .withDiagnostics(diagnostics)
+ .withMoreProperties(moreProperties)
+ _condensed
+ }
+ */
+
+ protected def init(outer: Context): this.type = {
+ this.outer = outer
+ this.implicitsCache = null
+ this.phasedCtx = this
+ this.phasedCtxs = null
+ setCreationTrace()
+ this
+ }
+
+ /** A fresh clone of this context. */
+ def fresh: FreshContext = clone.asInstanceOf[FreshContext].init(this)
+
+ final def withOwner(owner: Symbol): Context =
+ if (owner ne this.owner) fresh.setOwner(owner) else this
+
+ override def toString =
+ "Context(\n" +
+ (outersIterator map ( ctx => s" owner = ${ctx.owner}, scope = ${ctx.scope}") mkString "\n")
+ }
+
+ /** A condensed context provides only a small memory footprint over
+ * a Context base, and therefore can be stored without problems in
+ * long-lived objects.
+ abstract class CondensedContext extends Context {
+ override def condensed = this
+ }
+ */
+
+ /** A fresh context allows selective modification
+ * of its attributes using the with... methods.
+ */
+ abstract class FreshContext extends Context {
+ def setPeriod(period: Period): this.type = { this.period = period; this }
+ def setMode(mode: Mode): this.type = { this.mode = mode; this }
+ def setCompilerCallback(callback: CompilerCallback): this.type = { this.compilerCallback = callback; this }
+ def setSbtCallback(callback: AnalysisCallback): this.type = { this.sbtCallback = callback; this }
+ def setTyperState(typerState: TyperState): this.type = { this.typerState = typerState; this }
+ def setReporter(reporter: Reporter): this.type = setTyperState(typerState.withReporter(reporter))
+ def setNewTyperState: this.type = setTyperState(typerState.fresh(isCommittable = true))
+ def setExploreTyperState: this.type = setTyperState(typerState.fresh(isCommittable = false))
+ def setPrinterFn(printer: Context => Printer): this.type = { this.printerFn = printer; this }
+ def setOwner(owner: Symbol): this.type = { assert(owner != NoSymbol); this.owner = owner; this }
+ def setSettings(sstate: SettingsState): this.type = { this.sstate = sstate; this }
+ def setCompilationUnit(compilationUnit: CompilationUnit): this.type = { this.compilationUnit = compilationUnit; this }
+ def setTree(tree: Tree[_ >: Untyped]): this.type = { this.tree = tree; this }
+ def setScope(scope: Scope): this.type = { this.scope = scope; this }
+ def setNewScope: this.type = { this.scope = newScope; this }
+ def setTypeAssigner(typeAssigner: TypeAssigner): this.type = { this.typeAssigner = typeAssigner; this }
+ def setTyper(typer: Typer): this.type = { this.scope = typer.scope; setTypeAssigner(typer) }
+ def setImportInfo(importInfo: ImportInfo): this.type = { this.importInfo = importInfo; this }
+ def setRunInfo(runInfo: RunInfo): this.type = { this.runInfo = runInfo; this }
+ def setDiagnostics(diagnostics: Option[StringBuilder]): this.type = { this.diagnostics = diagnostics; this }
+ def setGadt(gadt: GADTMap): this.type = { this.gadt = gadt; this }
+ def setTypeComparerFn(tcfn: Context => TypeComparer): this.type = { this.typeComparer = tcfn(this); this }
+ def setSearchHistory(searchHistory: SearchHistory): this.type = { this.searchHistory = searchHistory; this }
+ def setFreshNames(freshNames: FreshNameCreator): this.type = { this.freshNames = freshNames; this }
+ def setMoreProperties(moreProperties: Map[Key[Any], Any]): this.type = { this.moreProperties = moreProperties; this }
+
+ def setProperty[T](key: Key[T], value: T): this.type =
+ setMoreProperties(moreProperties.updated(key, value))
+
+ def setPhase(pid: PhaseId): this.type = setPeriod(Period(runId, pid))
+ def setPhase(phase: Phase): this.type = setPeriod(Period(runId, phase.start, phase.end))
+
+ def setSetting[T](setting: Setting[T], value: T): this.type =
+ setSettings(setting.updateIn(sstate, value))
+
+ def setFreshGADTBounds: this.type = { this.gadt = new GADTMap(gadt.bounds); this }
+
+ def setDebug = setSetting(base.settings.debug, true)
+ }
+
+ implicit class ModeChanges(val c: Context) extends AnyVal {
+ final def withModeBits(mode: Mode): Context =
+ if (mode != c.mode) c.fresh.setMode(mode) else c
+
+ final def addMode(mode: Mode): Context = withModeBits(c.mode | mode)
+ final def maskMode(mode: Mode): Context = withModeBits(c.mode & mode)
+ final def retractMode(mode: Mode): Context = withModeBits(c.mode &~ mode)
+ }
+
+ implicit class FreshModeChanges(val c: FreshContext) extends AnyVal {
+ final def addMode(mode: Mode): c.type = c.setMode(c.mode | mode)
+ final def maskMode(mode: Mode): c.type = c.setMode(c.mode & mode)
+ final def retractMode(mode: Mode): c.type = c.setMode(c.mode &~ mode)
+ }
+
+ /** A class defining the initial context with given context base
+ * and set of possible settings.
+ */
+ private class InitialContext(val base: ContextBase, settings: SettingGroup) extends FreshContext {
+ outer = NoContext
+ period = InitialPeriod
+ mode = Mode.None
+ typerState = new TyperState(new ConsoleReporter())
+ printerFn = new RefinedPrinter(_)
+ owner = NoSymbol
+ sstate = settings.defaultState
+ tree = untpd.EmptyTree
+ typeAssigner = TypeAssigner
+ runInfo = new RunInfo(this)
+ diagnostics = None
+ freshNames = new FreshNameCreator.Default
+ moreProperties = Map.empty
+ typeComparer = new TypeComparer(this)
+ searchHistory = new SearchHistory(0, Map())
+ gadt = new GADTMap(SimpleMap.Empty)
+ }
+
+ @sharable object NoContext extends Context {
+ val base = null
+ override val implicits: ContextualImplicits = new ContextualImplicits(Nil, null)(this)
+ }
+
+ /** A context base defines state and associated methods that exist once per
+ * compiler run.
+ */
+ class ContextBase extends ContextState
+ with Denotations.DenotationsBase
+ with Phases.PhasesBase {
+
+ /** The applicable settings */
+ val settings = new ScalaSettings
+
+ /** The initial context */
+ val initialCtx: Context = new InitialContext(this, settings)
+
+ /** The symbol loaders */
+ val loaders = new SymbolLoaders
+
+ /** The platform, initialized by `initPlatform()`. */
+ private var _platform: Platform = _
+
+ /** The platform */
+ def platform: Platform = {
+ if (_platform == null) {
+ throw new IllegalStateException(
+ "initialize() must be called before accessing platform")
+ }
+ _platform
+ }
+
+ protected def newPlatform(implicit ctx: Context): Platform =
+ new JavaPlatform
+
+ /** The loader that loads the members of _root_ */
+ def rootLoader(root: TermSymbol)(implicit ctx: Context): SymbolLoader = platform.rootLoader(root)
+
+ // Set up some phases to get started */
+ usePhases(List(SomePhase))
+
+ /** The standard definitions */
+ val definitions = new Definitions
+
+ /** Initializes the `ContextBase` with a starting context.
+ * This initializes the `platform` and the `definitions`.
+ */
+ def initialize()(implicit ctx: Context): Unit = {
+ _platform = newPlatform
+ definitions.init()
+ }
+
+ def squashed(p: Phase): Phase = {
+ allPhases.find(_.period.containsPhaseId(p.id)).getOrElse(NoPhase)
+ }
+ }
+
+ /** The essential mutable state of a context base, collected into a common class */
+ class ContextState {
+ // Symbols state
+
+ /** A counter for unique ids */
+ private[core] var _nextId = 0
+
+ def nextId = { _nextId += 1; _nextId }
+
+ /** A map from a superclass id to the typeref of the class that has it */
+ private[core] var classOfId = new Array[ClassSymbol](Config.InitialSuperIdsSize)
+
+ /** A map from a the typeref of a class to its superclass id */
+ private[core] val superIdOfClass = new mutable.AnyRefMap[ClassSymbol, Int]
+
+ /** The last allocated superclass id */
+ private[core] var lastSuperId = -1
+
+ /** Allocate and return next free superclass id */
+ private[core] def nextSuperId: Int = {
+ lastSuperId += 1
+ if (lastSuperId >= classOfId.length) {
+ val tmp = new Array[ClassSymbol](classOfId.length * 2)
+ classOfId.copyToArray(tmp)
+ classOfId = tmp
+ }
+ lastSuperId
+ }
+
+ // Types state
+ /** A table for hash consing unique types */
+ private[core] val uniques = new util.HashSet[Type](Config.initialUniquesCapacity) {
+ override def hash(x: Type): Int = x.hash
+ }
+
+ /** A table for hash consing unique refined types */
+ private[dotc] val uniqueRefinedTypes = new RefinedUniques
+
+ /** A table for hash consing unique named types */
+ private[core] val uniqueNamedTypes = new NamedTypeUniques
+
+ /** A table for hash consing unique type bounds */
+ private[core] val uniqueTypeAliases = new TypeAliasUniques
+
+ private def uniqueSets = Map(
+ "uniques" -> uniques,
+ "uniqueRefinedTypes" -> uniqueRefinedTypes,
+ "uniqueNamedTypes" -> uniqueNamedTypes,
+ "uniqueTypeAliases" -> uniqueTypeAliases)
+
+ /** A map that associates label and size of all uniques sets */
+ def uniquesSizes: Map[String, Int] = uniqueSets.mapValues(_.size)
+
+ /** The number of recursive invocation of underlying on a NamedType
+ * during a controlled operation.
+ */
+ private[core] var underlyingRecursions: Int = 0
+
+ /** The set of named types on which a currently active invocation
+ * of underlying during a controlled operation exists. */
+ private[core] val pendingUnderlying = new mutable.HashSet[Type]
+
+ /** A flag that some unsafe nonvariant instantiation was encountered
+ * in this run. Used as a shortcut to a avoid scans of types in
+ * Typer.typedSelect.
+ */
+ private[dotty] var unsafeNonvariant: RunId = NoRunId
+
+ // Phases state
+
+ private[core] var phasesPlan: List[List[Phase]] = _
+
+ /** Phases by id */
+ private[core] var phases: Array[Phase] = _
+
+ /** Phases with consecutive Transforms grouped into a single phase, Empty array if squashing is disabled */
+ private[core] var squashedPhases: Array[Phase] = Array.empty[Phase]
+
+ /** Next denotation transformer id */
+ private[core] var nextDenotTransformerId: Array[Int] = _
+
+ private[core] var denotTransformers: Array[DenotTransformer] = _
+
+ // Printers state
+ /** Number of recursive invocations of a show method on current stack */
+ private[dotc] var toTextRecursions = 0
+
+ // Reporters state
+ private[dotc] var indent = 0
+
+ protected[dotc] val indentTab = " "
+
+ def reset() = {
+ for ((_, set) <- uniqueSets) set.clear()
+ for (i <- 0 until classOfId.length) classOfId(i) = null
+ superIdOfClass.clear()
+ lastSuperId = -1
+ }
+
+ // Test that access is single threaded
+
+ /** The thread on which `checkSingleThreaded was invoked last */
+ @sharable private var thread: Thread = null
+
+ /** Check that we are on the same thread as before */
+ def checkSingleThreaded() =
+ if (thread == null) thread = Thread.currentThread()
+ else assert(thread == Thread.currentThread(), "illegal multithreaded access to ContextBase")
+ }
+
+ object Context {
+
+ /** Implicit conversion that injects all printer operations into a context */
+ implicit def toPrinter(ctx: Context): Printer = ctx.printer
+
+ /** implicit conversion that injects all ContextBase members into a context */
+ implicit def toBase(ctx: Context): ContextBase = ctx.base
+
+ // @sharable val theBase = new ContextBase // !!! DEBUG, so that we can use a minimal context for reporting even in code that normally cannot access a context
+ }
+
+ /** Info that changes on each compiler run */
+ class RunInfo(initctx: Context) extends ImplicitRunInfo with ConstraintRunInfo {
+ implicit val ctx: Context = initctx
+ }
+
+ class GADTMap(initBounds: SimpleMap[Symbol, TypeBounds]) {
+ private var myBounds = initBounds
+ def setBounds(sym: Symbol, b: TypeBounds): Unit =
+ myBounds = myBounds.updated(sym, b)
+ def bounds = myBounds
+ }
+}