Skip to content

Commit 4688160

Browse files
committed
wip
1 parent 66b0939 commit 4688160

File tree

8 files changed

+108
-97
lines changed

8 files changed

+108
-97
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ predicate traitTypeParameterOccurrence(
8686
TypeParameter traitTp
8787
) {
8888
f = trait.getAssocItem(functionName) and
89-
traitTp = getAssocFunctionTypeAt(f, trait, pos, path) and
89+
traitTp = getAssocFunctionTypeInclNonMethodSelfAt(f, trait, pos, path) and
9090
traitTp = trait.(TraitTypeAbstraction).getATypeParameter()
9191
}
9292

@@ -141,7 +141,7 @@ pragma[nomagic]
141141
private Type getAssocFunctionNonTypeParameterTypeAt(
142142
ImplItemNode impl, Function f, FunctionPosition pos, TypePath path
143143
) {
144-
result = getAssocFunctionTypeAt(f, impl, pos, path) and
144+
result = getAssocFunctionTypeInclNonMethodSelfAt(f, impl, pos, path) and
145145
not result instanceof TypeParameter
146146
}
147147

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

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,9 @@ private newtype TAssocFunctionType =
8282
// through `i`. This ensures that `parent` is either a supertrait of `i` or
8383
// `i` in an `impl` block implementing `parent`.
8484
(parent = i or BaseTypes::rootTypesSatisfaction(_, TTrait(parent), i, _, _)) and
85-
exists(pos.getTypeMention(f))
85+
// We always include the `self` position, even for non-methods, where it is used
86+
// to match type qualifiers against the `impl` or trait type, such as in `Vec::new`.
87+
(exists(pos.getTypeMention(f)) or pos.isSelf())
8688
}
8789

8890
bindingset[abs, constraint, tp]
@@ -116,6 +118,22 @@ Type getAssocFunctionTypeAt(Function f, ImplOrTraitItemNode i, FunctionPosition
116118
)
117119
}
118120

