Skip to content

Commit bab59a8

Browse files
committed
Concentrate all stdlib patch code in Definitions
1 parent 4b6ac78 commit bab59a8

File tree

2 files changed

+50
-42
lines changed

2 files changed

+50
-42
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -186,14 +186,6 @@ class Definitions {
186186
cls
187187
}
188188

189-
/** If `sym` is a patched library class, the source file of its patch class,
190-
* otherwise `NoSource`
191-
*/
192-
def patchSource(sym: Symbol): SourceFile =
193-
if sym == ScalaPredefModuleClass then ScalaPredefModuleClassPatch.source
194-
else if sym == LanguageModuleClass then LanguageModuleClassPatch.source
195-
else NoSource
196-
197189
@tu lazy val RootClass: ClassSymbol = newPackageSymbol(
198190
NoSymbol, nme.ROOT, (root, rootcls) => ctx.base.rootLoader(root)).moduleClass.asClass
199191
@tu lazy val RootPackage: TermSymbol = newSymbol(
@@ -264,13 +256,6 @@ class Definitions {
264256
*/
265257
@tu lazy val ScalaShadowingPackage: TermSymbol = requiredPackage(nme.scalaShadowing)
266258

267-
/** The `scala.runtime.stdLibPacthes` package is contains objects
268-
* that contain defnitions that get added as members to standard library
269-
* objects with the same name.
270-
*/
271-
@tu lazy val StdLibPatchesPackage: TermSymbol = requiredPackage("scala.runtime.stdLibPatches")
272-
@tu lazy val ScalaPredefModuleClassPatch: Symbol = getModuleIfDefined("scala.runtime.stdLibPatches.Predef").moduleClass
273-
@tu lazy val LanguageModuleClassPatch: Symbol = getModuleIfDefined("scala.runtime.stdLibPatches.language").moduleClass
274259

275260
/** Note: We cannot have same named methods defined in Object and Any (and AnyVal, for that matter)
276261
* because after erasure the Any and AnyVal references get remapped to the Object methods
@@ -1119,6 +1104,55 @@ class Definitions {
11191104
|| sym.owner == CompiletimeOpsPackageObjectString.moduleClass && compiletimePackageStringTypes.contains(sym.name)
11201105
)
11211106

1107+
// ----- Scala-2 library patches --------------------------------------
1108+
1109+
/** The `scala.runtime.stdLibPacthes` package contains objects
1110+
* that contain defnitions that get added as members to standard library
1111+
* objects with the same name.
1112+
*/
1113+
@tu lazy val StdLibPatchesPackage: TermSymbol = requiredPackage("scala.runtime.stdLibPatches")
1114+
@tu private lazy val ScalaPredefModuleClassPatch: Symbol = getModuleIfDefined("scala.runtime.stdLibPatches.Predef").moduleClass
1115+
@tu private lazy val LanguageModuleClassPatch: Symbol = getModuleIfDefined("scala.runtime.stdLibPatches.language").moduleClass
1116+
1117+
/** If `sym` is a patched library class, the source file of its patch class,
1118+
* otherwise `NoSource`
1119+
*/
1120+
def patchSource(sym: Symbol)(using Context): SourceFile =
1121+
if sym == ScalaPredefModuleClass then ScalaPredefModuleClassPatch.source
1122+
else if sym == LanguageModuleClass then LanguageModuleClassPatch.source
1123+
else NoSource
1124+
1125+
/** A finalizer that patches standard library classes.
1126+
* It copies all non-private, non-synthetic definitions from `patchCls`
1127+
* to `denot` while changing their owners to `denot`. Before that it deletes
1128+
* any definitions of `denot` that have the same name as one of the copied
1129+
* definitions.
1130+
*
1131+
* To avpid running into cycles on bootstrap, patching happens only if `patchCls`
1132+
* is read from a classfile.
1133+
*/
1134+
def patchStdLibClass(denot: ClassDenotation)(using Context): Unit =
1135+
1136+
def patchWith(patchCls: Symbol) =
1137+
denot.sourceModule.info = denot.typeRef // we run into a cyclic reference when patching if this line is omitted
1138+
val scope = denot.info.decls.openForMutations
1139+
if patchCls.exists then
1140+
val patches = patchCls.info.decls.filter(patch =>
1141+
!patch.isConstructor && !patch.isOneOf(PrivateOrSynthetic))
1142+
for patch <- patches do
1143+
val e = scope.lookupEntry(patch.name)
1144+
if e != null then scope.unlink(e)
1145+
for patch <- patches do
1146+
patch.ensureCompleted()
1147+
patch.denot = patch.denot.copySymDenotation(owner = denot.symbol)
1148+
scope.enter(patch)
1149+
1150+
if denot.name == tpnme.Predef.moduleClassName && denot.symbol == ScalaPredefModuleClass then
1151+
patchWith(ScalaPredefModuleClassPatch)
1152+
else if denot.name == tpnme.language.moduleClassName && denot.symbol == LanguageModuleClass then
1153+
patchWith(LanguageModuleClassPatch)
1154+
end patchStdLibClass
1155+
11221156
// ----- Symbol sets ---------------------------------------------------
11231157

11241158
@tu lazy val AbstractFunctionType: Array[TypeRef] = mkArityArray("scala.runtime.AbstractFunction", MaxImplementedFunctionArity, 0)

compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -111,34 +111,8 @@ object Scala2Unpickler {
111111

112112
denot.info = tempInfo.finalized(normalizedParents)
113113
denot.ensureTypeParamsInCorrectOrder()
114-
if denot.name == tpnme.Predef.moduleClassName && denot.symbol == defn.ScalaPredefModuleClass then
115-
patchStdLibClass(denot, defn.ScalaPredefModuleClassPatch)
116-
else if denot.name == tpnme.language.moduleClassName && denot.symbol == defn.LanguageModuleClass then
117-
patchStdLibClass(denot, defn.LanguageModuleClassPatch)
114+
defn.patchStdLibClass(denot)
118115
}
119-
120-
/** A finalizer that patches standard library classes.
121-
* It copies all non-private, non-synthetic definitions from `patchCls`
122-
* to `denot` while changing their owners to `denot`. Before that it deletes
123-
* any definitions of `denot` that have the same name as one of the copied
124-
* definitions.
125-
*
126-
* To avpid running into cycles on bootstrap, patching happens only if `patchCls`
127-
* is read from a classfile.
128-
*/
129-
private def patchStdLibClass(denot: ClassDenotation, patchCls: Symbol)(using Context): Unit =
130-
denot.sourceModule.info = denot.typeRef // we run into a cyclic reference when patching if this line is omitted
131-
val scope = denot.info.decls.openForMutations
132-
if patchCls.exists then
133-
val patches = patchCls.info.decls.filter(patch =>
134-
!patch.isConstructor && !patch.isOneOf(PrivateOrSynthetic))
135-
for patch <- patches do
136-
val e = scope.lookupEntry(patch.name)
137-
if e != null then scope.unlink(e)
138-
for patch <- patches do
139-
patch.ensureCompleted()
140-
patch.denot = patch.denot.copySymDenotation(owner = denot.symbol)
141-
scope.enter(patch)
142116
}
143117

144118
/** Unpickle symbol table information descending from a class and/or module root

0 commit comments

Comments
 (0)