Files
codeql/rust/ql/test/query-tests/unusedentities/main.rs
2025-12-11 18:07:12 +00:00

597 lines
11 KiB
Rust

#![feature(let_chains)]
mod more;
mod unreachable;
use more::*;
use unreachable::*;
// --- locals ---
fn locals_1() {
let a = 1; // $ Alert[rust/unused-value]
let b = 1;
let c = 1;
let d = String::from("a"); // $ Alert[rust/unused-value]
let e = String::from("b");
let f = 1;
let _ = 1; // (deliberately unused)
println!("use {}", b);
if cond() {
println!("use {}", c);
}
println!("use {}", e);
assert!(f == 1);
}
fn locals_2() {
let a: i32; // $ Alert[rust/unused-variable]
let b: i32;
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; // $ Alert[rust/unused-value]
c = 1; // $ Alert[rust/unused-value]
c = 2;
println!("use {}", c);
c = 3; // $ Alert[rust/unused-value]
d = 1;
if cond() {
d = 2; // $ Alert[rust/unused-value]
d = 3;
} else {
}
println!("use {}", d);
e = 1; // $ Alert[rust/unused-value]
if cond() {
e = 2;
} else {
e = 3;
}
println!("use {}", e);
f = 1;
f += 1;
println!("use {}", f);
f += 1; // $ Alert[rust/unused-value]
f = 1;
f += 1; // $ Alert[rust/unused-value]
g = if cond() { 1 } else { 2 }; // $ Alert[rust/unused-value]
h = if cond() { 3 } else { 4 };
i = if cond() { h } else { 5 };
println!("use {}", i);
_ = 1; // GOOD (deliberately unused)
}
// --- structs ---
#[derive(Debug)]
struct MyStruct {
val: i64,
}
impl MyStruct {
fn my_get(&mut self) -> i64 {
return self.val;
}
fn get_flags(&self) -> i64 {
return 0;
}
}
fn structs() {
let a = MyStruct { val: 1 }; // $ Alert[rust/unused-value]
let b = MyStruct { val: 2 };
let c = MyStruct { val: 3 };
let mut d: MyStruct; // $ Alert[rust/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 }; // $ MISSING: Alert[rust/unused-value]
f.val = 7; // $ MISSING: Alert[rust/unused-value]
}
// --- arrays ---
fn arrays() {
let is = [1, 2, 3]; // $ Alert[rust/unused-value]
let js = [1, 2, 3];
let ks = [1, 2, 3];
println!("lets use {:?}", js);
for k in ks {
println!("lets use {}", k); // [unreachable FALSE POSITIVE]
}
}
// --- constants and statics ---
const CON1: i32 = 1;
const CON2: i32 = 2; // $ MISSING: Alert[rust/unused-value]
static mut STAT1: i32 = 1;
static mut STAT2: i32 = 2; // $ MISSING: Alert[rust/unused-value]
fn statics() {
static mut STAT3: i32 = 0;
static mut STAT4: i32 = 0; // $ MISSING: Alert[rust/unused-value]
unsafe {
let total = CON1 + STAT1 + STAT3; // $ Alert[rust/unused-value]
}
}
// --- parameters ---
fn parameters(
x: i32,
y: i32, // $ Alert[rust/unused-variable]
_z: i32, // (`_` is asking the compiler, and by extension us, to not warn that this is unused)
) -> i32 {
return x;
}
// --- loops ---
fn id(v: i32) -> i32 {
return v;
}
fn loops() {
let mut a: i64 = 10;
let b: i64 = 20;
let c: i64 = 30;
let d: i64 = 40;
let mut e: i64 = 50;
while a < b {
a += 1;
}
for x in c..d {
e += x;
}
for x in 1..10 { // $ Alert[rust/unused-variable]
}
for _ in 1..10 {}
for x in 1..10 {
println!("x is {}", x);
}
for x in 1..10 {
println!("x is {:?}", x);
}
for x in 1..10 {
println!("x + 1 is {}", x + 1);
}
for x in 1..10 {
for y in 1..x {
println!("y is {}", y);
}
}
for x in 1..10 {
println!("x is {x}");
}
for x in 1..10 {
_ = format!("x is {x}");
}
for x in 1..10 {
_ = format!("x is {x:?}");
}
[1, 2, 3].iter().for_each(|x| {
_ = format!("x is {x}");
});
for x in 1..10 {
println!("x is {val}", val = x);
}
for x in 1..10 {
assert!(x != 11);
}
for x in 1..10 {
assert_eq!(x, 1);
break;
}
for x in 1..10 {
assert_eq!(id(x), id(1));
break;
}
}
// --- lets ---
enum MyOption<T> {
None,
Some(T),
}
enum YesOrNo {
Yes,
No,
}
use YesOrNo::{No, Yes}; // allows `Yes`, `No` to be accessed without qualifiers.
struct MyPoint {
x: i64,
y: i64,
}
fn if_lets_matches() {
let mut total: i64 = 0;
if let Some(a) = Some(10) { // $ Alert[rust/unused-variable]
}
if let Some(b) = Some(20) {
total += b;
}
let mut next = Some(30);
while let Some(val) = // $ Alert[rust/unused-variable]
next
{
next = None;
}
let mut next2 = Some(40);
while let Some(val) = next2 {
total += val;
next2 = None;
}
let c = Some(60);
match c {
Some(val) => { // $ Alert[rust/unused-variable]
}
None => {}
}
let d = Some(70);
match d {
Some(val) => {
total += val; // $ Alert[rust/unused-value]
}
None => {}
}
let e = Option::Some(80);
match e {
Option::Some(val) => { // $ Alert[rust/unused-variable]
}
Option::None => {}
}
let f = MyOption::Some(90);
match f {
MyOption::Some(val) => { // $ Alert[rust/unused-variable]
}
MyOption::None => {}
}
let g: Result<i64, i64> = Ok(100);
match g {
Ok(_) => {}
Err(num) => {} // $ Alert[rust/unused-variable]
}
let h = YesOrNo::Yes;
match h {
YesOrNo::Yes => {}
YesOrNo::No => {}
}
let i = Yes;
match i {
Yes => {}
No => {}
}
if let j = Yes { // $ Alert[rust/unused-value]
}
if let k = Yes {
match k {
_ => {}
}
}
let l = Yes;
if let Yes = l {}
match 1 {
1 => {}
_ => {}
}
let p1 = MyPoint { x: 1, y: 2 };
match p1 {
MyPoint { x: 0, y: 0 } => {}
MyPoint { x: 1, y } => { // $ Alert[rust/unused-variable]
}
MyPoint { x: 2, y: _ } => {}
MyPoint { x: 3, y: a } => { // $ Alert[rust/unused-variable]
}
MyPoint { x: 4, .. } => {}
p => { // $ Alert[rust/unused-variable]
}
}
let duration1 = std::time::Duration::new(10, 0); // ten seconds
assert_eq!(duration1.as_secs(), 10);
let duration2: Result<std::time::Duration, String> = Ok(std::time::Duration::new(10, 0));
match duration2 {
Ok(n) => {
println!("duration was {} seconds", n.as_secs());
}
Err(_) => {
println!("failed");
}
}
let (left,
right) = // $ MISSING: Alert[rust/unused-value] $ SPURIOUS: Alert[rust/unused-variable]
(1, 2);
_ = left;
let pair = (1, 2);
let (left2,
right2) = // $ MISSING: Alert[rust/unused-value] $ SPURIOUS: Alert[rust/unused-variable]
pair;
_ = left2;
if let Some(m) = Some(10)
&& m > 0
{}
}
fn shadowing() -> i32 {
let x = 1; // $ Alert[rust/unused-value]
let mut y: i32; // $ Alert[rust/unused-variable]
{
let x = 2;
let mut y: i32;
{
let x = 3; // $ Alert[rust/unused-value]
let mut y: i32; // $ Alert[rust/unused-variable]
}
y = x;
return y;
}
}
// --- function pointers ---
type FuncPtr = fn(i32) -> i32;
fn increment(x: i32) -> i32 {
return x + 1;
}
fn func_ptrs() {
let my_func: FuncPtr = increment;
for x in 1..10 {
_ = x + 1;
}
for x in 1..10 {
_ = increment(x);
}
for x in 1..10 {
_ = my_func(x);
}
}
// --- folds and closures ---
fn folds_and_closures() {
let a1 = 1..10;
_ = a1.sum::<i32>();
let a2 = 1..10;
_ = a2.fold(0, |acc: i32, val: i32| -> i32 { acc + val });
let a3 = 1..10;
_ = a3.fold(0, |acc, val| acc + val);
let a4 = 1..10;
_ = a4.fold(0, |acc, val| acc); // $ Alert[rust/unused-variable]
let a5 = 1..10;
_ = a5.fold(0, |acc, val| val); // $ Alert[rust/unused-variable]
let i6 = 1;
let a6 = 1..10;
_ = a6.fold(0, |acc, val| acc + val + i6);
}
// --- traits ---
trait Incrementable {
fn increment(&mut self, times: i32, unused: &mut i32);
}
struct MyValue {
value: i32,
}
impl Incrementable for MyValue {
fn increment(
&mut self,
times: i32,
unused: &mut i32, // $ Alert[rust/unused-variable]
) {
self.value += times;
}
}
fn traits() {
let mut i = MyValue { value: 0 };
let a = 1;
let mut b = 2;
i.increment(a, &mut b);
}
// --- macros ---
macro_rules! set_value {
($x:expr,$y:expr) => {
$x = $y
};
}
macro_rules! use_value {
($x:expr) => {
println!("{}", $x)
};
}
fn macros1() {
let a: u16;
let b: u16 = 2;
set_value!(a, 1); // $ Alert[rust/unused-value]
use_value!(b);
match std::env::args().nth(1).unwrap().parse::<u16>() {
Ok(n) => {
use_value!(n);
}
_ => {}
}
}
fn macros2() {
let a: u16 = 3;
println!("{}", a);
match std::env::args().nth(1).unwrap().parse::<u16>() {
Ok(n) => {
println!("{}", n);
}
_ => {}
}
}
fn macros3() {
let x;
println!("The value of x is {}", ({ x = 10; 10 })); // $ Alert[rust/unused-value]
}
macro_rules! let_in_macro {
($e:expr) => {{
let var_in_macro = 0;
$e
}};
}
// Our analysis does not currently respect the hygiene rules of Rust macros
// (https://veykril.github.io/tlborm/decl-macros/minutiae/hygiene.html), because
// all we have access to is the expanded AST
fn hygiene_mismatch() {
let var_in_macro = 0; // $ SPURIOUS: Alert[rust/unused-value]
let_in_macro!(var_in_macro);
}
// --- references ---
fn references() {
let a = 1;
let b = &a;
let c = *b; // $ Alert[rust/unused-value]
let d = 2;
let e = 3;
let f = &&e;
assert!(&d != *f);
}
// --- declarations in types ---
pub struct my_declaration {
field1: fn(i32) -> i32,
field2: fn(x: i32) -> i32,
field3: fn(y: fn(z: i32) -> i32) -> i32,
}
type MyType = fn(x: i32) -> i32;
trait MyTrait {
fn my_func2(&self, x: i32) -> i32;
}
// --- main ---
fn main() {
locals_1();
locals_2();
structs();
arrays();
statics();
println!("lets use result {}", parameters(1, 2, 3));
loops();
if_lets_matches();
shadowing();
func_ptrs();
folds_and_closures();
macros1();
macros2();
macros3();
hygiene_mismatch();
references();
generics();
pointers();
unreachable_if_1();
unreachable_if_2();
unreachable_if_3();
unreachable_panic();
_ = unreachable_bail();
unreachable_match();
unreachable_loop();
unreachable_loop_async();
unreachable_paren();
unreachable_let_1();
unreachable_let_2();
unreachable_attributes();
}