Merge pull request #17497 from geoffw0/unusedvar

Rust: Placeholder queries for unused variable, unused value
This commit is contained in:
Geoffrey White
2024-09-20 12:52:33 +01:00
committed by GitHub
13 changed files with 273 additions and 0 deletions

View File

@@ -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 unused value:</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>

View File

@@ -0,0 +1,15 @@
/**
* @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 medium
* @id rust/unused-value
* @tags maintainability
*/
import rust
from Locatable e
where none() // TODO: implement query
select e, "Variable is assigned a value that is never used."

View File

@@ -0,0 +1,11 @@
fn get_average(values:&[i32]) -> f64 {
let mut sum = 0;
let mut average = 0.0; // BAD: unused value
for v in values {
sum += v;
}
average = sum as f64 / values.len() as f64;
return average;
}

View File

@@ -0,0 +1,11 @@
fn get_average(values:&[i32]) -> f64 {
let mut sum = 0;
let average;
for v in values {
sum += v;
}
average = sum as f64 / values.len() as f64;
return average;
}

View File

@@ -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>

View File

@@ -0,0 +1,15 @@
/**
* @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 medium
* @id rust/unused-variable
* @tags maintainability
*/
import rust
from Locatable e
where none() // TODO: implement query
select e, "Variable is not used."

View File

@@ -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;
}

View File

@@ -0,0 +1,9 @@
fn get_sum(values:&[i32]) -> i32 {
let mut sum = 0;
for v in values {
sum += v;
}
return sum;
}

View File

@@ -0,0 +1 @@
queries/unusedentities/UnusedValue.ql

View File

@@ -0,0 +1 @@
queries/unusedentities/UnusedVariable.ql

View File

@@ -0,0 +1,152 @@
//fn cond() -> bool;
// --- locals ---
fn locals_1() {
let a = 1; // BAD: unused value [NOT DETECTED]
let b = 1;
let c = 1;
let d = String::from("a"); // BAD: unused value [NOT DETECTED]
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 [NOT DETECTED]
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 [NOT DETECTED]
c = 1; // BAD: unused value [NOT DETECTED]
c = 2;
println!("use {}", c);
c = 3; // BAD: unused value [NOT DETECTED]
d = 1;
if cond() {
d = 2; // BAD: unused value [NOT DETECTED]
d = 3;
} else {
}
println!("use {}", d);
e = 1; // BAD: unused value [NOT DETECTED]
if cond() {
e = 2;
} else {
e = 3;
}
println!("use {}", e);
f = 1;
f += 1;
println!("use {}", f);
f += 1; // BAD: unused value [NOT DETECTED]
f = 1;
f += 1; // BAD: unused value [NOT DETECTED]
g = if cond() { 1 } else { 2 }; // BAD: unused value (x2) [NOT DETECTED]
h = if cond() { 3 } else { 4 };
i = if cond() { h } else { 5 };
println!("use {}", i);
_ = 1; // (deliberately unused) [NOT DETECTED]
}
// --- 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 [NOT DETECTED]
let b = MyStruct {val : 2 };
let c = MyStruct {val : 3 };
let mut d : MyStruct; // BAD: unused variable [NOT DETECTED]
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 [NOT DETECTED]
f.val = 7; // BAD: unused value [NOT DETECTED]
}
// --- arrays ---
fn arrays() {
let is = [1, 2, 3]; // BAD: unused values (x3) [NOT DETECTED]
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 [NOT DETECTED]
static mut STAT1: i32 = 1;
static mut STAT2: i32 = 2; // BAD: unused value [NOT DETECTED]
fn statics() {
static mut STAT3: i32 = 0;
static mut STAT4: i32 = 0; // BAD: unused value [NOT DETECTED]
unsafe
{
let total = CON1 + STAT1 + STAT3;
}
}
// --- parameters ---
fn parameters(
x: i32,
y: i32, // BAD: unused variable [NOT DETECTED]
_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));
}