Skip to content

Commit 5c132eb

Browse files
committed
wip6
1 parent f2fea03 commit 5c132eb

3 files changed

Lines changed: 133 additions & 73 deletions

File tree

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

Lines changed: 69 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -310,15 +310,11 @@ private module Input3 implements InputSig3 {
310310

311311
class Expr = Rust::Expr;
312312

313-
class ConditionalExpr extends AstNode, IfExpr {
314-
Expr getCondition() { result = super.getCondition() }
315-
313+
class ConditionalExpr extends IfExpr {
316314
Expr getThen() { result = super.getThen() }
317-
318-
Expr getElse() { result = super.getElse() }
319315
}
320316

321-
class BinaryExpr extends AstNode, Rust::BinaryExpr {
317+
class BinaryExpr extends Rust::BinaryExpr {
322318
Expr getLeftOperand() { result = super.getLhs() }
323319

324320
Expr getRightOperand() { result = super.getRhs() }
@@ -332,9 +328,7 @@ private module Input3 implements InputSig3 {
332328

333329
class AssignExpr extends Assignment, Rust::AssignmentExpr { }
334330

335-
class ParenExpr extends AstNode, Rust::ParenExpr {
336-
AstNode getExpr() { result = super.getExpr() }
337-
}
331+
class ParenExpr = Rust::ParenExpr;
338332

339333
class Variable extends Rust::Variable {
340334
AstNode getDefiningNode() {
@@ -372,6 +366,40 @@ private module Input3 implements InputSig3 {
372366
override AstNode getRightOperand() { result = this.getInitializer() }
373367
}
374368

369+
class CallTarget extends FunctionCallMatchingInput::Declaration {
370+
// TypeParameter getTypeParameter(TypeParameterPosition ppos);
371+
TypeMention getAdditionalTypeParameterConstraint(TypeParameter tp) {
372+
none() // todo
373+
}
374+
375+
Type getReturnType(TypePath path) {
376+
exists(FunctionPosition pos |
377+
pos.isReturn() and
378+
result = super.getDeclaredType(pos, path)
379+
)
380+
}
381+
382+
Type getParameterType(int index, TypePath path) {
383+
none() // todo
384+
}
385+
}
386+
387+
class Call extends Expr instanceof FunctionCallMatchingInput::Access {
388+
Type getTypeArgument(TypeArgumentPosition apos, TypePath path) {
389+
result = super.getTypeArgument(apos, path)
390+
}
391+
392+
/** Gets the target of this call. */
393+
CallTarget getTargetCertain() {
394+
exists(ImplOrTraitItemNodeOption i, FunctionDeclaration f, Path p |
395+
result.isFunction(i, f) and
396+
p = CallExprImpl::getFunctionPath(this) and
397+
f = resolvePath(p) and
398+
f.isDirectlyFor(i)
399+
)
400+
}
401+
}
402+
375403
predicate certainTypeEqualityInput(AstNode n1, TypePath prefix1, AstNode n2, TypePath prefix2) {
376404
n1 =
377405
any(IdentPat ip |
@@ -686,16 +714,38 @@ private class AssocFunctionDeclaration extends FunctionDeclaration {
686714
}
687715

688716
pragma[nomagic]
689-
private TypeMention getCallExprTypeMentionArgument(CallExpr ce, TypeArgumentPosition apos) {
690-
exists(Path p, int i | p = CallExprImpl::getFunctionPath(ce) |
691-
apos.asTypeParam() = resolvePath(p).getTypeParam(pragma[only_bind_into](i)) and
692-
result = getPathTypeArgument(p, pragma[only_bind_into](i))
717+
private TypePath getPathToImplSelfTypeParam(TypeParam tp) {
718+
exists(ImplItemNode impl |
719+
tp = impl.getTypeParam(_) and
720+
TTypeParamTypeParameter(tp) = impl.(Impl).getSelfTy().(TypeMention).getTypeAt(result)
693721
)
694722
}
695723

696724
pragma[nomagic]
697725
private Type getCallExprTypeArgument(CallExpr ce, TypeArgumentPosition apos, TypePath path) {
698-
result = getCallExprTypeMentionArgument(ce, apos).getTypeAt(path)
726+
exists(Path p, ItemNode resolved, TypeParam tp |
727+
p = CallExprImpl::getFunctionPath(ce) and
728+
resolved = resolvePath(p) and
729+
apos.asTypeParam() = tp
730+
|
731+
// For type parameters of the function we must resolve their
732+
// instantiation from the path. For instance, for `fn bar<A>(a: A) -> A`
733+
// and the path `bar<i64>`, we must resolve `A` to `i64`.
734+
exists(int i |
735+
tp = resolved.getTypeParam(pragma[only_bind_into](i)) and
736+
result = getPathTypeArgument(p, pragma[only_bind_into](i)).getTypeAt(path)
737+
)
738+
or
739+
// For type parameters of the `impl` block we must resolve their
740+
// instantiation from the path. For instance, for `impl<A> for Foo<A>`
741+
// and the path `Foo<i64>::bar` we must resolve `A` to `i64`.
742+
exists(ImplItemNode impl, TypePath pathToTp |
743+
resolved = impl.getASuccessor(_) and
744+
tp = impl.getTypeParam(_) and
745+
pathToTp = getPathToImplSelfTypeParam(tp) and
746+
result = p.getQualifier().(TypeMention).getTypeAt(pathToTp.appendInverse(path))
747+
)
748+
)
699749
or
700750
// Handle constructions that use `Self(...)` syntax
701751
exists(Path p, TypePath path0 |
@@ -764,61 +814,6 @@ private TypePath closureParameterPath(int arity, int index) {
764814

765815
/** Module for inferring certain type information. */
766816
private module CertainTypeInferenceInput {
767-
pragma[nomagic]
768-
private predicate callResolvesTo(CallExpr ce, Path p, Function f) {
769-
p = CallExprImpl::getFunctionPath(ce) and
770-
f = resolvePath(p)
771-
}
772-
773-
pragma[nomagic]
774-
private Type getCallExprType(CallExpr ce, Path p, FunctionDeclaration f, TypePath path) {
775-
exists(ImplOrTraitItemNodeOption i |
776-
callResolvesTo(ce, p, f) and
777-
result = f.getReturnType(i, path) and
778-
f.isDirectlyFor(i)
779-
)
780-
}
781-
782-
pragma[nomagic]
783-
private Type getCertainCallExprType(CallExpr ce, Path p, TypePath tp) {
784-
forex(Function f | callResolvesTo(ce, p, f) | result = getCallExprType(ce, p, f, tp))
785-
}
786-
787-
pragma[nomagic]
788-
private TypePath getPathToImplSelfTypeParam(TypeParam tp) {
789-
exists(ImplItemNode impl |
790-
tp = impl.getTypeParam(_) and
791-
TTypeParamTypeParameter(tp) = impl.(Impl).getSelfTy().(TypeMention).getTypeAt(result)
792-
)
793-
}
794-
795-
pragma[nomagic]
796-
private Type inferCertainCallExprType(CallExpr ce, TypePath path) {
797-
exists(Type ty, TypePath prefix, Path p | ty = getCertainCallExprType(ce, p, prefix) |
798-
exists(TypePath suffix, TypeParam tp |
799-
tp = ty.(TypeParamTypeParameter).getTypeParam() and
800-
path = prefix.append(suffix)
801-
|
802-
// For type parameters of the `impl` block we must resolve their
803-
// instantiation from the path. For instance, for `impl<A> for Foo<A>`
804-
// and the path `Foo<i64>::bar` we must resolve `A` to `i64`.
805-
exists(TypePath pathToTp |
806-
pathToTp = getPathToImplSelfTypeParam(tp) and
807-
result = p.getQualifier().(TypeMention).getTypeAt(pathToTp.appendInverse(suffix))
808-
)
809-
or
810-
// For type parameters of the function we must resolve their
811-
// instantiation from the path. For instance, for `fn bar<A>(a: A) -> A`
812-
// and the path `bar<i64>`, we must resolve `A` to `i64`.
813-
result = getCallExprTypeArgument(ce, TTypeParamTypeArgumentPosition(tp), suffix)
814-
)
815-
or
816-
not ty instanceof TypeParameter and
817-
result = ty and
818-
path = prefix
819-
)
820-
}
821-
822817
private Type inferCertainStructExprType(StructExpr se, TypePath path) {
823818
result = se.getPath().(TypeMention).getTypeAt(path)
824819
}
@@ -834,8 +829,6 @@ private module CertainTypeInferenceInput {
834829
Type inferCertainTypeInput(AstNode n, TypePath path) {
835830
result = inferFunctionBodyType(n, path)
836831
or
837-
result = inferCertainCallExprType(n, path)
838-
or
839832
result = inferLiteralType(n, path, true)
840833
or
841834
result = inferRefPatType(n) and
@@ -2612,6 +2605,11 @@ private module FunctionCallMatchingInput implements MatchingWithEnvironmentInput
26122605

26132606
FunctionDeclaration getFunction() { result = f }
26142607

2608+
predicate isFunction(ImplOrTraitItemNodeOption i_, Function f_) {
2609+
i_ = i and
2610+
f_ = f
2611+
}
2612+
26152613
predicate isAssocFunction(ImplOrTraitItemNode i_, Function f_) {
26162614
i_ = i.asSome() and
26172615
f_ = f

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

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2185,8 +2185,8 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
21852185
class AssignExpr extends Assignment;
21862186

21872187
/** A parenthesized expression. */
2188-
class ParenExpr extends AstNode {
2189-
AstNode getExpr();
2188+
class ParenExpr extends Expr {
2189+
Expr getExpr();
21902190
}
21912191

21922192
/** A variable, for example a local variable or a field. */
@@ -2221,6 +2221,29 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
22212221
AstNode getRightOperand();
22222222
}
22232223

2224+
class CallTarget {
2225+
TypeParameter getTypeParameter(TypeParameterPosition ppos);
2226+
2227+
TypeMention getAdditionalTypeParameterConstraint(TypeParameter tp);
2228+
2229+
Type getReturnType(TypePath path);
2230+
2231+
Type getParameterType(int index, TypePath path);
2232+
2233+
/** Gets a textual representation of this element. */
2234+
string toString();
2235+
2236+
/** Gets the location of this element. */
2237+
Location getLocation();
2238+
}
2239+
2240+
class Call extends Expr {
2241+
Type getTypeArgument(TypeArgumentPosition apos, TypePath path);
2242+
2243+
/** Gets the target of this call. */
2244+
CallTarget getTargetCertain();
2245+
}
2246+
22242247
/**
22252248
* Holds if the types of `n1` at `path1` and `n2` at `path2` are certainly equal.
22262249
*/
@@ -2305,6 +2328,32 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
23052328
path.isEmpty()
23062329
}
23072330

2331+
pragma[nomagic]
2332+
private Type getCertainCallExprType(Call call, TypePath path) {
2333+
forex(CallTarget target | target = call.getTargetCertain() |
2334+
result = target.getReturnType(path)
2335+
)
2336+
}
2337+
2338+
pragma[nomagic]
2339+
private Type inferCertainCallExprType(Call call, TypePath path) {
2340+
exists(Type ty, TypePath prefix | ty = getCertainCallExprType(call, prefix) |
2341+
exists(
2342+
CallTarget target, TypePath suffix, TypeParameterPosition tppos,
2343+
TypeArgumentPosition tapos
2344+
|
2345+
ty = target.getTypeParameter(tppos) and
2346+
path = prefix.append(suffix) and
2347+
result = call.getTypeArgument(tapos, suffix) and
2348+
typeArgumentParameterPositionMatch(tapos, tppos)
2349+
)
2350+
or
2351+
not ty instanceof TypeParameter and
2352+
result = ty and
2353+
path = prefix
2354+
)
2355+
}
2356+
23082357
/** Gets the inferred certain type of `n` at `path`. */
23092358
cached
23102359
Type inferCertainType(AstNode n, TypePath path) {
@@ -2317,6 +2366,8 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
23172366
or
23182367
result = inferLogicalOperationType(n, path)
23192368
or
2369+
result = inferCertainCallExprType(n, path)
2370+
or
23202371
infersCertainTypeAt(n, path, result.getATypeParameter())
23212372
}
23222373

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
| context.swift:17:10:17:10 | C<T>.init() | Unexpected result: target=init() |
2+
| context.swift:17:10:17:12 | call to C<T>.init() | Unexpected result: target=init() |
3+
| context.swift:17:14:18:1 | // $ type=C<T>\n | Missing result: type=C<T> |
4+
| context.swift:25:11:25:11 | A.init() | Unexpected result: target=init() |
5+
| context.swift:25:11:25:13 | call to A.init() | Unexpected result: target=init() |
6+
| context.swift:26:19:26:19 | D.init() | Unexpected result: target=init() |
7+
| context.swift:26:19:26:21 | call to D.init() | Unexpected result: target=init() |
8+
| context.swift:26:25:26:25 | B.init() | Unexpected result: target=init() |
9+
| context.swift:26:25:26:27 | call to B.init() | Unexpected result: target=init() |
10+
| file://:0:0:0:0 | A.init() | Unexpected result: target=init() |
11+
| file://:0:0:0:0 | call to A.init() | Unexpected result: target=init() |

0 commit comments

Comments
 (0)