Skip to content

Commit 5634395

Browse files
committed
Rust: Speedup type inference for Trait::function() calls
1 parent c3ac202 commit 5634395

File tree

1 file changed

+90
-28
lines changed

1 file changed

+90
-28
lines changed

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

Lines changed: 90 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2669,6 +2669,21 @@ private predicate inferMethodCallType =
26692669
* "calls" to tuple variants and tuple structs.
26702670
*/
26712671
private module NonMethodResolution {
2672+
pragma[nomagic]
2673+
private predicate traitFunctionResolutionDependsOnArgument0(
2674+
TraitItemNode trait, NonMethodFunction traitFunction, FunctionPosition pos, ImplItemNode impl,
2675+
NonMethodFunction implFunction, TypePath path, TypeParameter traitTp
2676+
) {
2677+
implFunction = impl.getAnAssocItem() and
2678+
implFunction.implements(traitFunction) and
2679+
FunctionOverloading::traitTypeParameterOccurrence(trait, traitFunction, _, pos, path, traitTp) and
2680+
(
2681+
traitTp = TSelfTypeParameter(trait)
2682+
or
2683+
FunctionOverloading::functionResolutionDependsOnArgument(impl, implFunction, traitTp, pos)
2684+
)
2685+
}
2686+
26722687
/**
26732688
* Holds if resolving the function `implFunction` in `impl` requires inspecting
26742689
* the type of applied _arguments_ or possibly knowing the return type.
@@ -2685,13 +2700,44 @@ private module NonMethodResolution {
26852700
TraitItemNode trait, NonMethodFunction traitFunction, FunctionPosition pos, ImplItemNode impl,
26862701
NonMethodFunction implFunction, TypePath path, TypeParameter traitTp
26872702
) {
2688-
implFunction = impl.getAnAssocItem() and
2689-
implFunction.implements(traitFunction) and
2690-
FunctionOverloading::traitTypeParameterOccurrence(trait, traitFunction, _, pos, path, traitTp) and
2691-
(
2692-
traitTp = TSelfTypeParameter(trait)
2703+
traitFunctionResolutionDependsOnArgument0(trait, traitFunction, pos, impl, implFunction, path,
2704+
traitTp) and
2705+
// Exclude functions where we cannot resolve all relevant type mentions; this allows
2706+
// for blanket implementations to be applied in those cases
2707+
forall(TypeParameter traitTp0 |
2708+
traitFunctionResolutionDependsOnArgument0(trait, traitFunction, _, impl, implFunction, _,
2709+
traitTp0)
2710+
|
2711+
exists(FunctionPosition pos0, TypePath path0 |
2712+
traitFunctionResolutionDependsOnArgument0(trait, traitFunction, pos0, impl, implFunction,
2713+
path0, traitTp0) and
2714+
exists(getAssocFunctionTypeInclNonMethodSelfAt(implFunction, impl, pos0, path0))
2715+
)
2716+
)
2717+
}
2718+
2719+
/**
2720+
* Holds if `f` inside `i` either implements trait function `traitFunction` inside `trait`
2721+
* or is equal to `traitFunction`, and the type of `f` at `pos` and `path` is `t`, which
2722+
* corresponds to the `Self` type parameter of `trait`.
2723+
*/
2724+
pragma[nomagic]
2725+
private predicate traitFunctionHasSelfType(
2726+
TraitItemNode trait, NonMethodFunction traitFunction, FunctionPosition pos, TypePath path,
2727+
Type t, ImplOrTraitItemNode i, NonMethodFunction f
2728+
) {
2729+
exists(ImplItemNode impl, NonMethodFunction implFunction, AssocFunctionType aft |
2730+
traitFunctionResolutionDependsOnArgument(trait, traitFunction, pos, impl, implFunction, path,
2731+
TSelfTypeParameter(trait)) and
2732+
aft.appliesTo(f, i, pos) and
2733+
t = aft.getTypeAt(path)
2734+
|
2735+
i = trait and
2736+
f = traitFunction
26932737
or
2694-
FunctionOverloading::functionResolutionDependsOnArgument(impl, implFunction, traitTp, pos)
2738+
i = impl and
2739+
f = implFunction and
2740+
not BlanketImplementation::isBlanketLike(i, _, _)
26952741
)
26962742
}
26972743

@@ -2848,10 +2894,25 @@ private module NonMethodResolution {
28482894
predicate hasNoCompatibleNonBlanketTarget() {
28492895
this.resolveCallTargetBlanketLikeCand(_, _, _, _) and
28502896
not exists(this.resolveCallTargetViaPathResolution()) and
2851-
forall(ImplOrTraitItemNode i, Function f |
2852-
this.(NonMethodArgsAreInstantiationsOfNonBlanketInput::Call).hasTargetCand(i, f)
2853-
|
2897+
forall(ImplOrTraitItemNode i, Function f | f = this.resolveCallTargetNonBlanketCand(i) |
28542898
NonMethodArgsAreInstantiationsOfNonBlanket::argsAreNotInstantiationsOf(this, i, f)
2899+
) and
2900+
(
2901+
not this.hasTraitResolved(_, _)
2902+
or
2903+
exists(
2904+
TraitItemNode trait, NonMethodFunction resolved, FunctionPosition pos, TypePath path,
2905+
Type t
2906+
|
2907+
this.(NonMethodArgsAreInstantiationsOfNonBlanketInput::Call)
2908+
.hasTraitResolvedSelfType(trait, resolved, pos, path, t)
2909+
|
2910+
forall(ImplOrTraitItemNode i, Function f |
2911+
traitFunctionHasSelfType(trait, resolved, pos, path, t, i, f)
2912+
|
2913+
NonMethodArgsAreInstantiationsOfNonBlanket::argsAreNotInstantiationsOf(this, i, f)
2914+
)
2915+
)
28552916
)
28562917
}
28572918

@@ -2994,29 +3055,30 @@ private module NonMethodResolution {
29943055
result = getArgType(this, pos, path, _)
29953056
}
29963057

3058+
/**
3059+
* Holds if this call is of the form `Trait::function(args)`, and the type at `pos` and
3060+
* `path` matches the `Self` type parameter of `Trait`.
3061+
*/
3062+
pragma[nomagic]
3063+
predicate hasTraitResolvedSelfType(
3064+
TraitItemNode trait, NonMethodFunction function, FunctionPosition pos, TypePath path, Type t
3065+
) {
3066+
this.hasTraitResolved(trait, function) and
3067+
FunctionOverloading::traitTypeParameterOccurrence(trait, function, _, pos, path,
3068+
TSelfTypeParameter(trait)) and
3069+
t = substituteLookupTraits(this.getArgType(pos, path)) and
3070+
t != TUnknownType()
3071+
}
3072+
29973073
predicate hasTargetCand(ImplOrTraitItemNode i, Function f) {
29983074
f = this.resolveCallTargetNonBlanketCand(i)
29993075
or
3000-
exists(TraitItemNode trait, NonMethodFunction resolved, ImplItemNode i1, Function f1 |
3001-
this.hasTraitResolved(trait, resolved) and
3002-
traitFunctionResolutionDependsOnArgument(trait, resolved, _, i1, f1, _, _) and
3003-
not BlanketImplementation::isBlanketLike(i, _, _)
3076+
exists(
3077+
TraitItemNode trait, NonMethodFunction resolved, FunctionPosition pos, TypePath path,
3078+
Type t
30043079
|
3005-
f = resolved and
3006-
i = trait
3007-
or
3008-
f = f1 and
3009-
i = i1 and
3010-
// Exclude functions where we cannot resolve all relevant type mentions; this allows
3011-
// for blanket implementations to be applied in those cases
3012-
forall(TypeParameter traitTp |
3013-
traitFunctionResolutionDependsOnArgument(trait, resolved, _, i1, f1, _, traitTp)
3014-
|
3015-
exists(FunctionPosition pos, TypePath path |
3016-
traitFunctionResolutionDependsOnArgument(trait, resolved, pos, i1, f1, path, traitTp) and
3017-
exists(getAssocFunctionTypeInclNonMethodSelfAt(f, i, pos, path))
3018-
)
3019-
)
3080+
this.hasTraitResolvedSelfType(trait, resolved, pos, path, t) and
3081+
traitFunctionHasSelfType(trait, resolved, pos, path, t, i, f)
30203082
)
30213083
}
30223084
}

0 commit comments

Comments
 (0)