From 0547e9c98d5a8ef5133291520223d67214a8a49a Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 1 Jun 2026 15:18:21 +0200 Subject: [PATCH 1/4] Rust: Path resolution for `static` items --- .../lib/codeql/rust/elements/StaticAccess.qll | 7 + .../rust/elements/internal/ConstImpl.qll | 4 +- .../rust/elements/internal/StaticImpl.qll | 31 ++- .../codeql/rust/internal/PathResolution.qll | 32 +++ rust/ql/lib/rust.qll | 1 + rust/ql/test/TestUtils.qll | 9 + .../generated/Const/Const.expected | 8 +- .../ExternItemList/ExternItemList.expected | 2 +- .../generated/Static/Static.expected | 8 +- .../macro-expansion/PrintAst.expected | 2 +- .../macro-expansion/test.expected | 2 +- .../const_access/const_access.expected | 15 +- .../const_access/const_access.ql | 14 +- .../test/library-tests/const_access/main.rs | 30 ++- .../library-tests/controlflow/Cfg.expected | 4 +- .../library-tests/path-resolution/main.rs | 46 ++++ .../path-resolution/path-resolution.expected | 199 ++++++++++-------- .../library-tests/static_access/Cargo.lock | 7 + .../test/library-tests/static_access/main.rs | 33 +++ .../static_access/static_access.expected | 8 + .../static_access/static_access.ql | 31 +++ .../test/library-tests/variables/variables.ql | 7 - 22 files changed, 378 insertions(+), 122 deletions(-) create mode 100644 rust/ql/lib/codeql/rust/elements/StaticAccess.qll create mode 100644 rust/ql/test/library-tests/static_access/Cargo.lock create mode 100644 rust/ql/test/library-tests/static_access/main.rs create mode 100644 rust/ql/test/library-tests/static_access/static_access.expected create mode 100644 rust/ql/test/library-tests/static_access/static_access.ql diff --git a/rust/ql/lib/codeql/rust/elements/StaticAccess.qll b/rust/ql/lib/codeql/rust/elements/StaticAccess.qll new file mode 100644 index 000000000000..50b4bea14d1a --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/StaticAccess.qll @@ -0,0 +1,7 @@ +/** + * This module provides the public class `StaticAccess`. + */ + +private import internal.StaticImpl + +final class StaticAccess = Impl::StaticAccess; diff --git a/rust/ql/lib/codeql/rust/elements/internal/ConstImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ConstImpl.qll index 44114674a566..776215ee4f40 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ConstImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ConstImpl.qll @@ -24,7 +24,9 @@ module Impl { * const X: i32 = 42; * ``` */ - class Const extends Generated::Const { } + class Const extends Generated::Const { + override string toStringImpl() { result = "const " + this.getName().getText() } + } /** * A constant access. diff --git a/rust/ql/lib/codeql/rust/elements/internal/StaticImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/StaticImpl.qll index 53042411bca4..7eb08653d2d3 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/StaticImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/StaticImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `Static`. * @@ -6,6 +5,9 @@ */ private import codeql.rust.elements.internal.generated.Static +private import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl +private import codeql.rust.elements.internal.PathExprImpl::Impl as PathExprImpl +private import codeql.rust.internal.PathResolution /** * INTERNAL: This module contains the customizable definition of `Static` and should not @@ -20,5 +22,30 @@ module Impl { * static X: i32 = 42; * ``` */ - class Static extends Generated::Static { } + class Static extends Generated::Static { + override string toStringImpl() { result = "static " + this.getName().getText() } + } + + /** + * A static access. + * + * For example: + * ```rust + * static X: i32 = 42; + * + * fn main() { + * println!("{}", X); + * } + * ``` + */ + class StaticAccess extends AstNodeImpl::AstNode, PathExprImpl::PathExpr { + private Static s; + + StaticAccess() { s = resolvePath(this.getPath()) } + + /** Gets the static being accessed. */ + Static getStatic() { result = s } + + override string getAPrimaryQlClass() { result = "StaticAccess" } + } } diff --git a/rust/ql/lib/codeql/rust/internal/PathResolution.qll b/rust/ql/lib/codeql/rust/internal/PathResolution.qll index 10d18786880b..7235f3e05e6c 100644 --- a/rust/ql/lib/codeql/rust/internal/PathResolution.qll +++ b/rust/ql/lib/codeql/rust/internal/PathResolution.qll @@ -659,6 +659,38 @@ private class ConstItemNode extends AssocItemNode instanceof Const { override TypeParam getTypeParam(int i) { none() } } +private class StaticItemNode extends ItemNode instanceof Static { + override string getName() { result = Static.super.getName().getText() } + + override Namespace getNamespace() { result.isValue() } + + override Visibility getVisibility() { result = Static.super.getVisibility() } + + override Attr getAnAttr() { result = Static.super.getAnAttr() } + + override TypeParam getTypeParam(int i) { none() } + + override predicate hasCanonicalPath(Crate c) { this.hasCanonicalPathPrefix(c) } + + bindingset[c] + private string getCanonicalPathPart(Crate c, int i) { + i = 0 and + result = this.getCanonicalPathPrefix(c) + or + i = 1 and + result = "::" + or + i = 2 and + result = this.getName() + } + + language[monotonicAggregates] + override string getCanonicalPath(Crate c) { + this.hasCanonicalPath(c) and + result = strictconcat(int i | i in [0 .. 2] | this.getCanonicalPathPart(c, i) order by i) + } +} + private class TypeItemTypeItemNode extends NamedItemNode, TypeItemNode instanceof TypeItem { override string getName() { result = TypeItem.super.getName().getText() } diff --git a/rust/ql/lib/rust.qll b/rust/ql/lib/rust.qll index 410f062d91ea..46e6e605d418 100644 --- a/rust/ql/lib/rust.qll +++ b/rust/ql/lib/rust.qll @@ -11,6 +11,7 @@ import codeql.rust.elements.AssignmentOperation import codeql.rust.elements.BitwiseOperation import codeql.rust.elements.ComparisonOperation import codeql.rust.elements.ConstAccess +import codeql.rust.elements.StaticAccess import codeql.rust.elements.DerefExpr import codeql.rust.elements.LiteralExprExt import codeql.rust.elements.LogicalOperation diff --git a/rust/ql/test/TestUtils.qll b/rust/ql/test/TestUtils.qll index a68d9554d34b..d622af7f4d35 100644 --- a/rust/ql/test/TestUtils.qll +++ b/rust/ql/test/TestUtils.qll @@ -20,3 +20,12 @@ class CrateElement extends Element { class Builtin extends AstNode { Builtin() { this.getFile().getAbsolutePath().matches("%/builtins/%.rs") } } + +predicate commmentAt(string text, string filepath, int line) { + exists(Comment c | + c.getLocation().hasLocationInfo(filepath, line, _, _, _) and + c.getCommentText().trim() = text and + c.fromSource() and + not text.matches("$%") + ) +} diff --git a/rust/ql/test/extractor-tests/generated/Const/Const.expected b/rust/ql/test/extractor-tests/generated/Const/Const.expected index cc1f282193fc..0ab5fbb85db4 100644 --- a/rust/ql/test/extractor-tests/generated/Const/Const.expected +++ b/rust/ql/test/extractor-tests/generated/Const/Const.expected @@ -1,13 +1,13 @@ instances -| gen_const.rs:4:5:7:22 | Const | isConst: | yes | isDefault: | no | hasImplementation: | yes | +| gen_const.rs:4:5:7:22 | const X | isConst: | yes | isDefault: | no | hasImplementation: | yes | getAttributeMacroExpansion getAttr getBody -| gen_const.rs:4:5:7:22 | Const | gen_const.rs:7:20:7:21 | 42 | +| gen_const.rs:4:5:7:22 | const X | gen_const.rs:7:20:7:21 | 42 | getGenericParamList getName -| gen_const.rs:4:5:7:22 | Const | gen_const.rs:7:11:7:11 | X | +| gen_const.rs:4:5:7:22 | const X | gen_const.rs:7:11:7:11 | X | getTypeRepr -| gen_const.rs:4:5:7:22 | Const | gen_const.rs:7:14:7:16 | i32 | +| gen_const.rs:4:5:7:22 | const X | gen_const.rs:7:14:7:16 | i32 | getVisibility getWhereClause diff --git a/rust/ql/test/extractor-tests/generated/ExternItemList/ExternItemList.expected b/rust/ql/test/extractor-tests/generated/ExternItemList/ExternItemList.expected index 8b6eb94b1b2c..579420663aff 100644 --- a/rust/ql/test/extractor-tests/generated/ExternItemList/ExternItemList.expected +++ b/rust/ql/test/extractor-tests/generated/ExternItemList/ExternItemList.expected @@ -3,4 +3,4 @@ instances getAttr getExternItem | gen_extern_item_list.rs:7:16:10:5 | ExternItemList | 0 | gen_extern_item_list.rs:8:9:8:17 | fn foo | -| gen_extern_item_list.rs:7:16:10:5 | ExternItemList | 1 | gen_extern_item_list.rs:9:9:9:24 | Static | +| gen_extern_item_list.rs:7:16:10:5 | ExternItemList | 1 | gen_extern_item_list.rs:9:9:9:24 | static BAR | diff --git a/rust/ql/test/extractor-tests/generated/Static/Static.expected b/rust/ql/test/extractor-tests/generated/Static/Static.expected index 074c6600f8c1..9ac6884c18c0 100644 --- a/rust/ql/test/extractor-tests/generated/Static/Static.expected +++ b/rust/ql/test/extractor-tests/generated/Static/Static.expected @@ -1,11 +1,11 @@ instances -| gen_static.rs:4:5:7:23 | Static | isMut: | no | isStatic: | yes | isUnsafe: | no | +| gen_static.rs:4:5:7:23 | static X | isMut: | no | isStatic: | yes | isUnsafe: | no | getAttributeMacroExpansion getAttr getBody -| gen_static.rs:4:5:7:23 | Static | gen_static.rs:7:21:7:22 | 42 | +| gen_static.rs:4:5:7:23 | static X | gen_static.rs:7:21:7:22 | 42 | getName -| gen_static.rs:4:5:7:23 | Static | gen_static.rs:7:12:7:12 | X | +| gen_static.rs:4:5:7:23 | static X | gen_static.rs:7:12:7:12 | X | getTypeRepr -| gen_static.rs:4:5:7:23 | Static | gen_static.rs:7:15:7:17 | i32 | +| gen_static.rs:4:5:7:23 | static X | gen_static.rs:7:15:7:17 | i32 | getVisibility diff --git a/rust/ql/test/extractor-tests/macro-expansion/PrintAst.expected b/rust/ql/test/extractor-tests/macro-expansion/PrintAst.expected index 6f0b278d062e..765b46d01d8a 100644 --- a/rust/ql/test/extractor-tests/macro-expansion/PrintAst.expected +++ b/rust/ql/test/extractor-tests/macro-expansion/PrintAst.expected @@ -957,7 +957,7 @@ macro_expansion.rs: # 94| getName(): [Name] MyTrait # 98| getItem(20): [Union] union MyDeriveUnion # 99| getDeriveMacroExpansion(0): [MacroItems] MacroItems -# 99| getItem(0): [Const] Const +# 99| getItem(0): [Const] const CONST_MyDeriveUnion # 98| getBody(): [IntegerLiteralExpr] 42 # 99| getName(): [Name] CONST_MyDeriveUnion # 98| getTypeRepr(): [PathTypeRepr] u32 diff --git a/rust/ql/test/extractor-tests/macro-expansion/test.expected b/rust/ql/test/extractor-tests/macro-expansion/test.expected index f47a7455e916..f7d5cae7340e 100644 --- a/rust/ql/test/extractor-tests/macro-expansion/test.expected +++ b/rust/ql/test/extractor-tests/macro-expansion/test.expected @@ -18,7 +18,7 @@ derive_macros | macro_expansion.rs:83:1:86:1 | struct MyDerive | 0 | 0 | macro_expansion.rs:84:8:85:9 | impl ...::Debug for MyDerive::<...> { ... } | | macro_expansion.rs:88:1:92:1 | enum MyDeriveEnum | 0 | 0 | macro_expansion.rs:89:6:91:12 | impl ...::PartialEq for MyDeriveEnum::<...> { ... } | | macro_expansion.rs:88:1:92:1 | enum MyDeriveEnum | 1 | 0 | macro_expansion.rs:89:6:89:17 | impl ...::Eq for MyDeriveEnum::<...> { ... } | -| macro_expansion.rs:98:1:102:1 | union MyDeriveUnion | 0 | 0 | macro_expansion.rs:99:7:99:19 | Const | +| macro_expansion.rs:98:1:102:1 | union MyDeriveUnion | 0 | 0 | macro_expansion.rs:99:7:99:19 | const CONST_MyDeriveUnion | | macro_expansion.rs:98:1:102:1 | union MyDeriveUnion | 0 | 1 | macro_expansion.rs:99:7:99:19 | impl MyTrait for MyDeriveUnion { ... } | macro_calls | macro_expansion.rs:5:9:5:35 | concat!... | macro_expansion.rs:5:17:5:34 | "Hello world!" | diff --git a/rust/ql/test/library-tests/const_access/const_access.expected b/rust/ql/test/library-tests/const_access/const_access.expected index 83c5022aca84..ccecf6365b49 100644 --- a/rust/ql/test/library-tests/const_access/const_access.expected +++ b/rust/ql/test/library-tests/const_access/const_access.expected @@ -1,8 +1,11 @@ testFailures constAccess -| main.rs:17:13:17:24 | GLOBAL_CONST | main.rs:1:1:1:29 | Const | -| main.rs:19:13:19:24 | STRING_CONST | main.rs:2:1:2:35 | Const | -| main.rs:21:13:21:33 | ...::ASSOC_CONST | main.rs:9:5:9:33 | Const | -| main.rs:23:13:23:35 | ...::MODULE_CONST | main.rs:13:5:13:38 | Const | -| main.rs:25:8:25:19 | GLOBAL_CONST | main.rs:1:1:1:29 | Const | -| main.rs:29:16:29:36 | ...::ASSOC_CONST | main.rs:9:5:9:33 | Const | +| main.rs:17:13:17:24 | GLOBAL_CONST | main.rs:1:1:1:29 | const GLOBAL_CONST | +| main.rs:19:13:19:24 | STRING_CONST | main.rs:2:1:2:35 | const STRING_CONST | +| main.rs:21:13:21:33 | ...::ASSOC_CONST | main.rs:9:5:9:33 | const ASSOC_CONST | +| main.rs:23:13:23:35 | ...::MODULE_CONST | main.rs:13:5:13:38 | const MODULE_CONST | +| main.rs:26:16:26:27 | GLOBAL_CONST | main.rs:1:1:1:29 | const GLOBAL_CONST | +| main.rs:30:16:30:36 | ...::ASSOC_CONST | main.rs:9:5:9:33 | const ASSOC_CONST | +| main.rs:33:20:33:31 | GLOBAL_CONST | main.rs:1:1:1:29 | const GLOBAL_CONST | +| main.rs:39:17:39:28 | STRING_CONST | main.rs:38:9:38:43 | const STRING_CONST | +| main.rs:43:21:43:32 | STRING_CONST | main.rs:42:13:42:48 | const STRING_CONST | diff --git a/rust/ql/test/library-tests/const_access/const_access.ql b/rust/ql/test/library-tests/const_access/const_access.ql index b3bb73633927..f10479fdb813 100644 --- a/rust/ql/test/library-tests/const_access/const_access.ql +++ b/rust/ql/test/library-tests/const_access/const_access.ql @@ -5,15 +5,25 @@ import TestUtils query predicate constAccess(ConstAccess ca, Const c) { toBeTested(ca) and c = ca.getConst() } module ConstAccessTest implements TestSig { + private predicate constAt(Const c, string filepath, int line) { + c.getLocation().hasLocationInfo(filepath, _, _, line, _) + } + string getARelevantTag() { result = "const_access" } predicate hasActualResult(Location location, string element, string tag, string value) { - exists(ConstAccess ca | + exists(ConstAccess ca, Const c, string filepath, int line | toBeTested(ca) and location = ca.getLocation() and element = ca.toString() and tag = "const_access" and - value = ca.getConst().getName().getText() + c = ca.getConst() and + constAt(c, filepath, line) + | + commmentAt(value, filepath, line) + or + not commmentAt(_, filepath, line) and + value = c.getName().getText() ) } } diff --git a/rust/ql/test/library-tests/const_access/main.rs b/rust/ql/test/library-tests/const_access/main.rs index 0cf2467d100a..aebf6bba1bfb 100644 --- a/rust/ql/test/library-tests/const_access/main.rs +++ b/rust/ql/test/library-tests/const_access/main.rs @@ -15,18 +15,34 @@ mod my_module { fn use_consts() { let x = GLOBAL_CONST; // $ const_access=GLOBAL_CONST - + let s = STRING_CONST; // $ const_access=STRING_CONST - + let y = MyStruct::ASSOC_CONST; // $ const_access=ASSOC_CONST - + let z = my_module::MODULE_CONST; // $ const_access=MODULE_CONST - - if GLOBAL_CONST > 0 { // $ const_access=GLOBAL_CONST + + #[rustfmt::skip] + let _ = if GLOBAL_CONST > 0 { // $ const_access=GLOBAL_CONST println!("positive"); - } - + }; + let arr = [MyStruct::ASSOC_CONST; 5]; // $ const_access=ASSOC_CONST + + #[rustfmt::skip] + let _ = if let GLOBAL_CONST = 0 { // $ const_access=GLOBAL_CONST + println!("zero"); + }; + + { + const STRING_CONST: &str = "inner"; // Inner1 + let _ = STRING_CONST; // $ const_access=Inner1 + + { + const STRING_CONST: &str = "inner2"; // Inner2 + let _ = STRING_CONST; // $ const_access=Inner2 + } + } } fn main() { diff --git a/rust/ql/test/library-tests/controlflow/Cfg.expected b/rust/ql/test/library-tests/controlflow/Cfg.expected index ef97a3b628f7..438b841ff165 100644 --- a/rust/ql/test/library-tests/controlflow/Cfg.expected +++ b/rust/ql/test/library-tests/controlflow/Cfg.expected @@ -1317,10 +1317,10 @@ edges | test.rs:533:21:533:48 | { ... } | test.rs:533:21:533:48 | { ... } | | | test.rs:533:48:533:48 | 0 | test.rs:533:21:533:48 | ... > ... | | | test.rs:536:9:536:10 | 42 | test.rs:529:41:537:5 | { ... } | | -| test.rs:539:5:548:5 | enter fn const_block_panic | test.rs:540:9:540:30 | Const | | +| test.rs:539:5:548:5 | enter fn const_block_panic | test.rs:540:9:540:30 | const N | | | test.rs:539:5:548:5 | exit fn const_block_panic (normal) | test.rs:539:5:548:5 | exit fn const_block_panic | | | test.rs:539:35:548:5 | { ... } | test.rs:539:5:548:5 | exit fn const_block_panic (normal) | | -| test.rs:540:9:540:30 | Const | test.rs:541:9:546:9 | ExprStmt | | +| test.rs:540:9:540:30 | const N | test.rs:541:9:546:9 | ExprStmt | | | test.rs:541:9:546:9 | ExprStmt | test.rs:541:12:541:16 | false | | | test.rs:541:9:546:9 | if false {...} | test.rs:547:9:547:9 | N | | | test.rs:541:12:541:16 | false | test.rs:541:9:546:9 | if false {...} | false | diff --git a/rust/ql/test/library-tests/path-resolution/main.rs b/rust/ql/test/library-tests/path-resolution/main.rs index c96f9ef30f0a..f95b6ef09ef3 100644 --- a/rust/ql/test/library-tests/path-resolution/main.rs +++ b/rust/ql/test/library-tests/path-resolution/main.rs @@ -1098,6 +1098,52 @@ mod self_types { } } +#[rustfmt::skip] +mod const_static { + use crate::const_static; // $ item=const_static + + pub const CONST_ITEM: i32 = 42; // $ item=i32 + + pub static STATIC_ITEM: i32 = 42; // $ item=i32 + + fn use_const_static() { + let _ = CONST_ITEM; // $ item=CONST_ITEM + let _ = STATIC_ITEM; // $ item=STATIC_ITEM + let _ = const_static::CONST_ITEM; // $ item=CONST_ITEM + let _ = const_static::STATIC_ITEM; // $ item=STATIC_ITEM + let _ = CONST_ALIAS; // $ item=C1 + let _ = STATIC_ALIAS; // $ item=S1 + + const CONST_ALIAS: i32 = CONST_ITEM // $ item=CONST_ITEM item=i32 + ; // C1 + static STATIC_ALIAS: i32 = STATIC_ITEM // $ item=STATIC_ITEM item=i32 + ; // S1 + + let _ = CONST_ALIAS; // $ item=C1 + let _ = STATIC_ALIAS; // $ item=S1 + + { + const CONST_ALIAS: i32 = CONST_ITEM // $ item=CONST_ITEM item=i32 + ; // C2 + static STATIC_ALIAS: i32 = STATIC_ITEM // $ item=STATIC_ITEM item=i32 + ; // S2 + + let _ = CONST_ALIAS; // $ item=C2 + let _ = STATIC_ALIAS; // $ item=S2 + } + + { + const CONST_ALIAS: i32 = CONST_ITEM // $ item=CONST_ITEM item=i32 + ; // C3 + static STATIC_ALIAS: i32 = STATIC_ITEM // $ item=STATIC_ITEM item=i32 + ; // S3 + + let _ = CONST_ALIAS; // $ item=C3 + let _ = STATIC_ALIAS; // $ item=S3 + } + } +} + fn main() { my::nested::nested1::nested2::f(); // $ item=I4 my::f(); // $ item=I38 diff --git a/rust/ql/test/library-tests/path-resolution/path-resolution.expected b/rust/ql/test/library-tests/path-resolution/path-resolution.expected index e85bb7876dab..ef881e62f53b 100644 --- a/rust/ql/test/library-tests/path-resolution/path-resolution.expected +++ b/rust/ql/test/library-tests/path-resolution/path-resolution.expected @@ -36,6 +36,7 @@ mod | main.rs:981:1:1022:1 | mod patterns | | main.rs:1024:1:1068:1 | mod self_constructors | | main.rs:1070:1:1099:1 | mod self_types | +| main.rs:1101:1:1145:1 | mod const_static | | my2/mod.rs:1:1:1:16 | mod nested2 | | my2/mod.rs:20:1:20:12 | mod my3 | | my2/mod.rs:22:1:23:10 | mod mymod | @@ -77,7 +78,7 @@ resolvePath | main.rs:37:17:37:24 | ...::f | main.rs:26:9:28:9 | fn f | | main.rs:39:17:39:23 | println | {EXTERNAL LOCATION} | MacroRules | | main.rs:40:17:40:17 | f | main.rs:26:9:28:9 | fn f | -| main.rs:47:9:47:13 | super | main.rs:1:1:1138:2 | SourceFile | +| main.rs:47:9:47:13 | super | main.rs:1:1:1184:2 | SourceFile | | main.rs:47:9:47:17 | ...::m1 | main.rs:20:1:44:1 | mod m1 | | main.rs:47:9:47:21 | ...::m2 | main.rs:25:5:43:5 | mod m2 | | main.rs:47:9:47:24 | ...::g | main.rs:30:9:34:9 | fn g | @@ -92,7 +93,7 @@ resolvePath | main.rs:68:17:68:19 | Foo | main.rs:66:9:66:21 | struct Foo | | main.rs:71:13:71:15 | Foo | main.rs:60:5:60:17 | struct Foo | | main.rs:73:5:73:5 | f | main.rs:62:5:69:5 | fn f | -| main.rs:75:5:75:8 | self | main.rs:1:1:1138:2 | SourceFile | +| main.rs:75:5:75:8 | self | main.rs:1:1:1184:2 | SourceFile | | main.rs:75:5:75:11 | ...::i | main.rs:78:1:90:1 | fn i | | main.rs:79:5:79:11 | println | {EXTERNAL LOCATION} | MacroRules | | main.rs:81:13:81:15 | Foo | main.rs:55:1:55:13 | struct Foo | @@ -114,7 +115,7 @@ resolvePath | main.rs:112:9:112:15 | println | {EXTERNAL LOCATION} | MacroRules | | main.rs:118:9:118:15 | println | {EXTERNAL LOCATION} | MacroRules | | main.rs:122:9:122:15 | println | {EXTERNAL LOCATION} | MacroRules | -| main.rs:125:13:125:17 | super | main.rs:1:1:1138:2 | SourceFile | +| main.rs:125:13:125:17 | super | main.rs:1:1:1184:2 | SourceFile | | main.rs:125:13:125:21 | ...::m5 | main.rs:110:1:114:1 | mod m5 | | main.rs:126:9:126:9 | f | main.rs:111:5:113:5 | fn f | | main.rs:126:9:126:9 | f | main.rs:117:5:119:5 | fn f | @@ -234,7 +235,7 @@ resolvePath | main.rs:407:13:407:16 | Self | main.rs:398:5:411:5 | trait Trait2 | | main.rs:407:13:407:19 | ...::g | main.rs:385:9:387:9 | fn g | | main.rs:409:13:409:16 | Self | main.rs:398:5:411:5 | trait Trait2 | -| main.rs:409:13:409:19 | ...::c | main.rs:394:9:395:9 | Const | +| main.rs:409:13:409:19 | ...::c | main.rs:394:9:395:9 | const c | | main.rs:416:10:418:5 | Trait1::<...> | main.rs:378:5:396:5 | trait Trait1 | | main.rs:417:7:417:7 | S | main.rs:413:5:413:13 | struct S | | main.rs:419:11:419:11 | S | main.rs:413:5:413:13 | struct S | @@ -245,7 +246,7 @@ resolvePath | main.rs:426:24:426:24 | S | main.rs:413:5:413:13 | struct S | | main.rs:427:13:427:19 | println | {EXTERNAL LOCATION} | MacroRules | | main.rs:428:13:428:16 | Self | main.rs:415:5:433:5 | impl Trait1::<...> for S { ... } | -| main.rs:428:13:428:19 | ...::c | main.rs:431:9:432:9 | Const | +| main.rs:428:13:428:19 | ...::c | main.rs:431:9:432:9 | const c | | main.rs:431:18:431:18 | S | main.rs:413:5:413:13 | struct S | | main.rs:431:22:431:22 | S | main.rs:413:5:413:13 | struct S | | main.rs:436:10:438:5 | Trait2::<...> | main.rs:398:5:411:5 | trait Trait2 | @@ -256,7 +257,7 @@ resolvePath | main.rs:441:13:441:19 | ...::g | main.rs:426:9:429:9 | fn g | | main.rs:442:13:442:19 | println | {EXTERNAL LOCATION} | MacroRules | | main.rs:443:13:443:16 | Self | main.rs:435:5:445:5 | impl Trait2::<...> for S { ... } | -| main.rs:443:13:443:19 | ...::c | main.rs:431:9:432:9 | Const | +| main.rs:443:13:443:19 | ...::c | main.rs:431:9:432:9 | const c | | main.rs:449:9:449:15 | println | {EXTERNAL LOCATION} | MacroRules | | main.rs:450:17:450:17 | S | main.rs:413:5:413:13 | struct S | | main.rs:451:9:455:9 | <...> | main.rs:378:5:396:5 | trait Trait1 | @@ -274,9 +275,9 @@ resolvePath | main.rs:463:9:463:9 | S | main.rs:413:5:413:13 | struct S | | main.rs:463:9:463:12 | ...::h | main.rs:389:9:392:9 | fn h | | main.rs:465:9:465:9 | S | main.rs:413:5:413:13 | struct S | -| main.rs:465:9:465:12 | ...::c | main.rs:431:9:432:9 | Const | +| main.rs:465:9:465:12 | ...::c | main.rs:431:9:432:9 | const c | | main.rs:466:9:470:9 | <...> | main.rs:378:5:396:5 | trait Trait1 | -| main.rs:466:9:470:12 | ...::c | main.rs:394:9:395:9 | Const | +| main.rs:466:9:470:12 | ...::c | main.rs:394:9:395:9 | const c | | main.rs:466:10:466:10 | S | main.rs:413:5:413:13 | struct S | | main.rs:467:14:469:11 | Trait1::<...> | main.rs:378:5:396:5 | trait Trait1 | | main.rs:468:13:468:13 | S | main.rs:413:5:413:13 | struct S | @@ -545,8 +546,8 @@ resolvePath | main.rs:1011:17:1011:20 | Some | {EXTERNAL LOCATION} | Some | | main.rs:1013:13:1013:16 | Some | {EXTERNAL LOCATION} | Some | | main.rs:1018:13:1018:16 | Some | {EXTERNAL LOCATION} | Some | -| main.rs:1018:18:1018:18 | z | main.rs:1005:5:1007:12 | Const | -| main.rs:1018:24:1018:24 | z | main.rs:1005:5:1007:12 | Const | +| main.rs:1018:18:1018:18 | z | main.rs:1005:5:1007:12 | const z | +| main.rs:1018:24:1018:24 | z | main.rs:1005:5:1007:12 | const z | | main.rs:1026:24:1026:26 | i32 | {EXTERNAL LOCATION} | struct i32 | | main.rs:1029:10:1029:20 | TupleStruct | main.rs:1026:5:1026:28 | struct TupleStruct | | main.rs:1031:19:1031:21 | i32 | {EXTERNAL LOCATION} | struct i32 | @@ -582,79 +583,109 @@ resolvePath | main.rs:1096:17:1096:17 | T | main.rs:1093:9:1093:9 | T | | main.rs:1097:16:1097:16 | T | main.rs:1093:9:1093:9 | T | | main.rs:1097:23:1097:26 | Self | main.rs:1090:5:1098:5 | union NonEmptyListUnion | -| main.rs:1102:5:1102:6 | my | main.rs:1:1:1:7 | mod my | -| main.rs:1102:5:1102:14 | ...::nested | my.rs:1:1:1:15 | mod nested | -| main.rs:1102:5:1102:23 | ...::nested1 | my/nested.rs:1:1:17:1 | mod nested1 | -| main.rs:1102:5:1102:32 | ...::nested2 | my/nested.rs:2:5:11:5 | mod nested2 | -| main.rs:1102:5:1102:35 | ...::f | my/nested.rs:3:9:5:9 | fn f | -| main.rs:1103:5:1103:6 | my | main.rs:1:1:1:7 | mod my | -| main.rs:1103:5:1103:9 | ...::f | my.rs:5:1:7:1 | fn f | -| main.rs:1104:5:1104:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 | -| main.rs:1104:5:1104:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 | -| main.rs:1104:5:1104:29 | ...::nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 | -| main.rs:1104:5:1104:32 | ...::f | my2/nested2.rs:3:9:5:9 | fn f | -| main.rs:1105:5:1105:5 | f | my2/nested2.rs:3:9:5:9 | fn f | -| main.rs:1106:5:1106:5 | g | my2/nested2.rs:7:9:9:9 | fn g | -| main.rs:1107:5:1107:9 | crate | main.rs:0:0:0:0 | Crate(main@0.0.1) | -| main.rs:1107:5:1107:12 | ...::h | main.rs:57:1:76:1 | fn h | -| main.rs:1108:5:1108:6 | m1 | main.rs:20:1:44:1 | mod m1 | -| main.rs:1108:5:1108:10 | ...::m2 | main.rs:25:5:43:5 | mod m2 | -| main.rs:1108:5:1108:13 | ...::g | main.rs:30:9:34:9 | fn g | -| main.rs:1109:5:1109:6 | m1 | main.rs:20:1:44:1 | mod m1 | -| main.rs:1109:5:1109:10 | ...::m2 | main.rs:25:5:43:5 | mod m2 | -| main.rs:1109:5:1109:14 | ...::m3 | main.rs:36:9:42:9 | mod m3 | -| main.rs:1109:5:1109:17 | ...::h | main.rs:37:27:41:13 | fn h | -| main.rs:1110:5:1110:6 | m4 | main.rs:46:1:53:1 | mod m4 | -| main.rs:1110:5:1110:9 | ...::i | main.rs:49:5:52:5 | fn i | -| main.rs:1111:5:1111:5 | h | main.rs:57:1:76:1 | fn h | -| main.rs:1112:5:1112:11 | f_alias | my2/nested2.rs:3:9:5:9 | fn f | -| main.rs:1113:5:1113:11 | g_alias | my2/nested2.rs:7:9:9:9 | fn g | -| main.rs:1114:5:1114:5 | j | main.rs:104:1:108:1 | fn j | -| main.rs:1115:5:1115:6 | m6 | main.rs:116:1:128:1 | mod m6 | -| main.rs:1115:5:1115:9 | ...::g | main.rs:121:5:127:5 | fn g | -| main.rs:1116:5:1116:6 | m7 | main.rs:130:1:149:1 | mod m7 | -| main.rs:1116:5:1116:9 | ...::f | main.rs:141:5:148:5 | fn f | -| main.rs:1117:5:1117:6 | m8 | main.rs:151:1:205:1 | mod m8 | -| main.rs:1117:5:1117:9 | ...::g | main.rs:189:5:204:5 | fn g | -| main.rs:1118:5:1118:6 | m9 | main.rs:207:1:215:1 | mod m9 | -| main.rs:1118:5:1118:9 | ...::f | main.rs:210:5:214:5 | fn f | -| main.rs:1119:5:1119:7 | m11 | main.rs:238:1:275:1 | mod m11 | -| main.rs:1119:5:1119:10 | ...::f | main.rs:243:5:246:5 | fn f | -| main.rs:1120:5:1120:7 | m15 | main.rs:306:1:375:1 | mod m15 | -| main.rs:1120:5:1120:10 | ...::f | main.rs:362:5:374:5 | fn f | -| main.rs:1121:5:1121:7 | m16 | main.rs:377:1:575:1 | mod m16 | -| main.rs:1121:5:1121:10 | ...::f | main.rs:447:5:471:5 | fn f | -| main.rs:1122:5:1122:20 | trait_visibility | main.rs:577:1:634:1 | mod trait_visibility | -| main.rs:1122:5:1122:23 | ...::f | main.rs:604:5:633:5 | fn f | -| main.rs:1123:5:1123:7 | m17 | main.rs:636:1:666:1 | mod m17 | -| main.rs:1123:5:1123:10 | ...::f | main.rs:660:5:665:5 | fn f | -| main.rs:1124:5:1124:11 | nested6 | my2/nested2.rs:14:5:18:5 | mod nested6 | -| main.rs:1124:5:1124:14 | ...::f | my2/nested2.rs:15:9:17:9 | fn f | -| main.rs:1125:5:1125:11 | nested8 | my2/nested2.rs:22:5:26:5 | mod nested8 | -| main.rs:1125:5:1125:14 | ...::f | my2/nested2.rs:23:9:25:9 | fn f | -| main.rs:1126:5:1126:7 | my3 | my2/mod.rs:20:1:20:12 | mod my3 | -| main.rs:1126:5:1126:10 | ...::f | my2/my3/mod.rs:1:1:5:1 | fn f | -| main.rs:1127:5:1127:12 | nested_f | my/my4/my5/mod.rs:1:1:3:1 | fn f | -| main.rs:1128:5:1128:12 | my_alias | main.rs:1:1:1:7 | mod my | -| main.rs:1128:5:1128:22 | ...::nested_f | my/my4/my5/mod.rs:1:1:3:1 | fn f | -| main.rs:1129:5:1129:7 | m18 | main.rs:668:1:686:1 | mod m18 | -| main.rs:1129:5:1129:12 | ...::m19 | main.rs:673:5:685:5 | mod m19 | -| main.rs:1129:5:1129:17 | ...::m20 | main.rs:678:9:684:9 | mod m20 | -| main.rs:1129:5:1129:20 | ...::g | main.rs:679:13:683:13 | fn g | -| main.rs:1130:5:1130:7 | m23 | main.rs:715:1:740:1 | mod m23 | -| main.rs:1130:5:1130:10 | ...::f | main.rs:735:5:739:5 | fn f | -| main.rs:1131:5:1131:7 | m24 | main.rs:742:1:810:1 | mod m24 | -| main.rs:1131:5:1131:10 | ...::f | main.rs:796:5:809:5 | fn f | -| main.rs:1132:5:1132:8 | zelf | main.rs:0:0:0:0 | Crate(main@0.0.1) | -| main.rs:1132:5:1132:11 | ...::h | main.rs:57:1:76:1 | fn h | -| main.rs:1133:5:1133:13 | z_changed | main.rs:815:1:815:9 | fn z_changed | -| main.rs:1134:5:1134:11 | AStruct | main.rs:817:1:817:17 | struct AStruct | -| main.rs:1134:5:1134:22 | ...::z_on_type | main.rs:821:5:821:17 | fn z_on_type | -| main.rs:1135:5:1135:11 | AStruct | main.rs:817:1:817:17 | struct AStruct | -| main.rs:1136:5:1136:29 | impl_with_attribute_macro | main.rs:960:1:979:1 | mod impl_with_attribute_macro | -| main.rs:1136:5:1136:35 | ...::test | main.rs:975:5:978:5 | fn test | -| main.rs:1137:5:1137:12 | patterns | main.rs:981:1:1022:1 | mod patterns | -| main.rs:1137:5:1137:18 | ...::test | main.rs:982:5:996:5 | fn test | +| main.rs:1103:9:1103:13 | crate | main.rs:0:0:0:0 | Crate(main@0.0.1) | +| main.rs:1103:9:1103:27 | ...::const_static | main.rs:1101:1:1145:1 | mod const_static | +| main.rs:1105:27:1105:29 | i32 | {EXTERNAL LOCATION} | struct i32 | +| main.rs:1107:29:1107:31 | i32 | {EXTERNAL LOCATION} | struct i32 | +| main.rs:1110:17:1110:26 | CONST_ITEM | main.rs:1105:5:1105:35 | const CONST_ITEM | +| main.rs:1111:17:1111:27 | STATIC_ITEM | main.rs:1107:5:1107:37 | static STATIC_ITEM | +| main.rs:1112:17:1112:28 | const_static | main.rs:1101:1:1145:1 | mod const_static | +| main.rs:1112:17:1112:40 | ...::CONST_ITEM | main.rs:1105:5:1105:35 | const CONST_ITEM | +| main.rs:1113:17:1113:28 | const_static | main.rs:1101:1:1145:1 | mod const_static | +| main.rs:1113:17:1113:41 | ...::STATIC_ITEM | main.rs:1107:5:1107:37 | static STATIC_ITEM | +| main.rs:1114:17:1114:27 | CONST_ALIAS | main.rs:1117:9:1118:13 | const CONST_ALIAS | +| main.rs:1115:17:1115:28 | STATIC_ALIAS | main.rs:1118:15:1120:13 | static STATIC_ALIAS | +| main.rs:1117:28:1117:30 | i32 | {EXTERNAL LOCATION} | struct i32 | +| main.rs:1117:34:1117:43 | CONST_ITEM | main.rs:1105:5:1105:35 | const CONST_ITEM | +| main.rs:1119:30:1119:32 | i32 | {EXTERNAL LOCATION} | struct i32 | +| main.rs:1119:36:1119:46 | STATIC_ITEM | main.rs:1107:5:1107:37 | static STATIC_ITEM | +| main.rs:1122:17:1122:27 | CONST_ALIAS | main.rs:1117:9:1118:13 | const CONST_ALIAS | +| main.rs:1123:17:1123:28 | STATIC_ALIAS | main.rs:1118:15:1120:13 | static STATIC_ALIAS | +| main.rs:1126:32:1126:34 | i32 | {EXTERNAL LOCATION} | struct i32 | +| main.rs:1126:38:1126:47 | CONST_ITEM | main.rs:1105:5:1105:35 | const CONST_ITEM | +| main.rs:1128:34:1128:36 | i32 | {EXTERNAL LOCATION} | struct i32 | +| main.rs:1128:40:1128:50 | STATIC_ITEM | main.rs:1107:5:1107:37 | static STATIC_ITEM | +| main.rs:1131:21:1131:31 | CONST_ALIAS | main.rs:1126:13:1127:17 | const CONST_ALIAS | +| main.rs:1132:21:1132:32 | STATIC_ALIAS | main.rs:1127:19:1129:17 | static STATIC_ALIAS | +| main.rs:1136:32:1136:34 | i32 | {EXTERNAL LOCATION} | struct i32 | +| main.rs:1136:38:1136:47 | CONST_ITEM | main.rs:1105:5:1105:35 | const CONST_ITEM | +| main.rs:1138:34:1138:36 | i32 | {EXTERNAL LOCATION} | struct i32 | +| main.rs:1138:40:1138:50 | STATIC_ITEM | main.rs:1107:5:1107:37 | static STATIC_ITEM | +| main.rs:1141:21:1141:31 | CONST_ALIAS | main.rs:1136:13:1137:17 | const CONST_ALIAS | +| main.rs:1142:21:1142:32 | STATIC_ALIAS | main.rs:1137:19:1139:17 | static STATIC_ALIAS | +| main.rs:1148:5:1148:6 | my | main.rs:1:1:1:7 | mod my | +| main.rs:1148:5:1148:14 | ...::nested | my.rs:1:1:1:15 | mod nested | +| main.rs:1148:5:1148:23 | ...::nested1 | my/nested.rs:1:1:17:1 | mod nested1 | +| main.rs:1148:5:1148:32 | ...::nested2 | my/nested.rs:2:5:11:5 | mod nested2 | +| main.rs:1148:5:1148:35 | ...::f | my/nested.rs:3:9:5:9 | fn f | +| main.rs:1149:5:1149:6 | my | main.rs:1:1:1:7 | mod my | +| main.rs:1149:5:1149:9 | ...::f | my.rs:5:1:7:1 | fn f | +| main.rs:1150:5:1150:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 | +| main.rs:1150:5:1150:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 | +| main.rs:1150:5:1150:29 | ...::nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 | +| main.rs:1150:5:1150:32 | ...::f | my2/nested2.rs:3:9:5:9 | fn f | +| main.rs:1151:5:1151:5 | f | my2/nested2.rs:3:9:5:9 | fn f | +| main.rs:1152:5:1152:5 | g | my2/nested2.rs:7:9:9:9 | fn g | +| main.rs:1153:5:1153:9 | crate | main.rs:0:0:0:0 | Crate(main@0.0.1) | +| main.rs:1153:5:1153:12 | ...::h | main.rs:57:1:76:1 | fn h | +| main.rs:1154:5:1154:6 | m1 | main.rs:20:1:44:1 | mod m1 | +| main.rs:1154:5:1154:10 | ...::m2 | main.rs:25:5:43:5 | mod m2 | +| main.rs:1154:5:1154:13 | ...::g | main.rs:30:9:34:9 | fn g | +| main.rs:1155:5:1155:6 | m1 | main.rs:20:1:44:1 | mod m1 | +| main.rs:1155:5:1155:10 | ...::m2 | main.rs:25:5:43:5 | mod m2 | +| main.rs:1155:5:1155:14 | ...::m3 | main.rs:36:9:42:9 | mod m3 | +| main.rs:1155:5:1155:17 | ...::h | main.rs:37:27:41:13 | fn h | +| main.rs:1156:5:1156:6 | m4 | main.rs:46:1:53:1 | mod m4 | +| main.rs:1156:5:1156:9 | ...::i | main.rs:49:5:52:5 | fn i | +| main.rs:1157:5:1157:5 | h | main.rs:57:1:76:1 | fn h | +| main.rs:1158:5:1158:11 | f_alias | my2/nested2.rs:3:9:5:9 | fn f | +| main.rs:1159:5:1159:11 | g_alias | my2/nested2.rs:7:9:9:9 | fn g | +| main.rs:1160:5:1160:5 | j | main.rs:104:1:108:1 | fn j | +| main.rs:1161:5:1161:6 | m6 | main.rs:116:1:128:1 | mod m6 | +| main.rs:1161:5:1161:9 | ...::g | main.rs:121:5:127:5 | fn g | +| main.rs:1162:5:1162:6 | m7 | main.rs:130:1:149:1 | mod m7 | +| main.rs:1162:5:1162:9 | ...::f | main.rs:141:5:148:5 | fn f | +| main.rs:1163:5:1163:6 | m8 | main.rs:151:1:205:1 | mod m8 | +| main.rs:1163:5:1163:9 | ...::g | main.rs:189:5:204:5 | fn g | +| main.rs:1164:5:1164:6 | m9 | main.rs:207:1:215:1 | mod m9 | +| main.rs:1164:5:1164:9 | ...::f | main.rs:210:5:214:5 | fn f | +| main.rs:1165:5:1165:7 | m11 | main.rs:238:1:275:1 | mod m11 | +| main.rs:1165:5:1165:10 | ...::f | main.rs:243:5:246:5 | fn f | +| main.rs:1166:5:1166:7 | m15 | main.rs:306:1:375:1 | mod m15 | +| main.rs:1166:5:1166:10 | ...::f | main.rs:362:5:374:5 | fn f | +| main.rs:1167:5:1167:7 | m16 | main.rs:377:1:575:1 | mod m16 | +| main.rs:1167:5:1167:10 | ...::f | main.rs:447:5:471:5 | fn f | +| main.rs:1168:5:1168:20 | trait_visibility | main.rs:577:1:634:1 | mod trait_visibility | +| main.rs:1168:5:1168:23 | ...::f | main.rs:604:5:633:5 | fn f | +| main.rs:1169:5:1169:7 | m17 | main.rs:636:1:666:1 | mod m17 | +| main.rs:1169:5:1169:10 | ...::f | main.rs:660:5:665:5 | fn f | +| main.rs:1170:5:1170:11 | nested6 | my2/nested2.rs:14:5:18:5 | mod nested6 | +| main.rs:1170:5:1170:14 | ...::f | my2/nested2.rs:15:9:17:9 | fn f | +| main.rs:1171:5:1171:11 | nested8 | my2/nested2.rs:22:5:26:5 | mod nested8 | +| main.rs:1171:5:1171:14 | ...::f | my2/nested2.rs:23:9:25:9 | fn f | +| main.rs:1172:5:1172:7 | my3 | my2/mod.rs:20:1:20:12 | mod my3 | +| main.rs:1172:5:1172:10 | ...::f | my2/my3/mod.rs:1:1:5:1 | fn f | +| main.rs:1173:5:1173:12 | nested_f | my/my4/my5/mod.rs:1:1:3:1 | fn f | +| main.rs:1174:5:1174:12 | my_alias | main.rs:1:1:1:7 | mod my | +| main.rs:1174:5:1174:22 | ...::nested_f | my/my4/my5/mod.rs:1:1:3:1 | fn f | +| main.rs:1175:5:1175:7 | m18 | main.rs:668:1:686:1 | mod m18 | +| main.rs:1175:5:1175:12 | ...::m19 | main.rs:673:5:685:5 | mod m19 | +| main.rs:1175:5:1175:17 | ...::m20 | main.rs:678:9:684:9 | mod m20 | +| main.rs:1175:5:1175:20 | ...::g | main.rs:679:13:683:13 | fn g | +| main.rs:1176:5:1176:7 | m23 | main.rs:715:1:740:1 | mod m23 | +| main.rs:1176:5:1176:10 | ...::f | main.rs:735:5:739:5 | fn f | +| main.rs:1177:5:1177:7 | m24 | main.rs:742:1:810:1 | mod m24 | +| main.rs:1177:5:1177:10 | ...::f | main.rs:796:5:809:5 | fn f | +| main.rs:1178:5:1178:8 | zelf | main.rs:0:0:0:0 | Crate(main@0.0.1) | +| main.rs:1178:5:1178:11 | ...::h | main.rs:57:1:76:1 | fn h | +| main.rs:1179:5:1179:13 | z_changed | main.rs:815:1:815:9 | fn z_changed | +| main.rs:1180:5:1180:11 | AStruct | main.rs:817:1:817:17 | struct AStruct | +| main.rs:1180:5:1180:22 | ...::z_on_type | main.rs:821:5:821:17 | fn z_on_type | +| main.rs:1181:5:1181:11 | AStruct | main.rs:817:1:817:17 | struct AStruct | +| main.rs:1182:5:1182:29 | impl_with_attribute_macro | main.rs:960:1:979:1 | mod impl_with_attribute_macro | +| main.rs:1182:5:1182:35 | ...::test | main.rs:975:5:978:5 | fn test | +| main.rs:1183:5:1183:12 | patterns | main.rs:981:1:1022:1 | mod patterns | +| main.rs:1183:5:1183:18 | ...::test | main.rs:982:5:996:5 | fn test | | my2/mod.rs:4:5:4:11 | println | {EXTERNAL LOCATION} | MacroRules | | my2/mod.rs:5:5:5:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 | | my2/mod.rs:5:5:5:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 | @@ -680,7 +711,7 @@ resolvePath | my2/my3/mod.rs:3:5:3:5 | g | my2/mod.rs:3:1:6:1 | fn g | | my2/my3/mod.rs:4:5:4:5 | h | main.rs:57:1:76:1 | fn h | | my2/my3/mod.rs:7:5:7:9 | super | my2/mod.rs:1:1:25:34 | SourceFile | -| my2/my3/mod.rs:7:5:7:16 | ...::super | main.rs:1:1:1138:2 | SourceFile | +| my2/my3/mod.rs:7:5:7:16 | ...::super | main.rs:1:1:1184:2 | SourceFile | | my2/my3/mod.rs:7:5:7:19 | ...::h | main.rs:57:1:76:1 | fn h | | my2/my3/mod.rs:8:5:8:9 | super | my2/mod.rs:1:1:25:34 | SourceFile | | my2/my3/mod.rs:8:5:8:12 | ...::g | my2/mod.rs:3:1:6:1 | fn g | diff --git a/rust/ql/test/library-tests/static_access/Cargo.lock b/rust/ql/test/library-tests/static_access/Cargo.lock new file mode 100644 index 000000000000..b9856cfaf77d --- /dev/null +++ b/rust/ql/test/library-tests/static_access/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "test" +version = "0.0.1" diff --git a/rust/ql/test/library-tests/static_access/main.rs b/rust/ql/test/library-tests/static_access/main.rs new file mode 100644 index 000000000000..33f170874cfb --- /dev/null +++ b/rust/ql/test/library-tests/static_access/main.rs @@ -0,0 +1,33 @@ +static GLOBAL_STATIC: i32 = 42; +static STRING_STATIC: &str = "hello"; + +mod my_module { + pub static MODULE_STATIC: i32 = 200; +} + +fn use_statics() { + let x = GLOBAL_STATIC; // $ static_access=GLOBAL_STATIC + + let s = STRING_STATIC; // $ static_access=STRING_STATIC + + let z = my_module::MODULE_STATIC; // $ static_access=MODULE_STATIC + + #[rustfmt::skip] + let _ = if GLOBAL_STATIC > 0 { // $ static_access=GLOBAL_STATIC + println!("positive"); + }; + + { + static STRING_STATIC: &str = "inner"; // Inner1 + let _ = STRING_STATIC; // $ static_access=Inner1 + + { + static STRING_STATIC: &str = "inner2"; // Inner2 + let _ = STRING_STATIC; // $ static_access=Inner2 + } + } +} + +fn main() { + use_statics(); +} diff --git a/rust/ql/test/library-tests/static_access/static_access.expected b/rust/ql/test/library-tests/static_access/static_access.expected new file mode 100644 index 000000000000..893b356418ff --- /dev/null +++ b/rust/ql/test/library-tests/static_access/static_access.expected @@ -0,0 +1,8 @@ +testFailures +staticAccess +| main.rs:9:13:9:25 | GLOBAL_STATIC | main.rs:1:1:1:31 | static GLOBAL_STATIC | +| main.rs:11:13:11:25 | STRING_STATIC | main.rs:2:1:2:37 | static STRING_STATIC | +| main.rs:13:13:13:36 | ...::MODULE_STATIC | main.rs:5:5:5:40 | static MODULE_STATIC | +| main.rs:16:16:16:28 | GLOBAL_STATIC | main.rs:1:1:1:31 | static GLOBAL_STATIC | +| main.rs:22:17:22:29 | STRING_STATIC | main.rs:21:9:21:45 | static STRING_STATIC | +| main.rs:26:21:26:33 | STRING_STATIC | main.rs:25:13:25:50 | static STRING_STATIC | diff --git a/rust/ql/test/library-tests/static_access/static_access.ql b/rust/ql/test/library-tests/static_access/static_access.ql new file mode 100644 index 000000000000..d755bf5a3506 --- /dev/null +++ b/rust/ql/test/library-tests/static_access/static_access.ql @@ -0,0 +1,31 @@ +import rust +import utils.test.InlineExpectationsTest +import TestUtils + +query predicate staticAccess(StaticAccess sa, Static s) { toBeTested(sa) and s = sa.getStatic() } + +module StaticAccessTest implements TestSig { + private predicate staticAt(Static s, string filepath, int line) { + s.getLocation().hasLocationInfo(filepath, _, _, line, _) + } + + string getARelevantTag() { result = "static_access" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + exists(StaticAccess sa, Static s, string filepath, int line | + toBeTested(sa) and + location = sa.getLocation() and + element = sa.toString() and + tag = "static_access" and + s = sa.getStatic() and + staticAt(s, filepath, line) + | + commmentAt(value, filepath, line) + or + not commmentAt(_, filepath, line) and + value = s.getName().getText() + ) + } +} + +import MakeTest diff --git a/rust/ql/test/library-tests/variables/variables.ql b/rust/ql/test/library-tests/variables/variables.ql index 9997b29c7d0e..8380512d99fb 100644 --- a/rust/ql/test/library-tests/variables/variables.ql +++ b/rust/ql/test/library-tests/variables/variables.ql @@ -38,13 +38,6 @@ module VariableAccessTest implements TestSig { if v.getPat().isFromMacroExpansion() then inMacro = true else inMacro = false } - private predicate commmentAt(string text, string filepath, int line) { - exists(Comment c | - c.getLocation().hasLocationInfo(filepath, line, _, _, _) and - c.getCommentText().trim() = text - ) - } - private predicate decl(Variable v, string value) { exists(string filepath, int line, boolean inMacro | declAt(v, filepath, line, inMacro) | commmentAt(value, filepath, line) and inMacro = false From c4e3720d8ac899c72973708427cafc01bf786b10 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 1 Jun 2026 13:57:28 +0200 Subject: [PATCH 2/4] Rust: Run codegen --- rust/ql/.generated.list | 1 - rust/ql/.gitattributes | 1 - rust/ql/lib/codeql/rust/elements/internal/StaticImpl.qll | 1 + 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/rust/ql/.generated.list b/rust/ql/.generated.list index 87cd5eb48085..0550763ed0c8 100644 --- a/rust/ql/.generated.list +++ b/rust/ql/.generated.list @@ -373,7 +373,6 @@ lib/codeql/rust/elements/internal/SliceTypeReprImpl.qll ba1a53a3ecc90a7f54c003fc lib/codeql/rust/elements/internal/SourceFileConstructor.qll 1dc559887ea7798774528b5505c8601c61030c17480f7ffca49b68b76fcc0321 75a635b88622e3110b16795bd12ca6fc4af176c92d6e441518d60aa47255edc1 lib/codeql/rust/elements/internal/SourceFileImpl.qll 829cc59d508c190fecfcfb0e27df232fd0a53cb98a6c6f110aecc7242db6f794 2834ab836557ae294410ccde023cca6ef6315aa4b78a7c238862437cec697583 lib/codeql/rust/elements/internal/StaticConstructor.qll 6dd7ee3fd16466c407de35b439074b56341fc97a9c36846b725c2eb43fd4a643 5bf5b0e78d0e9eb294a57b91075de6e4b86a9e6335f546c83ec11ab4c51e5679 -lib/codeql/rust/elements/internal/StaticImpl.qll 48071e29c72032b59ad82771d54be92ac0f4c1a68fb1129c5c7991385804d7b1 85c0be8e37a91d6e775b191f0cb52dd8bf70418e6e9947b82c58c40a6d73b406 lib/codeql/rust/elements/internal/StmtImpl.qll ea99d261f32592ff368cc3a1960864989897c92944f1675549e0753964cb562f 9117b4cdfad56f8fa3bc5d921c2146b4ff0658e8914ac51bf48eb3e68599dd6b lib/codeql/rust/elements/internal/StmtListConstructor.qll 435d59019e17a6279110a23d3d5dfbc1d1e16fc358a93a1d688484d22a754866 23fcb60a5cbb66174e459bc10bd7c28ed532fd1ab46f10b9f0c8a6291d3e343f lib/codeql/rust/elements/internal/StructConstructor.qll 52921ea6e70421fd08884dc061d0c2dfbbb8dd83d98f1f3c70572cfe57b2a173 dcb3ea8e45ee875525c645fe5d08e6db9013b86bd351c77df4590d0c1439ab9f diff --git a/rust/ql/.gitattributes b/rust/ql/.gitattributes index 6ea7d011a5d6..e88e5d2d9609 100644 --- a/rust/ql/.gitattributes +++ b/rust/ql/.gitattributes @@ -375,7 +375,6 @@ /lib/codeql/rust/elements/internal/SourceFileConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/SourceFileImpl.qll linguist-generated /lib/codeql/rust/elements/internal/StaticConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/StaticImpl.qll linguist-generated /lib/codeql/rust/elements/internal/StmtImpl.qll linguist-generated /lib/codeql/rust/elements/internal/StmtListConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/StructConstructor.qll linguist-generated diff --git a/rust/ql/lib/codeql/rust/elements/internal/StaticImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/StaticImpl.qll index 7eb08653d2d3..42045aea6842 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/StaticImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/StaticImpl.qll @@ -14,6 +14,7 @@ private import codeql.rust.internal.PathResolution * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A static item declaration. * From 1fd31d0ddd2983d52cdef650b7b37374a4edcf61 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 1 Jun 2026 20:21:02 +0200 Subject: [PATCH 3/4] Rust: Data flow for `const`s and `static`s --- .../internal/ControlFlowGraphImpl.qll | 2 ++ .../rust/controlflow/internal/Scope.qll | 11 ++++++++ .../rust/dataflow/internal/DataFlowImpl.qll | 16 ++++++++++- .../codeql/rust/dataflow/internal/Node.qll | 14 +++++++++- .../lib/codeql/rust/elements/StaticAccess.qll | 4 +++ .../rust/elements/internal/AstNodeImpl.qll | 16 ++++++++++- .../rust/elements/internal/ConstImpl.qll | 3 ++ .../rust/elements/internal/StaticImpl.qll | 14 ++++++++++ .../library-tests/controlflow/Cfg.expected | 3 +- .../dataflow/global/inline-flow.expected | 25 +++++++++++++++++ .../library-tests/dataflow/global/main.rs | 21 +++++++++++++- .../dataflow/global/viableCallable.expected | 28 +++++++++++-------- .../dataflow/global/viableCallable.ql | 3 +- .../dataflow/local/DataFlowStep.expected | 2 -- .../dataflow/local/DataFlowStep.ql | 4 ++- 15 files changed, 145 insertions(+), 21 deletions(-) diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll index 16e14ce84a2e..f8a182685b64 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll @@ -99,6 +99,8 @@ class FormatTemplateVariableAccessTree extends LeafTree, FormatTemplateVariableA class ItemTree extends LeafTree, Item { ItemTree() { not this instanceof MacroCall and + not this instanceof Const and + not this instanceof Static and this = any(StmtList s).getAStatement() } } diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/Scope.qll b/rust/ql/lib/codeql/rust/controlflow/internal/Scope.qll index 94c5300b062c..303920ce7d0e 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/Scope.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/Scope.qll @@ -45,3 +45,14 @@ final class CallableScope extends CfgScopeImpl, Callable { /** Holds if `scope` is exited when `last` finishes with completion `c`. */ override predicate scopeLast(AstNode last, Completion c) { last(this.getBody(), last, c) } } + +/** + * A special scope used to represent the context in which `const`s and + * `static`s are initialized. We do not actually compute a CFG for such + * scopes. + */ +final class SourceFileScope extends CfgScopeImpl, SourceFile { + override predicate scopeFirst(AstNode first) { none() } + + override predicate scopeLast(AstNode last, Completion c) { none() } +} diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll index 4ad3af0f42a0..a7e2e2e4c6bc 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll @@ -653,8 +653,22 @@ module RustDataFlowGen implements InputSig */ predicate jumpStep(Node node1, Node node2) { FlowSummaryImpl::Private::Steps::summaryJumpStep(node1.(FlowSummaryNode).getSummaryNode(), - node2.(FlowSummaryNode).getSummaryNode()) or + node2.(FlowSummaryNode).getSummaryNode()) + or FlowSummaryImpl::Private::Steps::sourceJumpStep(node1.(FlowSummaryNode).getSummaryNode(), node2) + or + exists(Const c | + node1.asExpr() = c.getBody() and + node2.asExpr() = c.getAnAccess() + ) + or + exists(StaticNode sn, Static s | s = sn.getStatic() | + node1 = sn and + node2.asExpr() = s.getAnAccess().(StaticReadAccess) + or + node1.asExpr() = [s.getBody(), s.getAnAccess().(StaticWriteAccess)] and + node2 = sn + ) } pragma[nomagic] diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/Node.qll b/rust/ql/lib/codeql/rust/dataflow/internal/Node.qll index 1ccb7db73f52..9ef2c3a08faf 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/Node.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/Node.qll @@ -704,6 +704,17 @@ final class CastNode extends ExprNode { CastNode() { none() } } +/** + * A node in the data flow graph that corresponds to a `static`. + */ +class StaticNode extends AstNodeNode, TStaticNode { + override Static n; + + StaticNode() { this = TStaticNode(n) } + + Static getStatic() { result = n } +} + cached newtype TNode = TExprNode(Expr e) { e.hasEnclosingCfgScope() and Stages::DataFlowStage::ref() } or @@ -755,4 +766,5 @@ newtype TNode = ) } or TClosureSelfReferenceNode(CfgScope c) { lambdaCreationExpr(c) } or - TCaptureNode(VariableCapture::Flow::SynthesizedCaptureNode cn) + TCaptureNode(VariableCapture::Flow::SynthesizedCaptureNode cn) or + TStaticNode(Static s) diff --git a/rust/ql/lib/codeql/rust/elements/StaticAccess.qll b/rust/ql/lib/codeql/rust/elements/StaticAccess.qll index 50b4bea14d1a..f0171a23771a 100644 --- a/rust/ql/lib/codeql/rust/elements/StaticAccess.qll +++ b/rust/ql/lib/codeql/rust/elements/StaticAccess.qll @@ -5,3 +5,7 @@ private import internal.StaticImpl final class StaticAccess = Impl::StaticAccess; + +final class StaticWriteAccess = Impl::StaticWriteAccess; + +final class StaticReadAccess = Impl::StaticReadAccess; diff --git a/rust/ql/lib/codeql/rust/elements/internal/AstNodeImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/AstNodeImpl.qll index 554942f0fddc..0c9d736cc57c 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/AstNodeImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/AstNodeImpl.qll @@ -48,15 +48,29 @@ module Impl { ) } + pragma[nomagic] + private predicate isConstOrStatic(File f) { + f = this.getFile() and + ( + this instanceof Const + or + this instanceof Static + ) + } + /** Gets the CFG scope that encloses this node, if any. */ cached CfgScope getEnclosingCfgScope() { exists(AstNode p | p = this.getParentNode() | - result = p + result = p and + not result instanceof SourceFile or not p instanceof CfgScope and + not this.isConstOrStatic(_) and result = p.getEnclosingCfgScope() ) + or + this.isConstOrStatic(result.(SourceFile).getFile()) } /** Holds if this node is inside a CFG scope. */ diff --git a/rust/ql/lib/codeql/rust/elements/internal/ConstImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ConstImpl.qll index 776215ee4f40..e90ae6217798 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ConstImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ConstImpl.qll @@ -25,6 +25,9 @@ module Impl { * ``` */ class Const extends Generated::Const { + /** Gets an access to this constant item. */ + ConstAccess getAnAccess() { this = result.getConst() } + override string toStringImpl() { result = "const " + this.getName().getText() } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/StaticImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/StaticImpl.qll index 42045aea6842..8002947bae8e 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/StaticImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/StaticImpl.qll @@ -7,6 +7,7 @@ private import codeql.rust.elements.internal.generated.Static private import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl private import codeql.rust.elements.internal.PathExprImpl::Impl as PathExprImpl +private import codeql.rust.elements.internal.VariableImpl::Impl as VariableImpl private import codeql.rust.internal.PathResolution /** @@ -24,6 +25,9 @@ module Impl { * ``` */ class Static extends Generated::Static { + /** Gets an access to this static item. */ + StaticAccess getAnAccess() { this = result.getStatic() } + override string toStringImpl() { result = "static " + this.getName().getText() } } @@ -49,4 +53,14 @@ module Impl { override string getAPrimaryQlClass() { result = "StaticAccess" } } + + /** A static write access. */ + class StaticWriteAccess extends StaticAccess { + StaticWriteAccess() { VariableImpl::assignmentOperationDescendant(_, this) } + } + + /** A static read access. */ + class StaticReadAccess extends StaticAccess { + StaticReadAccess() { not this instanceof StaticWriteAccess } + } } diff --git a/rust/ql/test/library-tests/controlflow/Cfg.expected b/rust/ql/test/library-tests/controlflow/Cfg.expected index 438b841ff165..2d1036c93c93 100644 --- a/rust/ql/test/library-tests/controlflow/Cfg.expected +++ b/rust/ql/test/library-tests/controlflow/Cfg.expected @@ -1317,10 +1317,9 @@ edges | test.rs:533:21:533:48 | { ... } | test.rs:533:21:533:48 | { ... } | | | test.rs:533:48:533:48 | 0 | test.rs:533:21:533:48 | ... > ... | | | test.rs:536:9:536:10 | 42 | test.rs:529:41:537:5 | { ... } | | -| test.rs:539:5:548:5 | enter fn const_block_panic | test.rs:540:9:540:30 | const N | | +| test.rs:539:5:548:5 | enter fn const_block_panic | test.rs:541:9:546:9 | ExprStmt | | | test.rs:539:5:548:5 | exit fn const_block_panic (normal) | test.rs:539:5:548:5 | exit fn const_block_panic | | | test.rs:539:35:548:5 | { ... } | test.rs:539:5:548:5 | exit fn const_block_panic (normal) | | -| test.rs:540:9:540:30 | const N | test.rs:541:9:546:9 | ExprStmt | | | test.rs:541:9:546:9 | ExprStmt | test.rs:541:12:541:16 | false | | | test.rs:541:9:546:9 | if false {...} | test.rs:547:9:547:9 | N | | | test.rs:541:12:541:16 | false | test.rs:541:9:546:9 | if false {...} | false | diff --git a/rust/ql/test/library-tests/dataflow/global/inline-flow.expected b/rust/ql/test/library-tests/dataflow/global/inline-flow.expected index 5caa5c1c3ed9..4828b56542b8 100644 --- a/rust/ql/test/library-tests/dataflow/global/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/global/inline-flow.expected @@ -222,6 +222,15 @@ edges | main.rs:415:18:415:38 | i.get_double_number() | main.rs:415:13:415:14 | n4 | provenance | | | main.rs:418:13:418:14 | n5 | main.rs:419:14:419:15 | n5 | provenance | | | main.rs:418:18:418:41 | ...::get_default(...) | main.rs:418:13:418:14 | n5 | provenance | | +| main.rs:426:30:426:39 | source(...) | main.rs:430:35:430:45 | CONST_VALUE | provenance | | +| main.rs:427:5:427:46 | static STATIC_VALUE | main.rs:433:32:433:43 | STATIC_VALUE | provenance | | +| main.rs:427:5:427:46 | static STATIC_VALUE | main.rs:437:18:437:29 | STATIC_VALUE | provenance | | +| main.rs:427:36:427:45 | source(...) | main.rs:427:5:427:46 | static STATIC_VALUE | provenance | | +| main.rs:430:35:430:45 | CONST_VALUE | main.rs:431:14:431:25 | CONST_VALUE2 | provenance | | +| main.rs:433:17:433:28 | static_value | main.rs:434:18:434:29 | static_value | provenance | | +| main.rs:433:32:433:43 | STATIC_VALUE | main.rs:433:17:433:28 | static_value | provenance | | +| main.rs:436:13:436:24 | STATIC_VALUE | main.rs:427:5:427:46 | static STATIC_VALUE | provenance | | +| main.rs:436:28:436:37 | source(...) | main.rs:436:13:436:24 | STATIC_VALUE | provenance | | nodes | main.rs:12:28:14:1 | { ... } | semmle.label | { ... } | | main.rs:13:5:13:13 | source(...) | semmle.label | source(...) | @@ -464,6 +473,17 @@ nodes | main.rs:418:13:418:14 | n5 | semmle.label | n5 | | main.rs:418:18:418:41 | ...::get_default(...) | semmle.label | ...::get_default(...) | | main.rs:419:14:419:15 | n5 | semmle.label | n5 | +| main.rs:426:30:426:39 | source(...) | semmle.label | source(...) | +| main.rs:427:5:427:46 | static STATIC_VALUE | semmle.label | static STATIC_VALUE | +| main.rs:427:36:427:45 | source(...) | semmle.label | source(...) | +| main.rs:430:35:430:45 | CONST_VALUE | semmle.label | CONST_VALUE | +| main.rs:431:14:431:25 | CONST_VALUE2 | semmle.label | CONST_VALUE2 | +| main.rs:433:17:433:28 | static_value | semmle.label | static_value | +| main.rs:433:32:433:43 | STATIC_VALUE | semmle.label | STATIC_VALUE | +| main.rs:434:18:434:29 | static_value | semmle.label | static_value | +| main.rs:436:13:436:24 | STATIC_VALUE | semmle.label | STATIC_VALUE | +| main.rs:436:28:436:37 | source(...) | semmle.label | source(...) | +| main.rs:437:18:437:29 | STATIC_VALUE | semmle.label | STATIC_VALUE | subpaths | main.rs:38:16:38:24 | source(...) | main.rs:26:28:26:33 | ...: i64 | main.rs:26:17:26:25 | SelfParam [Return] [&ref, MyStruct] | main.rs:38:5:38:5 | [post] a [MyStruct] | | main.rs:39:10:39:10 | a [MyStruct] | main.rs:30:17:30:21 | SelfParam [&ref, MyStruct] | main.rs:30:31:32:5 | { ... } | main.rs:39:10:39:21 | a.get_data() | @@ -525,3 +545,8 @@ testFailures | main.rs:412:14:412:15 | n3 | main.rs:371:13:371:21 | source(...) | main.rs:412:14:412:15 | n3 | $@ | main.rs:371:13:371:21 | source(...) | source(...) | | main.rs:416:14:416:15 | n4 | main.rs:391:13:391:22 | source(...) | main.rs:416:14:416:15 | n4 | $@ | main.rs:391:13:391:22 | source(...) | source(...) | | main.rs:419:14:419:15 | n5 | main.rs:395:13:395:21 | source(...) | main.rs:419:14:419:15 | n5 | $@ | main.rs:395:13:395:21 | source(...) | source(...) | +| main.rs:431:14:431:25 | CONST_VALUE2 | main.rs:426:30:426:39 | source(...) | main.rs:431:14:431:25 | CONST_VALUE2 | $@ | main.rs:426:30:426:39 | source(...) | source(...) | +| main.rs:434:18:434:29 | static_value | main.rs:427:36:427:45 | source(...) | main.rs:434:18:434:29 | static_value | $@ | main.rs:427:36:427:45 | source(...) | source(...) | +| main.rs:434:18:434:29 | static_value | main.rs:436:28:436:37 | source(...) | main.rs:434:18:434:29 | static_value | $@ | main.rs:436:28:436:37 | source(...) | source(...) | +| main.rs:437:18:437:29 | STATIC_VALUE | main.rs:427:36:427:45 | source(...) | main.rs:437:18:437:29 | STATIC_VALUE | $@ | main.rs:427:36:427:45 | source(...) | source(...) | +| main.rs:437:18:437:29 | STATIC_VALUE | main.rs:436:28:436:37 | source(...) | main.rs:437:18:437:29 | STATIC_VALUE | $@ | main.rs:436:28:436:37 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/dataflow/global/main.rs b/rust/ql/test/library-tests/dataflow/global/main.rs index ac737570771f..b3a3af1be95e 100644 --- a/rust/ql/test/library-tests/dataflow/global/main.rs +++ b/rust/ql/test/library-tests/dataflow/global/main.rs @@ -1,4 +1,4 @@ -fn source(i: i64) -> i64 { +const fn source(i: i64) -> i64 { 1000 + i } @@ -420,6 +420,25 @@ mod not_trait_dispatch { } } +mod const_static { + use super::{sink, source}; + + const CONST_VALUE: i64 = source(42); + static mut STATIC_VALUE: i64 = source(43); + + fn test_const_static() { + const CONST_VALUE2: i64 = CONST_VALUE; + sink(CONST_VALUE2); // $ hasValueFlow=42 + unsafe { + let static_value = STATIC_VALUE; + sink(static_value); // $ hasValueFlow=43 $ SPURIOUS: hasValueFlow=44 (statics are not control-flow sensitive) + + STATIC_VALUE = source(44); + sink(STATIC_VALUE); // $ hasValueFlow=44 $ SPURIOUS: hasValueFlow=43 (statics are not control-flow sensitive) + } + } +} + fn main() { data_out_of_call(); data_out_of_call_side_effect1(); diff --git a/rust/ql/test/library-tests/dataflow/global/viableCallable.expected b/rust/ql/test/library-tests/dataflow/global/viableCallable.expected index 26db4dc3962e..6f30416d54a7 100644 --- a/rust/ql/test/library-tests/dataflow/global/viableCallable.expected +++ b/rust/ql/test/library-tests/dataflow/global/viableCallable.expected @@ -128,14 +128,20 @@ | main.rs:416:9:416:16 | sink(...) | main.rs:5:1:7:1 | fn sink | | main.rs:418:18:418:41 | ...::get_default(...) | main.rs:394:9:396:9 | fn get_default | | main.rs:419:9:419:16 | sink(...) | main.rs:5:1:7:1 | fn sink | -| main.rs:424:5:424:22 | data_out_of_call(...) | main.rs:16:1:19:1 | fn data_out_of_call | -| main.rs:425:5:425:35 | data_out_of_call_side_effect1(...) | main.rs:35:1:40:1 | fn data_out_of_call_side_effect1 | -| main.rs:426:5:426:35 | data_out_of_call_side_effect2(...) | main.rs:42:1:50:1 | fn data_out_of_call_side_effect2 | -| main.rs:427:5:427:21 | data_in_to_call(...) | main.rs:56:1:59:1 | fn data_in_to_call | -| main.rs:428:5:428:23 | data_through_call(...) | main.rs:65:1:69:1 | fn data_through_call | -| main.rs:429:5:429:34 | data_through_nested_function(...) | main.rs:79:1:88:1 | fn data_through_nested_function | -| main.rs:431:5:431:24 | data_out_of_method(...) | main.rs:152:1:162:1 | fn data_out_of_method | -| main.rs:432:5:432:28 | data_in_to_method_call(...) | main.rs:169:1:179:1 | fn data_in_to_method_call | -| main.rs:433:5:433:25 | data_through_method(...) | main.rs:187:1:199:1 | fn data_through_method | -| main.rs:435:5:435:31 | test_operator_overloading(...) | main.rs:256:1:298:1 | fn test_operator_overloading | -| main.rs:436:5:436:22 | test_async_await(...) | main.rs:353:1:358:1 | fn test_async_await | +| main.rs:426:30:426:39 | source(...) | main.rs:1:1:3:1 | fn source | +| main.rs:427:36:427:45 | source(...) | main.rs:1:1:3:1 | fn source | +| main.rs:431:9:431:26 | sink(...) | main.rs:5:1:7:1 | fn sink | +| main.rs:434:13:434:30 | sink(...) | main.rs:5:1:7:1 | fn sink | +| main.rs:436:28:436:37 | source(...) | main.rs:1:1:3:1 | fn source | +| main.rs:437:13:437:30 | sink(...) | main.rs:5:1:7:1 | fn sink | +| main.rs:443:5:443:22 | data_out_of_call(...) | main.rs:16:1:19:1 | fn data_out_of_call | +| main.rs:444:5:444:35 | data_out_of_call_side_effect1(...) | main.rs:35:1:40:1 | fn data_out_of_call_side_effect1 | +| main.rs:445:5:445:35 | data_out_of_call_side_effect2(...) | main.rs:42:1:50:1 | fn data_out_of_call_side_effect2 | +| main.rs:446:5:446:21 | data_in_to_call(...) | main.rs:56:1:59:1 | fn data_in_to_call | +| main.rs:447:5:447:23 | data_through_call(...) | main.rs:65:1:69:1 | fn data_through_call | +| main.rs:448:5:448:34 | data_through_nested_function(...) | main.rs:79:1:88:1 | fn data_through_nested_function | +| main.rs:450:5:450:24 | data_out_of_method(...) | main.rs:152:1:162:1 | fn data_out_of_method | +| main.rs:451:5:451:28 | data_in_to_method_call(...) | main.rs:169:1:179:1 | fn data_in_to_method_call | +| main.rs:452:5:452:25 | data_through_method(...) | main.rs:187:1:199:1 | fn data_through_method | +| main.rs:454:5:454:31 | test_operator_overloading(...) | main.rs:256:1:298:1 | fn test_operator_overloading | +| main.rs:455:5:455:22 | test_async_await(...) | main.rs:353:1:358:1 | fn test_async_await | diff --git a/rust/ql/test/library-tests/dataflow/global/viableCallable.ql b/rust/ql/test/library-tests/dataflow/global/viableCallable.ql index 3daa8b4b17f5..dbb49e4855dd 100644 --- a/rust/ql/test/library-tests/dataflow/global/viableCallable.ql +++ b/rust/ql/test/library-tests/dataflow/global/viableCallable.ql @@ -1,5 +1,6 @@ import codeql.rust.dataflow.internal.DataFlowImpl query predicate viableCallable(DataFlowCall call, DataFlowCallable callee) { - RustDataFlow::viableCallable(call) = callee + RustDataFlow::viableCallable(call) = callee and + (call.asCall().fromSource() or call.isImplicitDerefCall(_, _, _, _)) } diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index e220a769eceb..7d70ff90eaa6 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -1,6 +1,4 @@ localStep -| file://:0:0:0:0 | [summary param] 0 in fn canonicalize | file://:0:0:0:0 | [summary] read: Argument[0].OptionalBarrier[normalize-path] in fn canonicalize | -| file://:0:0:0:0 | [summary] read: Argument[self].Reference in fn canonicalize | file://:0:0:0:0 | [summary] read: Argument[self].Reference.OptionalBarrier[normalize-path] in fn canonicalize | | main.rs:4:11:4:11 | [SSA] i | main.rs:5:12:5:12 | i | | main.rs:4:11:4:11 | i | main.rs:4:11:4:11 | [SSA] i | | main.rs:4:11:4:11 | i | main.rs:4:11:4:11 | i | diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.ql b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.ql index 21e459745291..14fa90e3d448 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.ql +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.ql @@ -5,7 +5,9 @@ import utils.test.TranslateModels query predicate localStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { // Local flow steps that don't originate from a flow summary. - RustDataFlow::simpleLocalFlowStep(nodeFrom, nodeTo, "") + RustDataFlow::simpleLocalFlowStep(nodeFrom, nodeTo, "") and + nodeFrom.getLocation().fromSource() and + nodeTo.getLocation().fromSource() } class Node extends DataFlow::Node { From dc0c7d7ec221af4b3e93dbfc71eac3133054da41 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 2 Jun 2026 14:41:27 +0200 Subject: [PATCH 4/4] Fix `commment` typos --- .../lib/utils/test/PathResolutionInlineExpectationsTest.qll | 6 +++--- rust/ql/test/TestUtils.qll | 2 +- rust/ql/test/library-tests/const_access/const_access.ql | 4 ++-- rust/ql/test/library-tests/static_access/static_access.ql | 4 ++-- rust/ql/test/library-tests/variables/variables.ql | 4 ++-- shared/util/codeql/util/test/InlineExpectationsTest.qll | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/rust/ql/lib/utils/test/PathResolutionInlineExpectationsTest.qll b/rust/ql/lib/utils/test/PathResolutionInlineExpectationsTest.qll index f4544cafacc1..a6ab8cd48cab 100644 --- a/rust/ql/lib/utils/test/PathResolutionInlineExpectationsTest.qll +++ b/rust/ql/lib/utils/test/PathResolutionInlineExpectationsTest.qll @@ -14,7 +14,7 @@ private module ResolveTest implements TestSig { i.getLocation().hasLocationInfo(filepath, _, _, line, _) } - private predicate commmentAt(string text, string filepath, int line) { + private predicate commentAt(string text, string filepath, int line) { exists(Comment c | c.getLocation().hasLocationInfo(filepath, line, _, _, _) and c.getCommentText().trim() = text and @@ -28,9 +28,9 @@ private module ResolveTest implements TestSig { if i instanceof SourceFile then value = i.getFile().getBaseName() else ( - commmentAt(value, filepath, line) + commentAt(value, filepath, line) or - not commmentAt(_, filepath, line) and + not commentAt(_, filepath, line) and value = i.getName() ) ) diff --git a/rust/ql/test/TestUtils.qll b/rust/ql/test/TestUtils.qll index d622af7f4d35..a55c24544b83 100644 --- a/rust/ql/test/TestUtils.qll +++ b/rust/ql/test/TestUtils.qll @@ -21,7 +21,7 @@ class Builtin extends AstNode { Builtin() { this.getFile().getAbsolutePath().matches("%/builtins/%.rs") } } -predicate commmentAt(string text, string filepath, int line) { +predicate commentAt(string text, string filepath, int line) { exists(Comment c | c.getLocation().hasLocationInfo(filepath, line, _, _, _) and c.getCommentText().trim() = text and diff --git a/rust/ql/test/library-tests/const_access/const_access.ql b/rust/ql/test/library-tests/const_access/const_access.ql index f10479fdb813..27d1726f1067 100644 --- a/rust/ql/test/library-tests/const_access/const_access.ql +++ b/rust/ql/test/library-tests/const_access/const_access.ql @@ -20,9 +20,9 @@ module ConstAccessTest implements TestSig { c = ca.getConst() and constAt(c, filepath, line) | - commmentAt(value, filepath, line) + commentAt(value, filepath, line) or - not commmentAt(_, filepath, line) and + not commentAt(_, filepath, line) and value = c.getName().getText() ) } diff --git a/rust/ql/test/library-tests/static_access/static_access.ql b/rust/ql/test/library-tests/static_access/static_access.ql index d755bf5a3506..8a21ee5fb9b1 100644 --- a/rust/ql/test/library-tests/static_access/static_access.ql +++ b/rust/ql/test/library-tests/static_access/static_access.ql @@ -20,9 +20,9 @@ module StaticAccessTest implements TestSig { s = sa.getStatic() and staticAt(s, filepath, line) | - commmentAt(value, filepath, line) + commentAt(value, filepath, line) or - not commmentAt(_, filepath, line) and + not commentAt(_, filepath, line) and value = s.getName().getText() ) } diff --git a/rust/ql/test/library-tests/variables/variables.ql b/rust/ql/test/library-tests/variables/variables.ql index 8380512d99fb..934b3c4c4200 100644 --- a/rust/ql/test/library-tests/variables/variables.ql +++ b/rust/ql/test/library-tests/variables/variables.ql @@ -40,9 +40,9 @@ module VariableAccessTest implements TestSig { private predicate decl(Variable v, string value) { exists(string filepath, int line, boolean inMacro | declAt(v, filepath, line, inMacro) | - commmentAt(value, filepath, line) and inMacro = false + commentAt(value, filepath, line) and inMacro = false or - not (commmentAt(_, filepath, line) and inMacro = false) and + not (commentAt(_, filepath, line) and inMacro = false) and value = v.getText() ) } diff --git a/shared/util/codeql/util/test/InlineExpectationsTest.qll b/shared/util/codeql/util/test/InlineExpectationsTest.qll index e2ea9b87e74c..e785adda4566 100644 --- a/shared/util/codeql/util/test/InlineExpectationsTest.qll +++ b/shared/util/codeql/util/test/InlineExpectationsTest.qll @@ -597,7 +597,7 @@ private string mainResultSet() { result = ["#select", "problems"] } * foo(); // $ Alert[rust/unreachable-code] * ``` * - * In the example above, the `$ Alert[rust/unused-value]` commment is only taken + * In the example above, the `$ Alert[rust/unused-value]` comment is only taken * into account in the test for the query with ID `rust/unused-value`, and vice * versa for the `$ Alert[rust/unreachable-code]` comment. *