From 84accd1c81846043ea1c42816f36b259ef99de97 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Fri, 20 Jun 2025 16:12:53 +0200 Subject: [PATCH 1/4] Rust: Implement overloaded index expression in type inference --- .../rust/dataflow/internal/DataFlowImpl.qll | 6 +- .../rust/elements/internal/CallImpl.qll | 16 ++++ .../codeql/rust/internal/TypeInference.qll | 77 ++++++++++--------- .../test/library-tests/type-inference/main.rs | 8 +- .../type-inference/type-inference.expected | 73 ++---------------- 5 files changed, 69 insertions(+), 111 deletions(-) diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll index 59ff2fc24c22..20c9e80b87aa 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll @@ -959,7 +959,11 @@ private module Cached { cached newtype TDataFlowCall = - TCall(CallCfgNode c) { Stages::DataFlowStage::ref() } or + TCall(CallCfgNode c) { + Stages::DataFlowStage::ref() and + // TODO: Handle index expressions as calls in data flow. + not c.getCall() instanceof IndexExpr + } or TSummaryCall( FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver ) { diff --git a/rust/ql/lib/codeql/rust/elements/internal/CallImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/CallImpl.qll index f350e88efad8..9cd45ca76709 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/CallImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/CallImpl.qll @@ -160,4 +160,20 @@ module Impl { pos.asPosition() = 0 and result = super.getOperand(1) } } + + private class IndexCall extends Call instanceof IndexExpr { + override string getMethodName() { result = "index" } + + override Trait getTrait() { result.getCanonicalPath() = "core::ops::index::Index" } + + override predicate implicitBorrowAt(ArgumentPosition pos, boolean certain) { + pos.isSelf() and certain = true + } + + override Expr getArgument(ArgumentPosition pos) { + pos.isSelf() and result = super.getBase() + or + pos.asPosition() = 0 and result = super.getIndex() + } + } } diff --git a/rust/ql/lib/codeql/rust/internal/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/TypeInference.qll index b560ac5ec8c1..04cb6b2c4840 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeInference.qll @@ -772,45 +772,48 @@ private Type inferCallExprBaseType(AstNode n, TypePath path) { n = a.getNodeAt(apos) and result = CallExprBaseMatching::inferAccessType(a, apos, path0) | - ( + if apos.isBorrowed(true) or - // The desugaring of the unary `*e` is `*Deref::deref(&e)`. To handle the - // deref expression after the call we must strip a `&` from the type at - // the return position. - apos.isReturn() and a instanceof DerefExpr - ) and - path0.isCons(TRefTypeParameter(), path) - or - apos.isBorrowed(false) and - exists(Type argType | argType = inferType(n) | - if argType = TRefType() + // The desugaring of the unary `*e` is `*Deref::deref(&e)` and the + // desugaring of `a[b]` is `*Index::index(&a, b)`. To handle the deref + // expression after the call we must strip a `&` from the type at the + // return position. + apos.isReturn() and + (a instanceof DerefExpr or a instanceof IndexExpr) + then path0.isCons(TRefTypeParameter(), path) + else + if apos.isBorrowed(false) then - path = path0 and - path0.isCons(TRefTypeParameter(), _) - or - // adjust for implicit deref - not path0.isCons(TRefTypeParameter(), _) and - not (path0.isEmpty() and result = TRefType()) and - path = TypePath::cons(TRefTypeParameter(), path0) - else ( - not ( - argType.(StructType).asItemNode() instanceof StringStruct and - result.(StructType).asItemNode() instanceof Builtins::Str - ) and - ( - not path0.isCons(TRefTypeParameter(), _) and - not (path0.isEmpty() and result = TRefType()) and - path = path0 - or - // adjust for implicit borrow - path0.isCons(TRefTypeParameter(), path) + exists(Type argType | argType = inferType(n) | + if argType = TRefType() + then + path = path0 and + path0.isCons(TRefTypeParameter(), _) + or + // adjust for implicit deref + not path0.isCons(TRefTypeParameter(), _) and + not (path0.isEmpty() and result = TRefType()) and + path = TypePath::cons(TRefTypeParameter(), path0) + else ( + not ( + argType.(StructType).asItemNode() instanceof StringStruct and + result.(StructType).asItemNode() instanceof Builtins::Str + ) and + ( + not path0.isCons(TRefTypeParameter(), _) and + not (path0.isEmpty() and result = TRefType()) and + path = path0 + or + // adjust for implicit borrow + path0.isCons(TRefTypeParameter(), path) + ) + ) ) + else ( + not apos.isBorrowed(_) and + path = path0 ) - ) - or - not apos.isBorrowed(_) and - path = path0 ) } @@ -1116,8 +1119,8 @@ private class Vec extends Struct { */ pragma[nomagic] private Type inferIndexExprType(IndexExpr ie, TypePath path) { - // TODO: Should be implemented as method resolution, using the special - // `std::ops::Index` trait. + // TODO: Method resolution to the `std::ops::Index` trait can handle the + // `Index` instances for slices and arrays. exists(TypePath exprPath, Builtins::BuiltinType t | TStruct(t) = inferType(ie.getIndex()) and ( @@ -1129,8 +1132,6 @@ private Type inferIndexExprType(IndexExpr ie, TypePath path) { ) and result = inferType(ie.getBase(), exprPath) | - exprPath.isCons(any(Vec v).getElementTypeParameter(), path) - or exprPath.isCons(any(ArrayTypeParameter tp), path) or exists(TypePath path0 | diff --git a/rust/ql/test/library-tests/type-inference/main.rs b/rust/ql/test/library-tests/type-inference/main.rs index 109581588a58..a963e2e0edc8 100644 --- a/rust/ql/test/library-tests/type-inference/main.rs +++ b/rust/ql/test/library-tests/type-inference/main.rs @@ -1856,21 +1856,21 @@ mod indexers { // MyVec::index fn index(&self, index: usize) -> &Self::Output { - &self.data[index] // $ fieldof=MyVec + &self.data[index] // $ fieldof=MyVec method=index } } fn analyze_slice(slice: &[S]) { - let x = slice[0].foo(); // $ method=foo type=x:S + let x = slice[0].foo(); // $ method=foo type=x:S method=index } pub fn f() { let mut vec = MyVec::new(); // $ type=vec:T.S vec.push(S); // $ method=push - vec[0].foo(); // $ MISSING: method=foo -- type inference does not support the `Index` trait yet + vec[0].foo(); // $ method=MyVec::index method=foo let xs: [S; 1] = [S]; - let x = xs[0].foo(); // $ method=foo type=x:S + let x = xs[0].foo(); // $ method=foo type=x:S method=index analyze_slice(&xs); } 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 3a628ac5c962..35df5930a5cc 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.expected +++ b/rust/ql/test/library-tests/type-inference/type-inference.expected @@ -31,23 +31,15 @@ inferType | dereference.rs:36:14:36:42 | MyIntPointer {...} | | dereference.rs:4:1:6:1 | MyIntPointer | | dereference.rs:36:36:36:40 | 34i64 | | {EXTERNAL LOCATION} | i64 | | dereference.rs:37:9:37:11 | _b2 | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:37:9:37:11 | _b2 | | file://:0:0:0:0 | & | -| dereference.rs:37:9:37:11 | _b2 | &T | {EXTERNAL LOCATION} | i64 | | dereference.rs:37:15:37:17 | * ... | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:37:15:37:17 | * ... | | file://:0:0:0:0 | & | -| dereference.rs:37:15:37:17 | * ... | &T | {EXTERNAL LOCATION} | i64 | | dereference.rs:37:16:37:17 | a2 | | dereference.rs:4:1:6:1 | MyIntPointer | | dereference.rs:40:9:40:10 | a3 | | dereference.rs:4:1:6:1 | MyIntPointer | | dereference.rs:40:14:40:42 | MyIntPointer {...} | | dereference.rs:4:1:6:1 | MyIntPointer | | dereference.rs:40:36:40:40 | 34i64 | | {EXTERNAL LOCATION} | i64 | | dereference.rs:41:9:41:11 | _b3 | | {EXTERNAL LOCATION} | bool | | dereference.rs:41:15:41:19 | (...) | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:41:15:41:19 | (...) | | file://:0:0:0:0 | & | -| dereference.rs:41:15:41:19 | (...) | &T | {EXTERNAL LOCATION} | i64 | | dereference.rs:41:15:41:33 | ... .is_positive() | | {EXTERNAL LOCATION} | bool | | dereference.rs:41:16:41:18 | * ... | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:41:16:41:18 | * ... | | file://:0:0:0:0 | & | -| dereference.rs:41:16:41:18 | * ... | &T | {EXTERNAL LOCATION} | i64 | | dereference.rs:41:17:41:18 | a3 | | dereference.rs:4:1:6:1 | MyIntPointer | | dereference.rs:46:9:46:10 | c1 | | dereference.rs:17:1:19:1 | MySmartPointer | | dereference.rs:46:9:46:10 | c1 | T | {EXTERNAL LOCATION} | char | @@ -66,11 +58,7 @@ inferType | dereference.rs:50:14:50:42 | MySmartPointer {...} | T | {EXTERNAL LOCATION} | char | | dereference.rs:50:38:50:40 | 'a' | | {EXTERNAL LOCATION} | char | | dereference.rs:51:9:51:11 | _d2 | | {EXTERNAL LOCATION} | char | -| dereference.rs:51:9:51:11 | _d2 | | file://:0:0:0:0 | & | -| dereference.rs:51:9:51:11 | _d2 | &T | {EXTERNAL LOCATION} | char | | dereference.rs:51:15:51:17 | * ... | | {EXTERNAL LOCATION} | char | -| dereference.rs:51:15:51:17 | * ... | | file://:0:0:0:0 | & | -| dereference.rs:51:15:51:17 | * ... | &T | {EXTERNAL LOCATION} | char | | dereference.rs:51:16:51:17 | c2 | | dereference.rs:17:1:19:1 | MySmartPointer | | dereference.rs:51:16:51:17 | c2 | T | {EXTERNAL LOCATION} | char | | dereference.rs:54:9:54:10 | c3 | | dereference.rs:17:1:19:1 | MySmartPointer | @@ -80,12 +68,8 @@ inferType | dereference.rs:54:38:54:42 | 34i64 | | {EXTERNAL LOCATION} | i64 | | dereference.rs:55:9:55:11 | _d3 | | {EXTERNAL LOCATION} | bool | | dereference.rs:55:15:55:19 | (...) | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:55:15:55:19 | (...) | | file://:0:0:0:0 | & | -| dereference.rs:55:15:55:19 | (...) | &T | {EXTERNAL LOCATION} | i64 | | dereference.rs:55:15:55:33 | ... .is_positive() | | {EXTERNAL LOCATION} | bool | | dereference.rs:55:16:55:18 | * ... | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:55:16:55:18 | * ... | | file://:0:0:0:0 | & | -| dereference.rs:55:16:55:18 | * ... | &T | {EXTERNAL LOCATION} | i64 | | dereference.rs:55:17:55:18 | c3 | | dereference.rs:17:1:19:1 | MySmartPointer | | dereference.rs:55:17:55:18 | c3 | T | {EXTERNAL LOCATION} | i64 | | dereference.rs:60:9:60:10 | e1 | | file://:0:0:0:0 | & | @@ -107,11 +91,7 @@ inferType | dereference.rs:64:14:64:17 | &'a' | &T | {EXTERNAL LOCATION} | char | | dereference.rs:64:15:64:17 | 'a' | | {EXTERNAL LOCATION} | char | | dereference.rs:65:9:65:11 | _f2 | | {EXTERNAL LOCATION} | char | -| dereference.rs:65:9:65:11 | _f2 | | file://:0:0:0:0 | & | -| dereference.rs:65:9:65:11 | _f2 | &T | {EXTERNAL LOCATION} | char | | dereference.rs:65:15:65:17 | * ... | | {EXTERNAL LOCATION} | char | -| dereference.rs:65:15:65:17 | * ... | | file://:0:0:0:0 | & | -| dereference.rs:65:15:65:17 | * ... | &T | {EXTERNAL LOCATION} | char | | dereference.rs:65:16:65:17 | e2 | | file://:0:0:0:0 | & | | dereference.rs:65:16:65:17 | e2 | &T | {EXTERNAL LOCATION} | char | | dereference.rs:68:9:68:10 | e3 | | file://:0:0:0:0 | & | @@ -121,12 +101,8 @@ inferType | dereference.rs:68:15:68:19 | 34i64 | | {EXTERNAL LOCATION} | i64 | | dereference.rs:69:9:69:11 | _f3 | | {EXTERNAL LOCATION} | bool | | dereference.rs:69:15:69:19 | (...) | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:69:15:69:19 | (...) | | file://:0:0:0:0 | & | -| dereference.rs:69:15:69:19 | (...) | &T | {EXTERNAL LOCATION} | i64 | | dereference.rs:69:15:69:33 | ... .is_positive() | | {EXTERNAL LOCATION} | bool | | dereference.rs:69:16:69:18 | * ... | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:69:16:69:18 | * ... | | file://:0:0:0:0 | & | -| dereference.rs:69:16:69:18 | * ... | &T | {EXTERNAL LOCATION} | i64 | | dereference.rs:69:17:69:18 | e3 | | file://:0:0:0:0 | & | | dereference.rs:69:17:69:18 | e3 | &T | {EXTERNAL LOCATION} | i64 | | dereference.rs:74:9:74:10 | g1 | | {EXTERNAL LOCATION} | Box | @@ -151,11 +127,7 @@ inferType | dereference.rs:78:25:78:37 | ...::new(...) | T | {EXTERNAL LOCATION} | char | | dereference.rs:78:34:78:36 | 'a' | | {EXTERNAL LOCATION} | char | | dereference.rs:79:9:79:11 | _h2 | | {EXTERNAL LOCATION} | char | -| dereference.rs:79:9:79:11 | _h2 | | file://:0:0:0:0 | & | -| dereference.rs:79:9:79:11 | _h2 | &T | {EXTERNAL LOCATION} | char | | dereference.rs:79:15:79:17 | * ... | | {EXTERNAL LOCATION} | char | -| dereference.rs:79:15:79:17 | * ... | | file://:0:0:0:0 | & | -| dereference.rs:79:15:79:17 | * ... | &T | {EXTERNAL LOCATION} | char | | dereference.rs:79:16:79:17 | g2 | | {EXTERNAL LOCATION} | Box | | dereference.rs:79:16:79:17 | g2 | A | {EXTERNAL LOCATION} | Global | | dereference.rs:79:16:79:17 | g2 | T | {EXTERNAL LOCATION} | char | @@ -168,12 +140,8 @@ inferType | dereference.rs:82:33:82:37 | 34i64 | | {EXTERNAL LOCATION} | i64 | | dereference.rs:83:9:83:11 | _h3 | | {EXTERNAL LOCATION} | bool | | dereference.rs:83:15:83:19 | (...) | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:83:15:83:19 | (...) | | file://:0:0:0:0 | & | -| dereference.rs:83:15:83:19 | (...) | &T | {EXTERNAL LOCATION} | i64 | | dereference.rs:83:15:83:33 | ... .is_positive() | | {EXTERNAL LOCATION} | bool | | dereference.rs:83:16:83:18 | * ... | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:83:16:83:18 | * ... | | file://:0:0:0:0 | & | -| dereference.rs:83:16:83:18 | * ... | &T | {EXTERNAL LOCATION} | i64 | | dereference.rs:83:17:83:18 | g3 | | {EXTERNAL LOCATION} | Box | | dereference.rs:83:17:83:18 | g3 | A | {EXTERNAL LOCATION} | Global | | dereference.rs:83:17:83:18 | g3 | T | {EXTERNAL LOCATION} | i64 | @@ -2372,27 +2340,15 @@ inferType | main.rs:1109:29:1109:33 | SelfParam | &T | main.rs:1082:5:1085:5 | MyInt | | main.rs:1109:29:1109:33 | SelfParam | &T.&T | main.rs:1082:5:1085:5 | MyInt | | main.rs:1109:43:1111:9 | { ... } | | {EXTERNAL LOCATION} | i64 | -| main.rs:1110:13:1110:22 | (...) | | file://:0:0:0:0 | & | | main.rs:1110:13:1110:22 | (...) | | main.rs:1082:5:1085:5 | MyInt | -| main.rs:1110:13:1110:22 | (...) | &T | file://:0:0:0:0 | & | -| main.rs:1110:13:1110:22 | (...) | &T | main.rs:1082:5:1085:5 | MyInt | -| main.rs:1110:13:1110:22 | (...) | &T.&T | main.rs:1082:5:1085:5 | MyInt | | main.rs:1110:13:1110:24 | ... .a | | {EXTERNAL LOCATION} | i64 | -| main.rs:1110:14:1110:21 | * ... | | file://:0:0:0:0 | & | | main.rs:1110:14:1110:21 | * ... | | main.rs:1082:5:1085:5 | MyInt | -| main.rs:1110:14:1110:21 | * ... | &T | file://:0:0:0:0 | & | -| main.rs:1110:14:1110:21 | * ... | &T | main.rs:1082:5:1085:5 | MyInt | -| main.rs:1110:14:1110:21 | * ... | &T.&T | main.rs:1082:5:1085:5 | MyInt | | main.rs:1110:15:1110:21 | (...) | | file://:0:0:0:0 | & | | main.rs:1110:15:1110:21 | (...) | | main.rs:1082:5:1085:5 | MyInt | -| main.rs:1110:15:1110:21 | (...) | &T | file://:0:0:0:0 | & | | main.rs:1110:15:1110:21 | (...) | &T | main.rs:1082:5:1085:5 | MyInt | -| main.rs:1110:15:1110:21 | (...) | &T.&T | main.rs:1082:5:1085:5 | MyInt | | main.rs:1110:16:1110:20 | * ... | | file://:0:0:0:0 | & | | main.rs:1110:16:1110:20 | * ... | | main.rs:1082:5:1085:5 | MyInt | -| main.rs:1110:16:1110:20 | * ... | &T | file://:0:0:0:0 | & | | main.rs:1110:16:1110:20 | * ... | &T | main.rs:1082:5:1085:5 | MyInt | -| main.rs:1110:16:1110:20 | * ... | &T.&T | main.rs:1082:5:1085:5 | MyInt | | main.rs:1110:17:1110:20 | self | | file://:0:0:0:0 | & | | main.rs:1110:17:1110:20 | self | &T | file://:0:0:0:0 | & | | main.rs:1110:17:1110:20 | self | &T | main.rs:1082:5:1085:5 | MyInt | @@ -2400,13 +2356,9 @@ inferType | main.rs:1114:33:1114:36 | SelfParam | | file://:0:0:0:0 | & | | main.rs:1114:33:1114:36 | SelfParam | &T | main.rs:1082:5:1085:5 | MyInt | | main.rs:1114:46:1116:9 | { ... } | | {EXTERNAL LOCATION} | i64 | -| main.rs:1115:13:1115:19 | (...) | | file://:0:0:0:0 | & | | main.rs:1115:13:1115:19 | (...) | | main.rs:1082:5:1085:5 | MyInt | -| main.rs:1115:13:1115:19 | (...) | &T | main.rs:1082:5:1085:5 | MyInt | | main.rs:1115:13:1115:21 | ... .a | | {EXTERNAL LOCATION} | i64 | -| main.rs:1115:14:1115:18 | * ... | | file://:0:0:0:0 | & | | main.rs:1115:14:1115:18 | * ... | | main.rs:1082:5:1085:5 | MyInt | -| main.rs:1115:14:1115:18 | * ... | &T | main.rs:1082:5:1085:5 | MyInt | | main.rs:1115:15:1115:18 | self | | file://:0:0:0:0 | & | | main.rs:1115:15:1115:18 | self | &T | main.rs:1082:5:1085:5 | MyInt | | main.rs:1120:13:1120:14 | x1 | | main.rs:1076:5:1077:19 | S | @@ -2504,16 +2456,10 @@ inferType | main.rs:1143:19:1143:23 | S(...) | T | main.rs:1079:5:1080:14 | S2 | | main.rs:1143:21:1143:22 | S2 | | main.rs:1079:5:1080:14 | S2 | | main.rs:1146:18:1146:23 | "{:?}\\n" | | {EXTERNAL LOCATION} | str | -| main.rs:1146:26:1146:30 | (...) | | file://:0:0:0:0 | & | | main.rs:1146:26:1146:30 | (...) | | main.rs:1076:5:1077:19 | S | -| main.rs:1146:26:1146:30 | (...) | &T | main.rs:1076:5:1077:19 | S | -| main.rs:1146:26:1146:30 | (...) | &T.T | main.rs:1079:5:1080:14 | S2 | | main.rs:1146:26:1146:30 | (...) | T | main.rs:1079:5:1080:14 | S2 | | main.rs:1146:26:1146:35 | ... .m1() | | main.rs:1079:5:1080:14 | S2 | -| main.rs:1146:27:1146:29 | * ... | | file://:0:0:0:0 | & | | main.rs:1146:27:1146:29 | * ... | | main.rs:1076:5:1077:19 | S | -| main.rs:1146:27:1146:29 | * ... | &T | main.rs:1076:5:1077:19 | S | -| main.rs:1146:27:1146:29 | * ... | &T.T | main.rs:1079:5:1080:14 | S2 | | main.rs:1146:27:1146:29 | * ... | T | main.rs:1079:5:1080:14 | S2 | | main.rs:1146:28:1146:29 | x6 | | file://:0:0:0:0 | & | | main.rs:1146:28:1146:29 | x6 | &T | main.rs:1076:5:1077:19 | S | @@ -2739,20 +2685,10 @@ inferType | main.rs:1251:15:1251:16 | &x | &T | main.rs:1227:5:1227:13 | S | | main.rs:1251:16:1251:16 | x | | main.rs:1227:5:1227:13 | S | | main.rs:1253:13:1253:13 | n | | {EXTERNAL LOCATION} | bool | -| main.rs:1253:13:1253:13 | n | | file://:0:0:0:0 | & | -| main.rs:1253:13:1253:13 | n | &T | {EXTERNAL LOCATION} | bool | -| main.rs:1253:13:1253:13 | n | &T | file://:0:0:0:0 | & | -| main.rs:1253:13:1253:13 | n | &T.&T | {EXTERNAL LOCATION} | bool | | main.rs:1253:17:1253:24 | * ... | | {EXTERNAL LOCATION} | bool | -| main.rs:1253:17:1253:24 | * ... | | file://:0:0:0:0 | & | -| main.rs:1253:17:1253:24 | * ... | &T | {EXTERNAL LOCATION} | bool | -| main.rs:1253:17:1253:24 | * ... | &T | file://:0:0:0:0 | & | -| main.rs:1253:17:1253:24 | * ... | &T.&T | {EXTERNAL LOCATION} | bool | | main.rs:1253:18:1253:24 | * ... | | {EXTERNAL LOCATION} | bool | | main.rs:1253:18:1253:24 | * ... | | file://:0:0:0:0 | & | | main.rs:1253:18:1253:24 | * ... | &T | {EXTERNAL LOCATION} | bool | -| main.rs:1253:18:1253:24 | * ... | &T | file://:0:0:0:0 | & | -| main.rs:1253:18:1253:24 | * ... | &T.&T | {EXTERNAL LOCATION} | bool | | main.rs:1253:19:1253:24 | &... | | file://:0:0:0:0 | & | | main.rs:1253:19:1253:24 | &... | &T | {EXTERNAL LOCATION} | bool | | main.rs:1253:19:1253:24 | &... | &T | file://:0:0:0:0 | & | @@ -3863,10 +3799,12 @@ inferType | main.rs:1859:14:1859:29 | ...[index] | | main.rs:1854:10:1854:10 | T | | main.rs:1859:24:1859:28 | index | | {EXTERNAL LOCATION} | usize | | main.rs:1863:22:1863:26 | slice | | file://:0:0:0:0 | & | +| main.rs:1863:22:1863:26 | slice | | file://:0:0:0:0 | [] | | main.rs:1863:22:1863:26 | slice | &T | file://:0:0:0:0 | [] | | main.rs:1863:22:1863:26 | slice | &T.[T] | main.rs:1830:5:1831:13 | S | | main.rs:1864:13:1864:13 | x | | main.rs:1830:5:1831:13 | S | | main.rs:1864:17:1864:21 | slice | | file://:0:0:0:0 | & | +| main.rs:1864:17:1864:21 | slice | | file://:0:0:0:0 | [] | | main.rs:1864:17:1864:21 | slice | &T | file://:0:0:0:0 | [] | | main.rs:1864:17:1864:21 | slice | &T.[T] | main.rs:1830:5:1831:13 | S | | main.rs:1864:17:1864:24 | slice[0] | | main.rs:1830:5:1831:13 | S | @@ -3881,7 +3819,10 @@ inferType | main.rs:1869:18:1869:18 | S | | main.rs:1830:5:1831:13 | S | | main.rs:1870:9:1870:11 | vec | | main.rs:1839:5:1842:5 | MyVec | | main.rs:1870:9:1870:11 | vec | T | main.rs:1830:5:1831:13 | S | +| main.rs:1870:9:1870:14 | vec[0] | | main.rs:1830:5:1831:13 | S | +| main.rs:1870:9:1870:20 | ... .foo() | | main.rs:1830:5:1831:13 | S | | main.rs:1870:13:1870:13 | 0 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1870:13:1870:13 | 0 | | {EXTERNAL LOCATION} | usize | | main.rs:1872:13:1872:14 | xs | | file://:0:0:0:0 | [] | | main.rs:1872:13:1872:14 | xs | | file://:0:0:0:0 | [] | | main.rs:1872:13:1872:14 | xs | [T;...] | main.rs:1830:5:1831:13 | S | @@ -3926,11 +3867,7 @@ inferType | main.rs:1899:26:1899:30 | value | | file://:0:0:0:0 | & | | main.rs:1899:26:1899:30 | value | &T | {EXTERNAL LOCATION} | i64 | | main.rs:1899:47:1901:9 | { ... } | | {EXTERNAL LOCATION} | i64 | -| main.rs:1899:47:1901:9 | { ... } | | file://:0:0:0:0 | & | -| main.rs:1899:47:1901:9 | { ... } | &T | {EXTERNAL LOCATION} | i64 | | main.rs:1900:13:1900:18 | * ... | | {EXTERNAL LOCATION} | i64 | -| main.rs:1900:13:1900:18 | * ... | | file://:0:0:0:0 | & | -| main.rs:1900:13:1900:18 | * ... | &T | {EXTERNAL LOCATION} | i64 | | main.rs:1900:14:1900:18 | value | | file://:0:0:0:0 | & | | main.rs:1900:14:1900:18 | value | &T | {EXTERNAL LOCATION} | i64 | | main.rs:1906:19:1906:23 | SelfParam | | file://:0:0:0:0 | & | From 846ef9ad5a2ff76ef6cac17c775e0342b1ac71b2 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Fri, 20 Jun 2025 16:18:05 +0200 Subject: [PATCH 2/4] Rust: Document spurious type --- .../test/library-tests/type-inference/main.rs | 8 +- .../type-inference/type-inference.expected | 214 +++++++++--------- 2 files changed, 114 insertions(+), 108 deletions(-) diff --git a/rust/ql/test/library-tests/type-inference/main.rs b/rust/ql/test/library-tests/type-inference/main.rs index a963e2e0edc8..18af89be3ab7 100644 --- a/rust/ql/test/library-tests/type-inference/main.rs +++ b/rust/ql/test/library-tests/type-inference/main.rs @@ -1861,7 +1861,13 @@ mod indexers { } fn analyze_slice(slice: &[S]) { - let x = slice[0].foo(); // $ method=foo type=x:S method=index + // NOTE: `slice` gets the spurious type `[]` because the desugaring of + // the index expression adds an implicit borrow. `&slice` has the type + // `&&[S]`, but the `index` methods takes a `&[S]`, so Rust adds an + // implicit dereference. We cannot currently handle a position that is + // both implicitly dereferenced and implicitly borrowed, so the extra + // type sneaks in. + let x = slice[0].foo(); // $ method=foo type=x:S method=index SPURIOUS: type=slice:[] } pub fn 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 35df5930a5cc..0ae35aba9171 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.expected +++ b/rust/ql/test/library-tests/type-inference/type-inference.expected @@ -3802,113 +3802,113 @@ inferType | main.rs:1863:22:1863:26 | slice | | file://:0:0:0:0 | [] | | main.rs:1863:22:1863:26 | slice | &T | file://:0:0:0:0 | [] | | main.rs:1863:22:1863:26 | slice | &T.[T] | main.rs:1830:5:1831:13 | S | -| main.rs:1864:13:1864:13 | x | | main.rs:1830:5:1831:13 | S | -| main.rs:1864:17:1864:21 | slice | | file://:0:0:0:0 | & | -| main.rs:1864:17:1864:21 | slice | | file://:0:0:0:0 | [] | -| main.rs:1864:17:1864:21 | slice | &T | file://:0:0:0:0 | [] | -| main.rs:1864:17:1864:21 | slice | &T.[T] | main.rs:1830:5:1831:13 | S | -| main.rs:1864:17:1864:24 | slice[0] | | main.rs:1830:5:1831:13 | S | -| main.rs:1864:17:1864:30 | ... .foo() | | main.rs:1830:5:1831:13 | S | -| main.rs:1864:23:1864:23 | 0 | | {EXTERNAL LOCATION} | i32 | -| main.rs:1868:13:1868:19 | mut vec | | main.rs:1839:5:1842:5 | MyVec | -| main.rs:1868:13:1868:19 | mut vec | T | main.rs:1830:5:1831:13 | S | -| main.rs:1868:23:1868:34 | ...::new(...) | | main.rs:1839:5:1842:5 | MyVec | -| main.rs:1868:23:1868:34 | ...::new(...) | T | main.rs:1830:5:1831:13 | S | -| main.rs:1869:9:1869:11 | vec | | main.rs:1839:5:1842:5 | MyVec | -| main.rs:1869:9:1869:11 | vec | T | main.rs:1830:5:1831:13 | S | -| main.rs:1869:18:1869:18 | S | | main.rs:1830:5:1831:13 | S | -| main.rs:1870:9:1870:11 | vec | | main.rs:1839:5:1842:5 | MyVec | -| main.rs:1870:9:1870:11 | vec | T | main.rs:1830:5:1831:13 | S | -| main.rs:1870:9:1870:14 | vec[0] | | main.rs:1830:5:1831:13 | S | -| main.rs:1870:9:1870:20 | ... .foo() | | main.rs:1830:5:1831:13 | S | -| main.rs:1870:13:1870:13 | 0 | | {EXTERNAL LOCATION} | i32 | -| main.rs:1870:13:1870:13 | 0 | | {EXTERNAL LOCATION} | usize | -| main.rs:1872:13:1872:14 | xs | | file://:0:0:0:0 | [] | -| main.rs:1872:13:1872:14 | xs | | file://:0:0:0:0 | [] | -| main.rs:1872:13:1872:14 | xs | [T;...] | main.rs:1830:5:1831:13 | S | -| main.rs:1872:13:1872:14 | xs | [T] | main.rs:1830:5:1831:13 | S | -| main.rs:1872:21:1872:21 | 1 | | {EXTERNAL LOCATION} | i32 | -| main.rs:1872:26:1872:28 | [...] | | file://:0:0:0:0 | [] | -| main.rs:1872:26:1872:28 | [...] | | file://:0:0:0:0 | [] | -| main.rs:1872:26:1872:28 | [...] | [T;...] | main.rs:1830:5:1831:13 | S | -| main.rs:1872:26:1872:28 | [...] | [T] | main.rs:1830:5:1831:13 | S | -| main.rs:1872:27:1872:27 | S | | main.rs:1830:5:1831:13 | S | -| main.rs:1873:13:1873:13 | x | | main.rs:1830:5:1831:13 | S | -| main.rs:1873:17:1873:18 | xs | | file://:0:0:0:0 | [] | -| main.rs:1873:17:1873:18 | xs | | file://:0:0:0:0 | [] | -| main.rs:1873:17:1873:18 | xs | [T;...] | main.rs:1830:5:1831:13 | S | -| main.rs:1873:17:1873:18 | xs | [T] | main.rs:1830:5:1831:13 | S | -| main.rs:1873:17:1873:21 | xs[0] | | main.rs:1830:5:1831:13 | S | -| main.rs:1873:17:1873:27 | ... .foo() | | main.rs:1830:5:1831:13 | S | -| main.rs:1873:20:1873:20 | 0 | | {EXTERNAL LOCATION} | i32 | -| main.rs:1875:23:1875:25 | &xs | | file://:0:0:0:0 | & | -| main.rs:1875:23:1875:25 | &xs | &T | file://:0:0:0:0 | [] | -| main.rs:1875:23:1875:25 | &xs | &T | file://:0:0:0:0 | [] | -| main.rs:1875:23:1875:25 | &xs | &T.[T;...] | main.rs:1830:5:1831:13 | S | -| main.rs:1875:23:1875:25 | &xs | &T.[T] | main.rs:1830:5:1831:13 | S | -| main.rs:1875:24:1875:25 | xs | | file://:0:0:0:0 | [] | -| main.rs:1875:24:1875:25 | xs | | file://:0:0:0:0 | [] | -| main.rs:1875:24:1875:25 | xs | [T;...] | main.rs:1830:5:1831:13 | S | -| main.rs:1875:24:1875:25 | xs | [T] | main.rs:1830:5:1831:13 | S | -| main.rs:1881:25:1881:35 | "Hello, {}" | | {EXTERNAL LOCATION} | str | -| main.rs:1881:25:1881:45 | ...::format(...) | | {EXTERNAL LOCATION} | String | -| main.rs:1881:25:1881:45 | { ... } | | {EXTERNAL LOCATION} | String | -| main.rs:1881:38:1881:45 | "World!" | | {EXTERNAL LOCATION} | str | -| main.rs:1887:19:1887:23 | SelfParam | | file://:0:0:0:0 | & | -| main.rs:1887:19:1887:23 | SelfParam | &T | main.rs:1886:5:1888:5 | Self [trait MyAdd] | -| main.rs:1887:26:1887:30 | value | | main.rs:1886:17:1886:17 | T | -| main.rs:1892:19:1892:23 | SelfParam | | file://:0:0:0:0 | & | -| main.rs:1892:19:1892:23 | SelfParam | &T | {EXTERNAL LOCATION} | i64 | -| main.rs:1892:26:1892:30 | value | | {EXTERNAL LOCATION} | i64 | -| main.rs:1892:46:1894:9 | { ... } | | {EXTERNAL LOCATION} | i64 | -| main.rs:1893:13:1893:17 | value | | {EXTERNAL LOCATION} | i64 | -| main.rs:1899:19:1899:23 | SelfParam | | file://:0:0:0:0 | & | -| main.rs:1899:19:1899:23 | SelfParam | &T | {EXTERNAL LOCATION} | i64 | -| main.rs:1899:26:1899:30 | value | | file://:0:0:0:0 | & | -| main.rs:1899:26:1899:30 | value | &T | {EXTERNAL LOCATION} | i64 | -| main.rs:1899:47:1901:9 | { ... } | | {EXTERNAL LOCATION} | i64 | -| main.rs:1900:13:1900:18 | * ... | | {EXTERNAL LOCATION} | i64 | -| main.rs:1900:14:1900:18 | value | | file://:0:0:0:0 | & | -| main.rs:1900:14:1900:18 | value | &T | {EXTERNAL LOCATION} | i64 | -| main.rs:1906:19:1906:23 | SelfParam | | file://:0:0:0:0 | & | -| main.rs:1906:19:1906:23 | SelfParam | &T | {EXTERNAL LOCATION} | i64 | -| main.rs:1906:26:1906:30 | value | | {EXTERNAL LOCATION} | bool | -| main.rs:1906:47:1912:9 | { ... } | | {EXTERNAL LOCATION} | i32 | -| main.rs:1906:47:1912:9 | { ... } | | {EXTERNAL LOCATION} | i64 | -| main.rs:1907:13:1911:13 | if value {...} else {...} | | {EXTERNAL LOCATION} | i32 | -| main.rs:1907:13:1911:13 | if value {...} else {...} | | {EXTERNAL LOCATION} | i64 | -| main.rs:1907:16:1907:20 | value | | {EXTERNAL LOCATION} | bool | -| main.rs:1907:22:1909:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| main.rs:1907:22:1909:13 | { ... } | | {EXTERNAL LOCATION} | i64 | -| main.rs:1908:17:1908:17 | 1 | | {EXTERNAL LOCATION} | i32 | -| main.rs:1908:17:1908:17 | 1 | | {EXTERNAL LOCATION} | i64 | -| main.rs:1909:20:1911:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| main.rs:1909:20:1911:13 | { ... } | | {EXTERNAL LOCATION} | i64 | -| main.rs:1910:17:1910:17 | 0 | | {EXTERNAL LOCATION} | i32 | -| main.rs:1910:17:1910:17 | 0 | | {EXTERNAL LOCATION} | i64 | -| main.rs:1916:13:1916:13 | x | | {EXTERNAL LOCATION} | i32 | -| main.rs:1916:13:1916:13 | x | | {EXTERNAL LOCATION} | i64 | -| main.rs:1916:22:1916:23 | 73 | | {EXTERNAL LOCATION} | i32 | -| main.rs:1916:22:1916:23 | 73 | | {EXTERNAL LOCATION} | i64 | -| main.rs:1917:9:1917:9 | x | | {EXTERNAL LOCATION} | i32 | -| main.rs:1917:9:1917:9 | x | | {EXTERNAL LOCATION} | i64 | -| main.rs:1917:9:1917:22 | x.my_add(...) | | {EXTERNAL LOCATION} | i64 | -| main.rs:1917:18:1917:21 | 5i64 | | {EXTERNAL LOCATION} | i64 | -| main.rs:1918:9:1918:9 | x | | {EXTERNAL LOCATION} | i32 | -| main.rs:1918:9:1918:9 | x | | {EXTERNAL LOCATION} | i64 | -| main.rs:1918:9:1918:23 | x.my_add(...) | | {EXTERNAL LOCATION} | i64 | -| main.rs:1918:18:1918:22 | &5i64 | | file://:0:0:0:0 | & | -| main.rs:1918:18:1918:22 | &5i64 | &T | {EXTERNAL LOCATION} | i64 | -| main.rs:1918:19:1918:22 | 5i64 | | {EXTERNAL LOCATION} | i64 | -| main.rs:1919:9:1919:9 | x | | {EXTERNAL LOCATION} | i32 | -| main.rs:1919:9:1919:9 | x | | {EXTERNAL LOCATION} | i64 | -| main.rs:1919:9:1919:22 | x.my_add(...) | | {EXTERNAL LOCATION} | i64 | -| main.rs:1919:18:1919:21 | true | | {EXTERNAL LOCATION} | bool | -| main.rs:1927:5:1927:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:1928:5:1928:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:1928:20:1928:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:1928:41:1928:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:1944:5:1944:15 | ...::f(...) | | {EXTERNAL LOCATION} | trait Future | +| main.rs:1870:13:1870:13 | x | | main.rs:1830:5:1831:13 | S | +| main.rs:1870:17:1870:21 | slice | | file://:0:0:0:0 | & | +| main.rs:1870:17:1870:21 | slice | | file://:0:0:0:0 | [] | +| main.rs:1870:17:1870:21 | slice | &T | file://:0:0:0:0 | [] | +| main.rs:1870:17:1870:21 | slice | &T.[T] | main.rs:1830:5:1831:13 | S | +| main.rs:1870:17:1870:24 | slice[0] | | main.rs:1830:5:1831:13 | S | +| main.rs:1870:17:1870:30 | ... .foo() | | main.rs:1830:5:1831:13 | S | +| main.rs:1870:23:1870:23 | 0 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1874:13:1874:19 | mut vec | | main.rs:1839:5:1842:5 | MyVec | +| main.rs:1874:13:1874:19 | mut vec | T | main.rs:1830:5:1831:13 | S | +| main.rs:1874:23:1874:34 | ...::new(...) | | main.rs:1839:5:1842:5 | MyVec | +| main.rs:1874:23:1874:34 | ...::new(...) | T | main.rs:1830:5:1831:13 | S | +| main.rs:1875:9:1875:11 | vec | | main.rs:1839:5:1842:5 | MyVec | +| main.rs:1875:9:1875:11 | vec | T | main.rs:1830:5:1831:13 | S | +| main.rs:1875:18:1875:18 | S | | main.rs:1830:5:1831:13 | S | +| main.rs:1876:9:1876:11 | vec | | main.rs:1839:5:1842:5 | MyVec | +| main.rs:1876:9:1876:11 | vec | T | main.rs:1830:5:1831:13 | S | +| main.rs:1876:9:1876:14 | vec[0] | | main.rs:1830:5:1831:13 | S | +| main.rs:1876:9:1876:20 | ... .foo() | | main.rs:1830:5:1831:13 | S | +| main.rs:1876:13:1876:13 | 0 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1876:13:1876:13 | 0 | | {EXTERNAL LOCATION} | usize | +| main.rs:1878:13:1878:14 | xs | | file://:0:0:0:0 | [] | +| main.rs:1878:13:1878:14 | xs | | file://:0:0:0:0 | [] | +| main.rs:1878:13:1878:14 | xs | [T;...] | main.rs:1830:5:1831:13 | S | +| main.rs:1878:13:1878:14 | xs | [T] | main.rs:1830:5:1831:13 | S | +| main.rs:1878:21:1878:21 | 1 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1878:26:1878:28 | [...] | | file://:0:0:0:0 | [] | +| main.rs:1878:26:1878:28 | [...] | | file://:0:0:0:0 | [] | +| main.rs:1878:26:1878:28 | [...] | [T;...] | main.rs:1830:5:1831:13 | S | +| main.rs:1878:26:1878:28 | [...] | [T] | main.rs:1830:5:1831:13 | S | +| main.rs:1878:27:1878:27 | S | | main.rs:1830:5:1831:13 | S | +| main.rs:1879:13:1879:13 | x | | main.rs:1830:5:1831:13 | S | +| main.rs:1879:17:1879:18 | xs | | file://:0:0:0:0 | [] | +| main.rs:1879:17:1879:18 | xs | | file://:0:0:0:0 | [] | +| main.rs:1879:17:1879:18 | xs | [T;...] | main.rs:1830:5:1831:13 | S | +| main.rs:1879:17:1879:18 | xs | [T] | main.rs:1830:5:1831:13 | S | +| main.rs:1879:17:1879:21 | xs[0] | | main.rs:1830:5:1831:13 | S | +| main.rs:1879:17:1879:27 | ... .foo() | | main.rs:1830:5:1831:13 | S | +| main.rs:1879:20:1879:20 | 0 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1881:23:1881:25 | &xs | | file://:0:0:0:0 | & | +| main.rs:1881:23:1881:25 | &xs | &T | file://:0:0:0:0 | [] | +| main.rs:1881:23:1881:25 | &xs | &T | file://:0:0:0:0 | [] | +| main.rs:1881:23:1881:25 | &xs | &T.[T;...] | main.rs:1830:5:1831:13 | S | +| main.rs:1881:23:1881:25 | &xs | &T.[T] | main.rs:1830:5:1831:13 | S | +| main.rs:1881:24:1881:25 | xs | | file://:0:0:0:0 | [] | +| main.rs:1881:24:1881:25 | xs | | file://:0:0:0:0 | [] | +| main.rs:1881:24:1881:25 | xs | [T;...] | main.rs:1830:5:1831:13 | S | +| main.rs:1881:24:1881:25 | xs | [T] | main.rs:1830:5:1831:13 | S | +| main.rs:1887:25:1887:35 | "Hello, {}" | | {EXTERNAL LOCATION} | str | +| main.rs:1887:25:1887:45 | ...::format(...) | | {EXTERNAL LOCATION} | String | +| main.rs:1887:25:1887:45 | { ... } | | {EXTERNAL LOCATION} | String | +| main.rs:1887:38:1887:45 | "World!" | | {EXTERNAL LOCATION} | str | +| main.rs:1893:19:1893:23 | SelfParam | | file://:0:0:0:0 | & | +| main.rs:1893:19:1893:23 | SelfParam | &T | main.rs:1892:5:1894:5 | Self [trait MyAdd] | +| main.rs:1893:26:1893:30 | value | | main.rs:1892:17:1892:17 | T | +| main.rs:1898:19:1898:23 | SelfParam | | file://:0:0:0:0 | & | +| main.rs:1898:19:1898:23 | SelfParam | &T | {EXTERNAL LOCATION} | i64 | +| main.rs:1898:26:1898:30 | value | | {EXTERNAL LOCATION} | i64 | +| main.rs:1898:46:1900:9 | { ... } | | {EXTERNAL LOCATION} | i64 | +| main.rs:1899:13:1899:17 | value | | {EXTERNAL LOCATION} | i64 | +| main.rs:1905:19:1905:23 | SelfParam | | file://:0:0:0:0 | & | +| main.rs:1905:19:1905:23 | SelfParam | &T | {EXTERNAL LOCATION} | i64 | +| main.rs:1905:26:1905:30 | value | | file://:0:0:0:0 | & | +| main.rs:1905:26:1905:30 | value | &T | {EXTERNAL LOCATION} | i64 | +| main.rs:1905:47:1907:9 | { ... } | | {EXTERNAL LOCATION} | i64 | +| main.rs:1906:13:1906:18 | * ... | | {EXTERNAL LOCATION} | i64 | +| main.rs:1906:14:1906:18 | value | | file://:0:0:0:0 | & | +| main.rs:1906:14:1906:18 | value | &T | {EXTERNAL LOCATION} | i64 | +| main.rs:1912:19:1912:23 | SelfParam | | file://:0:0:0:0 | & | +| main.rs:1912:19:1912:23 | SelfParam | &T | {EXTERNAL LOCATION} | i64 | +| main.rs:1912:26:1912:30 | value | | {EXTERNAL LOCATION} | bool | +| main.rs:1912:47:1918:9 | { ... } | | {EXTERNAL LOCATION} | i32 | +| main.rs:1912:47:1918:9 | { ... } | | {EXTERNAL LOCATION} | i64 | +| main.rs:1913:13:1917:13 | if value {...} else {...} | | {EXTERNAL LOCATION} | i32 | +| main.rs:1913:13:1917:13 | if value {...} else {...} | | {EXTERNAL LOCATION} | i64 | +| main.rs:1913:16:1913:20 | value | | {EXTERNAL LOCATION} | bool | +| main.rs:1913:22:1915:13 | { ... } | | {EXTERNAL LOCATION} | i32 | +| main.rs:1913:22:1915:13 | { ... } | | {EXTERNAL LOCATION} | i64 | +| main.rs:1914:17:1914:17 | 1 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1914:17:1914:17 | 1 | | {EXTERNAL LOCATION} | i64 | +| main.rs:1915:20:1917:13 | { ... } | | {EXTERNAL LOCATION} | i32 | +| main.rs:1915:20:1917:13 | { ... } | | {EXTERNAL LOCATION} | i64 | +| main.rs:1916:17:1916:17 | 0 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1916:17:1916:17 | 0 | | {EXTERNAL LOCATION} | i64 | +| main.rs:1922:13:1922:13 | x | | {EXTERNAL LOCATION} | i32 | +| main.rs:1922:13:1922:13 | x | | {EXTERNAL LOCATION} | i64 | +| main.rs:1922:22:1922:23 | 73 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1922:22:1922:23 | 73 | | {EXTERNAL LOCATION} | i64 | +| main.rs:1923:9:1923:9 | x | | {EXTERNAL LOCATION} | i32 | +| main.rs:1923:9:1923:9 | x | | {EXTERNAL LOCATION} | i64 | +| main.rs:1923:9:1923:22 | x.my_add(...) | | {EXTERNAL LOCATION} | i64 | +| main.rs:1923:18:1923:21 | 5i64 | | {EXTERNAL LOCATION} | i64 | +| main.rs:1924:9:1924:9 | x | | {EXTERNAL LOCATION} | i32 | +| main.rs:1924:9:1924:9 | x | | {EXTERNAL LOCATION} | i64 | +| main.rs:1924:9:1924:23 | x.my_add(...) | | {EXTERNAL LOCATION} | i64 | +| main.rs:1924:18:1924:22 | &5i64 | | file://:0:0:0:0 | & | +| main.rs:1924:18:1924:22 | &5i64 | &T | {EXTERNAL LOCATION} | i64 | +| main.rs:1924:19:1924:22 | 5i64 | | {EXTERNAL LOCATION} | i64 | +| main.rs:1925:9:1925:9 | x | | {EXTERNAL LOCATION} | i32 | +| main.rs:1925:9:1925:9 | x | | {EXTERNAL LOCATION} | i64 | +| main.rs:1925:9:1925:22 | x.my_add(...) | | {EXTERNAL LOCATION} | i64 | +| main.rs:1925:18:1925:21 | true | | {EXTERNAL LOCATION} | bool | +| main.rs:1933:5:1933:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:1934:5:1934:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:1934:20:1934:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:1934:41:1934:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:1950:5:1950:15 | ...::f(...) | | {EXTERNAL LOCATION} | trait Future | testFailures | main.rs:2:5:2:20 | f.write_str(...) | Unexpected result: method=write_str | | main.rs:5:5:5:20 | f.debug_struct(...) | Unexpected result: method=debug_struct | From 326c7de521b116f85d51fce73c10b8e906d66050 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Sat, 21 Jun 2025 13:16:40 +0200 Subject: [PATCH 3/4] Rust: Ensure index expressions are not handled as calls yet in data flow --- .../lib/codeql/rust/dataflow/internal/DataFlowImpl.qll | 10 +++++++--- rust/ql/lib/codeql/rust/dataflow/internal/Node.qll | 6 +++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll index 20c9e80b87aa..fb3a46d78663 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll @@ -145,9 +145,13 @@ final class ArgumentPosition extends ParameterPosition { * as the synthetic `ReceiverNode` is the argument for the `self` parameter. */ predicate isArgumentForCall(ExprCfgNode arg, CallCfgNode call, ParameterPosition pos) { - call.getPositionalArgument(pos.getPosition()) = arg - or - call.getReceiver() = arg and pos.isSelf() and not call.getCall().receiverImplicitlyBorrowed() + // TODO: Handle index expressions as calls in data flow. + not call.getCall() instanceof IndexExpr and + ( + call.getPositionalArgument(pos.getPosition()) = arg + or + call.getReceiver() = arg and pos.isSelf() and not call.getCall().receiverImplicitlyBorrowed() + ) } /** Provides logic related to SSA. */ diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/Node.qll b/rust/ql/lib/codeql/rust/dataflow/internal/Node.qll index 51343c1eb40a..b18ccbacbd6a 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/Node.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/Node.qll @@ -472,7 +472,11 @@ newtype TNode = getPostUpdateReverseStep(any(PostUpdateNode n).getPreUpdateNode().asExpr(), _) ] } or - TReceiverNode(CallCfgNode mc, Boolean isPost) { mc.getCall().receiverImplicitlyBorrowed() } or + TReceiverNode(CallCfgNode mc, Boolean isPost) { + mc.getCall().receiverImplicitlyBorrowed() and + // TODO: Handle index expressions as calls in data flow. + not mc.getCall() instanceof IndexExpr + } or TSsaNode(SsaImpl::DataFlowIntegration::SsaNode node) or TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) or TClosureSelfReferenceNode(CfgScope c) { lambdaCreationExpr(c, _) } or From 153e91bebbf8c458c76708148441bd1facdf078b Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Tue, 24 Jun 2025 09:30:23 +0200 Subject: [PATCH 4/4] Rust: Re-enable special casing in indexing for `Vec` --- rust/ql/lib/codeql/rust/internal/TypeInference.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rust/ql/lib/codeql/rust/internal/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/TypeInference.qll index 04cb6b2c4840..2052f3f74d9d 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeInference.qll @@ -1132,6 +1132,8 @@ private Type inferIndexExprType(IndexExpr ie, TypePath path) { ) and result = inferType(ie.getBase(), exprPath) | + exprPath.isCons(any(Vec v).getElementTypeParameter(), path) + or exprPath.isCons(any(ArrayTypeParameter tp), path) or exists(TypePath path0 |