-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix #11654: create new symbol for stdlib patches #11803
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1111,10 +1111,49 @@ class Definitions { | |
* 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( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it not be shorter to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That does not make much difference, as we change all fields here except |
||
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, | ||
assocFile = denot.symbol.associatedFile | ||
) | ||
|
||
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we use a TreeTypeMap to map the info instead? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You mean for the For non-inline symbols, we make strong assumptions on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I meant for both, but I don't know if TreeTypeMap works on inline defs There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see a principled way to do this --- a map needs to make assumptions about |
||
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)) | ||
|
@@ -1124,9 +1163,16 @@ class Definitions { | |
for patch <- patches do | ||
patch.ensureCompleted() | ||
if !recurse(patch) then | ||
patch.denot = patch.denot.copySymDenotation(owner = denot.symbol) | ||
scope.enter(patch) | ||
else if patch.isClass 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) = | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't we use
patch.copy(...)
here? Would that not be shorter?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason is that
info
andsymbol
depend on each other, andSymbol.copy
does not support that.