Skip to content

Commit 0ce3a9a

Browse files
committed
wip2
1 parent 66a235c commit 0ce3a9a

File tree

5 files changed

+370
-70
lines changed

5 files changed

+370
-70
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ private import TypeInference
1515
* Holds if `traitBound` is the first non-trivial trait bound of `tp`.
1616
*/
1717
pragma[nomagic]
18-
private predicate hasFirstNonTrivialTraitBound(TypeParamItemNode tp, Trait traitBound) {
18+
predicate hasFirstNonTrivialTraitBound(TypeParamItemNode tp, Trait traitBound) {
1919
traitBound =
2020
min(Trait trait, int i |
2121
trait = tp.resolveBound(i) and

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

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ private import Type
44
private import TypeAbstraction
55
private import TypeMention
66
private import TypeInference
7+
private import BlanketImplementation as BlanketImplementation
78

89
private newtype TFunctionPosition =
910
TArgumentFunctionPosition(ArgumentPosition pos) or
@@ -263,22 +264,25 @@ Type getNthLookupType(Type t, int n) {
263264
pragma[nomagic]
264265
int getLastLookupTypeIndex(Type t) { result = max(int n | exists(getNthLookupType(t, n))) }
265266

267+
bindingset[t]
268+
private Type subst(Type t) {
269+
result = substituteLookupTraits(t) and
270+
not result = TNeverType() and
271+
not result = TUnknownType()
272+
}
273+
266274
/**
267275
* A wrapper around `IsInstantiationOf` which ensures to substitute in lookup
268276
* traits when checking whether argument types are instantiations of function
269277
* types.
270278
*/
271-
module ArgIsInstantiationOf<
279+
module ArgIsInstantiationOfWithoutConstraints<
272280
HasTypeTreeSig Arg, IsInstantiationOfInputSig<Arg, AssocFunctionType> Input>
273281
{
274282
final private class ArgFinal = Arg;
275283

276284
private class ArgSubst extends ArgFinal {
277-
Type getTypeAt(TypePath path) {
278-
result = substituteLookupTraits(super.getTypeAt(path)) and
279-
not result = TNeverType() and
280-
not result = TUnknownType()
281-
}
285+
Type getTypeAt(TypePath path) { result = subst(super.getTypeAt(path)) }
282286
}
283287

284288
private module IsInstantiationOfInput implements
@@ -310,6 +314,56 @@ module ArgIsInstantiationOf<
310314
}
311315
}
312316

317+
/**
318+
* A wrapper around `IsInstantiationOfWithConstraints` which ensures to substitute
319+
* in lookup traits when checking whether argument types are instantiations of function
320+
* types.
321+
*/
322+
module ArgIsInstantiationOf<
323+
HasTypeTreeSig Arg, IsInstantiationOfInputSig<Arg, AssocFunctionType> Input>
324+
{
325+
final private class ArgFinal = Arg;
326+
327+
private class ArgSubst extends ArgFinal {
328+
Type getTypeAt(TypePath path) { result = subst(super.getTypeAt(path)) }
329+
}
330+
331+
private module IsInstantiationOfInput implements
332+
IsInstantiationOfWithConstraintsInputSig<ArgSubst, AssocFunctionType>
333+
{
334+
pragma[nomagic]
335+
predicate potentialInstantiationOf(
336+
ArgSubst arg, TypeAbstraction abs, AssocFunctionType constraint
337+
) {
338+
Input::potentialInstantiationOf(arg, abs, constraint)
339+
}
340+
341+
predicate relevantConstraint(AssocFunctionType constraint) {
342+
Input::relevantConstraint(constraint)
343+
}
344+
345+
Type getARelevantTypeParameterConstraint(TypeParameter tp) {
346+
exists(TypeParam param |
347+
tp.(TypeParamTypeParameter).getTypeParam() = param and
348+
BlanketImplementation::hasFirstNonTrivialTraitBound(param, result.(TraitType).getTrait())
349+
)
350+
}
351+
}
352+
353+
private module ArgSubstIsInstantiationOf =
354+
IsInstantiationOfWithConstraints<ArgSubst, AssocFunctionType, IsInstantiationOfInput>;
355+
356+
predicate argIsInstantiationOf(Arg arg, ImplOrTraitItemNode i, AssocFunctionType constraint) {
357+
ArgSubstIsInstantiationOf::isInstantiationOf(arg, i, constraint)
358+
}
359+
360+
predicate argIsNotInstantiationOf(
361+
Arg arg, ImplOrTraitItemNode i, AssocFunctionType constraint, TypePath path
362+
) {
363+
ArgSubstIsInstantiationOf::isNotInstantiationOf(arg, i, constraint, path)
364+
}
365+
}
366+
313367
/**
314368
* Provides the input for `ArgsAreInstantiationsOf`.
315369
*/
@@ -436,8 +490,6 @@ module ArgsAreInstantiationsOf<ArgsAreInstantiationsOfInputSig Input> {
436490
/**
437491
* Holds if all arguments of `call` have types that are instantiations of the
438492
* types of the corresponding parameters of `f` inside `i`.
439-
*
440-
* TODO: Check type parameter constraints as well.
441493
*/
442494
pragma[nomagic]
443495
predicate argsAreInstantiationsOf(Input::Call call, ImplOrTraitItemNode i, Function f) {
@@ -473,8 +525,6 @@ module ArgsAreInstantiationsOf<ArgsAreInstantiationsOfInputSig Input> {
473525
/**
474526
* Holds if _some_ argument of `call` has a type that is not an instantiation of the
475527
* type of the corresponding parameter of `f` inside `i`.
476-
*
477-
* TODO: Check type parameter constraints as well.
478528
*/
479529
pragma[nomagic]
480530
predicate argsAreNotInstantiationsOf(Input::Call call, ImplOrTraitItemNode i, Function f) {

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

Lines changed: 82 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2311,7 +2311,8 @@ private module MethodResolution {
23112311
}
23122312

23132313
private module ReceiverIsNotInstantiationOfBlanketLikeSelfParam =
2314-
ArgIsInstantiationOf<MethodCallCand, ReceiverIsNotInstantiationOfBlanketLikeSelfParamInput>;
2314+
ArgIsInstantiationOfWithoutConstraints<MethodCallCand,
2315+
ReceiverIsNotInstantiationOfBlanketLikeSelfParamInput>;
23152316

23162317
/**
23172318
* A configuration for matching the type qualifier of a method call
@@ -2368,7 +2369,8 @@ private module MethodResolution {
23682369
}
23692370

23702371
private module ReceiverIsNotInstantiationOfInherentSelfParam =
2371-
ArgIsInstantiationOf<MethodCallCand, ReceiverIsNotInstantiationOfInherentSelfParamInput>;
2372+
ArgIsInstantiationOfWithoutConstraints<MethodCallCand,
2373+
ReceiverIsNotInstantiationOfInherentSelfParamInput>;
23722374

23732375
/**
23742376
* A configuration for matching the types of positional arguments against the
@@ -2677,8 +2679,12 @@ private module NonMethodResolution {
26772679
f = impl.getASuccessor(_) and
26782680
not impl.(Impl).hasTrait() and
26792681
traitTp = TTypeParamTypeParameter(impl.resolveSelfTy().getTypeParam(0)) and
2680-
pos.isSelf() and
2681-
not f.hasSelfParam()
2682+
not f.hasSelfParam() and
2683+
(
2684+
pos.isSelf()
2685+
or
2686+
pos.getTypeMention(f) = any(ImplSelfMention self).getParentNode*()
2687+
)
26822688
}
26832689

26842690
pragma[nomagic]
@@ -2742,6 +2748,16 @@ private module NonMethodResolution {
27422748
not result.(Function).hasSelfParam()
27432749
}
27442750

2751+
/**
2752+
* Gets the associated function that this function call resolves to using path
2753+
* resolution, if any.
2754+
*/
2755+
pragma[nomagic]
2756+
NonMethodFunction getPathResolutionResolved(ImplOrTraitItemNode i) {
2757+
result = this.getPathResolutionResolved() and
2758+
result = i.getAnAssocItem()
2759+
}
2760+
27452761
/**
27462762
* Gets the blanket function that this call may resolve to, if any.
27472763
*/
@@ -2839,13 +2855,6 @@ private module NonMethodResolution {
28392855
or
28402856
NonMethodArgsAreInstantiationsOfNonBlanket::argsAreInstantiationsOf(this, i, result)
28412857
}
2842-
2843-
pragma[nomagic]
2844-
NonMethodFunction resolveTraitFunctionViaPathResolution(TraitItemNode trait) {
2845-
this.hasTrait() and
2846-
result = this.getPathResolutionResolved() and
2847-
result = trait.getAnAssocItem()
2848-
}
28492858
}
28502859

28512860
private newtype TCallAndBlanketPos =
@@ -2959,6 +2968,7 @@ private module NonMethodResolution {
29592968
}
29602969

29612970
class Call extends NonMethodCall {
2971+
// Call() { this = Debug::getRelevantLocatable() } // todo
29622972
Type getArgType(FunctionPosition pos, TypePath path) {
29632973
result = getArgType(this, pos, path, _)
29642974
}
@@ -3171,13 +3181,16 @@ private module NonMethodCallMatchingInput implements MatchingInputSig {
31713181
pragma[nomagic]
31723182
predicate hasUnknownTypeAt(FunctionPosition pos, TypePath path) {
31733183
exists(ImplOrTraitItemNodeOption i, NonMethodFunctionDeclaration f |
3174-
TNonMethodFunctionDeclaration(i, f) = this.getTarget()
3175-
or
3176-
f = this.resolveTraitFunctionViaPathResolution(i.asSome())
3177-
|
3184+
TNonMethodFunctionDeclaration(i, f) = this.getTarget() and
31783185
this.hasUnknownTypeAt(i.asSome(), f, pos, path)
31793186
)
31803187
or
3188+
forex(ImplOrTraitItemNode i, NonMethodFunctionDeclaration f |
3189+
f = this.getPathResolutionResolved(i)
3190+
|
3191+
this.hasUnknownTypeAt(i, f, pos, path)
3192+
)
3193+
or
31813194
// Tuple declarations, such as `Result::Ok(...)`, may also be context typed
31823195
exists(TupleLikeConstructor tc, TypeParameter tp |
31833196
tc = this.resolveCallTargetViaPathResolution() and
@@ -4077,50 +4090,60 @@ private module Cached {
40774090
*/
40784091
cached
40794092
Type inferType(AstNode n, TypePath path) {
4080-
Stages::TypeInferenceStage::ref() and
4081-
result = CertainTypeInference::inferCertainType(n, path)
4082-
or
4083-
// Don't propagate type information into a node which conflicts with certain
4084-
// type information.
4093+
// exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
4094+
// n.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
4095+
// |
4096+
// not (
4097+
// filepath.matches("%/camera.rs") and
4098+
// startline = [82 .. 94]
4099+
// )
4100+
// ) and
40854101
(
4086-
if CertainTypeInference::hasInferredCertainType(n)
4087-
then not CertainTypeInference::certainTypeConflict(n, path, result)
4088-
else any()
4089-
) and
4090-
(
4091-
result = inferAssignmentOperationType(n, path)
4092-
or
4093-
result = inferTypeEquality(n, path)
4094-
or
4095-
result = inferStructExprType(n, path)
4096-
or
4097-
result = inferMethodCallType(n, path)
4098-
or
4099-
result = inferNonMethodCallType(n, path)
4100-
or
4101-
result = inferOperationType(n, path)
4102+
Stages::TypeInferenceStage::ref() and
4103+
result = CertainTypeInference::inferCertainType(n, path)
41024104
or
4103-
result = inferFieldExprType(n, path)
4104-
or
4105-
result = inferTryExprType(n, path)
4106-
or
4107-
result = inferLiteralType(n, path, false)
4108-
or
4109-
result = inferAwaitExprType(n, path)
4110-
or
4111-
result = inferIndexExprType(n, path)
4112-
or
4113-
result = inferDereferencedExprPtrType(n, path)
4114-
or
4115-
result = inferForLoopExprType(n, path)
4116-
or
4117-
result = inferDynamicCallExprType(n, path)
4118-
or
4119-
result = inferClosureExprType(n, path)
4120-
or
4121-
result = inferStructPatType(n, path)
4122-
or
4123-
result = inferTupleStructPatType(n, path)
4105+
// Don't propagate type information into a node which conflicts with certain
4106+
// type information.
4107+
(
4108+
if CertainTypeInference::hasInferredCertainType(n)
4109+
then not CertainTypeInference::certainTypeConflict(n, path, result)
4110+
else any()
4111+
) and
4112+
(
4113+
result = inferAssignmentOperationType(n, path)
4114+
or
4115+
result = inferTypeEquality(n, path)
4116+
or
4117+
result = inferStructExprType(n, path)
4118+
or
4119+
result = inferMethodCallType(n, path)
4120+
or
4121+
result = inferNonMethodCallType(n, path)
4122+
or
4123+
result = inferOperationType(n, path)
4124+
or
4125+
result = inferFieldExprType(n, path)
4126+
or
4127+
result = inferTryExprType(n, path)
4128+
or
4129+
result = inferLiteralType(n, path, false)
4130+
or
4131+
result = inferAwaitExprType(n, path)
4132+
or
4133+
result = inferIndexExprType(n, path)
4134+
or
4135+
result = inferDereferencedExprPtrType(n, path)
4136+
or
4137+
result = inferForLoopExprType(n, path)
4138+
or
4139+
result = inferDynamicCallExprType(n, path)
4140+
or
4141+
result = inferClosureExprType(n, path)
4142+
or
4143+
result = inferStructPatType(n, path)
4144+
or
4145+
result = inferTupleStructPatType(n, path)
4146+
)
41244147
)
41254148
}
41264149
}
@@ -4137,8 +4160,8 @@ private module Debug {
41374160
Locatable getRelevantLocatable() {
41384161
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
41394162
result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
4140-
filepath.matches("%/sqlx.rs") and
4141-
startline = [56 .. 60]
4163+
filepath.matches("%/overloading.rs") and
4164+
startline = 276
41424165
)
41434166
}
41444167

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14369,3 +14369,4 @@ inferType
1436914369
| raw_pointer.rs:59:5:59:30 | raw_type_from_deref(...) | | {EXTERNAL LOCATION} | () |
1437014370
| raw_pointer.rs:59:25:59:29 | false | | {EXTERNAL LOCATION} | bool |
1437114371
testFailures
14372+
| main.rs:2222:32:2222:132 | //... | Fixed spurious result: target=S::my_add2 |

0 commit comments

Comments
 (0)