Skip to content

Commit

Permalink
wip2
Browse files Browse the repository at this point in the history
  • Loading branch information
hvitved committed Feb 13, 2025
1 parent be8d58e commit 486f813
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 7 deletions.
96 changes: 95 additions & 1 deletion rust/ql/lib/codeql/rust/elements/internal/TypeInference.qll
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,100 @@ private Type resolveMethodCallExprType(MethodCallExpr mce, TypePath path) {
)
}

private module FieldExprMatchingInput implements MatchingInputSig {
abstract class Decl extends AstNode {
TypeParameter getTypeParameter(int i) { none() }

abstract TypeRepr getTypeRepr();
}

private class RecordFieldDecl extends Decl instanceof RecordField {
override TypeRepr getTypeRepr() { result = RecordField.super.getTypeRepr() }
}

private class TupleFieldDecl extends Decl instanceof TupleField {
override TypeRepr getTypeRepr() { result = TupleField.super.getTypeRepr() }
}

class Access extends FieldExpr {
Type getTypeArgument(int i, TypePath path) { none() }

predicate noExplicitTypeArguments() { any() }
}

predicate target(Access a, Decl target) {
exists(Type t, Type lookupType, string name |
t = resolveType(a.getExpr()) and
name = a.getNameRef().getText() and
if t = TRefType()
then
// for reference types, lookup the field in the type being referenced
lookupType = resolveType(a.getExpr(), "0")
else lookupType = t
|
target = lookupType.getRecordField(name)
or
target = lookupType.getTupleField(name.toInt())
)
}

class Pos = int;

Pos getReturnPos() { result = -2 }

private AstNode getExplicitArgument(Access a, Pos pos) { result = a.getExpr() and pos = -1 }

private predicate explicitArgumentType(Access a, Pos pos, TypePath path, Type t) {
t = resolveType(getExplicitArgument(a, pos), path)
}

predicate argumentType(Access a, Pos pos, TypePath path, Type t) {
explicitArgumentType(a, pos, path, t)
// or
// implicitThis(a, pos, path, t)
}

pragma[nomagic]
predicate argumentIsTargetTyped(Access a, Pos pos) { isTargetTyped(getExplicitArgument(a, pos)) }

pragma[nomagic]
predicate argumentIsNotTargetTyped(Access a, Pos pos) {
exists(AstNode arg |
arg = getExplicitArgument(a, pos) and
not isTargetTyped(arg)
)
// or
// implicitThis(a, pos, _, _)
}

predicate parameterType(Decl decl, Pos pos, TypePath path, Type t) {
pos = -1 and
exists(Struct s | s.getRecordField(_) = decl or s.getTupleField(_) = decl |
t = TStruct(s) and
path.isEmpty()
or
exists(int i |
t = TTypeParameter(s.getGenericParamList().getTypeParam(i)) and
path = typePath(i)
)
)
}

pragma[nomagic]
predicate declType(Decl decl, TypePath path, Type t) {
t = decl.getTypeRepr().(TypeRepr_).resolveTypeAt(path)
}
}

private module FieldExprMatching = Matching<FieldExprMatchingInput>;

private Type resolveFieldExprType(FieldExpr fe, TypePath path) {
result = resolveFieldExprType0(fe, path)
or
// result = resolveFunctionReturnType(call.getStaticTarget(), path)
result = FieldExprMatching::resolveAccess(fe, -2, path)
}

