Skip to content

Commit 3696436

Browse files
committed
wip6
1 parent f2fea03 commit 3696436

3 files changed

Lines changed: 136 additions & 73 deletions

File tree

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

Lines changed: 72 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,43 @@ private module Input3 implements InputSig3 {
372366
override AstNode getRightOperand() { result = this.getInitializer() }
373367
}
374368

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

688719
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))
720+
private TypePath getPathToImplSelfTypeParam(TypeParam tp) {
721+
exists(ImplItemNode impl |
722+
tp = impl.getTypeParam(_) and
723+
TTypeParamTypeParameter(tp) = impl.(Impl).getSelfTy().(TypeMention).getTypeAt(result)
693724
)
694725
}
695726

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

765818
/** Module for inferring certain type information. */
766819
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-
822820
private Type inferCertainStructExprType(StructExpr se, TypePath path) {
823821
result = se.getPath().(TypeMention).getTypeAt(path)
824822
}
@@ -834,8 +832,6 @@ private module CertainTypeInferenceInput {
834832
Type inferCertainTypeInput(AstNode n, TypePath path) {
835833
result = inferFunctionBodyType(n, path)
836834
or
837-
result = inferCertainCallExprType(n, path)
838-
or
839835
result = inferLiteralType(n, path, true)
840836
or
841837
result = inferRefPatType(n) and
@@ -2612,6 +2608,11 @@ private module FunctionCallMatchingInput implements MatchingWithEnvironmentInput
26122608

26132609
FunctionDeclaration getFunction() { result = f }
26142610

2611+
predicate isFunction(ImplOrTraitItemNodeOption i_, Function f_) {
2612+
i_ = i and
2613+
f_ = f
2614+
}
2615+
26152616
predicate isAssocFunction(ImplOrTraitItemNode i_, Function f_) {
26162617
i_ = i.asSome() and
26172618
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)