Skip to content

Commit 1828d40

Browse files
authored
Merge pull request #19549 from paldepind/rust/type-inference-operators
Rust: Type inference for non-overloadable operators
2 parents 7ee1bd6 + 666726c commit 1828d40

File tree

4 files changed

+82
-6
lines changed

4 files changed

+82
-6
lines changed

rust/ql/lib/codeql/rust/internal/Type.qll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ private import codeql.rust.elements.internal.generated.Synth
99

1010
cached
1111
newtype TType =
12+
TUnit() or
1213
TStruct(Struct s) { Stages::TypeInferenceStage::ref() } or
1314
TEnum(Enum e) or
1415
TTrait(Trait t) or
@@ -48,6 +49,21 @@ abstract class Type extends TType {
4849
abstract Location getLocation();
4950
}
5051

52+
/** The unit type `()`. */
53+
class UnitType extends Type, TUnit {
54+
UnitType() { this = TUnit() }
55+
56+
override StructField getStructField(string name) { none() }
57+
58+
override TupleField getTupleField(int i) { none() }
59+
60+
override TypeParameter getTypeParameter(int i) { none() }
61+
62+
override string toString() { result = "()" }
63+
64+
override Location getLocation() { result instanceof EmptyLocation }
65+
}
66+
5167
abstract private class StructOrEnumType extends Type {
5268
abstract ItemNode asItemNode();
5369
}

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

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ private import Type as T
77
private import TypeMention
88
private import codeql.typeinference.internal.TypeInference
99
private import codeql.rust.frameworks.stdlib.Stdlib
10+
private import codeql.rust.frameworks.stdlib.Bultins as Builtins
1011

1112
class Type = T::Type;
1213

@@ -190,6 +191,21 @@ private Type inferAnnotatedType(AstNode n, TypePath path) {
190191
result = getTypeAnnotation(n).resolveTypeAt(path)
191192
}
192193

