diff --git a/compiler/src/dotty/tools/backend/ScalaPrimitives.scala b/compiler/src/dotty/tools/backend/ScalaPrimitives.scala index 451c9b2e8567..37e32f412bb5 100644 --- a/compiler/src/dotty/tools/backend/ScalaPrimitives.scala +++ b/compiler/src/dotty/tools/backend/ScalaPrimitives.scala @@ -10,8 +10,9 @@ import dotty.tools.dotc.report import dotty.tools.dotc.util.ReadOnlyMap import dotty.tools.dotc.ast.Trees.Select import dotty.tools.dotc.ast.tpd.* +import dotty.tools.dotc.core.Phases -import scala.annotation.threadUnsafe +import scala.annotation.constructorOnly /** Scala primitive operations are represented as methods in `Any` and * `AnyVal` subclasses. Here we demultiplex them by providing a mapping @@ -30,10 +31,10 @@ import scala.annotation.threadUnsafe * * Inspired from the `scalac` compiler. */ -class ScalaPrimitives(ictx: Context) { +class ScalaPrimitives(using @constructorOnly initCtx: Context) { import dotty.tools.backend.ScalaPrimitivesOps.* - @threadUnsafe private lazy val primitives: ReadOnlyMap[Symbol, Int] = init + private val primitives: ReadOnlyMap[Symbol, Int] = init /** Return the code for the given symbol. */ def getPrimitive(sym: Symbol): Int = { @@ -49,8 +50,7 @@ class ScalaPrimitives(ictx: Context) { * @param tpe The type of the receiver object. It is used only for array * operations */ - def getPrimitive(app: Apply, tpe: Type): Int = { - given Context = ictx + def getPrimitive(app: Apply, tpe: Type)(using Context): Int = { val fun = app.fun.symbol val code = app.fun match { case Select(_, nme.primitive.arrayLength) => @@ -117,14 +117,13 @@ class ScalaPrimitives(ictx: Context) { } /** Initialize the primitive map */ - private def init: ReadOnlyMap[Symbol, Int] = { + private def init(using Context): ReadOnlyMap[Symbol, Int] = atPhase(Phases.flattenPhase) { - given Context = ictx val primitives = MutableSymbolMap[Int](512) /** Add a primitive operation to the map */ def addPrimitive(s: Symbol, code: Int): Unit = { - assert(!primitives.contains(s), "Duplicate primitive " + s) + assert(!primitives.contains(s), s"Duplicate primitive for code $code: $s") primitives(s) = code } @@ -397,10 +396,9 @@ class ScalaPrimitives(ictx: Context) { def isPrimitive(sym: Symbol): Boolean = primitives.contains(sym) - def isPrimitive(fun: Tree): Boolean = - given Context = ictx + def isPrimitive(fun: Tree)(using Context): Boolean = primitives.contains(fun.symbol) - || (fun.symbol == NoSymbol // the only trees that do not have a symbol assigned are array.{update,select,length,clone}} + || (fun.symbol == NoSymbol // the only trees that do not have a symbol assigned are array.{update,select,length,clone} && { fun match case Select(_, nme.clone_) => false // but array.clone is NOT a primitive op. diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala b/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala index 862ec9275bdd..6bbf1833b125 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala @@ -1321,7 +1321,7 @@ trait BCodeBodyBuilder(val primitives: ScalaPrimitives) extends BCodeSkelBuilder } /* Is the given symbol a primitive operation? */ - def isPrimitive(fun: Tree): Boolean = { + def isPrimitive(fun: Tree)(using Context): Boolean = { primitives.isPrimitive(fun) } diff --git a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala index a071e53d7893..88b021bf9f1a 100644 --- a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala @@ -51,7 +51,7 @@ class GenBCode extends Phase { self => private var _primitives: ScalaPrimitives | Null = null def primitives(using Context): ScalaPrimitives = { if _primitives eq null then - _primitives = ScalaPrimitives(ctx) + _primitives = ScalaPrimitives() _primitives.nn } diff --git a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala index b7b31d3e9d4c..43a360caf99c 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala @@ -59,7 +59,7 @@ class JSCodeGen()(using genCtx: Context) { val sjsPlatform = dotty.tools.dotc.config.SJSPlatform.sjsPlatform val jsdefn = JSDefinitions.jsdefn - private val primitives = new JSPrimitives(genCtx) + private val primitives = new JSPrimitives()(using genCtx) val positionConversions = new JSPositions()(using genCtx) import positionConversions.* diff --git a/compiler/src/dotty/tools/backend/sjs/JSPrimitives.scala b/compiler/src/dotty/tools/backend/sjs/JSPrimitives.scala index 5957beb4df7d..bc176ba4af81 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSPrimitives.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSPrimitives.scala @@ -7,11 +7,12 @@ import Contexts.* import Symbols.* import Decorators.em import dotty.tools.backend.ScalaPrimitives - import dotty.tools.dotc.ast.tpd.* import dotty.tools.dotc.report import dotty.tools.dotc.util.ReadOnlyMap +import scala.annotation.constructorOnly + object JSPrimitives { inline val FirstJSPrimitiveCode = 300 @@ -68,22 +69,22 @@ object JSPrimitives { } -class JSPrimitives(ictx: Context) extends ScalaPrimitives(ictx) { +class JSPrimitives()(using @constructorOnly initCtx: Context) extends ScalaPrimitives { import JSPrimitives.* - private lazy val jsPrimitives: ReadOnlyMap[Symbol, Int] = initJSPrimitives(using ictx) + private val jsPrimitives: ReadOnlyMap[Symbol, Int] = initJSPrimitives override def getPrimitive(sym: Symbol): Int = jsPrimitives.getOrElse(sym, super.getPrimitive(sym)) - override def getPrimitive(app: Apply, tpe: Type): Int = - jsPrimitives.getOrElse(app.fun.symbol(using ictx), super.getPrimitive(app, tpe)) + override def getPrimitive(app: Apply, tpe: Type)(using Context): Int = + jsPrimitives.getOrElse(app.fun.symbol, super.getPrimitive(app, tpe)) override def isPrimitive(sym: Symbol): Boolean = jsPrimitives.contains(sym) || super.isPrimitive(sym) - override def isPrimitive(fun: Tree): Boolean = - jsPrimitives.contains(fun.symbol(using ictx)) || super.isPrimitive(fun) + override def isPrimitive(fun: Tree)(using Context): Boolean = + jsPrimitives.contains(fun.symbol) || super.isPrimitive(fun) /** Initialize the primitive map */ private def initJSPrimitives(using Context): ReadOnlyMap[Symbol, Int] = {