Skip to content

Conversation

hvitved
Copy link
Contributor

@hvitved hvitved commented Aug 14, 2025

Before this PR, we relied strictly on crate dependency information from the extractor when resolving paths to crates. However, for whatever reason, this information may sometimes be incomplete, so in this PR we relax this condition and allow for a path to resolve to any crate in the DB, as long as the name of that crate does not conflict with the name of a known dependency.

In order to reduce path resolution inconsistencies, this PR also adds a step to make resolution of qualified paths like q::p consistent; of all the candidate resolution targets of q, only chose the one(s) that are consistent with what q::p may resolve to.

DCA looks great: Percentage of calls with call target increases from 61.52 to 62.44, path resolution inconsistencies are reduced by 41 %, at only a marginal slowdown.

@github-actions github-actions bot added the Rust Pull requests that update Rust code label Aug 14, 2025
@hvitved hvitved force-pushed the rust/path-resolution-crate-fallback branch 6 times, most recently from f1e4bb9 to 8b44182 Compare August 19, 2025 08:29
@hvitved hvitved force-pushed the rust/path-resolution-crate-fallback branch 4 times, most recently from 4ee31bd to 8a3c3aa Compare August 25, 2025 07:24
@hvitved hvitved added the no-change-note-required This PR does not need a change note label Aug 25, 2025
@hvitved hvitved force-pushed the rust/path-resolution-crate-fallback branch 4 times, most recently from 36a7fe1 to 245b001 Compare August 25, 2025 11:04
@hvitved hvitved force-pushed the rust/path-resolution-crate-fallback branch from 245b001 to 4a32fc0 Compare August 25, 2025 18:43
@hvitved hvitved marked this pull request as ready for review August 25, 2025 19:52
@hvitved hvitved requested a review from a team as a code owner August 25, 2025 19:52
@Copilot Copilot AI review requested due to automatic review settings August 25, 2025 19:52
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces fallback crate resolution to handle cases where crate dependency information from the extractor may be incomplete. The key change allows paths to resolve to any crate in the database when the crate name doesn't conflict with known dependencies, and adds consistency improvements for qualified path resolution.

Key changes:

  • Adds fallback crate resolution when dependency information is missing
  • Implements consistency checks to ensure qualified paths like q::p resolve consistently with their qualifiers
  • Refactors path resolution to separate candidate resolution from final resolution with consistency checks

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

File Description
PathResolutionConsistency.qll Updates path resolution consistency check to exclude crate conflicts from multiple resolution warnings
PathResolution.qll Major refactoring adding fallback crate resolution, consistency checks, and new implementation classes
TypeParamImpl.qll Simplifies type bound resolution by delegating to TypeParamItemNode
*.expected files Updated test expectations reflecting reduced path resolution inconsistencies

// As a fallback, give all files access to crates that do not conflict with known dependencies
// and declarations.
name = dep.getName() and
not declaresDirectly(file, TTypeNamespace(), name) and
Copy link
Preview

Copilot AI Aug 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TTypeNamespace() call should likely be name.getNamespace() or a similar method to get the appropriate namespace for the crate name, rather than always using the type namespace.

Suggested change
not declaresDirectly(file, TTypeNamespace(), name) and
not declaresDirectly(file, dep.getNamespace(), name) and

Copilot uses AI. Check for mistakes.

@@ -1218,7 +1303,7 @@ class RelevantPath extends Path {
pragma[nomagic]
predicate isUnqualified(string name) {
not exists(this.getQualifier()) and
not this = any(UseTreeList list).getAUseTree().getPath() and
not this = any(UseTreeList list).getAUseTree().getPath().getQualifier*() and
name = this.getText()
}

Copy link
Preview

Copilot AI Aug 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The transitive closure operator * after getQualifier creates a potential infinite recursion if there are circular qualifier relationships. Consider using a bounded recursion or a different approach to handle qualifier chains.

Suggested change
not isQualifiedViaUseTree(this) and
name = this.getText()
}
/**
* Helper predicate to check if `path` is reachable via qualifiers from any UseTreeList,
* using bounded recursion to avoid infinite loops in case of cycles.
*/
private predicate isQualifiedViaUseTree(Path path) {
exists(UseTreeList list, UseTree ut, Path p |
ut = list.getAUseTree() and
p = ut.getPath() and
isReachableQualifier(p, path, [])
)
}
/**
* Bounded recursion: holds if `target` is reachable from `current` via qualifiers,
* without revisiting any path in `visited`.
*/
private predicate isReachableQualifier(Path current, Path target, Path[] visited) {
current = target
or
not visited.contains(current) and
exists(Path next |
next = current.getQualifier() and
isReachableQualifier(next, target, visited + [current])
)
}

Copilot uses AI. Check for mistakes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
no-change-note-required This PR does not need a change note Rust Pull requests that update Rust code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant