diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 0bbd62123195..8263bab70aca 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -1104,8 +1104,6 @@ class Definitions { @tu lazy val AbstractFunctionType: Array[TypeRef] = mkArityArray("scala.runtime.AbstractFunction", MaxImplementedFunctionArity, 0) val AbstractFunctionClassPerRun: PerRun[Array[Symbol]] = new PerRun(AbstractFunctionType.map(_.symbol.asClass)) def AbstractFunctionClass(n: Int)(using Context): Symbol = AbstractFunctionClassPerRun()(using ctx)(n) - @tu private lazy val ImplementedFunctionType = mkArityArray("scala.Function", MaxImplementedFunctionArity, 0) - def FunctionClassPerRun: PerRun[Array[Symbol]] = new PerRun(ImplementedFunctionType.map(_.symbol.asClass)) val LazyHolder: PerRun[Map[Symbol, Symbol]] = new PerRun({ def holderImpl(holderType: String) = requiredClass("scala.runtime." + holderType) @@ -1124,23 +1122,33 @@ class Definitions { @tu lazy val TupleType: Array[TypeRef] = mkArityArray("scala.Tuple", MaxTupleArity, 1) + private class FunType(prefix: String): + private var classRefs: Array[TypeRef] = new Array(22) + def apply(n: Int): TypeRef = + while n >= classRefs.length do + val classRefs1 = new Array[TypeRef](classRefs.length * 2) + Array.copy(classRefs, 0, classRefs1, 0, classRefs.length) + classRefs = classRefs1 + if classRefs(n) == null then + classRefs(n) = requiredClassRef(prefix + n.toString) + classRefs(n) + + private val erasedContextFunType = FunType("scala.ErasedContextFunction") + private val contextFunType = FunType("scala.ContextFunction") + private val erasedFunType = FunType("scala.ErasedFunction") + private val funType = FunType("scala.Function") + def FunctionClass(n: Int, isContextual: Boolean = false, isErased: Boolean = false)(using Context): Symbol = - if (isContextual && isErased) - requiredClass("scala.ErasedContextFunction" + n.toString) - else if (isContextual) - requiredClass("scala.ContextFunction" + n.toString) - else if (isErased) - requiredClass("scala.ErasedFunction" + n.toString) - else if (n <= MaxImplementedFunctionArity) - FunctionClassPerRun()(n) - else - requiredClass("scala.Function" + n.toString) - - @tu lazy val Function0_apply: Symbol = ImplementedFunctionType(0).symbol.requiredMethod(nme.apply) + ( if isContextual && isErased then erasedContextFunType(n) + else if isContextual then contextFunType(n) + else if isErased then erasedFunType(n) + else funType(n) + ).symbol.asClass + + @tu lazy val Function0_apply: Symbol = FunctionClass(0).requiredMethod(nme.apply) def FunctionType(n: Int, isContextual: Boolean = false, isErased: Boolean = false)(using Context): TypeRef = - if (n <= MaxImplementedFunctionArity && (!isContextual || ctx.erasedTypes) && !isErased) ImplementedFunctionType(n) - else FunctionClass(n, isContextual, isErased).typeRef + FunctionClass(n, isContextual && !ctx.erasedTypes, isErased).typeRef lazy val PolyFunctionClass = requiredClass("scala.PolyFunction") def PolyFunctionType = PolyFunctionClass.typeRef diff --git a/compiler/src/dotty/tools/dotc/core/Names.scala b/compiler/src/dotty/tools/dotc/core/Names.scala index d5e538abeac0..fea9edd18fa4 100644 --- a/compiler/src/dotty/tools/dotc/core/Names.scala +++ b/compiler/src/dotty/tools/dotc/core/Names.scala @@ -258,6 +258,15 @@ object Names { val (first, last, sep) = split if (first.isEmpty) f2(last) else str.sanitize(f1(first) + sep + f2(last)) } + + protected def computeToString: String + + @sharable private var myToString: String = null + + override def toString = + if myToString == null then myToString = computeToString + myToString + } /** A simple name is essentially an interned string */ @@ -371,7 +380,7 @@ object Names { override def hashCode: Int = start - override def toString: String = + protected def computeToString: String = if (length == 0) "" else { if (Config.checkBackendNames) @@ -500,7 +509,7 @@ object Names { case qual: QualifiedInfo => qual.name case _ => underlying.lastPart } - override def toString: String = info.mkString(underlying) + protected def computeToString: String = info.mkString(underlying) override def debugString: String = s"${underlying.debugString}[$info]" } diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index 6416c38d007a..7f7edb35495a 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -219,10 +219,7 @@ object SymbolLoaders { Stats.record("package scopes") /** The scope of a package. This is different from a normal scope - * in two aspects: - * - * 1. Names of scope entries are kept in mangled form. - * 2. Some function types in the `scala` package are synthesized. + * in that names of scope entries are kept in mangled form. */ final class PackageScope extends MutableScope { override def newScopeEntry(name: Name, sym: Symbol)(using Context): ScopeEntry = diff --git a/tests/pos-with-compiler/lazyValsSepComp.scala b/tests/pos-with-compiler/lazyValsSepComp.scala index 31f1619fcc25..78edf31d4567 100644 --- a/tests/pos-with-compiler/lazyValsSepComp.scala +++ b/tests/pos-with-compiler/lazyValsSepComp.scala @@ -12,5 +12,5 @@ import dotty.tools.dotc.core.Contexts._ object Foo { val definitions: Definitions = null def defn = definitions - def go = defn.FunctionClassPerRun + def go = defn.ScalaBoxedClasses }