Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rust: Placeholder queries for unused variable, unused value #17497

Merged
merged 10 commits into from
Sep 20, 2024
24 changes: 24 additions & 0 deletions rust/ql/src/queries/unusedentities/UnusedValue.qhelp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>

<overview>
<p>This rule finds values that are assigned to variables but never used. Unused values should be removed to increase readability and avoid confusion.</p>
</overview>

<recommendation>
<p>Remove any unused values. Also remove any variables that only hold unused values.</p>
</recommendation>

<example>
<p>In the following example, there is a variable <code>average</code> that is initialized to <code>0</code>, but that value is never used:</p>
<sample src="UnusedValueBad.rs" />
<p>The problem can be fixed by removing the value and the variable that contains it:</p>
<sample src="UnusedValueGood.rs" />
</example>

<references>
<li>GeeksforGeeks: <a href="https://www.geeksforgeeks.org/how-to-avoid-unused-variable-warning-in-rust/">How to avoid unused Variable warning in Rust?</a></li>
</references>
</qhelp>
11 changes: 11 additions & 0 deletions rust/ql/src/queries/unusedentities/UnusedValue.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* @name Unused value
* @description Unused values may be an indication that the code is incomplete or has a typo.
* @kind problem
* @problem.severity recommendation
* @precision high
* @id rust/unused-value
* @tags maintainability
*/

select 1, "Variable is assigned a value that is never used."
10 changes: 10 additions & 0 deletions rust/ql/src/queries/unusedentities/UnusedValueBad.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
fn get_sum(values:&[i32]) -> i32 {
let mut sum = 0;
let mut average = 0; // BAD: unused value

for v in values {
sum += v;
}

return sum;
}
geoffw0 marked this conversation as resolved.
Show resolved Hide resolved
9 changes: 9 additions & 0 deletions rust/ql/src/queries/unusedentities/UnusedValueGood.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
fn get_sum(values:&[i32]) -> i32 {
let mut sum = 0;

for v in values {
sum += v;
}

return sum;
}
24 changes: 24 additions & 0 deletions rust/ql/src/queries/unusedentities/UnusedVariable.qhelp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>

<overview>
<p>This rule finds variables that are never accessed. Unused variables should be removed to increase readability and avoid confusion.</p>
</overview>

<recommendation>
<p>Remove any unused variables.</p>
</recommendation>

<example>
<p>In the following example, there is an unused variable <code>average</code> that is never used:</p>
<sample src="UnusedVariableBad.rs" />
<p>The problem can be fixed simply by removing the variable:</p>
<sample src="UnusedVariableGood.rs" />
</example>

<references>
<li>GeeksforGeeks: <a href="https://www.geeksforgeeks.org/how-to-avoid-unused-variable-warning-in-rust/">How to avoid unused Variable warning in Rust?</a></li>
</references>
</qhelp>
11 changes: 11 additions & 0 deletions rust/ql/src/queries/unusedentities/UnusedVariable.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* @name Unused variable
* @description Unused variables may be an indication that the code is incomplete or has a typo.
* @kind problem
* @problem.severity recommendation
* @precision high
* @id rust/unused-variable
* @tags maintainability
*/

select 1, "Variable is not used."
10 changes: 10 additions & 0 deletions rust/ql/src/queries/unusedentities/UnusedVariableBad.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
fn get_sum(values:&[i32]) -> i32 {
let mut sum = 0;
let mut average; // BAD: unused variable

for v in values {
sum += v;
}

return sum;
}
9 changes: 9 additions & 0 deletions rust/ql/src/queries/unusedentities/UnusedVariableGood.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
fn get_sum(values:&[i32]) -> i32 {
let mut sum = 0;

for v in values {
sum += v;
}

return sum;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
| 1 | Variable is assigned a value that is never used. |
1 change: 1 addition & 0 deletions rust/ql/test/query-tests/unusedentities/UnusedValue.qlref
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
queries/unusedentities/UnusedValue.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
| 1 | Variable is not used. |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
queries/unusedentities/UnusedVariable.ql
152 changes: 152 additions & 0 deletions rust/ql/test/query-tests/unusedentities/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@

//fn cond() -> bool;

// --- locals ---

fn locals_1() {
let a = 1; // BAD: unused value
let b = 1;
let c = 1;
let d = String::from("a"); // BAD: unused value
let e = String::from("b");
let _ = 1; // (deliberately unused)

println!("use {}", b);

if cond() {
println!("use {}", c);
}

println!("use {}", e);
}

fn locals_2() {
let a: i32;
let b: i32; // BAD: unused variable
let mut c: i32;
let mut d: i32;
let mut e: i32;
let mut f: i32;
let g: i32;
let h: i32;
let i: i32;

b = 1; // BAD: unused value

c = 1; // BAD: unused value
c = 2;
println!("use {}", c);
c = 3; // BAD: unused value

d = 1;
if cond() {
d = 2; // BAD: unused value
d = 3;
} else {
}
println!("use {}", d);

e = 1; // BAD: unused value
if cond() {
e = 2;
} else {
e = 3;
}
println!("use {}", e);

f = 1;
f += 1;
println!("use {}", f);
f += 1; // BAD: unused value
f = 1;
f += 1; // BAD: unused value

g = if cond() { 1 } else { 2 }; // BAD: unused value (x2)
h = if cond() { 3 } else { 4 };
i = if cond() { h } else { 5 };
println!("use {}", i);

_ = 1; // (deliberately unused)
}

// --- structs ---

#[derive(Debug)]
struct MyStruct {
val: i64
}

impl MyStruct {
fn my_get(&mut self) -> i64 {
return self.val;
}
}

fn structs() {
let a = MyStruct {val : 1 }; // BAD: unused value
let b = MyStruct {val : 2 };
let c = MyStruct {val : 3 };
let mut d : MyStruct; // BAD: unused variable
let mut e : MyStruct;
let mut f : MyStruct;

println!("lets use {:?} and {}", b, c.val);

e = MyStruct {val : 4 };
println!("lets use {}", e.my_get());
e.val = 5;
println!("lets use {}", e.my_get());

f = MyStruct {val : 6 }; // BAD: unused value
f.val = 7; // BAD: unused value
}

// --- arrays ---

fn arrays() {
let is = [1, 2, 3]; // BAD: unused values (x3)
let js = [1, 2, 3];
let ks = [1, 2, 3];

println!("lets use {:?}", js);

for k in ks {
println!("lets use {}", k);
}
}

// --- constants and statics ---

const CON1: i32 = 1;
const CON2: i32 = 2; // BAD: unused value
static mut STAT1: i32 = 1;
static mut STAT2: i32 = 2; // BAD: unused value

fn statics() {
static mut STAT3: i32 = 0;
static mut STAT4: i32 = 0; // BAD: unused value

unsafe
{
let total = CON1 + STAT1 + STAT3;
}
}

// --- parameters ---

fn parameters(
x: i32,
y: i32, // BAD: unused variable
_z: i32 // (`_` is asking the compiler, and by extension us, to not warn that this is unused)
) -> i32 {
return x;
}

fn main() {
locals_1();
locals_2();
structs();
arrays();
statics();
println!("lets use result {}", parameters(1, 2, 3));
}
Loading