rulewright 0.1.2

Executable engineering standards for Rust workspaces
Documentation
use crate::{Example, FileCtx, Violation, infra::parse, violation};

#[rustfmt::skip]
const EXAMPLES: &[Example] = &[
    Example {
        label: "static mut declaration",
        code: "static mut X: i32 = 0;",
        pass: false,
    },
    Example {
        label: "static Mutex",
        code: "static X: Mutex<i32> = Mutex::new(0);",
        pass: true,
    },
    Example {
        label: "comment with static mut",
        code: "// static mut X: i32 = 0;",
        pass: true,
    },
    Example {
        label: "static mut in string literal",
        code: r#"let msg = "static mut is dangerous";"#,
        pass: true,
    },
];

crate::line_rule!(
    static_mut,
    "Ban `static mut` declarations — use `AtomicT`, `Mutex`, or `OnceLock`.",
    "static mut is unsound in multithreaded code and deprecated. Use AtomicT, Mutex, or OnceLock instead.",
    High,
);

fn check_static_mut(ctx: &FileCtx<'_>) -> Vec<Violation> {
    let mut out = Vec::new();

    for (i, line) in ctx.lines.iter().enumerate() {
        let lineno = i + 1;
        let trimmed = line.trim();

        if parse::is_comment(trimmed) {
            continue;
        }

        if crate::infra::helpers::contains_outside_strings(line, "static mut ") {
            out.push(violation(
                ctx.rel,
                lineno,
                "`static mut` is UB-prone (use AtomicT, Mutex, or OnceLock)",
            ));
        }
    }

    out
}

crate::rulewright_test!(check_static_mut, {
    crate::example_tests!(EXAMPLES, check_static_mut);
});