Skip to content

Do not patch stdlib symbols anymore #23193

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: hamza-main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 0 additions & 105 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1438,111 +1438,6 @@ class Definitions {
|| sym.owner == CompiletimeOpsStringModuleClass && compiletimePackageStringTypes.contains(sym.name)
)

// ----- Scala-2 library patches --------------------------------------

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

/** If `sym` is a patched library class, the source file of its patch class,
* otherwise `NoSource`
*/
def patchSource(sym: Symbol)(using Context): SourceFile =
if sym == ScalaPredefModuleClass then ScalaPredefModuleClassPatch.source
else if sym == LanguageModuleClass then LanguageModuleClassPatch.source
else NoSource

/** A finalizer that patches standard library classes.
* It copies all non-private, non-synthetic definitions from `patchCls`
* to `denot` while changing their owners to `denot`. Before that it deletes
* any definitions of `denot` that have the same name as one of the copied
* definitions.
*
* If an object is present in both the original class and the patch class,
* it is not overwritten. Instead its members are copied recursively.
*
* To avpid running into cycles on bootstrap, patching happens only if `patchCls`
* is read from a classfile.
*/
def patchStdLibClass(denot: ClassDenotation)(using Context): Unit =
def patch2(denot: ClassDenotation, patchCls: Symbol): Unit =
val scope = denot.info.decls.openForMutations

def recurse(patch: Symbol) = patch.is(Module) && scope.lookup(patch.name).exists

def makeClassSymbol(patch: Symbol, parents: List[Type], selfInfo: TypeOrSymbol) =
newClassSymbol(
owner = denot.symbol,
name = patch.name.asTypeName,
flags = patch.flags,
// need to rebuild a fresh ClassInfo
infoFn = cls => ClassInfo(
prefix = denot.symbol.thisType,
cls = cls,
declaredParents = parents, // assume parents in patch don't refer to symbols in the patch
decls = newScope,
selfInfo =
if patch.is(Module)
then TermRef(denot.symbol.thisType, patch.name.sourceModuleName)
else selfInfo // assume patch self type annotation does not refer to symbols in the patch
),
privateWithin = patch.privateWithin,
coord = denot.symbol.coord,
compUnitInfo = denot.symbol.compilationUnitInfo
)

def makeNonClassSymbol(patch: Symbol) =
if patch.is(Inline) then
// Inline symbols contain trees in annotations, which is coupled
// with the underlying symbol.
// Changing owner for inline symbols is a simple workaround.
patch.denot = patch.denot.copySymDenotation(owner = denot.symbol)
patch
else
// change `info` which might contain reference to the patch
patch.copy(
owner = denot.symbol,
info =
if patch.is(Module)
then TypeRef(denot.symbol.thisType, patch.name.moduleClassName)
else patch.info // assume non-object info does not refer to symbols in the patch
)

if patchCls.exists then
val patches = patchCls.info.decls.filter(patch =>
!patch.isConstructor && !patch.isOneOf(PrivateOrSynthetic))
for patch <- patches if !recurse(patch) do
val e = scope.lookupEntry(patch.name)
if e != null then scope.unlink(e)
for patch <- patches do
patch.ensureCompleted()
if !recurse(patch) then
val sym =
patch.info match
case ClassInfo(_, _, parents, _, selfInfo) =>
makeClassSymbol(patch, parents, selfInfo)
case _ =>
makeNonClassSymbol(patch)
end match
sym.annotations = patch.annotations
scope.enter(sym)
if patch.isClass then
patch2(scope.lookup(patch.name).asClass, patch)

def patchWith(patchCls: Symbol) =
denot.sourceModule.info = denot.typeRef // we run into a cyclic reference when patching if this line is omitted
patch2(denot, patchCls)

if denot.name == tpnme.Predef.moduleClassName && denot.symbol == ScalaPredefModuleClass then
patchWith(ScalaPredefModuleClassPatch)
else if denot.name == tpnme.language.moduleClassName && denot.symbol == LanguageModuleClass then
patchWith(LanguageModuleClassPatch)
end patchStdLibClass

// ----- Symbol sets ---------------------------------------------------

@tu lazy val topClasses: Set[Symbol] = Set(AnyClass, MatchableClass, ObjectClass, AnyValClass)
Expand Down
1 change: 0 additions & 1 deletion compiler/src/dotty/tools/dotc/core/Symbols.scala
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,6 @@ object Symbols extends SymUtils {
if file != null && !file.isScalaBinary then
mySource = ctx.getSource(file)
else
mySource = defn.patchSource(this)
if !mySource.exists then
val compUnitInfo = compilationUnitInfo
if compUnitInfo != null then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1138,7 +1138,6 @@ class TreeUnpickler(reader: TastyReader,
val stats = rdr.readIndexedStats(localDummy, end)
tparams ++ vparams ++ stats
})
defn.patchStdLibClass(cls)
NamerOps.addConstructorProxies(cls)
NamerOps.addContextBoundCompanions(cls)
setSpan(start,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ object Scala2Unpickler {

denot.info = tempInfo.finalized(normalizedParents)
denot.ensureTypeParamsInCorrectOrder()
defn.patchStdLibClass(denot)
}
}

Expand Down
1 change: 0 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1757,7 +1757,6 @@ class Namer { typer: Typer =>
cls.setStableConstructor()
enterParentRefinementSyms(parentRefinements.toList)
processExports(using localCtx)
defn.patchStdLibClass(cls)
addConstructorProxies(cls)
}
}
Expand Down
Loading
Loading