diff --git a/rust/ql/lib/codeql/rust/internal/Type.qll b/rust/ql/lib/codeql/rust/internal/Type.qll index 9ffbf0614635..bb698236debc 100644 --- a/rust/ql/lib/codeql/rust/internal/Type.qll +++ b/rust/ql/lib/codeql/rust/internal/Type.qll @@ -9,6 +9,7 @@ private import codeql.rust.elements.internal.generated.Synth cached newtype TType = + TUnit() or TStruct(Struct s) { Stages::TypeInferenceStage::ref() } or TEnum(Enum e) or TTrait(Trait t) or @@ -48,6 +49,21 @@ abstract class Type extends TType { abstract Location getLocation(); } +/** The unit type `()`. */ +class UnitType extends Type, TUnit { + UnitType() { this = TUnit() } + + override StructField getStructField(string name) { none() } + + override TupleField getTupleField(int i) { none() } + + override TypeParameter getTypeParameter(int i) { none() } + + override string toString() { result = "()" } + + override Location getLocation() { result instanceof EmptyLocation } +} + abstract private class StructOrEnumType extends Type { abstract ItemNode asItemNode(); } diff --git a/rust/ql/lib/codeql/rust/internal/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/TypeInference.qll index 278d9ebc3176..c13d80c2d198 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeInference.qll @@ -7,6 +7,7 @@ private import Type as T private import TypeMention private import codeql.typeinference.internal.TypeInference private import codeql.rust.frameworks.stdlib.Stdlib +private import codeql.rust.frameworks.stdlib.Bultins as Builtins class Type = T::Type; @@ -190,6 +191,21 @@ private Type inferAnnotatedType(AstNode n, TypePath path) { result = getTypeAnnotation(n).resolveTypeAt(path) } +private Type inferLogicalOperationType(AstNode n, TypePath path) { + exists(Builtins::BuiltinType t, BinaryLogicalOperation be | + n = [be, be.getLhs(), be.getRhs()] and + path.isEmpty() and + result = TStruct(t) and + t instanceof Builtins::Bool + ) +} + +private Type inferAssignmentOperationType(AstNode n, TypePath path) { + n instanceof AssignmentOperation and + path.isEmpty() and + result = TUnit() +} + /** * Holds if the type of `n1` at `path1` is the same as the type of `n2` at * `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 break.getTarget() = n2.(LoopExpr) and path1 = path2 ) + or + exists(AssignmentExpr be | + n1 = be.getLhs() and + n2 = be.getRhs() and + path1 = path2 + ) } pragma[nomagic] @@ -932,8 +954,6 @@ private Type inferTryExprType(TryExpr te, TypePath path) { ) } -private import codeql.rust.frameworks.stdlib.Bultins as Builtins - pragma[nomagic] private StructType inferLiteralType(LiteralExpr le) { exists(Builtins::BuiltinType t | result = TStruct(t) | @@ -1156,6 +1176,10 @@ private module Cached { Stages::TypeInferenceStage::ref() and result = inferAnnotatedType(n, path) or + result = inferLogicalOperationType(n, path) + or + result = inferAssignmentOperationType(n, path) + or result = inferTypeEquality(n, path) or result = inferImplicitSelfType(n, path) diff --git a/rust/ql/test/library-tests/type-inference/main.rs b/rust/ql/test/library-tests/type-inference/main.rs index 7ac5710b7a1a..b33010e7b83c 100644 --- a/rust/ql/test/library-tests/type-inference/main.rs +++ b/rust/ql/test/library-tests/type-inference/main.rs @@ -1224,6 +1224,21 @@ mod builtins { } } +mod operators { + pub fn f() { + let x = true && false; // $ type=x:bool + let y = true || false; // $ type=y:bool + + let mut a; + if 34 == 33 { + let z = (a = 1); // $ type=z:() type=a:i32 + } else { + a = 2; // $ type=a:i32 + } + a; // $ type=a:i32 + } +} + fn main() { field_access::f(); method_impl::f(); @@ -1242,4 +1257,5 @@ fn main() { borrowed_typed::f(); try_expressions::f(); builtins::f(); + operators::f(); } diff --git a/rust/ql/test/library-tests/type-inference/type-inference.expected b/rust/ql/test/library-tests/type-inference/type-inference.expected index b91a839b5ab9..b8b52cf4b50c 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.expected +++ b/rust/ql/test/library-tests/type-inference/type-inference.expected @@ -1581,7 +1581,27 @@ inferType | main.rs:1222:17:1222:20 | true | | file:///BUILTINS/types.rs:3:1:5:16 | bool | | main.rs:1223:13:1223:13 | f | | file:///BUILTINS/types.rs:3:1:5:16 | bool | | main.rs:1223:17:1223:21 | false | | file:///BUILTINS/types.rs:3:1:5:16 | bool | -| main.rs:1229:5:1229:20 | ...::f(...) | | main.rs:67:5:67:21 | Foo | -| main.rs:1230:5:1230:60 | ...::g(...) | | main.rs:67:5:67:21 | Foo | -| main.rs:1230:20:1230:38 | ...::Foo {...} | | main.rs:67:5:67:21 | Foo | -| main.rs:1230:41:1230:59 | ...::Foo {...} | | main.rs:67:5:67:21 | Foo | +| main.rs:1229:13:1229:13 | x | | file:///BUILTINS/types.rs:3:1:5:16 | bool | +| main.rs:1229:17:1229:20 | true | | file:///BUILTINS/types.rs:3:1:5:16 | bool | +| main.rs:1229:17:1229:29 | ... && ... | | file:///BUILTINS/types.rs:3:1:5:16 | bool | +| main.rs:1229:25:1229:29 | false | | file:///BUILTINS/types.rs:3:1:5:16 | bool | +| main.rs:1230:13:1230:13 | y | | file:///BUILTINS/types.rs:3:1:5:16 | bool | +| main.rs:1230:17:1230:20 | true | | file:///BUILTINS/types.rs:3:1:5:16 | bool | +| main.rs:1230:17:1230:29 | ... \|\| ... | | file:///BUILTINS/types.rs:3:1:5:16 | bool | +| main.rs:1230:25:1230:29 | false | | file:///BUILTINS/types.rs:3:1:5:16 | bool | +| main.rs:1232:13:1232:17 | mut a | | file:///BUILTINS/types.rs:12:1:12:15 | i32 | +| main.rs:1233:12:1233:13 | 34 | | file:///BUILTINS/types.rs:12:1:12:15 | i32 | +| main.rs:1233:18:1233:19 | 33 | | file:///BUILTINS/types.rs:12:1:12:15 | i32 | +| main.rs:1234:17:1234:17 | z | | file://:0:0:0:0 | () | +| main.rs:1234:21:1234:27 | (...) | | file://:0:0:0:0 | () | +| main.rs:1234:22:1234:22 | a | | file:///BUILTINS/types.rs:12:1:12:15 | i32 | +| main.rs:1234:22:1234:26 | ... = ... | | file://:0:0:0:0 | () | +| main.rs:1234:26:1234:26 | 1 | | file:///BUILTINS/types.rs:12:1:12:15 | i32 | +| main.rs:1236:13:1236:13 | a | | file:///BUILTINS/types.rs:12:1:12:15 | i32 | +| main.rs:1236:13:1236:17 | ... = ... | | file://:0:0:0:0 | () | +| main.rs:1236:17:1236:17 | 2 | | file:///BUILTINS/types.rs:12:1:12:15 | i32 | +| main.rs:1238:9:1238:9 | a | | file:///BUILTINS/types.rs:12:1:12:15 | i32 | +| main.rs:1244:5:1244:20 | ...::f(...) | | main.rs:67:5:67:21 | Foo | +| main.rs:1245:5:1245:60 | ...::g(...) | | main.rs:67:5:67:21 | Foo | +| main.rs:1245:20:1245:38 | ...::Foo {...} | | main.rs:67:5:67:21 | Foo | +| main.rs:1245:41:1245:59 | ...::Foo {...} | | main.rs:67:5:67:21 | Foo |