Skip to content

Commit 07312a8

Browse files
committed
Rust, WIP: Improve performance, maybe
1 parent df2ccb4 commit 07312a8

File tree

2 files changed

+46
-45
lines changed

2 files changed

+46
-45
lines changed

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ private module Input2 implements InputSig2 {
120120
result = tp.(SelfTypeParameter).getTrait()
121121
}
122122

123-
predicate typeSatisfiesConstraint(TypeAbstraction abs, TypeMention sub, TypeMention sup) {
123+
predicate typeMentionSatisfiesConstraint(TypeAbstraction abs, TypeMention sub, TypeMention sup) {
124124
// `impl` blocks implementing traits
125125
exists(Impl impl |
126126
abs = impl and
@@ -1003,8 +1003,7 @@ private module Cached {
10031003
or
10041004
// The type of `receiver` is a type parameter and the method comes from a
10051005
// trait bound on the type parameter.
1006-
result =
1007-
getTypeParameterMethod(inferTypeDeref(receiver, TypePath::nil()), receiver.getField())
1006+
result = getTypeParameterMethod(receiver.resolveTypeAt(TypePath::nil()), receiver.getField())
10081007
)
10091008
}
10101009

shared/typeinference/codeql/typeinference/internal/TypeInference.qll

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -252,42 +252,6 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
252252
result = app.resolveTypeAt(TypePath::cons(tp, suffix))
253253
)
254254
}
255-
256-
/**
257-
* Holds if `term1` is a possible instantiation of `term2`. That is, by
258-
* substituting the type parameters in `term2` it is possible to obtain
259-
* `term1`.
260-
*
261-
* For instance, if `A` and `B` are type parameters we have:
262-
* - `Pair<int, string>` is an instantiation of `A`
263-
* - `Pair<int, string>` is an instantiation of `Pair<A, B>`
264-
* - `Pair<int, int>` is an instantiation of `Pair<A, A>`
265-
* - `Pair<int, bool>` is _not_ an instantiation of `Pair<A, A>`
266-
* - `Pair<int, string>` is _not_ an instantiation of `Pair<string, string>`
267-
*/
268-
bindingset[abs, term1, term2]
269-
predicate isInstantiationOf(TypeAbstraction abs, App term1, Term term2) {
270-
// Check the root type
271-
exists(Type root |
272-
root = term2.resolveTypeAt(TypePath::nil()) and
273-
(
274-
root = abs.getATypeParameter()
275-
or
276-
root = term1.resolveTypeAt(TypePath::nil()) and
277-
forall(TypePath path, Type t | term2.resolveTypeAt(path) = t |
278-
if t = abs.getATypeParameter() then any() else term1.resolveTypeAt(path) = t
279-
) and
280-
forall(TypeParameter tp, TypePath path1, TypePath path2 |
281-
tp = abs.getATypeParameter() and
282-
tp = term2.resolveTypeAt(path1) and
283-
tp = term2.resolveTypeAt(path2) and
284-
path1 != path2
285-
|
286-
term1.resolveTypeAt(path1) = term1.resolveTypeAt(path2)
287-
)
288-
)
289-
)
290-
}
291255
}
292256

293257
/** Provides the input to `Make2`. */
@@ -332,8 +296,6 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
332296
*/
333297
TypeMention getABaseTypeMention(Type t);
334298

335-
predicate typeSatisfiesConstraint(TypeAbstraction abs, TypeMention sub, TypeMention sup);
336-
337299
/**
338300
* Gets a type constraint on the type parameter `tp`, if any. All
339301
* instantiations of the type parameter must satisfy the constraint.
@@ -348,6 +310,16 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
348310
* the type parameter `T` has the constraint `IComparable<T>`.
349311
*/
350312
TypeMention getTypeParameterConstraint(TypeParameter tp);
313+
314+
/**
315+
* Holds if
316+
* - `abs` is a type abstraction of the free type variables in `typeMention`
317+
* and `constraint`, - and every instantiation of `typeMention` satisfies
318+
* `constraint`.
319+
*/
320+
predicate typeMentionSatisfiesConstraint(
321+
TypeAbstraction abs, TypeMention typeMention, TypeMention constraint
322+
);
351323
}
352324

353325
module Make2<InputSig2 Input2> {
@@ -461,7 +433,18 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
461433
)
462434
}
463435

464-
// bindingset[abs, app, term]
436+
/**
437+
* Holds if `term1` is a possible instantiation of `term2`. That is, by
438+
* making appropriate substitutions for the free type parameters in
439+
* `term2`, given by `aps`, it is possible to obtain `term1`.
440+
*
441+
* For instance, if `A` and `B` are free type parameters we have:
442+
* - `Pair<int, string>` is an instantiation of `A`
443+
* - `Pair<int, string>` is an instantiation of `Pair<A, B>`
444+
* - `Pair<int, int>` is an instantiation of `Pair<A, A>`
445+
* - `Pair<int, bool>` is _not_ an instantiation of `Pair<A, A>`
446+
* - `Pair<int, string>` is _not_ an instantiation of `Pair<string, string>`
447+
*/
465448
predicate isInstantiationOf(App app, TypeAbstraction abs, TypeMention term) {
466449
potentialInstantiationOf(abs, app, term) and
467450
// All the concrete types in `term` are satisfied
@@ -494,18 +477,37 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
494477
not exists(TypePath path, Type t | ment.resolveTypeAt(path) = t)
495478
}
496479

480+
module IsInstantiationOfInput implements IsInstantiationOfSig<TypeMention> {
481+
pragma[nomagic]
482+
private predicate getConstraintLhs(Type type, TypeAbstraction abs, TypeMention lhs) {
483+
typeMentionSatisfiesConstraint(abs, lhs, _) and type = resolveTypeMentionRoot(lhs)
484+
}
485+
486+
pragma[nomagic]
487+
private predicate getConstraintRhs(Type type, TypeMention rhs) {
488+
typeMentionSatisfiesConstraint(_, _, rhs) and type = resolveTypeMentionRoot(rhs)
489+
}
490+
491+
predicate potentialInstantiationOf(TypeAbstraction abs, TypeMention sub, TypeMention sup) {
492+
exists(Type type | getConstraintRhs(type, sub) and getConstraintLhs(type, abs, sup))
493+
}
494+
}
495+
497496
// The type mention `sub` satisfies `sup` with the type `t` at the path `path`.
498497
predicate typeSatisfiesConstraintTrans(
499498
TypeAbstraction abs, TypeMention sub, TypeMention sup, TypePath path, Type t
500499
) {
501500
// base case
502-
typeSatisfiesConstraint(abs, sub, sup) and
501+
typeMentionSatisfiesConstraint(abs, sub, sup) and
503502
sup.resolveTypeAt(path) = t
504503
or
505504
// recursive case
506505
exists(TypeAbstraction midAbs, TypeMention midSup, TypeMention midSub |
507-
typeSatisfiesConstraint(abs, sub, midSup) and
508-
TypeTreeUtils<TypeMention, TypeMention>::isInstantiationOf(abs, midSup, midSub) and
506+
typeMentionSatisfiesConstraint(abs, sub, midSup) and
507+
// NOTE: `midAbs` describe the free type variables in `midSub`, hence
508+
// we use that for instantiation check.
509+
IsInstantiationOf<TypeMention, IsInstantiationOfInput>::isInstantiationOf(midSup, midAbs,
510+
midSub) and
509511
(
510512
typeSatisfiesConstraintTrans(midAbs, midSub, sup, path, t) and
511513
not t = abs.getATypeParameter()

0 commit comments

Comments
 (0)