Skip to content

Commit 2b340b1

Browse files
committed
Rust: Exclude results inside macro expansions from unused entity queries
1 parent fec31a6 commit 2b340b1

File tree

7 files changed

+27
-18
lines changed

7 files changed

+27
-18
lines changed

rust/ql/lib/codeql/rust/elements/internal/AstNodeImpl.qll

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,29 @@ module Impl {
2626
result = getImmediateParent(e)
2727
}
2828

29-
/** Gets the nearest enclosing parent of `ast` that is an `AstNode`. */
30-
private AstNode getParentOfAst(AstNode ast) {
31-
result = getParentOfAstStep*(getImmediateParent(ast))
32-
}
33-
3429
class AstNode extends Generated::AstNode {
30+
/**
31+
* Gets the nearest enclosing parent of this node, which is also an `AstNode`,
32+
* if any.
33+
*/
34+
AstNode getParentNode() { result = getParentOfAstStep*(getImmediateParent(this)) }
35+
3536
/** Gets the immediately enclosing callable of this node, if any. */
3637
cached
3738
Callable getEnclosingCallable() {
38-
exists(AstNode p | p = getParentOfAst(this) |
39+
exists(AstNode p | p = this.getParentNode() |
3940
result = p
4041
or
4142
not p instanceof Callable and
4243
result = p.getEnclosingCallable()
4344
)
4445
}
46+
47+
/** Holds if this node is inside a macro expansion. */
48+
predicate isInMacroExpansion() {
49+
this = any(MacroCall mc).getExpanded()
50+
or
51+
this.getParentNode().isInMacroExpansion()
52+
}
4553
}
4654
}

rust/ql/src/queries/unusedentities/UnreachableCode.ql

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ predicate hiddenNode(AstNode n) {
2929
not succ(n, _) and
3030
not succ(_, n)
3131
or
32-
n instanceof ControlFlowGraphImpl::PostOrderTree // location is counter-intuitive
32+
n instanceof ControlFlowGraphImpl::PostOrderTree and // location is counter-intuitive
33+
not n instanceof MacroExpr
34+
or
35+
n.isInMacroExpansion()
3336
}
3437

3538
/**

rust/ql/src/queries/unusedentities/UnusedValue.ql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,6 @@ where
2020
not write = any(Ssa::WriteDefinition def).getWriteAccess().getAstNode() and
2121
// avoid overlap with the unused variable query
2222
not isUnused(v) and
23-
not v instanceof DiscardVariable
23+
not v instanceof DiscardVariable and
24+
not write.isInMacroExpansion()
2425
select write, "Variable '" + v + "' is assigned a value that is never used."

rust/ql/src/queries/unusedentities/UnusedVariable.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ predicate isUnused(Variable v) {
1010
not exists(v.getAnAccess()) and
1111
not exists(v.getInitializer()) and
1212
not v instanceof DiscardVariable and
13+
not v.getPat().isInMacroExpansion() and
1314
exists(File f | f.getBaseName() = "main.rs" | v.getLocation().getFile() = f) // temporarily severely limit results
1415
}

rust/ql/test/query-tests/unusedentities/UnreachableCode.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
| unreachable.rs:31:9:31:23 | ExprStmt | This code is never reached. |
44
| unreachable.rs:38:9:38:23 | ExprStmt | This code is never reached. |
55
| unreachable.rs:59:5:59:19 | ExprStmt | This code is never reached. |
6-
| unreachable.rs:106:13:106:20 | ExprStmt | This code is never reached. |
7-
| unreachable.rs:115:13:115:20 | ExprStmt | This code is never reached. |
6+
| unreachable.rs:106:13:106:20 | MacroExpr | This code is never reached. |
7+
| unreachable.rs:115:13:115:20 | MacroExpr | This code is never reached. |
88
| unreachable.rs:141:5:141:19 | ExprStmt | This code is never reached. |
99
| unreachable.rs:148:9:148:23 | ExprStmt | This code is never reached. |
1010
| unreachable.rs:157:13:157:27 | ExprStmt | This code is never reached. |

rust/ql/test/query-tests/unusedentities/UnusedValue.expected

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,7 @@
1111
| main.rs:87:9:87:9 | a | Variable 'a' is assigned a value that is never used. |
1212
| main.rs:108:9:108:10 | is | Variable 'is' is assigned a value that is never used. |
1313
| main.rs:131:13:131:17 | total | Variable 'total' is assigned a value that is never used. |
14-
| main.rs:194:13:194:31 | res | Variable 'res' is assigned a value that is never used. |
15-
| main.rs:206:9:206:24 | kind | Variable 'kind' is assigned a value that is never used. |
16-
| main.rs:210:9:210:32 | kind | Variable 'kind' is assigned a value that is never used. |
1714
| main.rs:266:13:266:17 | total | Variable 'total' is assigned a value that is never used. |
18-
| main.rs:334:5:334:39 | kind | Variable 'kind' is assigned a value that is never used. |
1915
| main.rs:359:9:359:9 | x | Variable 'x' is assigned a value that is never used. |
2016
| main.rs:367:17:367:17 | x | Variable 'x' is assigned a value that is never used. |
2117
| more.rs:24:9:24:11 | val | Variable 'val' is assigned a value that is never used. |

rust/ql/test/query-tests/unusedentities/main.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ fn loops() {
191191
}
192192

193193
for x in 1..10 {
194-
_ = format!("x is {x}"); // $ SPURIOUS: Alert[rust/unused-value]
194+
_ = format!("x is {x}");
195195
}
196196

197197
for x in 1..10 {
@@ -203,11 +203,11 @@ fn loops() {
203203
}
204204

205205
for x in 1..10 {
206-
assert_eq!(x, 1); // $ SPURIOUS: Alert[rust/unused-value]
206+
assert_eq!(x, 1);
207207
}
208208

209209
for x in 1..10 {
210-
assert_eq!(id(x), id(1)); // $ SPURIOUS: Alert[rust/unused-value]
210+
assert_eq!(id(x), id(1));
211211
}
212212
}
213213

@@ -331,7 +331,7 @@ fn if_lets_matches() {
331331
}
332332

333333
let duration1 = std::time::Duration::new(10, 0); // ten seconds
334-
assert_eq!(duration1.as_secs(), 10); // $ SPURIOUS: Alert[rust/unused-value]
334+
assert_eq!(duration1.as_secs(), 10);
335335

336336
let duration2: Result<std::time::Duration, String> = Ok(std::time::Duration::new(10, 0));
337337
match duration2 {

0 commit comments

Comments
 (0)