121+
/**
122+
* Same as `getAssocFunctionTypeAt`, but also includes types at the `self` position
123+
* for non-methods.
124+
*/
125+
pragma[nomagic]
126+
Type getAssocFunctionTypeInclNonMethodSelfAt(
127+
Function f, ImplOrTraitItemNode i, FunctionPosition pos, TypePath path
128+
) {
129+
result = getAssocFunctionTypeAt(f, i, pos, path)
130+
or
131+
f = i.getASuccessor(_) and
132+
not f.hasSelfParam() and
133+
pos.isSelf() and
134+
result = resolveImplOrTraitType(i, path)
135+
}
136+
119137
/**
120138
* The type of an associated function at a given position, when its implicit
121139
* `Self` type parameter is specialized to a given trait or `impl` block.
@@ -174,7 +192,7 @@ class AssocFunctionType extends MkAssocFunctionType {
174192
Type getTypeAt(TypePath path) {
175193
exists(Function f, FunctionPosition pos, ImplOrTraitItemNode i, Type t |
176194
this.appliesTo(f, i, pos) and
177-
t = getAssocFunctionTypeAt(f, i, pos, path)
195+
t = getAssocFunctionTypeInclNonMethodSelfAt(f, i, pos, path)
178196
|
179197
not t instanceof SelfTypeParameter and
180198
result = t
@@ -184,9 +202,12 @@ class AssocFunctionType extends MkAssocFunctionType {
184202
}
185203

186204
private TypeMention getTypeMention() {
187-
exists(Function f, FunctionPosition pos |
188-
this.appliesTo(f, _, pos) and
205+
exists(Function f, ImplOrTraitItemNode i, FunctionPosition pos | this.appliesTo(f, i, pos) |
189206
result = pos.getTypeMention(f)
207+
or
208+
pos.isSelf() and
209+
not f.hasSelfParam() and
210+
result = [i.(Impl).getSelfTy().(TypeMention), i.(TypeMention)]
190211
)
191212
}
192213

@@ -294,8 +315,9 @@ module ArgIsInstantiationOf<
294315
*/
295316
signature module ArgsAreInstantiationsOfInputSig {
296317
/**
297-
* Holds if `f` implements a trait function with type parameter `traitTp`, where
298-
* we need to check that the type of `f` for `traitTp` is satisfied.
318+
* Holds if `f` implements (or is itself) a trait function with type parameter
319+
* `traitTp`, where we need to check that the type of `f` for `traitTp` is
320+
* satisfied.
299321
*
300322
* `pos` is one of the positions in `f` in which the relevant type occours.
301323
*/

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

Lines changed: 52 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -286,11 +286,13 @@ private class FunctionDeclaration extends Function {
286286
}
287287

288288
pragma[nomagic]
289-
Type getParameterType(ImplOrTraitItemNodeOption i, FunctionPosition pos, TypePath path) {
289+
Type getParameterTypeInclNonMethodSelf(
290+
ImplOrTraitItemNodeOption i, FunctionPosition pos, TypePath path
291+
) {
290292
i = parent and
291293
(
292294
not pos.isReturn() and
293-
result = getAssocFunctionTypeAt(this, i.asSome(), pos, path)
295+
result = getAssocFunctionTypeInclNonMethodSelfAt(this, i.asSome(), pos, path)
294296
or
295297
i.isNone() and
296298
result = this.getParam(pos.asPosition()).getTypeRepr().(TypeMention).getTypeAt(path)
@@ -322,13 +324,6 @@ private class FunctionDeclaration extends Function {
322324
else result = this.resolveRetType(i, path)
323325
}
324326

325-
Type getDeclaredType(ImplOrTraitItemNodeOption i, FunctionPosition pos, TypePath path) {
326-
result = this.getParameterType(i, pos, path)
327-
or
328-
pos.isReturn() and
329-
result = this.getReturnType(i, path)
330-
}
331-
332327
string toStringExt(ImplOrTraitItemNode i) {
333328
i = parent.asSome() and
334329
if this = i.getAnAssocItem()
@@ -1059,13 +1054,24 @@ private Path getCallExprPathQualifier(CallExpr ce) {
10591054
*
10601055
* For example, the type qualifier of `Foo::<i32>::default()` is `Foo::<i32>`,
10611056
* but only when `Foo` is not a trait.
1057+
*
1058+
* `isDefaultTypeArg` indicates whether the returned type is a default type
1059+
* argument, for example in `Vec::new()` the default type for the type parameter
1060+
* `A` of `Vec` is `Global`.
10621061
*/
10631062
pragma[nomagic]
1064-
private Type getCallExprTypeQualifier(CallExpr ce, TypePath path) {
1065-
exists(TypeMention tm |
1066-
tm = getCallExprPathQualifier(ce) and
1063+
private Type getCallExprTypeQualifier(CallExpr ce, TypePath path, boolean isDefaultTypeArg) {
1064+
exists(TypeMention tm | tm = getCallExprPathQualifier(ce) |
10671065
result = tm.getTypeAt(path) and
1068-
not resolvePath(tm) instanceof Trait
1066+
not resolvePath(tm) instanceof Trait and
1067+
isDefaultTypeArg = false
1068+
or
1069+
exists(TypeParameter tp, TypePath suffix |
1070+
result =
1071+
tm.(NonAliasPathTypeMention).getDefaultTypeForTypeParameterInNonAnnotationAt(tp, suffix) and
1072+
path = TypePath::cons(tp, suffix) and
1073+
isDefaultTypeArg = true
1074+
)
10691075
)
10701076
}
10711077

@@ -1148,7 +1154,7 @@ private module ContextTyping {
11481154
) and
11491155
not (
11501156
tp instanceof TSelfTypeParameter and
1151-
exists(getCallExprTypeQualifier(this, _))
1157+
exists(getCallExprTypeQualifier(this, _, _))
11521158
)
11531159
)
11541160
}
@@ -1947,7 +1953,7 @@ private module MethodResolution {
19471953
*/
19481954
pragma[nomagic]
19491955
predicate hasTypeQualifiedCandidate(ImplItemNode impl) {
1950-
exists(getCallExprTypeQualifier(this, _)) and
1956+
exists(getCallExprTypeQualifier(this, _, _)) and
19511957
CallExprImpl::getResolvedFunction(this) = impl.getADescendant()
19521958
}
19531959

@@ -1966,7 +1972,7 @@ private module MethodResolution {
19661972

19671973
// needed for `TypeQualifierIsInstantiationOfImplSelfInput`
19681974
Type getTypeAt(TypePath path) {
1969-
result = substituteLookupTraits(getCallExprTypeQualifier(this, path))
1975+
result = substituteLookupTraits(getCallExprTypeQualifier(this, path, _))
19701976
}
19711977

19721978
override predicate supportsAutoDerefAndBorrow() { none() }
@@ -2422,7 +2428,10 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi
24222428
}
24232429

24242430
Type getDeclaredType(DeclarationPosition dpos, TypePath path) {
2425-
result = m.getDeclaredType(someParent, dpos, path)
2431+
result = m.getParameterTypeInclNonMethodSelf(someParent, dpos, path)
2432+
or
2433+
dpos.isReturn() and
2434+
result = m.getReturnType(someParent, path)
24262435
}
24272436

24282437
string toString() { result = m.toStringExt(parent) }
@@ -2743,7 +2752,7 @@ private module NonMethodResolution {
27432752
result = this.getPathResolutionResolved() and
27442753
result = i.getASuccessor(_) and
27452754
not exists(this.resolveCallTargetViaPathResolution()) and
2746-
FunctionOverloading::functionResolutionDependsOnArgument(i, result, _, _)
2755+
implTraitTypeParameterOccurrence(_, _, _, i, result, _, _)
27472756
}
27482757

27492758
pragma[nomagic]
@@ -2778,14 +2787,9 @@ private module NonMethodResolution {
27782787
this.resolveCallTargetBlanketLikeCand(_, _, _, _) and
27792788
not exists(this.resolveCallTargetViaPathResolution()) and
27802789
forall(ImplOrTraitItemNode i, Function f |
2781-
this.(NonMethodNonTraitArgsAreInstantiationsOfNonBlanketInput::Call).hasTargetCand(i, f)
2790+
this.(NonMethodArgsAreInstantiationsOfNonBlanketInput::Call).hasTargetCand(i, f)
27822791
|
2783-
NonMethodNonTraitArgsAreInstantiationsOfNonBlanket::argsAreNotInstantiationsOf(this, i, f)
2784-
) and
2785-
forall(ImplOrTraitItemNode i, Function f |
2786-
this.(NonMethodTraitArgsAreInstantiationsOfNonBlanketInput::Call).hasTargetCand(i, f)
2787-
|
2788-
NonMethodTraitArgsAreInstantiationsOfNonBlanket::argsAreNotInstantiationsOf(this, i, f)
2792+
NonMethodArgsAreInstantiationsOfNonBlanket::argsAreNotInstantiationsOf(this, i, f)
27892793
)
27902794
}
27912795

@@ -2796,7 +2800,7 @@ private module NonMethodResolution {
27962800
ItemNode resolveCallTargetViaPathResolution() {
27972801
not this.hasTrait() and
27982802
result = this.getPathResolutionResolved() and
2799-
not FunctionOverloading::functionResolutionDependsOnArgument(_, result, _, _)
2803+
not implTraitTypeParameterOccurrence(_, _, _, _, result, _, _)
28002804
}
28012805

28022806
/**
@@ -2809,9 +2813,7 @@ private module NonMethodResolution {
28092813
or
28102814
NonMethodArgsAreInstantiationsOfBlanket::argsAreInstantiationsOf(this, i, result)
28112815
or
2812-
NonMethodNonTraitArgsAreInstantiationsOfNonBlanket::argsAreInstantiationsOf(this, i, result)
2813-
or
2814-
NonMethodTraitArgsAreInstantiationsOfNonBlanket::argsAreInstantiationsOf(this, i, result)
2816+
NonMethodArgsAreInstantiationsOfNonBlanket::argsAreInstantiationsOf(this, i, result)
28152817
}
28162818

28172819
pragma[nomagic]
@@ -2890,21 +2892,27 @@ private module NonMethodResolution {
28902892
private module ArgIsInstantiationOfBlanketParam =
28912893
ArgIsInstantiationOf<CallAndBlanketPos, ArgIsInstantiationOfBlanketParamInput>;
28922894

2893-
private Type getArgType(NonMethodCall call, FunctionPosition pos, TypePath path) {
2894-
result = inferType(call.getNodeAt(pos), path)
2895+
private Type getArgType(
2896+
NonMethodCall call, FunctionPosition pos, TypePath path, boolean isDefaultTypeArg
2897+
) {
2898+
result = inferType(call.getNodeAt(pos), path) and
2899+
isDefaultTypeArg = false
2900+
or
2901+
result = getCallExprTypeQualifier(call, path, isDefaultTypeArg) and
2902+
pos.isSelf()
28952903
}
28962904

28972905
private module NonMethodArgsAreInstantiationsOfBlanketInput implements
28982906
ArgsAreInstantiationsOfInputSig
28992907
{
29002908
predicate toCheck(ImplOrTraitItemNode i, Function f, TypeParameter traitTp, FunctionPosition pos) {
2901-
// For calls to blanket functions, we check all the positions in which a
2902-
// type parameter occurs.
29032909
implTraitTypeParameterOccurrence(_, _, pos, i, f, _, traitTp)
29042910
}
29052911

29062912
final class Call extends NonMethodCall {
2907-
Type getArgType(FunctionPosition pos, TypePath path) { result = getArgType(this, pos, path) }
2913+
Type getArgType(FunctionPosition pos, TypePath path) {
2914+
result = getArgType(this, pos, path, false)
2915+
}
29082916

29092917
predicate hasTargetCand(ImplOrTraitItemNode i, Function f) {
29102918
f = this.resolveCallTargetBlanketCand(i)
@@ -2915,31 +2923,10 @@ private module NonMethodResolution {
29152923
private module NonMethodArgsAreInstantiationsOfBlanket =
29162924
ArgsAreInstantiationsOf<NonMethodArgsAreInstantiationsOfBlanketInput>;
29172925

2918-
private module NonMethodNonTraitArgsAreInstantiationsOfNonBlanketInput implements
2926+
private module NonMethodArgsAreInstantiationsOfNonBlanketInput implements
29192927
ArgsAreInstantiationsOfInputSig
29202928
{
29212929
predicate toCheck(ImplOrTraitItemNode i, Function f, TypeParameter traitTp, FunctionPosition pos) {
2922-
// For calls to non-blanket functions, where no trait qualifier is supplied, e.g.
2923-
// `Vec::from(...)` we only check the positions needed for disambiguating sibling
2924-
// implementations.
2925-
FunctionOverloading::functionResolutionDependsOnArgument(i, f, traitTp, pos)
2926-
}
2927-
2928-
class Call extends NonMethodCall {
2929-
Type getArgType(FunctionPosition pos, TypePath path) { result = getArgType(this, pos, path) }
2930-
2931-
predicate hasTargetCand(ImplOrTraitItemNode i, Function f) {
2932-
f = this.resolveCallTargetNonBlanketCand(i)
2933-
}
2934-
}
2935-
}
2936-
2937-
private module NonMethodTraitArgsAreInstantiationsOfNonBlanketInput implements
2938-
ArgsAreInstantiationsOfInputSig
2939-
{
2940-
predicate toCheck(ImplOrTraitItemNode i, Function f, TypeParameter traitTp, FunctionPosition pos) {
2941-
// For calls to non-blanket functions, where a trait qualifier is supplied, e.g.
2942-
// `From::from(...)`, we check all the positions in which a type parameter occurs.
29432930
implTraitTypeParameterOccurrence(_, _, pos, i, f, _, traitTp)
29442931
or
29452932
// Also match against the trait function itself
@@ -2948,9 +2935,13 @@ private module NonMethodResolution {
29482935
}
29492936

29502937
class Call extends NonMethodCall {
2951-
Type getArgType(FunctionPosition pos, TypePath path) { result = getArgType(this, pos, path) }
2938+
Type getArgType(FunctionPosition pos, TypePath path) {
2939+
result = getArgType(this, pos, path, _)
2940+
}
29522941

29532942
predicate hasTargetCand(ImplOrTraitItemNode i, Function f) {
2943+
f = this.resolveCallTargetNonBlanketCand(i)
2944+
or
29542945
exists(TraitItemNode trait, NonMethodFunction resolved, ImplItemNode i1, Function f1 |
29552946
this.hasTraitResolved(trait, resolved) and
29562947
implTraitTypeParameterOccurrence(trait, resolved, _, i1, f1, _, _) and
@@ -2975,11 +2966,8 @@ private module NonMethodResolution {
29752966
}
29762967
}
29772968

2978-
private module NonMethodNonTraitArgsAreInstantiationsOfNonBlanket =
2979-
ArgsAreInstantiationsOf<NonMethodNonTraitArgsAreInstantiationsOfNonBlanketInput>;
2980-
2981-
private module NonMethodTraitArgsAreInstantiationsOfNonBlanket =
2982-
ArgsAreInstantiationsOf<NonMethodTraitArgsAreInstantiationsOfNonBlanketInput>;
2969+
private module NonMethodArgsAreInstantiationsOfNonBlanket =
2970+
ArgsAreInstantiationsOf<NonMethodArgsAreInstantiationsOfNonBlanketInput>;
29832971
}
29842972

29852973
abstract private class TupleLikeConstructor extends Addressable {
@@ -3079,26 +3067,7 @@ private module NonMethodCallMatchingInput implements MatchingInputSig {
30793067
}
30803068

30813069
override Type getParameterType(DeclarationPosition dpos, TypePath path) {
3082-
// For associated functions, we may also need to match type arguments against
3083-
// the `Self` type. For example, in
3084-
//
3085-
// ```rust
3086-
// struct Foo<T>(T);
3087-
//
3088-
// impl<T : Default> Foo<T> {
3089-
// fn default() -> Self {
3090-
// Foo(Default::default())
3091-
// }
3092-
// }
3093-
//
3094-
// Foo::<i32>::default();
3095-
// ```
3096-
//
3097-
// we need to match `i32` against the type parameter `T` of the `impl` block.
3098-
dpos.isSelf() and
3099-
result = resolveImplOrTraitType(i.asSome(), path)
3100-
or
3101-
result = f.getParameterType(i, dpos, path)
3070+
result = f.getParameterTypeInclNonMethodSelf(i, dpos, path)
31023071
}
31033072

31043073
override Type getReturnType(TypePath path) { result = f.getReturnType(i, path) }
@@ -3143,7 +3112,7 @@ private module NonMethodCallMatchingInput implements MatchingInputSig {
31433112
pragma[nomagic]
31443113
Type getInferredType(AccessPosition apos, TypePath path) {
31453114
apos.isSelf() and
3146-
result = getCallExprTypeQualifier(this, path)
3115+
result = getCallExprTypeQualifier(this, path, false)
31473116
or
31483117
result = inferType(this.getNodeAt(apos), path)
31493118
}

0 commit comments

Comments
 (0)