pragma[nomagic]
RecordField resolveRecordFieldExpr(FieldExpr fe) {
exists(Type t, string name |
Expand Down Expand Up @@ -1035,7 +1129,7 @@ TupleField resolveTupleFieldExpr(FieldExpr fe) {
}

pragma[nomagic]
private Type resolveFieldExprType(FieldExpr fe, TypePath path) {
private Type resolveFieldExprType0(FieldExpr fe, TypePath path) {
exists(RecordField f |
f = resolveRecordFieldExpr(fe) and
result = f.getTypeRepr().(TypeRepr_).resolveTypeAt(path) and
Expand Down
12 changes: 6 additions & 6 deletions rust/ql/test/library-tests/type-inference/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,19 @@ mod m2 {

impl MyThing<S1> {
fn m1(self) -> S1 {
self.a // `self.a` missing type
self.a
}
}

impl MyThing<S2> {
fn m1(self) -> Self {
Self { a: self.a } // `self.a` missing type
Self { a: self.a }
}
}

impl<T> MyThing<T> {
fn m2(self) -> T {
self.a // `self.a` missing type
self.a
}
}

Expand Down Expand Up @@ -97,13 +97,13 @@ mod m3 {

impl MyTrait<S1> for MyThing<S1> {
fn m1(self) -> S1 {
self.a // `self.a` missing type
self.a
}
}

impl MyTrait<Self> for MyThing<S2> {
fn m1(self) -> Self {
Self { a: self.a } // `self.a` missing type, `Self` missing type at path 0
Self { a: self.a }
}
}

Expand Down Expand Up @@ -150,7 +150,7 @@ mod m4 {

impl<T> MyTrait<T> for MyThing<T> {
fn m1(self) -> T {
self.a // `self.a` missing type
self.a
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,19 @@
| main.rs:40:15:40:18 | SelfParam | 0 | main.rs:34:5:35:14 | struct S1 |
| main.rs:41:13:41:16 | self | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:41:13:41:16 | self | 0 | main.rs:34:5:35:14 | struct S1 |
| main.rs:41:13:41:18 | self.a | | main.rs:34:5:35:14 | struct S1 |
| main.rs:46:15:46:18 | SelfParam | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:46:15:46:18 | SelfParam | 0 | main.rs:36:5:37:14 | struct S2 |
| main.rs:47:13:47:30 | Self {...} | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:47:13:47:30 | Self {...} | 0 | main.rs:36:5:37:14 | struct S2 |
| main.rs:47:23:47:26 | self | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:47:23:47:26 | self | 0 | main.rs:36:5:37:14 | struct S2 |
| main.rs:47:23:47:28 | self.a | | main.rs:36:5:37:14 | struct S2 |
| main.rs:52:15:52:18 | SelfParam | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:52:15:52:18 | SelfParam | 0 | main.rs:51:10:51:10 | T |
| main.rs:53:13:53:16 | self | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:53:13:53:16 | self | 0 | main.rs:51:10:51:10 | T |
| main.rs:53:13:53:18 | self.a | | main.rs:51:10:51:10 | T |
| main.rs:58:13:58:13 | x | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:58:13:58:13 | x | 0 | main.rs:34:5:35:14 | struct S1 |
| main.rs:58:17:58:33 | MyThing {...} | | main.rs:29:5:32:5 | struct MyThing |
Expand Down Expand Up @@ -64,11 +68,14 @@
| main.rs:99:15:99:18 | SelfParam | 0 | main.rs:78:5:79:14 | struct S1 |
| main.rs:100:13:100:16 | self | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:100:13:100:16 | self | 0 | main.rs:78:5:79:14 | struct S1 |
| main.rs:100:13:100:18 | self.a | | main.rs:78:5:79:14 | struct S1 |
| main.rs:105:15:105:18 | SelfParam | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:105:15:105:18 | SelfParam | 0 | main.rs:80:5:81:14 | struct S2 |
| main.rs:106:13:106:30 | Self {...} | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:106:13:106:30 | Self {...} | 0 | main.rs:80:5:81:14 | struct S2 |
| main.rs:106:23:106:26 | self | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:106:23:106:26 | self | 0 | main.rs:80:5:81:14 | struct S2 |
| main.rs:106:23:106:28 | self.a | | main.rs:80:5:81:14 | struct S2 |
| main.rs:111:13:111:13 | x | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:111:13:111:13 | x | 0 | main.rs:78:5:79:14 | struct S1 |
| main.rs:111:17:111:33 | MyThing {...} | | main.rs:73:5:76:5 | struct MyThing |
Expand Down Expand Up @@ -107,6 +114,7 @@
| main.rs:152:15:152:18 | SelfParam | 0 | main.rs:151:10:151:10 | T |
| main.rs:153:13:153:16 | self | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:153:13:153:16 | self | 0 | main.rs:151:10:151:10 | T |
| main.rs:153:13:153:18 | self.a | | main.rs:151:10:151:10 | T |
| main.rs:158:13:158:13 | x | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:158:13:158:13 | x | 0 | main.rs:131:5:132:14 | struct S1 |
| main.rs:158:17:158:33 | MyThing {...} | | main.rs:126:5:129:5 | struct MyThing |
Expand Down

0 comments on commit 486f813

Please sign in to comment.