Skip to content

Commit d5f062f

Browse files
committed
wip
1 parent 369a0cb commit d5f062f

File tree

2 files changed

+34
-15
lines changed

2 files changed

+34
-15
lines changed

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

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2440,42 +2440,61 @@ private module AssocFunctionResolution {
24402440
SelfArgIsNotInstantiationOfInherent::argIsNotInstantiationOf(this, impl, _, _)
24412441
}
24422442

2443-
/**
2444-
* Holds if this function call has no inherent target, i.e., it does not
2445-
* resolve to a function in an `impl` block for the type of the receiver.
2446-
*/
24472443
pragma[nomagic]
2448-
predicate hasNoInherentTarget() {
2449-
afc_.hasTrait()
2450-
or
2444+
predicate hasNoInherentTargetCheck() {
24512445
exists(
24522446
TypePath strippedTypePath, Type strippedType, string name, int arity,
2453-
TypeOption typeQualifier, TypeOption traitQualifier, boolean hasReceiver
2447+
TypeOption typeQualifier, TypeOption traitQualifier, boolean hasReceiver,
2448+
boolean targetMustBeMethod
24542449
|
24552450
// Calls to inherent functions are always of the form `x.m(...)` or `Foo::bar(...)`,
24562451
// where `Foo` is a type. In case `bar` is a method, we can use both the type qualifier
24572452
// and the type of the first argument to rule out candidates
2458-
selfPosAdj_.isTypeQualifier() and hasReceiver = false
2453+
selfPosAdj_.isTypeQualifier() and targetMustBeMethod = false
24592454
or
2460-
selfPosAdj_.asPosition() = 0 and hasReceiver = true
2455+
selfPosAdj_.asPosition() = 0 and targetMustBeMethod = true
24612456
|
2462-
afc_.hasSyntacticInfo(name, arity, typeQualifier, traitQualifier, _) and
2457+
afc_.hasSyntacticInfo(name, arity, typeQualifier, traitQualifier, hasReceiver) and
2458+
(if hasReceiver = true then targetMustBeMethod = true else any()) and
24632459
this.hasSignature(_, selfPosAdj_, strippedTypePath, strippedType, name, arity) and
24642460
forall(Impl i |
24652461
i.isInherent() and
24662462
(
24672463
assocFunctionInfoNonBlanketLikeCheck(_, name, arity, selfPosAdj_, i, _,
2468-
strippedTypePath, strippedType, typeQualifier, traitQualifier, hasReceiver)
2464+
strippedTypePath, strippedType, typeQualifier, traitQualifier, targetMustBeMethod)
24692465
or
24702466
assocFunctionInfoNonBlanketLikeTypeParamCheck(_, name, arity, selfPosAdj_, i, _,
2471-
strippedTypePath, typeQualifier, traitQualifier, hasReceiver)
2467+
strippedTypePath, typeQualifier, traitQualifier, targetMustBeMethod)
24722468
)
24732469
|
24742470
this.hasIncompatibleInherentTarget(i)
24752471
)
24762472
)
24772473
}
24782474

2475+
/**
2476+
* Holds if this function call has no inherent target, i.e., it does not
2477+
* resolve to a function in an `impl` block for the type of the receiver.
2478+
*/
2479+
pragma[nomagic]
2480+
predicate hasNoInherentTarget() {
2481+
afc_.hasTrait()
2482+
or
2483+
this.hasNoInherentTargetCheck() and
2484+
if exists(getNonTypeParameterTypeQualifier(afc_)) and not selfPosAdj_.isTypeQualifier()
2485+
then
2486+
// If this call is of the form `Foo::bar(x)` and we are resolving with respect to the type
2487+
// of `x`, then we additionally need to check that the type qualifier does not give rise
2488+
// to an inherent target
2489+
exists(FunctionPosition typeQualifierPos |
2490+
typeQualifierPos.isTypeQualifier() and
2491+
MkAssocFunctionCallCand(afc_, typeQualifierPos, _, _)
2492+
.(AssocFunctionCallCand)
2493+
.hasNoInherentTargetCheck()
2494+
)
2495+
else any()
2496+
}
2497+
24792498
pragma[nomagic]
24802499
private predicate selfArgIsInstantiationOf(ImplOrTraitItemNode i, string name, int arity) {
24812500
SelfArgIsInstantiationOf::argIsInstantiationOf(this, i, _) and

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ mod inherent_before_trait {
421421
// <S<i32>_as_Trait>::foo
422422
fn foo(&self) {
423423
S::foo(self); // $ MISSING: target=S<i32>::foo
424-
S::<i32>::foo(self); // $ MISSING: target=S<i32>::foo
424+
S::<i32>::foo(self); // $ target=S<i32>::foo
425425
self.foo() // $ target=<S<i32>_as_Trait>::foo
426426
}
427427

@@ -437,7 +437,7 @@ mod inherent_before_trait {
437437
// <S<i64>_as_Trait>::foo
438438
fn foo(&self) {
439439
// `S::foo(self);` is not valid
440-
S::<i64>::foo(self); // $ MISSING: target=<S<i64>_as_Trait>::foo
440+
S::<i64>::foo(self); // $ target=<S<i64>_as_Trait>::foo
441441
self.foo() // $ target=<S<i64>_as_Trait>::foo
442442
}
443443

0 commit comments

Comments
 (0)