Skip to content

Commit 0db4536

Browse files
committed
wip
1 parent 485e994 commit 0db4536

File tree

8 files changed

+187
-91
lines changed

8 files changed

+187
-91
lines changed

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

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
private import rust
66
private import codeql.rust.elements.internal.generated.ParentChild
7+
private import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl
78
private import codeql.rust.internal.CachedStages
89
private import codeql.rust.frameworks.stdlib.Builtins as Builtins
910
private import codeql.util.Option
@@ -604,7 +605,13 @@ private class EnumItemNode extends TypeItemNode instanceof Enum {
604605
}
605606
}
606607

607-
private class VariantItemNode extends ItemNode instanceof Variant {
608+
/** An item that can be called with arguments. */
609+
abstract class CallableItemNode extends ItemNode {
610+
/** Gets the number of parameters of this item. */
611+
abstract int getNumberOfParameters();
612+
}
613+
614+
private class VariantItemNode extends CallableItemNode instanceof Variant {
608615
override string getName() { result = Variant.super.getName().getText() }
609616

610617
override Namespace getNamespace() {
@@ -617,6 +624,10 @@ private class VariantItemNode extends ItemNode instanceof Variant {
617624

618625
override Visibility getVisibility() { result = super.getEnum().getVisibility() }
619626

627+
override int getNumberOfParameters() {
628+
result = super.getFieldList().(TupleFieldList).getNumberOfFields()
629+
}
630+
620631
override predicate hasCanonicalPath(Crate c) { this.hasCanonicalPathPrefix(c) }
621632

622633
bindingset[c]
@@ -638,7 +649,7 @@ private class VariantItemNode extends ItemNode instanceof Variant {
638649
}
639650
}
640651

641-
class FunctionItemNode extends AssocItemNode instanceof Function {
652+
class FunctionItemNode extends AssocItemNode, CallableItemNode instanceof Function {
642653
override string getName() { result = Function.super.getName().getText() }
643654

644655
override predicate hasImplementation() { Function.super.hasImplementation() }
@@ -648,6 +659,13 @@ class FunctionItemNode extends AssocItemNode instanceof Function {
648659
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
649660

650661
override Visibility getVisibility() { result = Function.super.getVisibility() }
662+
663+
override int getNumberOfParameters() {
664+
exists(int arr |
665+
arr = super.getNumberOfParams() and
666+
if super.hasSelfParam() then result = arr + 1 else result = arr
667+
)
668+
}
651669
}
652670

653671
abstract class ImplOrTraitItemNode extends ItemNode {
@@ -867,7 +885,7 @@ private class ImplItemNodeImpl extends ImplItemNode {
867885
TraitItemNode resolveTraitTyCand() { result = resolvePathCand(this.getTraitPath()) }
868886
}
869887

870-
private class StructItemNode extends TypeItemNode instanceof Struct {
888+
private class StructItemNode extends TypeItemNode, CallableItemNode instanceof Struct {
871889
override string getName() { result = Struct.super.getName().getText() }
872890

873891
override Namespace getNamespace() {
@@ -879,6 +897,10 @@ private class StructItemNode extends TypeItemNode instanceof Struct {
879897

880898
override Visibility getVisibility() { result = Struct.super.getVisibility() }
881899

900+
override int getNumberOfParameters() {
901+
result = super.getFieldList().(TupleFieldList).getNumberOfFields()
902+
}
903+
882904
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
883905

884906
override predicate hasCanonicalPath(Crate c) { this.hasCanonicalPathPrefix(c) }
@@ -1719,6 +1741,14 @@ private ItemNode resolvePathCand(RelevantPath path) {
17191741
or
17201742
not pathUsesNamespace(path, _) and
17211743
not path = any(MacroCall mc).getPath()
1744+
) and
1745+
(
1746+
not path = CallExprImpl::getFunctionPath(_)
1747+
or
1748+
exists(CallExpr ce |
1749+
path = CallExprImpl::getFunctionPath(ce) and
1750+
result.(CallableItemNode).getNumberOfParameters() = ce.getNumberOfArgs()
1751+
)
17221752
)
17231753
}
17241754

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

Lines changed: 112 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -871,11 +871,6 @@ private module FunctionOverloading {
871871
Impl impl, TraitItemNode trait, Type rootType, TypeMention selfTy
872872
) {
873873
trait = impl.(ImplItemNode).resolveTraitTy() and
874-
// If `impl` has an expansion from a macro attribute, then it's been
875-
// superseded by the output of the expansion (and usually the expansion
876-
// contains the same `impl` block so considering both would give spurious
877-
// siblings).
878-
not exists(impl.getAttributeMacroExpansion()) and
879874
selfTy = impl.getSelfTy() and
880875
rootType = selfTy.resolveType()
881876
}
@@ -1393,7 +1388,8 @@ private module MethodCallResolution {
13931388
Function m, string name, int arity, ImplItemNode i, FunctionType selfType, TypePath blanketPath,
13941389
TypeParam blanketTypeParam
13951390
) {
1396-
methodInfoTypeParam(m, name, arity, i, selfType, blanketPath, blanketTypeParam) and
1391+
methodInfo(m, name, arity, i, selfType, _, _) and
1392+
TTypeParamTypeParameter(blanketTypeParam) = selfType.getTypeAt(blanketPath) and
13971393
blanketTypeParam = i.getBlanketImplementationTypeParam()
13981394
}
13991395

@@ -1702,7 +1698,7 @@ private module MethodCallResolution {
17021698
}
17031699

17041700
pragma[nomagic]
1705-
predicate hasInfo(
1701+
predicate hasSignature(
17061702
MethodCall mc, TypePath strippedTypePath, Type strippedType, string name, int arity
17071703
) {
17081704
strippedType = this.getTypeAt(strippedTypePath) and
@@ -1728,7 +1724,7 @@ private module MethodCallResolution {
17281724
pragma[nomagic]
17291725
predicate hasNoInherentTarget() {
17301726
exists(TypePath strippedTypePath, Type strippedType, string name, int arity |
1731-
this.hasInfo(_, strippedTypePath, strippedType, name, arity) and
1727+
this.hasSignature(_, strippedTypePath, strippedType, name, arity) and
17321728
forall(Impl i |
17331729
methodInfoNonBlanket(_, name, arity, i, _, strippedTypePath, strippedType) and
17341730
not i.hasTrait()
@@ -1800,7 +1796,7 @@ private module MethodCallResolution {
18001796
MethodCallCand mcc, Function m, TypePath blanketPath, TypeParam blanketTypeParam
18011797
) {
18021798
exists(MethodCall mc, string name, int arity |
1803-
mcc.hasInfo(mc, _, _, name, arity) and
1799+
mcc.hasSignature(mc, _, _, name, arity) and
18041800
methodCallBlanketCandidate(mc, m, _, _, blanketPath, blanketTypeParam)
18051801
)
18061802
}
@@ -1821,7 +1817,7 @@ private module MethodCallResolution {
18211817
MethodCall mc, Function m, string name, int arity, TypePath strippedTypePath,
18221818
Type strippedType
18231819
|
1824-
mcc.hasInfo(mc, strippedTypePath, strippedType, name, arity)
1820+
mcc.hasSignature(mc, strippedTypePath, strippedType, name, arity)
18251821
|
18261822
methodCallNonBlanketCandidate(mc, m, abs, constraint, strippedTypePath, strippedType)
18271823
or
@@ -2035,7 +2031,21 @@ private Type inferMethodCallExprType(AstNode n, TypePath path) {
20352031
)
20362032
}
20372033

2038-
/** Provides logic for resolving function calls. */
2034+
/**
2035+
* Provides logic for resolving function calls.
2036+
*
2037+
* We distinguish between three cases:
2038+
*
2039+
* 1. The qualifier of the function call is _not_ a trait, and the function call
2040+
* can be resolved using path resolution. In this case we use the resolved
2041+
* function directly, we do not even check the receiver type in case the resolved
2042+
* function is a method.
2043+
*
2044+
* 2. The qualifier of the function call _is_ a trait, and the function call can be
2045+
* resolved using path resolution. In this case we use the resolved function
2046+
* directly, we do not even check the receiver type in case the resolved
2047+
* function is a method.
2048+
*/
20392049
private module FunctionCallResolution {
20402050
private import FunctionOverloading
20412051

@@ -2068,7 +2078,17 @@ private module FunctionCallResolution {
20682078

20692079
/** A function call, `f(x)`. */
20702080
final class FunctionCall extends CallExpr {
2071-
private ItemNode getPathResolutionResolvedFunction() {
2081+
pragma[nomagic]
2082+
predicate hasSignature(string name, int arity) {
2083+
name = CallExprImpl::getFunctionPath(this).getText() and
2084+
arity = this.getNumberOfArgs()
2085+
}
2086+
2087+
/**
2088+
* Gets the item that this function call resolves to using path resolution,
2089+
* if any.
2090+
*/
2091+
ItemNode getPathResolutionResolvedFunction() {
20722092
result = CallExprImpl::getResolvedFunction(this)
20732093
}
20742094

@@ -2078,7 +2098,7 @@ private module FunctionCallResolution {
20782098
}
20792099

20802100
pragma[nomagic]
2081-
predicate hasInfo(
2101+
predicate hasSignature(
20822102
TypePath strippedTypePath, Type strippedType, TraitItemNode trait, Function resolved
20832103
) {
20842104
this.getTypeAt(strippedTypePath) = strippedType and
@@ -2089,9 +2109,8 @@ private module FunctionCallResolution {
20892109

20902110
pragma[nomagic]
20912111
private Function getATargetMethodCand() {
2092-
exists(TraitItemNode trait, ImplOrTraitItemNode i, FunctionType self |
2093-
FunctionMethodCallIsInstantiationOfInput::potentialInstantiationOf(this, trait, i, self,
2094-
result) and
2112+
exists(ImplOrTraitItemNode i, FunctionType self |
2113+
FunctionMethodCallIsInstantiationOfInput::potentialInstantiationOf(this, i, self, result) and
20952114
IsInstantiationOf<FunctionCall, FunctionType, FunctionMethodCallIsInstantiationOfInput>::isInstantiationOf(this,
20962115
i, self)
20972116
)
@@ -2156,6 +2175,38 @@ private module FunctionCallResolution {
21562175
}
21572176
}
21582177

2178+
private module SatisfiesBlanketConstraintInput implements
2179+
MethodCallResolution::BlanketImplementation::SatisfiesBlanketConstraintInputSig<FunctionCall>
2180+
{
2181+
pragma[nomagic]
2182+
private predicate hasBlanketCandidate(
2183+
FunctionCall call, Trait trait, Function m, TypePath blanketPath, TypeParam blanketTypeParam
2184+
) {
2185+
not exists(call.getPathResolutionResolvedFunction()) and
2186+
exists(string name, int arity, ImplItemNode impl |
2187+
call.hasSignature(name, arity + 1) and
2188+
MethodCallResolution::methodInfoBlanket(m, name, arity, impl, _, blanketPath,
2189+
blanketTypeParam) and
2190+
trait = impl.resolveTraitTy()
2191+
)
2192+
}
2193+
2194+
pragma[nomagic]
2195+
private predicate functionCallTraitCandidate(Element mc, Trait trait) {
2196+
hasBlanketCandidate(mc, trait, _, _, _)
2197+
}
2198+
2199+
pragma[nomagic]
2200+
predicate hasBlanketCandidate(
2201+
FunctionCall call, Function m, TypePath blanketPath, TypeParam blanketTypeParam
2202+
) {
2203+
exists(Trait trait |
2204+
hasBlanketCandidate(call, trait, m, blanketPath, blanketTypeParam) and
2205+
TraitIsVisible<functionCallTraitCandidate/2>::traitIsVisible(call, trait)
2206+
)
2207+
}
2208+
}
2209+
21592210
/**
21602211
* A configuration for matching the type of the first argument in a function call
21612212
* against the type of a `self` parameter.
@@ -2195,15 +2246,21 @@ private module FunctionCallResolution {
21952246

21962247
pragma[nomagic]
21972248
additional predicate potentialInstantiationOf(
2198-
FunctionCall call, TraitItemNode trait, ImplOrTraitItemNode i, FunctionType selfType,
2199-
Function f
2249+
FunctionCall call, ImplOrTraitItemNode i, FunctionType selfType, Function f
22002250
) {
2201-
exists(Function resolved, TypePath strippedTypePath, Type strippedType |
2202-
call.hasInfo(strippedTypePath, strippedType, trait, resolved)
2203-
|
2204-
methodInfo(strippedTypePath, strippedType, trait, f, resolved)
2251+
(
2252+
exists(
2253+
TraitItemNode trait, Function resolved, TypePath strippedTypePath, Type strippedType
2254+
|
2255+
call.hasSignature(strippedTypePath, strippedType, trait, resolved)
2256+
|
2257+
methodInfo(strippedTypePath, strippedType, trait, f, resolved)
2258+
or
2259+
methodInfoTypeParam(strippedTypePath, trait, f, resolved)
2260+
)
22052261
or
2206-
methodInfoTypeParam(strippedTypePath, trait, f, resolved)
2262+
MethodCallResolution::BlanketImplementation::SatisfiesBlanketConstraint<FunctionCall, SatisfiesBlanketConstraintInput>::satisfiesBlanketConstraint(call,
2263+
f)
22072264
) and
22082265
MethodCallResolution::methodInfo(f, _, _, i, selfType, _, _)
22092266
}
@@ -2212,7 +2269,7 @@ private module FunctionCallResolution {
22122269
predicate potentialInstantiationOf(
22132270
FunctionCall call, TypeAbstraction abs, FunctionType constraint
22142271
) {
2215-
potentialInstantiationOf(call, _, abs, constraint, _)
2272+
potentialInstantiationOf(call, abs, constraint, _)
22162273
}
22172274

22182275
predicate relevantTypeMention(FunctionType constraint) {
@@ -2423,7 +2480,7 @@ private module OperationResolution {
24232480
Type getTypeAt(TypePath path) { result = substituteLookupTraits(this.getTypeAt0(path)) }
24242481

24252482
pragma[nomagic]
2426-
predicate hasInfo(
2483+
predicate hasSignature(
24272484
TypePath strippedTypePath, Type strippedType, Trait trait, string name, int arity
24282485
) {
24292486
name = this.(Call).getMethodName() and
@@ -2461,18 +2518,39 @@ private module OperationResolution {
24612518
}
24622519
}
24632520

2521+
private module SatisfiesBlanketConstraintInput implements
2522+
MethodCallResolution::BlanketImplementation::SatisfiesBlanketConstraintInputSig<Op>
2523+
{
2524+
pragma[nomagic]
2525+
private predicate methodInfoBlanket(
2526+
Function m, string name, int arity, ImplItemNode impl, Trait trait, TypePath blanketPath,
2527+
TypeParam blanketTypeParam
2528+
) {
2529+
MethodCallResolution::methodInfoBlanket(m, name, arity, impl, _, blanketPath, blanketTypeParam) and
2530+
trait = impl.resolveTraitTy()
2531+
}
2532+
2533+
pragma[nomagic]
2534+
predicate hasBlanketCandidate(
2535+
Op op, Function m, TypePath blanketPath, TypeParam blanketTypeParam
2536+
) {
2537+
exists(Trait trait, string name, int arity, ImplItemNode impl |
2538+
op.hasSignature(_, _, trait, name, arity) and
2539+
methodInfoBlanket(m, name, arity, impl, trait, blanketPath, blanketTypeParam)
2540+
)
2541+
}
2542+
}
2543+
24642544
private module OperationIsInstantiationOfInput implements
24652545
IsInstantiationOfInputSig<Op, FunctionType>
24662546
{
2467-
// todo
24682547
bindingset[strippedTypePath]
24692548
private predicate methodInfoNonBlanket(
24702549
TypeAbstraction abs, FunctionType constraint, Trait trait, string name, int arity,
24712550
TypePath strippedTypePath, Type strippedType
24722551
) {
24732552
MethodCallResolution::methodInfoNonBlanket(_, name, arity, abs, constraint, strippedTypePath,
24742553
strippedType) and
2475-
not abs.(ImplItemNode).isBlanketImplementation() and
24762554
(
24772555
trait = abs.(ImplItemNode).resolveTraitTy()
24782556
or
@@ -2483,9 +2561,15 @@ private module OperationResolution {
24832561
pragma[nomagic]
24842562
predicate potentialInstantiationOf(Op op, TypeAbstraction abs, FunctionType constraint) {
24852563
exists(Trait trait, string name, int arity, TypePath strippedTypePath, Type strippedType |
2486-
op.hasInfo(strippedTypePath, strippedType, trait, name, arity) and
2564+
op.hasSignature(strippedTypePath, strippedType, trait, name, arity) and
24872565
methodInfoNonBlanket(abs, constraint, trait, name, arity, strippedTypePath, strippedType)
24882566
)
2567+
or
2568+
exists(Function m |
2569+
MethodCallResolution::methodInfoBlanket(m, _, _, abs, constraint, _, _) and
2570+
MethodCallResolution::BlanketImplementation::SatisfiesBlanketConstraint<Op, SatisfiesBlanketConstraintInput>::satisfiesBlanketConstraint(op,
2571+
m)
2572+
)
24892573
}
24902574

24912575
predicate relevantTypeMention(FunctionType constraint) {

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ mod basic_blanket_impl {
5151
println!("{x3:?}");
5252
let x4 = (&S1).duplicate(); // $ target=Clone1duplicate
5353
println!("{x4:?}");
54-
let x5 = S1::duplicate(&S1); // $ MISSING: target=Clone1duplicate
54+
let x5 = S1::duplicate(&S1); // $ target=Clone1duplicate
5555
println!("{x5:?}");
5656
let x6 = S2.duplicate(); // $ MISSING: target=Clone1duplicate
5757
println!("{x6:?}");
@@ -174,11 +174,11 @@ pub mod sql_exec {
174174
let c = MySqlConnection {}; // $ certainType=c:MySqlConnection
175175

176176
c.execute1(); // $ target=execute1
177-
MySqlConnection::execute1(&c); // $ MISSING: target=execute1
177+
MySqlConnection::execute1(&c); // $ target=execute1
178178

179179
c.execute2("SELECT * FROM users"); // $ target=execute2
180180
c.execute2::<&str>("SELECT * FROM users"); // $ target=execute2
181-
MySqlConnection::execute2(&c, "SELECT * FROM users"); // $ MISSING: target=execute2
182-
MySqlConnection::execute2::<&str>(&c, "SELECT * FROM users"); // $ MISSING: target=execute2
181+
MySqlConnection::execute2(&c, "SELECT * FROM users"); // $ target=execute2
182+
MySqlConnection::execute2::<&str>(&c, "SELECT * FROM users"); // $ target=execute2
183183
}
184184
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2630,10 +2630,10 @@ pub mod path_buf {
26302630
}
26312631
}
26322632

2633+
mod blanket_impl;
26332634
mod closure;
26342635
mod dereference;
26352636
mod dyn_type;
2636-
mod blanket_impl;
26372637

26382638
fn main() {
26392639
field_access::f(); // $ target=f

0 commit comments

Comments
 (0)