-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Correct owner chains when mixing byname implicits and inlining #5767
Conversation
When constructing the dictionary for a byname implicit resolution we have to ensure that the owners of any definitions which have been hoisted into the dictionary are correct. Prior to this PR this was only done fully for implicit expansions which didn't involve inlining. We fix that here by ensuring that all definitions under a given dictionary entry are owned directly or indirectly by that dictionary entry. Fixes scala#5766.
val nonLocalOwners = localOwners.filter(sym => !localOwners.contains(sym.owner)).toList.map(_.owner) | ||
val newOwners = nonLocalOwners.map(_ => newowner) | ||
new TreeTypeMap(oldOwners = nonLocalOwners, newOwners = newOwners).apply(tree) | ||
} |
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.
Can this be simplified further?
def changeNonLocalOwners(newOwner: Symbol)(implicit ctx: Context): Tree = {
val localOwnerAcc = new TreeAccumulator[List[Symbol]] {
def apply(ss: List[Symbol], tree: Tree)(implicit ctx: Context) = tree match {
case tree: DefTree =>
if (tree.symbol.exists) tree.symbol :: ss
else ss
case _ =>
foldOver(ss, tree)
}
}
}
val nonLocalOwners = localOwnerAcc(Nil, tree).map(_.owner).distinct
val newOwners = nonLocalOwners.map(_ => newOwner)
new TreeTypeMap(oldOwners = nonLocalOwners, newOwners = newOwners).apply(tree)
}
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.
I think the idea of using an accumulator is good, but why the detour via lists? Let's use an accumulator over an immutable set instead.
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.
Updated:
def changeNonLocalOwners(newOwner: Symbol)(implicit ctx: Context): Tree = {
val ownerAcc = new TreeAccumulator[Set[Symbol]] {
def apply(ss: Set[Symbol], tree: Tree)(implicit ctx: Context) = tree match {
case tree: DefTree =>
if (tree.symbol.exists) ss + tree.symbol.owner
else ss
case _ =>
foldOver(ss, tree)
}
}
}
val owners = ownerAcc(Set.empty, tree)
val newOwners = List.fill(owners.size)(newOwner)
new TreeTypeMap(oldOwners = owners.toList, newOwners = newOwners).apply(tree)
}
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.
Otherwise LGTM.
val nonLocalOwners = localOwners.filter(sym => !localOwners.contains(sym.owner)).toList.map(_.owner) | ||
val newOwners = nonLocalOwners.map(_ => newowner) | ||
new TreeTypeMap(oldOwners = nonLocalOwners, newOwners = newOwners).apply(tree) | ||
} |
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.
I think the idea of using an accumulator is good, but why the detour via lists? Let's use an accumulator over an immutable set instead.
Incorporated review feedback. I'll merge when green.
When constructing the dictionary for a byname implicit resolution we have to ensure that the owners of any definitions which have been hoisted into the dictionary are correct. Prior to this PR this was only
done fully for implicit expansions which didn't involve inlining. We fix that here by ensuring that all definitions under a given dictionary entry are owned directly or indirectly by that dictionary entry.
Fixes #5766.