Skip to content

Commit b042f1d

Browse files
committed
Rust: Take trait visibility into account when resolving methods
1 parent e0d7cb4 commit b042f1d

File tree

3 files changed

+22
-6
lines changed

3 files changed

+22
-6
lines changed

rust/ql/lib/codeql/rust/internal/PathResolution.qll

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ abstract class ItemNode extends Locatable {
216216
// items made available through `use` are available to nodes that contain the `use`
217217
exists(UseItemNode use |
218218
use = this.getASuccessor(_, _) and
219-
result = use.(ItemNode).getASuccessor(name, kind)
219+
result = use.getASuccessor(name, kind)
220220
)
221221
or
222222
exists(ExternCrateItemNode ec | result = ec.(ItemNode).getASuccessor(name, kind) |
@@ -1215,6 +1215,7 @@ private predicate declares(ItemNode item, Namespace ns, string name) {
12151215
class RelevantPath extends Path {
12161216
RelevantPath() { not this = any(VariableAccess va).(PathExpr).getPath() }
12171217

1218+
/** Holds if this is an unqualified path with the textual value `name`. */
12181219
pragma[nomagic]
12191220
predicate isUnqualified(string name) {
12201221
not exists(this.getQualifier()) and
@@ -1572,7 +1573,7 @@ private module Debug {
15721573
useImportEdge(use, name, item, kind)
15731574
}
15741575

1575-
ItemNode debuggetASuccessor(ItemNode i, string name, SuccessorKind kind) {
1576+
ItemNode debugGetASuccessor(ItemNode i, string name, SuccessorKind kind) {
15761577
i = getRelevantLocatable() and
15771578
result = i.getASuccessor(name, kind)
15781579
}

rust/ql/lib/codeql/rust/internal/TypeInference.qll

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1891,7 +1891,7 @@ private predicate methodCandidate(Type type, string name, int arity, Impl impl)
18911891
*/
18921892
pragma[nomagic]
18931893
private predicate methodCandidateTrait(Type type, Trait trait, string name, int arity, Impl impl) {
1894-
trait = resolvePath(impl.(ImplItemNode).getTraitPath()) and
1894+
trait = impl.(ImplItemNode).resolveTraitTy() and
18951895
methodCandidate(type, name, arity, impl)
18961896
}
18971897

@@ -1902,6 +1902,16 @@ private predicate isMethodCall(MethodCall mc, Type rootType, string name, int ar
19021902
arity = mc.getNumberOfArguments()
19031903
}
19041904

1905+
/** Holds if the trait `trait` is visible at the method call `mc`. */
1906+
bindingset[mc, trait]
1907+
pragma[inline_late]
1908+
predicate methodCallTraitIsVisible(MethodCall mc, TraitItemNode trait) {
1909+
exists(ItemNode encl |
1910+
encl.getADescendant*() = mc and
1911+
trait = encl.getASuccessor(_, _)
1912+
)
1913+
}
1914+
19051915
private module IsInstantiationOfInput implements IsInstantiationOfInputSig<MethodCall> {
19061916
pragma[nomagic]
19071917
predicate potentialInstantiationOf(MethodCall mc, TypeAbstraction impl, TypeMention constraint) {
@@ -1912,7 +1922,12 @@ private module IsInstantiationOfInput implements IsInstantiationOfInputSig<Metho
19121922
methodCandidateTrait(rootType, mc.getTrait(), name, arity, impl)
19131923
or
19141924
not exists(mc.getTrait()) and
1915-
methodCandidate(rootType, name, arity, impl)
1925+
methodCandidate(rootType, name, arity, impl) and
1926+
(
1927+
methodCallTraitIsVisible(mc, impl.(ImplItemNode).resolveTraitTy())
1928+
or
1929+
not exists(impl.(ImplItemNode).resolveTraitTy())
1930+
)
19161931
)
19171932
}
19181933

rust/ql/test/library-tests/type-inference/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,11 @@ mod trait_visibility {
150150
let x = X;
151151
{
152152
use m::Foo;
153-
x.a_method(); // $ target=Foo::a_method SPURIOUS: target=Bar::a_method
153+
x.a_method(); // $ target=Foo::a_method
154154
}
155155
{
156156
use m::Bar;
157-
x.a_method(); // $ target=Bar::a_method SPURIOUS: target=Foo::a_method
157+
x.a_method(); // $ target=Bar::a_method
158158
}
159159
{
160160
use m::Bar;

0 commit comments

Comments
 (0)