Skip to content

Commit b1d79d2

Browse files
committed
wip
1 parent 485e994 commit b1d79d2

File tree

8 files changed

+185
-97
lines changed

8 files changed

+185
-97
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: 110 additions & 34 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
}
@@ -1380,8 +1375,8 @@ private module MethodCallResolution {
13801375

13811376
/**
13821377
* Holds if method `m` with the name `name` and the arity `arity` exists in
1383-
* [blanket implementation][1] `i` and the type of the `self` parameter is
1384-
* `selfType`.
1378+
* [blanket implementation][1] `impl` of `trait`, and the type of the `self`
1379+
* parameter is`selfType`.
13851380
*
13861381
* `blanketPath` points to the type `blanketTypeParam` inside `selfType`, which
13871382
* is the type parameter used in the blanket implementation.
@@ -1390,11 +1385,13 @@ private module MethodCallResolution {
13901385
*/
13911386
pragma[nomagic]
13921387
predicate methodInfoBlanket(
1393-
Function m, string name, int arity, ImplItemNode i, FunctionType selfType, TypePath blanketPath,
1394-
TypeParam blanketTypeParam
1388+
Function m, string name, int arity, ImplItemNode impl, Trait trait, FunctionType selfType,
1389+
TypePath blanketPath, TypeParam blanketTypeParam
13951390
) {
1396-
methodInfoTypeParam(m, name, arity, i, selfType, blanketPath, blanketTypeParam) and
1397-
blanketTypeParam = i.getBlanketImplementationTypeParam()
1391+
methodInfo(m, name, arity, impl, selfType, _, _) and
1392+
TTypeParamTypeParameter(blanketTypeParam) = selfType.getTypeAt(blanketPath) and
1393+
blanketTypeParam = impl.getBlanketImplementationTypeParam() and
1394+
trait = impl.resolveTraitTy()
13981395
}
13991396

14001397
pragma[nomagic]
@@ -1479,7 +1476,7 @@ private module MethodCallResolution {
14791476
) {
14801477
exists(string name, int arity |
14811478
mc.hasNameAndArity(name, arity) and
1482-
methodInfoBlanket(m, name, arity, i, self, blanketPath, blanketTypeParam)
1479+
methodInfoBlanket(m, name, arity, i, _, self, blanketPath, blanketTypeParam)
14831480
|
14841481
methodCallVisibleImplTraitCandidate(mc, i)
14851482
or
@@ -1702,7 +1699,7 @@ private module MethodCallResolution {
17021699
}
17031700

17041701
pragma[nomagic]
1705-
predicate hasInfo(
1702+
predicate hasSignature(
17061703
MethodCall mc, TypePath strippedTypePath, Type strippedType, string name, int arity
17071704
) {
17081705
strippedType = this.getTypeAt(strippedTypePath) and
@@ -1728,7 +1725,7 @@ private module MethodCallResolution {
17281725
pragma[nomagic]
17291726
predicate hasNoInherentTarget() {
17301727
exists(TypePath strippedTypePath, Type strippedType, string name, int arity |
1731-
this.hasInfo(_, strippedTypePath, strippedType, name, arity) and
1728+
this.hasSignature(_, strippedTypePath, strippedType, name, arity) and
17321729
forall(Impl i |
17331730
methodInfoNonBlanket(_, name, arity, i, _, strippedTypePath, strippedType) and
17341731
not i.hasTrait()
@@ -1800,7 +1797,7 @@ private module MethodCallResolution {
18001797
MethodCallCand mcc, Function m, TypePath blanketPath, TypeParam blanketTypeParam
18011798
) {
18021799
exists(MethodCall mc, string name, int arity |
1803-
mcc.hasInfo(mc, _, _, name, arity) and
1800+
mcc.hasSignature(mc, _, _, name, arity) and
18041801
methodCallBlanketCandidate(mc, m, _, _, blanketPath, blanketTypeParam)
18051802
)
18061803
}
@@ -1821,7 +1818,7 @@ private module MethodCallResolution {
18211818
MethodCall mc, Function m, string name, int arity, TypePath strippedTypePath,
18221819
Type strippedType
18231820
|
1824-
mcc.hasInfo(mc, strippedTypePath, strippedType, name, arity)
1821+
mcc.hasSignature(mc, strippedTypePath, strippedType, name, arity)
18251822
|
18261823
methodCallNonBlanketCandidate(mc, m, abs, constraint, strippedTypePath, strippedType)
18271824
or
@@ -2035,7 +2032,21 @@ private Type inferMethodCallExprType(AstNode n, TypePath path) {
20352032
)
20362033
}
20372034

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

@@ -2068,7 +2079,11 @@ private module FunctionCallResolution {
20682079

20692080
/** A function call, `f(x)`. */
20702081
final class FunctionCall extends CallExpr {
2071-
private ItemNode getPathResolutionResolvedFunction() {
2082+
/**
2083+
* Gets the item that this function call resolves to using path resolution,
2084+
* if any.
2085+
*/
2086+
ItemNode getPathResolutionResolvedFunction() {
20722087
result = CallExprImpl::getResolvedFunction(this)
20732088
}
20742089

@@ -2078,7 +2093,7 @@ private module FunctionCallResolution {
20782093
}
20792094

20802095
pragma[nomagic]
2081-
predicate hasInfo(
2096+
predicate hasSignature(
20822097
TypePath strippedTypePath, Type strippedType, TraitItemNode trait, Function resolved
20832098
) {
20842099
this.getTypeAt(strippedTypePath) = strippedType and
@@ -2089,9 +2104,8 @@ private module FunctionCallResolution {
20892104

20902105
pragma[nomagic]
20912106
private Function getATargetMethodCand() {
2092-
exists(TraitItemNode trait, ImplOrTraitItemNode i, FunctionType self |
2093-
FunctionMethodCallIsInstantiationOfInput::potentialInstantiationOf(this, trait, i, self,
2094-
result) and
2107+
exists(ImplOrTraitItemNode i, FunctionType self |
2108+
FunctionMethodCallIsInstantiationOfInput::potentialInstantiationOf(this, i, self, result) and
20952109
IsInstantiationOf<FunctionCall, FunctionType, FunctionMethodCallIsInstantiationOfInput>::isInstantiationOf(this,
20962110
i, self)
20972111
)
@@ -2156,6 +2170,43 @@ private module FunctionCallResolution {
21562170
}
21572171
}
21582172

2173+
private module SatisfiesBlanketConstraintInput implements
2174+
MethodCallResolution::BlanketImplementation::SatisfiesBlanketConstraintInputSig<FunctionCall>
2175+
{
2176+
pragma[nomagic]
2177+
private predicate hasSignature(FunctionCall call, string name, int arity) {
2178+
name = CallExprImpl::getFunctionPath(call).getText() and
2179+
arity = call.getNumberOfArgs() - 1
2180+
}
2181+
2182+
pragma[nomagic]
2183+
private predicate hasBlanketCandidate(
2184+
FunctionCall call, Trait trait, Function m, TypePath blanketPath, TypeParam blanketTypeParam
2185+
) {
2186+
not exists(call.getPathResolutionResolvedFunction()) and
2187+
exists(string name, int arity, ImplItemNode impl |
2188+
hasSignature(call, name, arity) and
2189+
MethodCallResolution::methodInfoBlanket(m, name, arity, impl, trait, _, blanketPath,
2190+
blanketTypeParam)
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,31 @@ private module OperationResolution {
24612518
}
24622519
}
24632520

2521+
private module SatisfiesBlanketConstraintInput implements
2522+
MethodCallResolution::BlanketImplementation::SatisfiesBlanketConstraintInputSig<Op>
2523+
{
2524+
pragma[nomagic]
2525+
predicate hasBlanketCandidate(
2526+
Op op, Function m, TypePath blanketPath, TypeParam blanketTypeParam
2527+
) {
2528+
exists(Trait trait, string name, int arity, ImplItemNode impl |
2529+
op.hasSignature(_, _, trait, name, arity) and
2530+
MethodCallResolution::methodInfoBlanket(m, name, arity, impl, trait, _, blanketPath,
2531+
blanketTypeParam)
2532+
)
2533+
}
2534+
}
2535+
24642536
private module OperationIsInstantiationOfInput implements
24652537
IsInstantiationOfInputSig<Op, FunctionType>
24662538
{
2467-
// todo
24682539
bindingset[strippedTypePath]
24692540
private predicate methodInfoNonBlanket(
24702541
TypeAbstraction abs, FunctionType constraint, Trait trait, string name, int arity,
24712542
TypePath strippedTypePath, Type strippedType
24722543
) {
24732544
MethodCallResolution::methodInfoNonBlanket(_, name, arity, abs, constraint, strippedTypePath,
24742545
strippedType) and
2475-
not abs.(ImplItemNode).isBlanketImplementation() and
24762546
(
24772547
trait = abs.(ImplItemNode).resolveTraitTy()
24782548
or
@@ -2483,9 +2553,15 @@ private module OperationResolution {
24832553
pragma[nomagic]
24842554
predicate potentialInstantiationOf(Op op, TypeAbstraction abs, FunctionType constraint) {
24852555
exists(Trait trait, string name, int arity, TypePath strippedTypePath, Type strippedType |
2486-
op.hasInfo(strippedTypePath, strippedType, trait, name, arity) and
2556+
op.hasSignature(strippedTypePath, strippedType, trait, name, arity) and
24872557
methodInfoNonBlanket(abs, constraint, trait, name, arity, strippedTypePath, strippedType)
24882558
)
2559+
or
2560+
exists(Function m |
2561+
MethodCallResolution::methodInfoBlanket(m, _, _, abs, _, constraint, _, _) and
2562+
MethodCallResolution::BlanketImplementation::SatisfiesBlanketConstraint<Op, SatisfiesBlanketConstraintInput>::satisfiesBlanketConstraint(op,
2563+
m)
2564+
)
24892565
}
24902566

24912567
predicate relevantTypeMention(FunctionType constraint) {

0 commit comments

Comments
 (0)