@@ -9,7 +9,7 @@ import unpickleScala2.Scala2Unpickler.ensureConstructor
99import scala .collection .mutable
1010import collection .mutable
1111import Denotations .SingleDenotation
12- import util .SimpleIdentityMap
12+ import util .{ SimpleIdentityMap , SourceFile , NoSource }
1313import typer .ImportInfo .RootRef
1414
1515import scala .annotation .tailrec
@@ -252,6 +252,7 @@ class Definitions {
252252 * or classes with the same name. But their binary artifacts are
253253 * in `scalaShadowing` so they don't clash with the same-named `scala`
254254 * members at runtime.
255+ * It is used only for non-bootstrapped code
255256 */
256257 @ tu lazy val ScalaShadowingPackage : TermSymbol = requiredPackage(nme.scalaShadowing)
257258
@@ -481,12 +482,12 @@ class Definitions {
481482 newPermanentSymbol(ScalaPackageClass , tpnme.IMPLICITkw , EmptyFlags , TypeBounds .empty).entered
482483 def ImplicitScrutineeTypeRef : TypeRef = ImplicitScrutineeTypeSym .typeRef
483484
484-
485485 @ tu lazy val ScalaPredefModule : Symbol = requiredModule(" scala.Predef" )
486486 @ tu lazy val Predef_conforms : Symbol = ScalaPredefModule .requiredMethod(nme.conforms_)
487487 @ tu lazy val Predef_classOf : Symbol = ScalaPredefModule .requiredMethod(nme.classOf )
488488 @ tu lazy val Predef_identity : Symbol = ScalaPredefModule .requiredMethod(nme.identity)
489489 @ tu lazy val Predef_undefined : Symbol = ScalaPredefModule .requiredMethod(nme.??? )
490+ @ tu lazy val ScalaPredefModuleClass : ClassSymbol = ScalaPredefModule .moduleClass.asClass
490491
491492 @ tu lazy val SubTypeClass : ClassSymbol = requiredClass(" scala.<:<" )
492493 @ tu lazy val SubType_refl : Symbol = SubTypeClass .companionModule.requiredMethod(nme.refl)
@@ -510,7 +511,7 @@ class Definitions {
510511 // will return "null" when called recursively, see #1856.
511512 def DottyPredefModule : Symbol = {
512513 if (myDottyPredefModule == null ) {
513- myDottyPredefModule = requiredModule (" dotty.DottyPredef" )
514+ myDottyPredefModule = getModuleIfDefined (" dotty.DottyPredef" )
514515 assert(myDottyPredefModule != null )
515516 }
516517 myDottyPredefModule
@@ -782,6 +783,7 @@ class Definitions {
782783 @ tu lazy val Mirror_SingletonProxyClass : ClassSymbol = requiredClass(" scala.deriving.Mirror.SingletonProxy" )
783784
784785 @ tu lazy val LanguageModule : Symbol = requiredModule(" scala.language" )
786+ @ tu lazy val LanguageModuleClass : Symbol = LanguageModule .moduleClass.asClass
785787 @ tu lazy val LanguageExperimentalModule : Symbol = requiredModule(" scala.language.experimental" )
786788 @ tu lazy val NonLocalReturnControlClass : ClassSymbol = requiredClass(" scala.runtime.NonLocalReturnControl" )
787789 @ tu lazy val SelectableClass : ClassSymbol = requiredClass(" scala.Selectable" )
@@ -1101,6 +1103,65 @@ class Definitions {
11011103 || sym.owner == CompiletimeOpsPackageObjectString .moduleClass && compiletimePackageStringTypes.contains(sym.name)
11021104 )
11031105
1106+ // ----- Scala-2 library patches --------------------------------------
1107+
1108+ /** The `scala.runtime.stdLibPacthes` package contains objects
1109+ * that contain defnitions that get added as members to standard library
1110+ * objects with the same name.
1111+ */
1112+ @ tu lazy val StdLibPatchesPackage : TermSymbol = requiredPackage(" scala.runtime.stdLibPatches" )
1113+ @ tu private lazy val ScalaPredefModuleClassPatch : Symbol = getModuleIfDefined(" scala.runtime.stdLibPatches.Predef" ).moduleClass
1114+ @ tu private lazy val LanguageModuleClassPatch : Symbol = getModuleIfDefined(" scala.runtime.stdLibPatches.language" ).moduleClass
1115+
1116+ /** If `sym` is a patched library class, the source file of its patch class,
1117+ * otherwise `NoSource`
1118+ */
1119+ def patchSource (sym : Symbol )(using Context ): SourceFile =
1120+ if sym == ScalaPredefModuleClass then ScalaPredefModuleClassPatch .source
1121+ else if sym == LanguageModuleClass then LanguageModuleClassPatch .source
1122+ else NoSource
1123+
1124+ /** A finalizer that patches standard library classes.
1125+ * It copies all non-private, non-synthetic definitions from `patchCls`
1126+ * to `denot` while changing their owners to `denot`. Before that it deletes
1127+ * any definitions of `denot` that have the same name as one of the copied
1128+ * definitions.
1129+ *
1130+ * If an object is present in both the original class and the patch class,
1131+ * it is not overwritten. Instead its members are copied recursively.
1132+ *
1133+ * To avpid running into cycles on bootstrap, patching happens only if `patchCls`
1134+ * is read from a classfile.
1135+ */
1136+ def patchStdLibClass (denot : ClassDenotation )(using Context ): Unit =
1137+
1138+ def patch2 (denot : ClassDenotation , patchCls : Symbol ): Unit =
1139+ val scope = denot.info.decls.openForMutations
1140+ def recurse (patch : Symbol ) = patch.is(Module ) && scope.lookup(patch.name).exists
1141+ if patchCls.exists then
1142+ val patches = patchCls.info.decls.filter(patch =>
1143+ ! patch.isConstructor && ! patch.isOneOf(PrivateOrSynthetic ))
1144+ for patch <- patches if ! recurse(patch) do
1145+ val e = scope.lookupEntry(patch.name)
1146+ if e != null then scope.unlink(e)
1147+ for patch <- patches do
1148+ patch.ensureCompleted()
1149+ if ! recurse(patch) then
1150+ patch.denot = patch.denot.copySymDenotation(owner = denot.symbol)
1151+ scope.enter(patch)
1152+ else if patch.isClass then
1153+ patch2(scope.lookup(patch.name).asClass, patch)
1154+
1155+ def patchWith (patchCls : Symbol ) =
1156+ denot.sourceModule.info = denot.typeRef // we run into a cyclic reference when patching if this line is omitted
1157+ patch2(denot, patchCls)
1158+
1159+ if denot.name == tpnme.Predef .moduleClassName && denot.symbol == ScalaPredefModuleClass then
1160+ patchWith(ScalaPredefModuleClassPatch )
1161+ else if denot.name == tpnme.language.moduleClassName && denot.symbol == LanguageModuleClass then
1162+ patchWith(LanguageModuleClassPatch )
1163+ end patchStdLibClass
1164+
11041165 // ----- Symbol sets ---------------------------------------------------
11051166
11061167 @ tu lazy val AbstractFunctionType : Array [TypeRef ] = mkArityArray(" scala.runtime.AbstractFunction" , MaxImplementedFunctionArity , 0 )
0 commit comments