Skip to content

Commit 3ee8989

Browse files
committed
Rust: Handle inherent implementations shadowing trait implementations
1 parent 4513106 commit 3ee8989

File tree

4 files changed

+37
-17
lines changed

4 files changed

+37
-17
lines changed

rust/ql/lib/codeql/rust/elements/internal/MethodCallExprImpl.qll

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@ private import codeql.rust.internal.TypeInference
1414
* be referenced directly.
1515
*/
1616
module Impl {
17-
private predicate isImplFunction(Function f) { f = any(ImplItemNode impl).getAnAssocItem() }
17+
private predicate isInherentImplFunction(Function f) {
18+
f = any(Impl impl | not impl.hasTrait()).(ImplItemNode).getAnAssocItem()
19+
}
20+
21+
private predicate isTraitImplFunction(Function f) {
22+
f = any(Impl impl | impl.hasTrait()).(ImplItemNode).getAnAssocItem()
23+
}
1824

1925
// the following QLdoc is generated: if you need to edit it, do it in the schema file
2026
/**
@@ -28,16 +34,22 @@ module Impl {
2834
override Function getStaticTarget() {
2935
result = resolveMethodCallExpr(this) and
3036
(
31-
// prioritize `impl` methods first
32-
isImplFunction(result)
37+
// prioritize inherent implementation methods first
38+
isInherentImplFunction(result)
3339
or
34-
not isImplFunction(resolveMethodCallExpr(this)) and
40+
not isInherentImplFunction(resolveMethodCallExpr(this)) and
3541
(
36-
// then trait methods with default implementations
37-
result.hasBody()
42+
// then trait implementation methods
43+
isTraitImplFunction(result)
3844
or
39-
// and finally trait methods without default implementations
40-
not resolveMethodCallExpr(this).hasBody()
45+
not isTraitImplFunction(resolveMethodCallExpr(this)) and
46+
(
47+
// then trait methods with default implementations
48+
result.hasBody()
49+
or
50+
// and finally trait methods without default implementations
51+
not resolveMethodCallExpr(this).hasBody()
52+
)
4153
)
4254
)
4355
}

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

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -974,14 +974,27 @@ private module Cached {
974974

975975
string getField() { result = mce.getIdentifier().getText() }
976976

977+
int getNumberOfArgs() { result = mce.getArgList().getNumberOfArgs() }
978+
977979
Type resolveTypeAt(TypePath path) { result = inferReceiverType(this, path) }
978980
}
979981

982+
/** Holds if a method for `type` with the name `name` and the arity `arity` exists in `impl`. */
983+
pragma[nomagic]
984+
private predicate methodCandidate(Type type, string name, int arity, Impl impl) {
985+
type = impl.(ImplTypeAbstraction).getSelfTy().(TypeReprMention).resolveType() and
986+
exists(Function f |
987+
f = impl.(ImplItemNode).getASuccessor(name) and
988+
f.getParamList().hasSelfParam() and
989+
arity = f.getParamList().getNumberOfParams()
990+
)
991+
}
992+
980993
private module IsInstantiationOfInput implements IsInstantiationOfSig<ReceiverExpr> {
981994
predicate potentialInstantiationOf(ReceiverExpr receiver, TypeAbstraction impl, TypeMention sub) {
982-
sub.resolveType() = receiver.resolveTypeAt(TypePath::nil()) and
983-
sub = impl.(ImplTypeAbstraction).getSelfTy().(TypeReprMention) and
984-
exists(impl.(ImplItemNode).getASuccessor(receiver.getField()))
995+
methodCandidate(receiver.resolveTypeAt(TypePath::nil()), receiver.getField(),
996+
receiver.getNumberOfArgs(), impl) and
997+
sub = impl.(ImplTypeAbstraction).getSelfTy()
985998
}
986999
}
9871000

rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected

Lines changed: 0 additions & 5 deletions
This file was deleted.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ mod impl_overlap {
399399
pub fn f() {
400400
let x = S1;
401401
println!("{:?}", x.common_method()); // $ method=S1::common_method SPURIOUS: method=<S1_as_OverlappingTrait>::common_method
402-
println!("{:?}", x.common_method_2()); // $ method=S1::common_method_2 SPURIOUS: method=<S1_as_OverlappingTrait>::common_method_2
402+
println!("{:?}", x.common_method_2()); // $ method=S1::common_method_2
403403
}
404404
}
405405

0 commit comments

Comments
 (0)