Merge pull request #19362 from hvitved/rust/crate-extraction-workarounds

Rust: Crate graph extraction workarounds
This commit is contained in:
Tom Hvitved
2025-04-30 15:11:26 +02:00
committed by GitHub
2 changed files with 61 additions and 15 deletions

View File

@@ -120,7 +120,7 @@ module Stages {
or
exists(resolvePath(_))
or
exists(any(ItemNode i).getASuccessor(_))
exists(any(ItemNode i).getASuccessorFull(_))
or
exists(any(ItemNode i).getASuccessorRec(_))
or

View File

@@ -172,9 +172,14 @@ abstract class ItemNode extends Locatable {
result = this.(TypeParamItemNode).resolveABound().getASuccessorRec(name).(AssocItemNode)
}
/** Gets a successor named `name` of this item, if any. */
/**
* Gets a successor named `name` of this item, if any.
*
* Whenever a function exists in both source code and in library code,
* both are included
*/
cached
ItemNode getASuccessor(string name) {
ItemNode getASuccessorFull(string name) {
Stages::PathResolutionStage::ref() and
result = this.getASuccessorRec(name)
or
@@ -202,6 +207,22 @@ abstract class ItemNode extends Locatable {
result.(CrateItemNode).isPotentialDollarCrateTarget()
}
/** Gets a successor named `name` of this item, if any. */
pragma[nomagic]
ItemNode getASuccessor(string name) {
result = this.getASuccessorFull(name) and
(
// when a function exists in both source code and in library code, it is because
// we also extracted the source code as library code, and hence we only want
// the function from source code
result.fromSource()
or
not result instanceof Function
or
not this.getASuccessorFull(name).(Function).fromSource()
)
}
/** Gets the location of this item. */
Location getLocation() { result = super.getLocation() }
}
@@ -234,7 +255,7 @@ abstract private class ModuleLikeNode extends ItemNode {
private class SourceFileItemNode extends ModuleLikeNode, SourceFile {
pragma[nomagic]
ModuleLikeNode getSuper() {
result = any(ModuleItemNode mod | fileImport(mod, this)).getASuccessor("super")
result = any(ModuleItemNode mod | fileImport(mod, this)).getASuccessorFull("super")
}
override string getName() { result = "(source file)" }
@@ -297,7 +318,7 @@ class CrateItemNode extends ItemNode instanceof Crate {
predicate isPotentialDollarCrateTarget() {
exists(string name, RelevantPath p |
p.isDollarCrateQualifiedPath(name) and
exists(this.getASuccessor(name))
exists(this.getASuccessorFull(name))
)
}
@@ -323,7 +344,14 @@ abstract private class AssocItemNode extends ItemNode, AssocItem {
private class ConstItemNode extends AssocItemNode instanceof Const {
override string getName() { result = Const.super.getName().getText() }
override predicate hasImplementation() { super.hasBody() }
override predicate hasImplementation() {
super.hasBody()
or
// for trait items from library code, we do not currently know if they
// have default implementations or not, so we assume they do
not this.fromSource() and
this = any(TraitItemNode t).getAnAssocItem()
}
override Namespace getNamespace() { result.isValue() }
@@ -359,7 +387,14 @@ private class VariantItemNode extends ItemNode instanceof Variant {
class FunctionItemNode extends AssocItemNode instanceof Function {
override string getName() { result = Function.super.getName().getText() }
override predicate hasImplementation() { super.hasBody() }
override predicate hasImplementation() {
super.hasBody()
or
// for trait items from library code, we do not currently know if they
// have default implementations or not, so we assume they do
not this.fromSource() and
this = any(TraitItemNode t).getAnAssocItem()
}
override Namespace getNamespace() { result.isValue() }
@@ -862,6 +897,12 @@ class RelevantPath extends Path {
this.getQualifier().(RelevantPath).isCratePath("$crate", _) and
this.getText() = name
}
// TODO: Remove once the crate graph extractor generates publicly visible paths
predicate requiresExtractorWorkaround() {
not this.fromSource() and
this = any(RelevantPath p).getQualifier()
}
}
private predicate isModule(ItemNode m) { m instanceof Module }
@@ -916,8 +957,8 @@ private predicate unqualifiedPathLookup(ItemNode encl, string name, Namespace ns
}
pragma[nomagic]
private ItemNode getASuccessor(ItemNode pred, string name, Namespace ns) {
result = pred.getASuccessor(name) and
private ItemNode getASuccessorFull(ItemNode pred, string name, Namespace ns) {
result = pred.getASuccessorFull(name) and
ns = result.getNamespace()
}
@@ -954,7 +995,7 @@ private predicate keywordLookup(ItemNode encl, string name, Namespace ns, Releva
pragma[nomagic]
private ItemNode unqualifiedPathLookup(RelevantPath p, Namespace ns) {
exists(ItemNode encl, string name | result = getASuccessor(encl, name, ns) |
exists(ItemNode encl, string name | result = getASuccessorFull(encl, name, ns) |
unqualifiedPathLookup(encl, name, ns, p)
or
keywordLookup(encl, name, ns, p)
@@ -978,7 +1019,7 @@ private ItemNode resolvePath0(RelevantPath path, Namespace ns) {
or
exists(ItemNode q, string name |
q = resolvePathQualifier(path, name) and
result = getASuccessor(q, name, ns)
result = getASuccessorFull(q, name, ns)
)
or
result = resolveUseTreeListItem(_, _, path) and
@@ -1029,6 +1070,7 @@ pragma[nomagic]
private ItemNode resolvePathPrivate(
RelevantPath path, ModuleLikeNode itemParent, ModuleLikeNode pathParent
) {
not path.requiresExtractorWorkaround() and
result = resolvePath1(path) and
itemParent = result.getImmediateParentModule() and
not result.isPublic() and
@@ -1062,7 +1104,11 @@ private ModuleLikeNode getAPrivateVisibleModule(ModuleLikeNode itemParent) {
cached
ItemNode resolvePath(RelevantPath path) {
result = resolvePath1(path) and
result.isPublic()
(
result.isPublic()
or
path.requiresExtractorWorkaround()
)
or
exists(ModuleLikeNode itemParent, ModuleLikeNode pathParent |
result = resolvePathPrivate(path, itemParent, pathParent) and
@@ -1098,12 +1144,12 @@ private ItemNode resolveUseTreeListItem(Use use, UseTree tree, RelevantPath path
mid = resolveUseTreeListItem(use, midTree) and
tree = midTree.getUseTreeList().getAUseTree() and
isUseTreeSubPathUnqualified(tree, path, pragma[only_bind_into](name)) and
result = mid.getASuccessor(pragma[only_bind_into](name))
result = mid.getASuccessorFull(pragma[only_bind_into](name))
)
or
exists(ItemNode q, string name |
q = resolveUseTreeListItemQualifier(use, tree, path, name) and
result = q.getASuccessor(name)
result = q.getASuccessorFull(name)
)
}
@@ -1133,7 +1179,7 @@ private predicate useImportEdge(Use use, string name, ItemNode item) {
then
exists(ItemNode encl, Namespace ns |
encl.getADescendant() = use and
item = getASuccessor(used, name, ns) and
item = getASuccessorFull(used, name, ns) and
// glob imports can be shadowed
not declares(encl, ns, name) and
not name = ["super", "self", "Self", "$crate", "crate"]