194+
private Type inferLogicalOperationType(AstNode n, TypePath path) {
195+
exists(Builtins::BuiltinType t, BinaryLogicalOperation be |
196+
n = [be, be.getLhs(), be.getRhs()] and
197+
path.isEmpty() and
198+
result = TStruct(t) and
199+
t instanceof Builtins::Bool
200+
)
201+
}
202+
203+
private Type inferAssignmentOperationType(AstNode n, TypePath path) {
204+
n instanceof AssignmentOperation and
205+
path.isEmpty() and
206+
result = TUnit()
207+
}
208+
193209
/**
194210
* Holds if the type of `n1` at `path1` is the same as the type of `n2` at
195211
* `path2` and type information should propagate in both directions through the
@@ -237,6 +253,12 @@ private predicate typeEquality(AstNode n1, TypePath path1, AstNode n2, TypePath
237253
break.getTarget() = n2.(LoopExpr) and
238254
path1 = path2
239255
)
256+
or
257+
exists(AssignmentExpr be |
258+
n1 = be.getLhs() and
259+
n2 = be.getRhs() and
260+
path1 = path2
261+
)
240262
}
241263

242264
pragma[nomagic]
@@ -932,8 +954,6 @@ private Type inferTryExprType(TryExpr te, TypePath path) {
932954
)
933955
}
934956

935-
private import codeql.rust.frameworks.stdlib.Bultins as Builtins
936-
937957
pragma[nomagic]
938958
private StructType inferLiteralType(LiteralExpr le) {
939959
exists(Builtins::BuiltinType t | result = TStruct(t) |
@@ -1156,6 +1176,10 @@ private module Cached {
11561176
Stages::TypeInferenceStage::ref() and
11571177
result = inferAnnotatedType(n, path)
11581178
or
1179+
result = inferLogicalOperationType(n, path)
1180+
or
1181+
result = inferAssignmentOperationType(n, path)
1182+
or
11591183
result = inferTypeEquality(n, path)
11601184
or
11611185
result = inferImplicitSelfType(n, path)

rust/ql/test/library-tests/type-inference/main.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,6 +1224,21 @@ mod builtins {
12241224
}
12251225
}
12261226

1227+
mod operators {
1228+
pub fn f() {
1229+
let x = true && false; // $ type=x:bool
1230+
let y = true || false; // $ type=y:bool
1231+
1232+
let mut a;
1233+
if 34 == 33 {
1234+
let z = (a = 1); // $ type=z:() type=a:i32
1235+
} else {
1236+
a = 2; // $ type=a:i32
1237+
}
1238+
a; // $ type=a:i32
1239+
}
1240+
}
1241+
12271242
fn main() {
12281243
field_access::f();
12291244
method_impl::f();
@@ -1242,4 +1257,5 @@ fn main() {
12421257
borrowed_typed::f();
12431258
try_expressions::f();
12441259
builtins::f();
1260+
operators::f();
12451261
}

rust/ql/test/library-tests/type-inference/type-inference.expected

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,7 +1581,27 @@ inferType
15811581
| main.rs:1222:17:1222:20 | true | | file:///BUILTINS/types.rs:3:1:5:16 | bool |
15821582
| main.rs:1223:13:1223:13 | f | | file:///BUILTINS/types.rs:3:1:5:16 | bool |
15831583
| main.rs:1223:17:1223:21 | false | | file:///BUILTINS/types.rs:3:1:5:16 | bool |
1584-
| main.rs:1229:5:1229:20 | ...::f(...) | | main.rs:67:5:67:21 | Foo |
1585-
| main.rs:1230:5:1230:60 | ...::g(...) | | main.rs:67:5:67:21 | Foo |
1586-
| main.rs:1230:20:1230:38 | ...::Foo {...} | | main.rs:67:5:67:21 | Foo |
1587-
| main.rs:1230:41:1230:59 | ...::Foo {...} | | main.rs:67:5:67:21 | Foo |
1584+
| main.rs:1229:13:1229:13 | x | | file:///BUILTINS/types.rs:3:1:5:16 | bool |
1585+
| main.rs:1229:17:1229:20 | true | | file:///BUILTINS/types.rs:3:1:5:16 | bool |
1586+
| main.rs:1229:17:1229:29 | ... && ... | | file:///BUILTINS/types.rs:3:1:5:16 | bool |
1587+
| main.rs:1229:25:1229:29 | false | | file:///BUILTINS/types.rs:3:1:5:16 | bool |
1588+
| main.rs:1230:13:1230:13 | y | | file:///BUILTINS/types.rs:3:1:5:16 | bool |
1589+
| main.rs:1230:17:1230:20 | true | | file:///BUILTINS/types.rs:3:1:5:16 | bool |
1590+
| main.rs:1230:17:1230:29 | ... \|\| ... | | file:///BUILTINS/types.rs:3:1:5:16 | bool |
1591+
| main.rs:1230:25:1230:29 | false | | file:///BUILTINS/types.rs:3:1:5:16 | bool |
1592+
| main.rs:1232:13:1232:17 | mut a | | file:///BUILTINS/types.rs:12:1:12:15 | i32 |
1593+
| main.rs:1233:12:1233:13 | 34 | | file:///BUILTINS/types.rs:12:1:12:15 | i32 |
1594+
| main.rs:1233:18:1233:19 | 33 | | file:///BUILTINS/types.rs:12:1:12:15 | i32 |
1595+
| main.rs:1234:17:1234:17 | z | | file://:0:0:0:0 | () |
1596+
| main.rs:1234:21:1234:27 | (...) | | file://:0:0:0:0 | () |
1597+
| main.rs:1234:22:1234:22 | a | | file:///BUILTINS/types.rs:12:1:12:15 | i32 |
1598+
| main.rs:1234:22:1234:26 | ... = ... | | file://:0:0:0:0 | () |
1599+
| main.rs:1234:26:1234:26 | 1 | | file:///BUILTINS/types.rs:12:1:12:15 | i32 |
1600+
| main.rs:1236:13:1236:13 | a | | file:///BUILTINS/types.rs:12:1:12:15 | i32 |
1601+
| main.rs:1236:13:1236:17 | ... = ... | | file://:0:0:0:0 | () |
1602+
| main.rs:1236:17:1236:17 | 2 | | file:///BUILTINS/types.rs:12:1:12:15 | i32 |
1603+
| main.rs:1238:9:1238:9 | a | | file:///BUILTINS/types.rs:12:1:12:15 | i32 |
1604+
| main.rs:1244:5:1244:20 | ...::f(...) | | main.rs:67:5:67:21 | Foo |
1605+
| main.rs:1245:5:1245:60 | ...::g(...) | | main.rs:67:5:67:21 | Foo |
1606+
| main.rs:1245:20:1245:38 | ...::Foo {...} | | main.rs:67:5:67:21 | Foo |
1607+
| main.rs:1245:41:1245:59 | ...::Foo {...} | | main.rs:67:5:67:21 | Foo |

0 commit comments

Comments
 (0)