use std::ffi::OsStr;
use std::io::{Read, Write};
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::sync::OnceLock;
use std::{env, fs};
fn main() {
let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR must be set"));
fs::write(out_dir.join("lint_errors.rs"), "").expect("failed to write lint_errors.rs");
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=src/terms/analytic_penalties/manifest.rs");
let manifest_dir =
PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR must be set"));
if !manifest_dir.join("tests").is_dir() {
return;
}
forbid_claude_build_rs_edits(&manifest_dir);
forbid_build_rs_self_tampering(&manifest_dir);
assert_warnings_are_denied(&manifest_dir);
scan_for_cluster_infra_leaks(&manifest_dir);
emit_python_penalty_manifest(&manifest_dir)
.expect("failed to emit Python analytic-penalty manifest");
let needle: &str = concat!("TO", "DO");
let mut todo_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_banned_marker(&manifest_dir, &manifest_dir, needle, &mut todo_offenders);
let mut todo_history_violations: Vec<(PathBuf, usize, String, String)> = Vec::new();
run_todo_marker_history_audit(&manifest_dir, needle, &mut todo_history_violations);
let mut cosmetic_dodge_violations: Vec<(PathBuf, usize, String, String)> = Vec::new();
run_cosmetic_wording_dodge_audit(&manifest_dir, &mut cosmetic_dodge_violations);
let mut deferred_marker_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_deferred_work_markers(&manifest_dir, &manifest_dir, &mut deferred_marker_offenders);
let mut owed_work_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_owed_work_prose(&manifest_dir, &manifest_dir, &mut owed_work_offenders);
let mut allow_offenders: Vec<(PathBuf, usize, String, String)> = Vec::new();
scan_for_banned_allow(&manifest_dir, &manifest_dir, &mut allow_offenders);
let mut underscore_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_let_underscore(&manifest_dir, &manifest_dir, &mut underscore_offenders);
let mut ignored: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_ignored_tests(&manifest_dir, &manifest_dir, &mut ignored);
let mut substring_offenders: Vec<(PathBuf, usize, &'static str, String)> = Vec::new();
scan_for_banned_substrings(&manifest_dir, &manifest_dir, &mut substring_offenders);
let mut unsafe_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_unsafe_without_safety(&manifest_dir, &manifest_dir, &mut unsafe_offenders);
let mut transmute_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_transmute_without_safety(&manifest_dir, &manifest_dir, &mut transmute_offenders);
let mut panic_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_panic_without_safety(&manifest_dir, &manifest_dir, &mut panic_offenders);
let mut silent_corruption_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_silent_corruption_laundering(
&manifest_dir,
&manifest_dir,
&mut silent_corruption_offenders,
);
let mut dead_cfg_gate_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_dead_cfg_gates(&manifest_dir, &manifest_dir, &mut dead_cfg_gate_offenders);
let mut feature_cfg_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_feature_cfg_gates(&manifest_dir, &manifest_dir, &mut feature_cfg_offenders);
let mut cargo_feature_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_cargo_feature_entries(&manifest_dir, &manifest_dir, &mut cargo_feature_offenders);
let mut cargo_lint_allow_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_cargo_lint_allows(
&manifest_dir,
&manifest_dir,
&mut cargo_lint_allow_offenders,
);
let gamfit_version =
read_gamfit_project_version(&manifest_dir).expect("failed to read gamfit version");
let mut gamfit_version_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_non_latest_gamfit_versions(
&manifest_dir,
&gamfit_version,
&mut gamfit_version_offenders,
);
let mut should_panic_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_bare_should_panic(&manifest_dir, &manifest_dir, &mut should_panic_offenders);
let mut debug_eprintln_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_debug_eprintln(&manifest_dir, &manifest_dir, &mut debug_eprintln_offenders);
let mut dead_guard_const_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_dead_guard_consts(
&manifest_dir,
&manifest_dir,
&mut dead_guard_const_offenders,
);
let mut underscore_fn_arg_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_underscore_fn_args(
&manifest_dir,
&manifest_dir,
&mut underscore_fn_arg_offenders,
);
let mut useless_test_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_useless_tests(&manifest_dir, &manifest_dir, &mut useless_test_offenders);
let mut cfg_test_pub_offenders: Vec<(PathBuf, usize, String, String)> = Vec::new();
scan_for_cfg_test_on_pub_items(&manifest_dir, &manifest_dir, &mut cfg_test_pub_offenders);
let mut noop_self_consuming_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_noop_self_consuming_fns(
&manifest_dir,
&manifest_dir,
&mut noop_self_consuming_offenders,
);
let mut stub_body_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_stub_function_bodies(&manifest_dir, &manifest_dir, &mut stub_body_offenders);
let mut noop_sentinel_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_noop_sentinel_control_flow(&manifest_dir, &manifest_dir, &mut noop_sentinel_offenders);
let mut dodge_name_offenders: Vec<(PathBuf, usize, String, String)> = Vec::new();
scan_for_dodge_named_fns(&manifest_dir, &manifest_dir, &mut dodge_name_offenders);
let mut vendor_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_vendor_directories(&manifest_dir, &manifest_dir, &mut vendor_offenders);
let mut oversized_file_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_oversized_tracked_files(&manifest_dir, &mut oversized_file_offenders);
let mut mechanical_part_offenders: Vec<(PathBuf, usize, String)> = Vec::new();
scan_for_mechanical_part_files(&manifest_dir, &mut mechanical_part_offenders);
let mut history_violations: Vec<(PathBuf, usize, String, String)> = Vec::new();
run_unimplemented_history_audit(&manifest_dir, &mut history_violations);
let mut src_test_only_offenders: Vec<(PathBuf, usize, String, String)> = Vec::new();
let mut src_unreferenced_pub_scoped: Vec<(PathBuf, usize, String, String)> = Vec::new();
scan_for_src_items_used_only_by_tests(
&manifest_dir,
&mut src_test_only_offenders,
&mut src_unreferenced_pub_scoped,
);
let mut sections: Vec<Section> = Vec::new();
if !todo_offenders.is_empty() {
sections.push(Section {
title: format!("{} marker", needle),
rows: todo_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !deferred_marker_offenders.is_empty() {
sections.push(Section {
title:
"deferred-work marker in disguise (a `fixme`/`xxx`/`hack`/`todo` comment lead-in, \
or a deferral word carrying an issue ref like `Follow-up (#932):`) — a relabelled \
marker is still owed work; implement it or delete the whole note, do not rename \
the marker"
.to_string(),
rows: deferred_marker_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !owed_work_offenders.is_empty() {
sections.push(Section {
title:
"owed work disguised as prose to dodge the marker ban (`not yet wired`, `deferred to a follow-up`, `PLAN (not yet implemented)`, `not wired into ...`) — this is a TODO in a limitation costume. FINISH the work: implement and wire it. Do NOT delete the comment, reword it into a 'documented limitation', or defer it again — a relabel is the same evasion the bare-marker ban forbids"
.to_string(),
rows: owed_work_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !allow_offenders.is_empty() {
sections.push(Section {
title: "#[allow(...)] / #[expect(...)] (any lint, anywhere — fix the underlying code instead of silencing the lint)".to_string(),
rows: allow_offenders
.iter()
.map(|(r, l, lint, s)| (r.clone(), *l, Some(lint.clone()), s.clone()))
.collect(),
});
}
if !underscore_offenders.is_empty() {
sections.push(Section {
title: "let _ binding (bare `_`, `_name`, or all-underscore tuple pattern)".to_string(),
rows: underscore_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !ignored.is_empty() {
sections.push(Section {
title: "#[ignore] test".to_string(),
rows: ignored
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !substring_offenders.is_empty() {
let mut by_label: std::collections::BTreeMap<&'static str, Vec<(PathBuf, usize, String)>> =
std::collections::BTreeMap::new();
for (rel, line_no, label, line) in &substring_offenders {
by_label
.entry(*label)
.or_default()
.push((rel.clone(), *line_no, line.clone()));
}
for (label, rows_in) in by_label {
sections.push(Section {
title: label.to_string(),
rows: rows_in
.into_iter()
.map(|(r, l, s)| (r, l, None, s))
.collect(),
});
}
}
if !unsafe_offenders.is_empty() {
sections.push(Section {
title: "unsafe without `// SAFETY:`".to_string(),
rows: unsafe_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !transmute_offenders.is_empty() {
sections.push(Section {
title: "mem::transmute without `// SAFETY:` justification".to_string(),
rows: transmute_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !silent_corruption_offenders.is_empty() {
sections.push(Section {
title: "silent-corruption laundering: a contract-guard was replaced by a benign/NaN value at a site documented as impossible — restore the hard guard (panic with // SAFETY, or a real error), do NOT emit a corrupting sentinel".to_string(),
rows: silent_corruption_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !panic_offenders.is_empty() {
sections.push(Section {
title: "panic!() in non-test code without `// SAFETY:` justification".to_string(),
rows: panic_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !dead_cfg_gate_offenders.is_empty() {
sections.push(Section {
title: "#[cfg(any())]/#[cfg(all())] (empty-arg cfg — permanently false/true)"
.to_string(),
rows: dead_cfg_gate_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !feature_cfg_offenders.is_empty() {
sections.push(Section {
title: "#[cfg(feature = ...)] / #[cfg_attr(feature = ...)] (feature gating banned — autoderive paths from problem characteristics; do not branch the codebase on opt-in flags)".to_string(),
rows: feature_cfg_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !cargo_lint_allow_offenders.is_empty() {
sections.push(Section {
title: "Cargo.toml [lints.*] `allow` entry (manifest-level lint silencing banned — fix the code instead of disabling the lint)".to_string(),
rows: cargo_lint_allow_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !gamfit_version_offenders.is_empty() {
sections.push(Section {
title: format!(
"non-latest gamfit version reference (expected {})",
gamfit_version
),
rows: gamfit_version_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !cargo_feature_offenders.is_empty() {
sections.push(Section {
title: "Cargo.toml [features] entry (feature definitions banned — delete the [features] section and the corresponding cfg-gates)".to_string(),
rows: cargo_feature_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !should_panic_offenders.is_empty() {
sections.push(Section {
title: "#[should_panic] without `expected = \"...\"`".to_string(),
rows: should_panic_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !debug_eprintln_offenders.is_empty() {
sections.push(Section {
title: "eprintln!/eprint! with {:?} debug formatting (use real logging or delete)"
.to_string(),
rows: debug_eprintln_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !dead_guard_const_offenders.is_empty() {
sections.push(Section {
title:
"const <name>: bool = <literal> (dead-by-construction guard — use cfg or delete)"
.to_string(),
rows: dead_guard_const_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !underscore_fn_arg_offenders.is_empty() {
sections.push(Section {
title:
"underscore-prefixed fn parameter (use the value, restructure the API, or delete the param)"
.to_string(),
rows: underscore_fn_arg_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !useless_test_offenders.is_empty() {
sections.push(Section {
title:
"#[test] function without assertions (test must verify something — add assert! / assert_eq! / ? / #[should_panic] or delete the test)"
.to_string(),
rows: useless_test_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !cfg_test_pub_offenders.is_empty() {
sections.push(Section {
title:
"#[cfg(test)] on src/ item (move into a private `#[cfg(test)] mod tests { ... }` / `mod test_support` / `mod tests_*` / `mod *_tests`, or delete the unused item — `#[cfg(test)]` is not a dead_code-lint escape hatch, regardless of visibility)"
.to_string(),
rows: cfg_test_pub_offenders
.iter()
.map(|(r, l, item, s)| (r.clone(), *l, Some(item.clone()), s.clone()))
.collect(),
});
}
if !noop_self_consuming_offenders.is_empty() {
sections.push(Section {
title:
"no-op self-consuming fn (empty body with by-value `self` — likely a `let _` launderer; use or restructure the return value)"
.to_string(),
rows: noop_self_consuming_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !stub_body_offenders.is_empty() {
sections.push(Section {
title:
"stub function body (multi-arg function whose entire body is a sentinel like None/Ok(())/Default::default() — implement the function, return a real Result/Error, or delete the function)"
.to_string(),
rows: stub_body_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !noop_sentinel_offenders.is_empty() {
sections.push(Section {
title:
"sentinel-preserving fake use (parameter is read only by a no-op guard/discard; use it for behavior, return a real error, or delete it)"
.to_string(),
rows: noop_sentinel_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !dodge_name_offenders.is_empty() {
sections.push(Section {
title:
"dodge-named function (name announces lint-laundering intent — implement real behavior or restructure so the value isn't unused)"
.to_string(),
rows: dodge_name_offenders
.iter()
.map(|(r, l, ident, s)| (r.clone(), *l, Some(ident.clone()), s.clone()))
.collect(),
});
}
if !vendor_offenders.is_empty() {
sections.push(Section {
title:
"`vendor/` directory present — vendoring forks upstream dependencies past the same lint gate this scanner enforces; use `[dependencies]` in Cargo.toml (crates.io version or `git = ...`) instead"
.to_string(),
rows: vendor_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !oversized_file_offenders.is_empty() {
sections.push(Section {
title: "tracked file over 10k lines (split the file; issue #780 line-count gate)"
.to_string(),
rows: oversized_file_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !mechanical_part_offenders.is_empty() {
sections.push(Section {
title:
"mechanical file-splitting banned (`part_<NNN>.rs` / `*_parts/` / `split_parts/` \
is line-count splitting, not logical decomposition — split by cohesive concern \
into descriptively-named modules; numbered parts are slop)"
.to_string(),
rows: mechanical_part_offenders
.iter()
.map(|(r, l, s)| (r.clone(), *l, None, s.clone()))
.collect(),
});
}
if !history_violations.is_empty() {
sections.push(Section {
title: "unimplemented!/todo!/unreachable! removed without real implementation \
(history audit — ban_history.txt)"
.to_string(),
rows: history_violations
.iter()
.map(|(file, line, sig, reason)| {
(file.clone(), *line, Some(reason.clone()), sig.clone())
})
.collect(),
});
}
if !todo_history_violations.is_empty() {
sections.push(Section {
title: format!(
"{} comment/marker removed without corresponding code change \
(history audit — todo_history.txt plus git HEAD)",
needle
),
rows: todo_history_violations
.iter()
.map(|(file, line, reason, site)| {
(file.clone(), *line, Some(reason.clone()), site.clone())
})
.collect(),
});
}
if !cosmetic_dodge_violations.is_empty() {
sections.push(Section {
title:
"cosmetic wording dodge (history audit): an owed-work/deferral note was reworded \
or deleted from a non-test src file while the comment-stripped code stayed \
byte-identical — the work was NOT done, only the wording. Do the real work or \
restore the honest note; rewording a build.rs-flagged signal to satisfy the \
scanner is banned"
.to_string(),
rows: cosmetic_dodge_violations
.iter()
.map(|(file, line, reason, site)| {
(file.clone(), *line, Some(reason.clone()), site.clone())
})
.collect(),
});
}
if !src_test_only_offenders.is_empty() {
sections.push(Section {
title:
"src/ item referenced only by tests (production code with no production consumers — implement a real caller, delete the item, or move it into a `#[cfg(test)]` private mod if it's genuinely test-support)"
.to_string(),
rows: src_test_only_offenders
.iter()
.map(|(r, l, hint, s)| (r.clone(), *l, Some(hint.clone()), s.clone()))
.collect(),
});
}
if !src_unreferenced_pub_scoped.is_empty() {
sections.push(Section {
title:
"pub(crate)/pub(super) item in src/ with ZERO consumers anywhere (no production caller, no test reference — implement a real caller or delete the item; rustc's `dead_code` lint cannot see this in a library-shaped crate)"
.to_string(),
rows: src_unreferenced_pub_scoped
.iter()
.map(|(r, l, hint, s)| (r.clone(), *l, Some(hint.clone()), s.clone()))
.collect(),
});
}
if sections.is_empty() {
return;
}
render_report(§ions);
let total_rows: usize = sections.iter().map(|s| s.rows.len()).sum();
println!(
"cargo:warning=ban-scanner FAILED: {} violation(s) across {} rule(s); build aborted \u{2014} every offending file:line is on an 'error:' line above",
total_rows,
sections.len()
);
std::process::exit(1);
}
fn forbid_build_rs_self_tampering(manifest_dir: &Path) {
let path = manifest_dir.join("build.rs");
let src = std::fs::read_to_string(&path)
.unwrap_or_else(|e| panic!("self-integrity gate: cannot read build.rs at {path:?}: {e}"));
let lines: Vec<&str> = src.lines().collect();
let render_call = format!("render_report(&{});", "sections");
let exit_core_a = format!("std::process::{}(1)", "exit");
let exit_core_b = format!("process::{}(1)", "exit");
let exit_any = format!("process::{}(", "exit");
let env_needles = [
format!("env::{}(", "var"),
format!("std::{}", "env"),
format!("option_{}", "env!"),
];
let render_sites: Vec<usize> = lines
.iter()
.enumerate()
.filter(|(_, l)| l.trim() == render_call)
.map(|(i, _)| i)
.collect();
if render_sites.len() != 1 {
panic!(
"self-integrity gate: expected exactly one `{render_call}` report site, found {}. \
The ban-scanner aggregator was moved, duplicated, or removed — restore the single \
hard-failing report path.",
render_sites.len()
);
}
let r = render_sites[0];
let render_indent = lines[r].len() - lines[r].trim_start().len();
let branch_starts = [
"if ", "} else", "else ", "else{", "match ", "for ", "while ", "loop ", "loop{",
];
let mut hard_exit_found = false;
for line in &lines[r + 1..] {
let t = line.trim();
if t.is_empty() || t.starts_with("//") {
continue;
}
let indent = line.len() - line.trim_start().len();
if (t.starts_with(exit_core_a.as_str()) || t.starts_with(exit_core_b.as_str()))
&& indent == render_indent
{
hard_exit_found = true;
break;
}
if indent < render_indent {
break;
}
if t.starts_with("return") {
panic!(
"self-integrity gate: a `return` precedes the ban-scanner's hard exit. The \
report path must end in an unconditional process exit, not return early."
);
}
if branch_starts.iter().any(|k| t.starts_with(*k)) {
panic!(
"self-integrity gate: the ban-scanner's hard exit was made CONDITIONAL by \
`{t}`. The exit must be unconditional — no branch, loop, or env switch may \
guard it."
);
}
}
if !hard_exit_found {
panic!(
"self-integrity gate: the ban-scanner no longer ends in an unconditional process \
exit immediately after `{render_call}`. It appears to have been turned into a \
warning or otherwise bypassed — restore the hard exit."
);
}
for (i, line) in lines.iter().enumerate() {
let t = line.trim();
if t.starts_with("//") {
continue;
}
let is_branch = t.starts_with("if ") || t.contains("else if ");
if !is_branch || !env_needles.iter().any(|n| line.contains(n.as_str())) {
continue;
}
let window_end = (i + 40).min(lines.len());
for body in &lines[i + 1..window_end] {
let bt = body.trim();
if bt.starts_with("//") {
continue;
}
if bt.contains(exit_any.as_str()) {
panic!(
"self-integrity gate: a process exit is reachable under an \
environment-variable branch (`{t}`). Env-gating a hard-fail gate in \
build.rs is banned — gates must always fire."
);
}
}
}
let hack_phrases = [
format!("{}{}", "velocity ", "unblock"),
format!("{}{}", "temp ", "velocity"),
format!("{}{}", "temporarily ", "non-fatal"),
format!("{}{}", "temporarily ", "disabled"),
format!("{}{}", "demoted from a ", "hard"),
format!("{}{}", "do not ", "merge"),
];
let lower = src.to_lowercase();
for phrase in &hack_phrases {
if lower.contains(phrase.as_str()) {
panic!(
"self-integrity gate: build.rs contains temporary-bypass hack language \
(`{phrase}`). The gates here are not to be temporarily weakened; fix the \
underlying violations instead of weakening a gate."
);
}
}
for (line_no, raw) in lines.iter().enumerate() {
for literal in raw.split('"').skip(1).step_by(2) {
let len = literal.len();
let all_lower_hex = literal
.bytes()
.all(|b| b.is_ascii_digit() || (b'a'..=b'f').contains(&b));
let has_digit = literal.bytes().any(|b| b.is_ascii_digit());
let has_hex_letter = literal.bytes().any(|b| (b'a'..=b'f').contains(&b));
if (7..=40).contains(&len) && all_lower_hex && has_digit && has_hex_letter {
panic!(
"self-integrity gate: build.rs contains a hardcoded commit-SHA literal \
(`{literal}` at line {}). build.rs must operate on git history \
generically; pinning a commit is an allowlist that exempts hand-picked \
commits from a history audit and is banned. Remove the exemption and do \
the real work the audit demands instead of suppressing it.",
line_no + 1
);
}
}
}
}
fn forbid_claude_build_rs_edits(manifest_dir: &Path) {
let output = Command::new("git")
.arg("-C")
.arg(manifest_dir)
.arg("log")
.arg("-1")
.arg("--format=%an|%ae")
.arg("--")
.arg("build.rs")
.output()
.expect("failed to run git log for build.rs author audit");
if !output.status.success() {
panic!(
"failed to query git history for build.rs author: {}",
String::from_utf8_lossy(&output.stderr)
);
}
let info = String::from_utf8_lossy(&output.stdout);
let info = info.trim();
let is_claude = info.to_lowercase().contains("claude")
|| info.to_lowercase().contains("anthropic");
if is_claude {
panic!(
"Sorry Claude! build.rs was last edited by a non-human author ({info}). \
Claude may propose changes to build.rs, but only a human may author the \
commit. The checks in this file are not to be weakened or removed under \
any circumstances. Please have a human maintainer re-commit any needed \
change to build.rs.",
);
}
}
fn assert_warnings_are_denied(manifest_dir: &Path) {
let cargo_toml = manifest_dir.join("Cargo.toml");
let content = fs::read_to_string(&cargo_toml)
.unwrap_or_else(|e| panic!("failed to read {}: {e}", cargo_toml.display()));
let mut in_lints_rust = false;
let mut found_level: Option<String> = None;
for raw in content.lines() {
let line = raw.trim();
if line.starts_with('[') && line.ends_with(']') {
in_lints_rust = line == "[lints.rust]";
continue;
}
if !in_lints_rust {
continue;
}
let code = line.split('#').next().unwrap_or("").trim();
if let Some(rest) = code.strip_prefix("warnings") {
let rest = rest.trim_start();
if let Some(value) = rest.strip_prefix('=') {
let value = value.trim();
let level = if let Some(idx) = value.find("level") {
value[idx..]
.split('=')
.nth(1)
.map(|s| s.trim().trim_matches('"').trim_matches('\'').to_string())
} else {
Some(value.trim_matches('"').trim_matches('\'').to_string())
};
found_level = level;
break;
}
}
}
match found_level.as_deref() {
Some("deny") => {}
Some(other) => panic!(
"[lints.rust] warnings MUST be \"deny\", found \"{other}\" in {}. \
Restore `warnings = \"deny\"`; warnings are not permitted to accumulate.",
cargo_toml.display()
),
None => panic!(
"[lints.rust] warnings = \"deny\" is missing from {}. \
It MUST be present and set to \"deny\".",
cargo_toml.display()
),
}
}
#[derive(Clone)]
struct PenaltyWrapperManifest {
kind_tag: String,
rust_type: String,
python_wrapper: String,
row_block_diagonal: bool,
}
fn emit_python_penalty_manifest(manifest_dir: &Path) -> std::io::Result<()> {
let penalties_dir = manifest_dir
.join("src")
.join("terms")
.join("analytic_penalties");
let registry = fs::read_to_string(penalties_dir.join("manifest.rs"))?;
let mut wrappers = Vec::new();
for line in registry.lines() {
let trimmed = line.trim();
if !trimmed.starts_with("register!(") {
continue;
}
let inside = trimmed
.trim_start_matches("register!(")
.trim_end_matches(");");
let mut pieces = inside.split(',').map(str::trim);
let variant = match pieces.next() {
Some(value) if !value.is_empty() => value,
_ => continue,
};
let rust_type = match pieces.next() {
Some(value) if !value.is_empty() => value,
_ => continue,
};
let source = penalty_manifest_source_for_type(®istry, rust_type)?;
wrappers.push(PenaltyWrapperManifest {
kind_tag: manifest_const_string(&source, "KIND_TAG")?,
rust_type: format!("{variant}:{rust_type}"),
python_wrapper: manifest_const_string(&source, "PYTHON_WRAPPER")?,
row_block_diagonal: manifest_const_bool(&source, "ROW_BLOCK_DIAGONAL")?,
});
}
let mut output = String::from(
"# Generated by build.rs from src/terms/analytic_penalties/manifest.rs.\n\
PENALTY_MANIFEST = (\n",
);
for wrapper in wrappers {
output.push_str(" {\n");
output.push_str(&format!(" \"kind\": {:?},\n", wrapper.kind_tag));
output.push_str(&format!(" \"rust\": {:?},\n", wrapper.rust_type));
output.push_str(&format!(
" \"python\": {:?},\n",
wrapper.python_wrapper
));
output.push_str(&format!(
" \"row_block_diagonal\": {},\n",
if wrapper.row_block_diagonal {
"True"
} else {
"False"
}
));
output.push_str(" },\n");
}
output.push_str(")\n");
let manifest_path = manifest_dir.join("gamfit").join("_penalties_manifest.py");
if let Ok(existing) = fs::read_to_string(&manifest_path) {
if existing == output {
return Ok(());
}
}
fs::write(manifest_path, output)
}
fn penalty_manifest_source_for_type(registry: &str, rust_type: &str) -> std::io::Result<String> {
let marker = format!("impl PenaltyManifest for {rust_type} {{");
if let Some(start) = registry.find(&marker) {
let rest = ®istry[start..];
if let Some(end) = rest.find("\n}") {
return Ok(rest[..end + 2].to_string());
}
}
Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
format!("missing PenaltyManifest impl for {rust_type}"),
))
}
fn manifest_const_string(source: &str, key: &str) -> std::io::Result<String> {
let needle = format!("const {key}: &'static str = ");
for line in source.lines() {
let trimmed = line.trim();
if !trimmed.starts_with(&needle) {
continue;
}
let value = trimmed
.trim_start_matches(&needle)
.trim_end_matches(';')
.trim();
return Ok(value.trim_matches('"').to_string());
}
Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!("missing manifest const {key}"),
))
}
fn manifest_const_bool(source: &str, key: &str) -> std::io::Result<bool> {
let needle = format!("const {key}: bool = ");
for line in source.lines() {
let trimmed = line.trim();
if !trimmed.starts_with(&needle) {
continue;
}
let value = trimmed
.trim_start_matches(&needle)
.trim_end_matches(';')
.trim();
return match value {
"true" => Ok(true),
"false" => Ok(false),
_ => Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!("invalid bool manifest const {key}: {value}"),
)),
};
}
Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!("missing manifest const {key}"),
))
}
fn read_gamfit_project_version(manifest_dir: &Path) -> std::io::Result<String> {
let path = manifest_dir.join("pyproject.toml");
let content = fs::read_to_string(&path)?;
read_toml_version_line(&content).ok_or_else(|| {
std::io::Error::new(
std::io::ErrorKind::InvalidData,
"pyproject.toml is missing a top-level version",
)
})
}
fn scan_for_non_latest_gamfit_versions(
root: &Path,
latest: &str,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
require_toml_version(
root,
Path::new("crates/gam-pyffi/Cargo.toml"),
latest,
offenders,
);
require_uv_lock_gamfit_version(root, latest, offenders);
visit_files(root, root, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
scan_gamfit_version_content(rel, content, latest, offenders);
});
}
fn require_toml_version(
root: &Path,
rel: &Path,
latest: &str,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
let path = root.join(rel);
let content = match fs::read_to_string(&path) {
Ok(content) => content,
Err(_) => {
offenders.push((
rel.to_path_buf(),
1,
format!("missing version file; expected gamfit {latest}"),
));
return;
}
};
for (idx, line) in content.lines().enumerate() {
let trimmed = line.trim();
if !trimmed.starts_with("version = ") {
continue;
}
match read_quoted_value_after_prefix(trimmed, "version = ") {
Some(version) if version == latest => return,
Some(_) | None => {
offenders.push((rel.to_path_buf(), idx + 1, line.to_string()));
return;
}
}
}
offenders.push((
rel.to_path_buf(),
1,
format!("missing version line; expected gamfit {latest}"),
));
}
fn require_uv_lock_gamfit_version(
root: &Path,
latest: &str,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
let rel = Path::new("uv.lock");
let content = match fs::read_to_string(root.join(rel)) {
Ok(content) => content,
Err(_) => {
offenders.push((
rel.to_path_buf(),
1,
format!("missing uv.lock gamfit package; expected {latest}"),
));
return;
}
};
let mut inside_package = false;
let mut inside_gamfit = false;
for (idx, line) in content.lines().enumerate() {
let trimmed = line.trim();
if trimmed == "[[package]]" {
inside_package = true;
inside_gamfit = false;
continue;
}
if !inside_package {
continue;
}
if trimmed == "name = \"gamfit\"" {
inside_gamfit = true;
continue;
}
if inside_gamfit && trimmed.starts_with("version = ") {
match read_quoted_value_after_prefix(trimmed, "version = ") {
Some(version) if version == latest => return,
Some(_) | None => {
offenders.push((rel.to_path_buf(), idx + 1, line.to_string()));
return;
}
}
}
}
offenders.push((
rel.to_path_buf(),
1,
format!("missing gamfit package version; expected {latest}"),
));
}
fn read_toml_version_line(content: &str) -> Option<String> {
for line in content.lines() {
let trimmed = line.trim();
if let Some(version) = read_quoted_value_after_prefix(trimmed, "version = ") {
return Some(version.to_string());
}
}
None
}
fn read_quoted_value_after_prefix<'a>(line: &'a str, prefix: &str) -> Option<&'a str> {
let rest = line.strip_prefix(prefix)?.trim_start();
let rest = rest.strip_prefix('"')?;
let end = rest.find('"')?;
Some(&rest[..end])
}
fn gamfit_versions_in_line(line: &str) -> Vec<String> {
let mut versions = Vec::new();
let mut search_start = 0usize;
while let Some(offset) = line[search_start..].find("0.1.") {
let start = search_start + offset;
let mut end = start + "0.1.".len();
while end < line.len() && line.as_bytes()[end].is_ascii_digit() {
end += 1;
}
if end > start + "0.1.".len() {
versions.push(line[start..end].to_string());
}
search_start = end;
}
versions
}
fn scan_gamfit_version_content(
rel: &Path,
content: &str,
latest: &str,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
for (line_idx, line) in content.lines().enumerate() {
let lower = line.to_ascii_lowercase();
if !lower.contains("gamfit") || !line.contains("0.1.") {
continue;
}
for version in gamfit_versions_in_line(line) {
if version != latest {
offenders.push((rel.to_path_buf(), line_idx + 1, line.to_string()));
}
}
}
}
struct Section {
title: String,
rows: Vec<(PathBuf, usize, Option<String>, String)>,
}
fn render_report(sections: &[Section]) {
let total: usize = sections.iter().map(|s| s.rows.len()).sum();
eprintln!();
eprintln!(
"error: {} ban violation{} across {} rule{}",
total,
if total == 1 { "" } else { "s" },
sections.len(),
if sections.len() == 1 { "" } else { "s" },
);
for section in sections {
eprintln!();
eprintln!(
"error — {} ({} hit{})",
section.title,
section.rows.len(),
if section.rows.len() == 1 { "" } else { "s" },
);
for (rel, line_no, tag, line) in §ion.rows {
let trimmed = line.trim();
let snippet: String = trimmed.chars().take(160).collect();
match tag {
Some(t) => eprintln!(" error: {}:{}: [{}] {}", rel.display(), line_no, t, snippet),
None => eprintln!(" error: {}:{}: {}", rel.display(), line_no, snippet),
}
}
}
eprintln!();
eprintln!("summary:");
for section in sections {
eprintln!(" {:>5} {}", section.rows.len(), section.title);
}
eprintln!();
}
fn banned_substrings() -> &'static [(&'static str, &'static str, bool)] {
&[
("dbg!(", "dbg!", true),
("todo!(", "todo!", true),
("unimplemented!(", "unimplemented!", true),
("unreachable!(", "unreachable!", true),
("assert!(true)", "assert!(true)", false),
("assert!(false)", "assert!(false)", false),
("debug_assert!(", "debug_assert!", false),
("debug_assert_eq!(", "debug_assert_eq!", false),
("debug_assert_ne!(", "debug_assert_ne!", false),
("hint::black_box(", "hint::black_box", true),
("std::hint::black_box(", "std::hint::black_box", true),
("core::hint::black_box(", "core::hint::black_box", true),
("cfg!(debug_assertions)", "cfg!(debug_assertions)", true),
("cfg(debug_assertions)", "cfg(debug_assertions)", true),
("cfg!(test)", "cfg!(test)", true),
("Arc::strong_count(", "Arc::strong_count", true),
("Arc::weak_count(", "Arc::weak_count", true),
("Rc::strong_count(", "Rc::strong_count", true),
("Rc::weak_count(", "Rc::weak_count", true),
(
"ends_with(\".rs\")",
"ends_with(\".rs\")",
false,
),
(
"ends_with(\".rs\"",
"ends_with(\".rs\"",
false,
),
("std::process::exit(", "std::process::exit", false),
("process::exit(", "process::exit", false),
("std::process::abort(", "std::process::abort", false),
("process::abort(", "process::abort", false),
("println!(", "println!", true),
("print!(", "print!", true),
("mem::forget(", "mem::forget", true),
("Box::leak(", "Box::leak", true),
("env::var(", "env::var", false),
("env::var_os(", "env::var_os", false),
("env::vars(", "env::vars", false),
("env::vars_os(", "env::vars_os", false),
("if let Ok(_)", "if let Ok(_)", false),
("if let Some(_)", "if let Some(_)", false),
("if let Err(_)", "if let Err(_)", false),
("== true", "== true", false),
("== false", "== false", false),
("!= true", "!= true", false),
("!= false", "!= false", false),
("thread::sleep(", "thread::sleep", true),
("std::thread::sleep(", "std::thread::sleep", true),
("spin_loop()", "spin_loop", false),
("thread::yield_now(", "thread::yield_now", false),
("std::thread::yield_now(", "std::thread::yield_now", false),
]
}
fn scan_for_banned_substrings(
root: &Path,
dir: &Path,
offenders: &mut Vec<(PathBuf, usize, &'static str, String)>,
) {
let needles = banned_substrings();
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
let mask = compute_test_mask(content, rel);
let stripped_lines = strip_file_lines(content);
for (idx, line) in content.lines().enumerate() {
let stripped = stripped_lines.get(idx).map(String::as_str).unwrap_or(line);
let in_test = mask.get(idx).copied().unwrap_or(false);
for (needle, label, test_aware) in needles {
if *test_aware && in_test {
continue;
}
if stripped.contains(needle) {
offenders.push((rel.to_path_buf(), idx + 1, *label, line.to_string()));
}
}
}
});
}
fn compute_test_mask(content: &str, rel: &Path) -> Vec<bool> {
let lines: Vec<&str> = content.lines().collect();
let n = lines.len();
let mut mask = vec![false; n];
let rel_str = rel.to_string_lossy().replace('\\', "/");
let file_is_test = rel_str.starts_with("tests/")
|| rel_str.starts_with("bench/")
|| rel_str.starts_with("benches/")
|| rel_str.starts_with("examples/")
|| path_matches_crates_test(&rel_str)
|| file_stem_is_exempt_test_module(rel);
if file_is_test {
mask.fill(true);
return mask;
}
let stripped_all = strip_file_lines(content);
for line in &stripped_all {
if is_cfg_test_inner_attr_line(line) {
mask.fill(true);
return mask;
}
}
let mut depth: i32 = 0;
let mut pending_attr = false;
let mut gate_stack: Vec<i32> = Vec::new();
for (idx, _raw) in lines.iter().enumerate() {
let stripped = stripped_all.get(idx).cloned().unwrap_or_default();
if is_cfg_test_attr_line(&stripped) {
pending_attr = true;
}
let bytes = stripped.as_bytes();
let inside_at_line_start = !gate_stack.is_empty();
mask[idx] = inside_at_line_start;
for &b in bytes {
if b == b'{' {
depth += 1;
if pending_attr {
gate_stack.push(depth - 1);
pending_attr = false;
}
} else if b == b'}' {
if let Some(&entry) = gate_stack.last()
&& depth - 1 == entry
{
gate_stack.pop();
}
depth -= 1;
}
}
}
mask
}
fn file_stem_is_exempt_test_module(rel: &Path) -> bool {
let Some(stem) = rel.file_stem().and_then(|s| s.to_str()) else {
return false;
};
is_exempt_test_submodule_name(stem)
}
fn is_cfg_test_inner_attr_line(stripped: &str) -> bool {
let bytes = stripped.as_bytes();
let mut i = 0usize;
while i + 2 < bytes.len() {
if bytes[i] == b'#' && bytes[i + 1] == b'!' && bytes[i + 2] == b'[' {
let rest = &stripped[i + 3..];
if let Some(pos) = rest.find("cfg(") {
let abs = i + 3 + pos;
let before_ok = abs == 0 || !is_ident_byte(bytes[abs - 1]);
if before_ok {
let args_start = abs + 4;
if let Some(end) = find_matching_paren(&bytes[args_start..]) {
let args = &stripped[args_start..args_start + end];
if cfg_args_contain_test(args) {
return true;
}
}
}
}
}
i += 1;
}
false
}
fn path_matches_crates_test(rel: &str) -> bool {
let Some(rest) = rel.strip_prefix("crates/") else {
return false;
};
let Some(slash) = rest.find('/') else {
return false;
};
let tail = &rest[slash + 1..];
tail.starts_with("tests/") || tail.starts_with("benches/")
}
fn is_cfg_test_attr_line(stripped: &str) -> bool {
let bytes = stripped.as_bytes();
let mut i = 0usize;
while i + 1 < bytes.len() {
if bytes[i] == b'#' && bytes[i + 1] == b'[' {
let rest = &stripped[i + 2..];
if let Some(pos) = rest.find("cfg(") {
let abs = i + 2 + pos;
let before_ok = abs == 0 || !is_ident_byte(bytes[abs - 1]);
if before_ok {
let args_start = abs + 4; if let Some(end) = find_matching_paren(&bytes[args_start..]) {
let args = &stripped[args_start..args_start + end];
if cfg_args_contain_test(args) {
return true;
}
}
}
}
}
i += 1;
}
false
}
fn find_matching_paren(bytes: &[u8]) -> Option<usize> {
let mut depth: i32 = 1;
let mut i = 0usize;
while i < bytes.len() {
match bytes[i] {
b'(' => depth += 1,
b')' => {
depth -= 1;
if depth == 0 {
return Some(i);
}
}
_ => {}
}
i += 1;
}
None
}
fn cfg_args_contain_test(args: &str) -> bool {
let bytes = args.as_bytes();
let kw = b"test";
let mut i = 0usize;
while i + kw.len() <= bytes.len() {
if &bytes[i..i + kw.len()] == kw {
let before_ok = i == 0 || !is_ident_byte(bytes[i - 1]);
let after_ok = i + kw.len() == bytes.len() || !is_ident_byte(bytes[i + kw.len()]);
if before_ok && after_ok {
return true;
}
}
i += 1;
}
false
}
fn scan_for_unsafe_without_safety(
root: &Path,
dir: &Path,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
if !content.contains("unsafe") {
return;
}
let lines: Vec<&str> = content.lines().collect();
let stripped_lines = strip_file_lines(content);
for (idx, line) in lines.iter().enumerate() {
let stripped = stripped_lines.get(idx).map(String::as_str).unwrap_or(line);
if !line_has_keyword(stripped, "unsafe") {
continue;
}
if line.contains("SAFETY:") {
continue;
}
if is_unsafe_marker_impl(stripped) {
continue;
}
let mut justified = false;
let mut seen = 0usize;
let mut k = idx;
while k > 0 && seen < 10 {
k -= 1;
let prev = lines[k];
if prev.trim().is_empty() {
break;
}
seen += 1;
if prev.contains("SAFETY:") {
justified = true;
break;
}
}
if !justified {
offenders.push((rel.to_path_buf(), idx + 1, line.to_string()));
}
}
});
}
fn is_unsafe_marker_impl(stripped: &str) -> bool {
for marker in ["Send", "Sync"] {
let needle_owned = format!("unsafe impl {}", marker);
let needle = needle_owned.as_str();
let bytes = stripped.as_bytes();
let nb = needle.as_bytes();
let mut i = 0usize;
while i + nb.len() <= bytes.len() {
if &bytes[i..i + nb.len()] == nb {
let after = i + nb.len();
if after == bytes.len() {
return true;
}
let c = bytes[after];
if c == b'<' || c.is_ascii_whitespace() {
return true;
}
if after + 3 <= bytes.len() && &bytes[after..after + 3] == b"for" {
return true;
}
}
i += 1;
}
}
false
}
fn scan_for_transmute_without_safety(
root: &Path,
dir: &Path,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
if !content.contains("transmute") {
return;
}
let lines: Vec<&str> = content.lines().collect();
let stripped_lines = strip_file_lines(content);
for (idx, line) in lines.iter().enumerate() {
let stripped = stripped_lines.get(idx).map(String::as_str).unwrap_or(line);
if !line_has_keyword(stripped, "transmute") {
continue;
}
if !stripped.contains("mem::") && !stripped.contains("transmute::<") {
continue;
}
if line.contains("SAFETY:") {
continue;
}
let mut justified = false;
let mut seen = 0usize;
let mut k = idx;
while k > 0 && seen < 10 {
k -= 1;
let prev = lines[k];
if prev.trim().is_empty() {
break;
}
seen += 1;
if prev.contains("SAFETY:") {
justified = true;
break;
}
}
if !justified {
offenders.push((rel.to_path_buf(), idx + 1, line.to_string()));
}
}
});
}
fn scan_for_silent_corruption_laundering(
root: &Path,
dir: &Path,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
let nan_lit = format!("f64::{}", "NAN");
let nan_core = format!("core::f64::{}", "NAN");
let nan_std = format!("std::f64::{}", "NAN");
let is_nan = format!(".is_{}()", "nan");
let contract_tokens: Vec<String> = vec![
format!("{}", "unreachable"),
format!("{}", "impossible"),
format!("{} {}", "silently", "corrupt"),
format!("{} {}", "programming", "error"),
format!("{} {}", "must", "override"),
format!("{} {}", "cannot", "happen"),
format!("{} {}", "can not", "happen"),
format!("{} {}", "should", "never"),
format!("{} {}", "shall", "never"),
format!("{} {}", "never", "reached"),
format!("{} {}", "never", "happen"),
format!("{} {}", "never", "occur"),
];
let benign_okunit = format!("{}(())", "Ok");
let benign_none = "None".to_string();
let benign_default = format!("{}::default()", "Default");
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
let has_nan = content.contains(&nan_lit);
let lower_all = content.to_lowercase();
let has_contract = contract_tokens.iter().any(|t| lower_all.contains(t));
if !has_nan && !has_contract {
return;
}
let mask = compute_test_mask(content, rel);
let lines: Vec<&str> = content.lines().collect();
let stripped_lines = strip_file_lines(content);
for (idx, line) in lines.iter().enumerate() {
if mask.get(idx).copied().unwrap_or(false) {
continue;
}
let stripped = stripped_lines.get(idx).map(String::as_str).unwrap_or(line);
let strimmed = stripped.trim();
let mut found_contract_comment = false;
let lo = idx.saturating_sub(6);
for raw in lines.iter().take(idx).skip(lo) {
if !raw.contains("//") {
continue;
}
let raw_lower = raw.to_lowercase();
if contract_tokens.iter().any(|t| raw_lower.contains(t)) {
found_contract_comment = true;
break;
}
}
if !found_contract_comment {
continue;
}
let mut emit_ctx = false;
let mut body = strimmed.to_string();
if let Some(rest) = body.strip_prefix("return ") {
emit_ctx = true;
body = rest.to_string();
}
if let Some(rest) = body.strip_prefix("=> ") {
emit_ctx = true;
body = rest.to_string();
}
let body = body.trim().trim_end_matches([';', ',']).trim();
let is_comparison = strimmed.contains(&is_nan)
|| strimmed.contains("!= ")
|| strimmed.contains("== ")
|| strimmed.contains(".partial_cmp")
|| strimmed.contains("matches!");
let bare_nan = body == nan_lit || body == nan_core || body == nan_std;
let is_nan_aggregate = {
let open = body.starts_with('(') || body.starts_with('[');
let closed = body.ends_with(')') || body.ends_with(']');
if open && closed && body.len() >= 2 {
let inner = &body[1..body.len() - 1];
let inner_main = inner.split(';').next().unwrap_or(inner);
!inner_main.trim().is_empty()
&& inner_main.split(',').all(|p| {
let p = p.trim();
p == nan_lit
|| p == nan_core
|| p == nan_std
|| p == "0.0"
|| p == "None"
})
&& (inner_main.contains(&nan_lit)
|| inner_main.contains(&nan_core)
|| inner_main.contains(&nan_std))
} else {
false
}
};
let _ = emit_ctx;
if (bare_nan || is_nan_aggregate) && !is_comparison {
offenders.push((rel.to_path_buf(), idx + 1, line.to_string()));
continue;
}
let is_zero_float = body == "0.0" || body == "0.0_f64" || body == "0f64";
let is_okunit = body == benign_okunit;
let is_none = body == benign_none;
let is_default = body == benign_default;
let is_zeros =
(body.starts_with("Array") && body.contains("::zeros")) || body.ends_with("::zeros()");
let is_zero_tuple = body.starts_with('(') && body.ends_with(')') && {
let inner = &body[1..body.len() - 1];
!inner.is_empty()
&& inner.split(',').all(|p| {
let p = p.trim();
p == "0.0" || p == "0.0_f64" || p == "0f64"
})
};
let body_is_benign =
is_zero_float || is_okunit || is_none || is_default || is_zeros || is_zero_tuple;
if body_is_benign {
offenders.push((rel.to_path_buf(), idx + 1, line.to_string()));
}
}
});
}
fn scan_for_panic_without_safety(
root: &Path,
dir: &Path,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
if !content.contains("panic!(") {
return;
}
let mask = compute_test_mask(content, rel);
let lines: Vec<&str> = content.lines().collect();
let stripped_lines = strip_file_lines(content);
for (idx, line) in lines.iter().enumerate() {
if mask.get(idx).copied().unwrap_or(false) {
continue;
}
let stripped = stripped_lines.get(idx).map(String::as_str).unwrap_or(line);
if !stripped.contains("panic!(") {
continue;
}
if line.contains("SAFETY:") {
continue;
}
let mut justified = false;
let mut seen = 0usize;
let mut k = idx;
while k > 0 && seen < 10 {
k -= 1;
let prev = lines[k];
if prev.trim().is_empty() {
break;
}
seen += 1;
if prev.contains("SAFETY:") {
justified = true;
break;
}
}
if !justified {
offenders.push((rel.to_path_buf(), idx + 1, line.to_string()));
}
}
});
}
fn scan_for_dead_cfg_gates(root: &Path, dir: &Path, offenders: &mut Vec<(PathBuf, usize, String)>) {
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
if !content.contains("cfg(") {
return;
}
for (idx, line) in content.lines().enumerate() {
let stripped = strip_strings_and_comments(line);
if !stripped.contains("#[") {
continue;
}
if line_has_empty_cfg_gate(&stripped) {
offenders.push((rel.to_path_buf(), idx + 1, line.to_string()));
}
}
});
}
fn scan_for_feature_cfg_gates(
root: &Path,
dir: &Path,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
if !content.contains("feature") {
return;
}
let stripped_lines = strip_file_lines(content);
for (idx, line) in content.lines().enumerate() {
let stripped = stripped_lines.get(idx).map(String::as_str).unwrap_or(line);
if !(stripped.contains("#[") || stripped.contains("#![")) {
continue;
}
if !(stripped.contains("cfg(") || stripped.contains("cfg_attr(")) {
continue;
}
if line_has_feature_predicate(stripped) && !line_is_cuda_feature_gate(stripped) {
offenders.push((rel.to_path_buf(), idx + 1, line.to_string()));
}
}
});
}
fn line_has_feature_predicate(stripped: &str) -> bool {
let bytes = stripped.as_bytes();
let kw = b"feature";
let mut i = 0usize;
while i + kw.len() <= bytes.len() {
if &bytes[i..i + kw.len()] == kw {
let before_ok = i == 0 || !is_ident_byte(bytes[i - 1]);
let after_pos = i + kw.len();
let after_ok = after_pos == bytes.len() || !is_ident_byte(bytes[after_pos]);
if before_ok && after_ok {
let mut j = after_pos;
while j < bytes.len() && bytes[j].is_ascii_whitespace() {
j += 1;
}
if j < bytes.len() && bytes[j] == b'=' {
return true;
}
}
}
i += 1;
}
false
}
fn line_is_cuda_feature_gate(stripped: &str) -> bool {
let mut rest = stripped;
let mut saw_cuda = false;
while let Some(pos) = rest.find("feature") {
let after = &rest[pos + "feature".len()..];
let Some(eq_pos) = after.find('=') else {
return false;
};
let after_eq = after[eq_pos + 1..].trim_start();
if !after_eq.starts_with("\"cuda\"") {
return false;
}
saw_cuda = true;
rest = &after_eq["\"cuda\"".len()..];
}
saw_cuda
}
fn scan_for_cargo_feature_entries(
root: &Path,
dir: &Path,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
visit_files(root, dir, &mut |rel, content| {
let basename = rel.file_name().and_then(OsStr::to_str).unwrap_or("");
if basename != "Cargo.toml" {
return;
}
let mut in_features = false;
for (idx, line) in content.lines().enumerate() {
let trimmed = line.trim();
let code_part = match trimmed.find('#') {
Some(p) => trimmed[..p].trim_end(),
None => trimmed,
};
if code_part.starts_with('[') && code_part.ends_with(']') {
let header = code_part
.trim_start_matches('[')
.trim_end_matches(']')
.trim();
in_features = header == "features"
|| header.starts_with("features.")
|| header == "workspace.features"
|| header.starts_with("workspace.features.");
continue;
}
if !in_features {
continue;
}
if code_part.is_empty() {
continue;
}
let bytes = code_part.as_bytes();
let mut j = 0usize;
while j < bytes.len()
&& (bytes[j].is_ascii_alphanumeric() || bytes[j] == b'_' || bytes[j] == b'-')
{
j += 1;
}
if j == 0 {
continue;
}
let mut k = j;
while k < bytes.len() && bytes[k].is_ascii_whitespace() {
k += 1;
}
let rel_str = rel.to_string_lossy().replace('\\', "/");
let pyo3_extension_module_idiom = rel_str == "crates/gam-pyffi/Cargo.toml"
&& (code_part == "default = [\"extension-module\"]"
|| code_part == "extension-module = [\"pyo3/extension-module\"]");
if k < bytes.len()
&& bytes[k] == b'='
&& code_part != "default = []"
&& !code_part.starts_with("cuda = ")
&& !pyo3_extension_module_idiom
{
offenders.push((rel.to_path_buf(), idx + 1, line.to_string()));
}
}
});
}
fn scan_for_cargo_lint_allows(
root: &Path,
dir: &Path,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
visit_files(root, dir, &mut |rel, content| {
let basename = rel.file_name().and_then(OsStr::to_str).unwrap_or("");
if basename != "Cargo.toml" {
return;
}
let mut in_lints = false;
for (idx, line) in content.lines().enumerate() {
let trimmed = line.trim();
let code_part = match trimmed.find('#') {
Some(p) => trimmed[..p].trim_end(),
None => trimmed,
};
if code_part.starts_with('[') && code_part.ends_with(']') {
let header = code_part
.trim_start_matches('[')
.trim_end_matches(']')
.trim();
in_lints = header == "lints"
|| header.starts_with("lints.")
|| header == "workspace.lints"
|| header.starts_with("workspace.lints.");
continue;
}
if !in_lints || code_part.is_empty() {
continue;
}
if code_part.contains("\"allow\"") {
offenders.push((rel.to_path_buf(), idx + 1, line.to_string()));
}
}
});
}
fn scan_for_cfg_test_on_pub_items(
root: &Path,
dir: &Path,
offenders: &mut Vec<(PathBuf, usize, String, String)>,
) {
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
let in_src = rel_str.starts_with("src/")
|| rel_str
.strip_prefix("crates/")
.and_then(|rest| rest.find('/').map(|i| &rest[i + 1..]))
.is_some_and(|tail| tail.starts_with("src/"));
if !in_src {
return;
}
if !content.contains("cfg(") {
return;
}
let lines: Vec<&str> = content.lines().collect();
let stripped_lines = strip_file_lines(content);
let n = lines.len();
for idx in 0..n {
let stripped = stripped_lines
.get(idx)
.map(String::as_str)
.unwrap_or(lines[idx]);
if !is_cfg_test_attr_line(stripped) {
continue;
}
let mut j = idx + 1;
let mut item_line: Option<usize> = None;
while j < n {
let sj = stripped_lines
.get(j)
.map(String::as_str)
.unwrap_or(lines[j]);
let t = sj.trim();
if t.is_empty() {
j += 1;
continue;
}
if t.starts_with("//") {
j += 1;
continue;
}
if t.starts_with("#[") || t.starts_with("#![") {
j += 1;
continue;
}
item_line = Some(j);
break;
}
let Some(item_idx) = item_line else {
continue;
};
let item_raw = lines.get(item_idx).copied().unwrap_or("");
let item_trim = item_raw.trim_start();
if let Some(rest) = item_trim.strip_prefix("mod ") {
let name: String = rest
.chars()
.take_while(|c| c.is_ascii_alphanumeric() || *c == '_')
.collect();
if !name.is_empty() && is_exempt_test_submodule_name(&name) {
continue;
}
}
let mut descriptor: String = item_trim
.chars()
.take_while(|c| *c != '{' && *c != ';' && *c != '\n')
.collect();
descriptor = descriptor.trim().chars().take(80).collect();
offenders.push((
rel.to_path_buf(),
idx + 1,
descriptor,
lines[idx].to_string(),
));
}
});
}
fn is_exempt_test_submodule_name(name: &str) -> bool {
name == "tests"
|| name == "test_support"
|| name.starts_with("tests_")
|| name.ends_with("_tests")
}
fn line_has_empty_cfg_gate(stripped: &str) -> bool {
for marker in ["cfg(any(", "cfg(all("] {
let mut search_from = 0usize;
while let Some(rel_pos) = stripped[search_from..].find(marker) {
let inner_start = search_from + rel_pos + marker.len();
let bytes = stripped.as_bytes();
let mut j = inner_start;
while j < bytes.len() && bytes[j].is_ascii_whitespace() {
j += 1;
}
if j < bytes.len() && bytes[j] == b')' {
return true;
}
search_from = inner_start;
}
}
false
}
fn scan_for_bare_should_panic(
root: &Path,
dir: &Path,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
if !content.contains("#[should_panic") {
return;
}
for (idx, line) in content.lines().enumerate() {
let trimmed = line.trim_start();
if trimmed.starts_with("#[should_panic]")
|| (trimmed.starts_with("#[should_panic") && !trimmed.contains("expected"))
{
offenders.push((rel.to_path_buf(), idx + 1, line.to_string()));
}
}
});
}
fn scan_for_dead_guard_consts(
root: &Path,
dir: &Path,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
if !content.contains("const ") {
return;
}
let trait_impl_mask = compute_trait_impl_mask(content);
let stripped_lines = strip_file_lines(content);
for (idx, line) in content.lines().enumerate() {
let stripped = stripped_lines.get(idx).map(String::as_str).unwrap_or(line);
if !line_has_keyword(stripped, "const") {
continue;
}
if line_matches_bool_literal_const(stripped) {
if trait_impl_mask.get(idx).copied().unwrap_or(false) {
continue;
}
offenders.push((rel.to_path_buf(), idx + 1, line.to_string()));
}
}
});
}
fn compute_trait_impl_mask(content: &str) -> Vec<bool> {
let lines: Vec<&str> = content.lines().collect();
let n = lines.len();
let mut mask = vec![false; n];
let stripped_lines: Vec<String> = strip_file_lines(content);
let mut stack: Vec<(i32, bool)> = Vec::new();
let mut depth: i32 = 0;
let mut pending_impl = false;
let mut pending_is_trait = false;
for (idx, stripped) in stripped_lines.iter().enumerate() {
let inside_trait_impl = stack.iter().any(|(_, t)| *t);
mask[idx] = inside_trait_impl;
let trimmed = stripped.trim_start();
let starts_impl = trimmed.starts_with("impl ")
|| trimmed.starts_with("impl<")
|| trimmed.starts_with("unsafe impl ")
|| trimmed.starts_with("unsafe impl<")
|| trimmed.starts_with("default impl ")
|| trimmed.starts_with("default impl<");
if starts_impl && depth == 0 {
pending_impl = true;
pending_is_trait = stripped.contains(" for ");
} else if pending_impl && stripped.contains(" for ") {
pending_is_trait = true;
}
let bytes = stripped.as_bytes();
for &b in bytes {
if b == b'{' {
let opened_at_depth = depth;
depth += 1;
if pending_impl && opened_at_depth == 0 {
stack.push((opened_at_depth, pending_is_trait));
pending_impl = false;
pending_is_trait = false;
} else {
stack.push((opened_at_depth, false));
}
} else if b == b'}' {
if let Some(&(entry, _)) = stack.last()
&& depth - 1 == entry
{
stack.pop();
}
depth -= 1;
}
}
}
mask
}
fn compute_trait_def_mask(content: &str) -> Vec<bool> {
let lines: Vec<&str> = content.lines().collect();
let n = lines.len();
let mut mask = vec![false; n];
let stripped_lines: Vec<String> = strip_file_lines(content);
let mut stack: Vec<(i32, bool)> = Vec::new();
let mut depth: i32 = 0;
let mut pending_trait = false;
for (idx, stripped) in stripped_lines.iter().enumerate() {
let inside_trait_def = stack.iter().any(|(_, t)| *t);
mask[idx] = inside_trait_def;
let trimmed = stripped.trim_start();
let starts_trait = trimmed.starts_with("trait ")
|| trimmed.starts_with("trait<")
|| trimmed.starts_with("pub trait ")
|| trimmed.starts_with("pub trait<")
|| trimmed.starts_with("pub(crate) trait ")
|| trimmed.starts_with("pub(crate) trait<")
|| trimmed.starts_with("pub(super) trait ")
|| trimmed.starts_with("pub(super) trait<")
|| trimmed.starts_with("unsafe trait ")
|| trimmed.starts_with("unsafe trait<")
|| trimmed.starts_with("pub unsafe trait ")
|| trimmed.starts_with("pub unsafe trait<")
|| trimmed.starts_with("pub(crate) unsafe trait ")
|| trimmed.starts_with("pub(crate) unsafe trait<")
|| trimmed.starts_with("pub(super) unsafe trait ")
|| trimmed.starts_with("pub(super) unsafe trait<");
if starts_trait && depth == 0 {
pending_trait = true;
}
let bytes = stripped.as_bytes();
for &b in bytes {
if b == b'{' {
let opened_at_depth = depth;
depth += 1;
if pending_trait && opened_at_depth == 0 {
stack.push((opened_at_depth, true));
pending_trait = false;
} else {
stack.push((opened_at_depth, false));
}
} else if b == b'}' {
if let Some(&(entry, _)) = stack.last()
&& depth - 1 == entry
{
stack.pop();
}
depth -= 1;
}
}
}
mask
}
fn line_matches_bool_literal_const(stripped: &str) -> bool {
let bytes = stripped.as_bytes();
let kw = b"const";
let mut i = 0usize;
'outer: while i + kw.len() <= bytes.len() {
if &bytes[i..i + kw.len()] != kw {
i += 1;
continue;
}
let before_ok = i == 0 || !is_ident_byte(bytes[i - 1]);
let after_ok = i + kw.len() < bytes.len() && !is_ident_byte(bytes[i + kw.len()]);
if !before_ok || !after_ok {
i += 1;
continue;
}
let mut j = i + kw.len();
while j < bytes.len() && bytes[j].is_ascii_whitespace() {
j += 1;
}
if j >= bytes.len() || !(bytes[j].is_ascii_alphabetic() || bytes[j] == b'_') {
i += 1;
continue;
}
while j < bytes.len() && is_ident_byte(bytes[j]) {
j += 1;
}
while j < bytes.len() && bytes[j].is_ascii_whitespace() {
j += 1;
}
if j >= bytes.len() || bytes[j] != b':' {
i += 1;
continue;
}
j += 1;
while j < bytes.len() && bytes[j].is_ascii_whitespace() {
j += 1;
}
let bool_kw = b"bool";
if j + bool_kw.len() > bytes.len() || &bytes[j..j + bool_kw.len()] != bool_kw {
i += 1;
continue;
}
let after = j + bool_kw.len();
if after < bytes.len() && is_ident_byte(bytes[after]) {
i += 1;
continue;
}
j = after;
while j < bytes.len() && bytes[j].is_ascii_whitespace() {
j += 1;
}
if j >= bytes.len() || bytes[j] != b'=' {
i += 1;
continue;
}
j += 1;
while j < bytes.len() && bytes[j].is_ascii_whitespace() {
j += 1;
}
for lit in [b"true".as_ref(), b"false".as_ref()] {
if j + lit.len() <= bytes.len() && &bytes[j..j + lit.len()] == lit {
let after_lit = j + lit.len();
let bound_ok = after_lit == bytes.len() || !is_ident_byte(bytes[after_lit]);
if bound_ok {
let mut k = after_lit;
while k < bytes.len() && bytes[k].is_ascii_whitespace() {
k += 1;
}
if k < bytes.len() && bytes[k] == b';' {
return true;
}
}
}
}
i += 1;
continue 'outer;
}
false
}
fn scan_for_debug_eprintln(root: &Path, dir: &Path, offenders: &mut Vec<(PathBuf, usize, String)>) {
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
if !content.contains("eprint") {
return;
}
let mask = compute_test_mask(content, rel);
let stripped_lines = strip_file_lines(content);
for (idx, line) in content.lines().enumerate() {
if mask.get(idx).copied().unwrap_or(false) {
continue;
}
let stripped = stripped_lines.get(idx).map(String::as_str).unwrap_or(line);
if !stripped.contains("eprintln!(") && !stripped.contains("eprint!(") {
continue;
}
if line.contains(":?}") || line.contains(":#?}") {
offenders.push((rel.to_path_buf(), idx + 1, line.to_string()));
}
}
});
}
fn strip_strings_and_comments(line: &str) -> String {
strip_strings_and_comments_stateful(line, false, 0).0
}
fn strip_file_lines(content: &str) -> Vec<String> {
let mut out: Vec<String> = Vec::new();
let mut in_str = false;
let mut quote: u8 = 0;
let mut raw_hashes: u8 = 0;
for line in content.lines() {
let (stripped, after_in_str, after_quote, after_hashes) =
strip_strings_and_comments_stateful_raw(line, in_str, quote, raw_hashes);
out.push(stripped);
in_str = after_in_str;
quote = after_quote;
raw_hashes = after_hashes;
}
out
}
fn strip_strings_and_comments_stateful(
line: &str,
in_str_in: bool,
quote_in: u8,
) -> (String, bool, u8) {
let result = strip_strings_and_comments_stateful_raw(line, in_str_in, quote_in, 0);
(result.0, result.1, result.2)
}
fn strip_strings_and_comments_stateful_raw(
line: &str,
in_str_in: bool,
quote_in: u8,
hashes_in: u8,
) -> (String, bool, u8, u8) {
let bytes = line.as_bytes();
let mut out = Vec::with_capacity(bytes.len());
let mut i = 0usize;
let mut in_str = in_str_in;
let mut str_quote: u8 = quote_in;
let mut raw_hashes: u8 = hashes_in;
while i < bytes.len() {
let c = bytes[i];
if in_str && str_quote == b'r' {
if c == b'"' {
let need = raw_hashes as usize;
let mut k = i + 1;
let mut count = 0usize;
while k < bytes.len() && bytes[k] == b'#' && count < need {
k += 1;
count += 1;
}
if count == need {
in_str = false;
str_quote = 0;
raw_hashes = 0;
out.push(b'"');
for _ in 0..need {
out.push(b'#');
}
i = k;
continue;
}
}
out.push(b' ');
i += 1;
continue;
}
if in_str {
if c == b'\\' && i + 1 < bytes.len() {
out.push(b' ');
out.push(b' ');
i += 2;
continue;
}
if c == str_quote {
in_str = false;
out.push(c);
} else {
out.push(b' ');
}
i += 1;
continue;
}
if c == b'/' && i + 1 < bytes.len() && bytes[i + 1] == b'/' {
break;
}
let prev_is_ident = i > 0 && (bytes[i - 1].is_ascii_alphanumeric() || bytes[i - 1] == b'_');
if !prev_is_ident
&& (c == b'r' || (c == b'b' && i + 1 < bytes.len() && bytes[i + 1] == b'r'))
{
let prefix_len = if c == b'b' { 2usize } else { 1usize };
let mut k = i + prefix_len;
let mut hashes = 0usize;
while k < bytes.len() && bytes[k] == b'#' {
k += 1;
hashes += 1;
}
if k < bytes.len() && bytes[k] == b'"' && hashes <= u8::MAX as usize {
in_str = true;
str_quote = b'r';
raw_hashes = hashes as u8;
for j in i..=k {
out.push(bytes[j]);
}
i = k + 1;
continue;
}
}
if c == b'"' {
in_str = true;
str_quote = c;
out.push(c);
i += 1;
continue;
}
if c == b'\'' {
let is_char_lit = if i + 1 < bytes.len() && bytes[i + 1] == b'\\' {
let mut k = i + 2;
let mut found = false;
while k < bytes.len() && k < i + 10 {
if bytes[k] == b'\'' {
found = true;
break;
}
k += 1;
}
found
} else if i + 2 < bytes.len() && bytes[i + 1] != b'\'' && bytes[i + 2] == b'\'' {
true
} else if i + 3 < bytes.len() && bytes[i + 1] != b'\'' && bytes[i + 3] == b'\'' {
true
} else {
false
};
if is_char_lit {
in_str = true;
str_quote = c;
out.push(c);
i += 1;
continue;
}
out.push(c);
i += 1;
continue;
}
out.push(c);
i += 1;
}
let s = String::from_utf8(out).unwrap_or_else(|_| line.to_string());
(s, in_str, str_quote, raw_hashes)
}
fn line_has_keyword(line: &str, kw: &str) -> bool {
let bytes = line.as_bytes();
let kw_bytes = kw.as_bytes();
if kw_bytes.is_empty() || bytes.len() < kw_bytes.len() {
return false;
}
let mut i = 0usize;
while i + kw_bytes.len() <= bytes.len() {
if &bytes[i..i + kw_bytes.len()] == kw_bytes {
let before_ok = i == 0 || !is_ident_byte(bytes[i - 1]);
let after_ok =
i + kw_bytes.len() == bytes.len() || !is_ident_byte(bytes[i + kw_bytes.len()]);
if before_ok && after_ok {
return true;
}
}
i += 1;
}
false
}
fn scan_for_banned_marker(
root: &Path,
dir: &Path,
needle: &str,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
visit_files(root, dir, &mut |rel, content| {
if rel.to_string_lossy().replace('\\', "/") == "build.rs" {
return;
}
if !content.contains(needle) {
return;
}
for (idx, line) in content.lines().enumerate() {
if line.contains(needle) {
offenders.push((rel.to_path_buf(), idx + 1, line.to_string()));
}
}
});
}
fn scan_for_deferred_work_markers(
root: &Path,
dir: &Path,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
let pure_markers: Vec<String> = vec![
format!("{}{}", "fix", "me"),
format!("{}{}", "x", "xx"),
"hack".to_string(),
];
let deferral_words: Vec<String> = vec![
format!("{}-{}", "follow", "up"),
format!("{}{}", "follow", "up"),
format!("{}{}", "de", "ferred"),
format!("{}{}", "de", "fer"),
"revisit".to_string(),
format!("{}{}", "stop", "gap"),
"punt".to_string(),
format!("{}{}", "t", "bd"),
format!("{}{}", "w", "ip"),
"later".to_string(),
format!("{}{}", "place", "holder"),
];
visit_files(root, dir, &mut |rel, content| {
if rel.to_string_lossy().replace('\\', "/") == "build.rs" {
return;
}
for (idx, line) in content.lines().enumerate() {
let Some(body) = comment_body(line) else {
continue;
};
let body_l = body.to_lowercase();
let mut hit = pure_markers.iter().any(|w| lead_token_is(&body_l, w));
if !hit {
hit = deferral_words.iter().any(|w| {
body_l
.strip_prefix(w.as_str())
.is_some_and(|rest| marker_issue_ref_follows(rest.trim_start()))
});
}
if hit {
offenders.push((rel.to_path_buf(), idx + 1, line.trim().to_string()));
}
}
});
}
fn comment_body(line: &str) -> Option<&str> {
let t = line.trim_start();
for lead in ["///", "//!", "//", "/**", "/*", "#"] {
if let Some(rest) = t.strip_prefix(lead) {
if lead == "#" && rest.trim_start().starts_with('[') {
return None;
}
return Some(rest.trim_start());
}
}
None
}
fn lead_token_is(body: &str, word: &str) -> bool {
match body.strip_prefix(word) {
Some(rest) => rest
.chars()
.next()
.map(|c| !c.is_ascii_alphanumeric())
.unwrap_or(true),
None => false,
}
}
fn marker_issue_ref_follows(rest: &str) -> bool {
let b = rest.as_bytes();
let close = match b.first() {
Some(b'(') => b')',
Some(b'[') => b']',
Some(b'{') => b'}',
_ => return false,
};
let mut i = 1usize;
if b.get(i) == Some(&b'#') {
i += 1;
}
let digits_start = i;
while i < b.len() && b[i].is_ascii_digit() {
i += 1;
}
if i == digits_start {
return false;
}
b.get(i) == Some(&close)
}
fn comment_text_is_owed_work(text: &str) -> bool {
let strong: Vec<String> = vec![
format!("not yet {}", "wired"),
format!("not yet {}", "implemented"),
format!("not yet {}", "supported"),
format!("not yet {}", "hooked"),
format!("not yet {}", "done"),
format!("not yet {}", "finished"),
format!("not {} yet", "implemented"),
format!("not {} yet", "supported"),
format!("not {} yet", "wired"),
format!("to be {} yet", "wired"),
format!("deferred to a {}", "follow"),
format!("left to a {}", "follow"),
format!("for a {}-up", "follow"),
format!("in a {}-up", "follow"),
format!("to a {}-up", "follow"),
format!("remains to be {}", "implemented"),
format!("needs to be {}", "implemented"),
format!("will be {}", "implemented"),
format!("will be {}", "wired"),
format!("yet to be {}", "implemented"),
format!("yet to be {}", "wired"),
];
if strong.iter().any(|p| text.contains(p.as_str())) {
return true;
}
let bare_scope: Vec<String> = vec![
format!("not wired {}", "into"),
format!("not wired {}", "through"),
format!("is not {}", "wired"),
format!("{} wired", "isn't"),
];
if bare_scope.iter().any(|p| text.contains(p.as_str())) {
let temporal = [" yet", " will ", " soon", " later", " eventually", " once "];
return temporal.iter().any(|c| text.contains(c));
}
false
}
fn scan_for_owed_work_prose(root: &Path, dir: &Path, offenders: &mut Vec<(PathBuf, usize, String)>) {
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if !rel_str.starts_with("src/") {
return;
}
for (idx, line) in content.lines().enumerate() {
let Some(text) = line_comment_text(line) else {
continue;
};
if comment_text_is_owed_work(&text) {
offenders.push((rel.to_path_buf(), idx + 1, line.trim().to_string()));
}
}
});
}
fn line_comment_text(line: &str) -> Option<String> {
let bytes = line.as_bytes();
let mut i = 0usize;
while i + 1 < bytes.len() {
if bytes[i] == b'/' && bytes[i + 1] == b'/' {
if i > 0 && bytes[i - 1] == b':' {
i += 2;
continue;
}
return Some(line[i + 2..].to_lowercase());
}
i += 1;
}
None
}
fn scan_for_banned_allow(
root: &Path,
dir: &Path,
offenders: &mut Vec<(PathBuf, usize, String, String)>,
) {
const SILENCERS: &[&str] = &["allow(", "expect("];
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
if !SILENCERS.iter().any(|s| content.contains(s)) {
return;
}
let stripped_lines = strip_file_lines(content);
for (idx, line) in content.lines().enumerate() {
let code = stripped_lines.get(idx).map(String::as_str).unwrap_or(line);
if !code.contains("#[") {
continue;
}
for silencer in SILENCERS {
let mut search_from = 0usize;
while let Some(rel_idx) = code[search_from..].find(silencer) {
let abs_match = search_from + rel_idx;
let mut k = abs_match;
while k > 0 && code.as_bytes()[k - 1].is_ascii_whitespace() {
k -= 1;
}
let prefix = &code[..k];
let is_attr = prefix.ends_with("#[") || prefix.ends_with("#![");
let start = abs_match + silencer.len();
if !is_attr {
search_from = start;
continue;
}
let Some(end_rel) = code[start..].find(')') else {
break;
};
let inside = &code[start..start + end_rel];
let mut first_label: Option<String> = None;
let mut any_lint = false;
for tok in inside.split(',') {
let trimmed = tok.trim();
if trimmed.is_empty() {
continue;
}
any_lint = true;
if first_label.is_none() {
let bare = trimmed
.trim_start_matches("rustc::")
.trim_start_matches("rustdoc::");
first_label = Some(bare.to_string());
}
}
if any_lint {
let attr = silencer.trim_end_matches('(');
let label = first_label.unwrap_or_else(|| "<empty>".to_string());
offenders.push((
rel.to_path_buf(),
idx + 1,
format!("{attr}({label})"),
line.to_string(),
));
}
search_from = start + end_rel + 1;
if search_from >= code.len() {
break;
}
}
}
}
});
}
fn scan_for_let_underscore(root: &Path, dir: &Path, offenders: &mut Vec<(PathBuf, usize, String)>) {
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
if !content.contains("let ") {
return;
}
let mask = compute_test_mask(content, rel);
let stripped_lines = strip_file_lines(content);
for (idx, line) in content.lines().enumerate() {
if mask.get(idx).copied().unwrap_or(false) {
continue;
}
let stripped = stripped_lines.get(idx).map(String::as_str).unwrap_or(line);
if stripped_line_has_let_underscore(stripped) {
offenders.push((rel.to_path_buf(), idx + 1, line.to_string()));
}
}
});
}
fn stripped_line_has_let_underscore(line: &str) -> bool {
let bytes = line.as_bytes();
let mut i = 0usize;
while i < bytes.len() {
if i + 3 < bytes.len()
&& &bytes[i..i + 3] == b"let"
&& (i == 0 || !is_ident_byte(bytes[i - 1]))
&& bytes[i + 3].is_ascii_whitespace()
{
let mut j = i + 3;
while j < bytes.len() && bytes[j].is_ascii_whitespace() {
j += 1;
}
if j + 3 <= bytes.len()
&& &bytes[j..j + 3] == b"mut"
&& j + 3 < bytes.len()
&& bytes[j + 3].is_ascii_whitespace()
{
j += 3;
while j < bytes.len() && bytes[j].is_ascii_whitespace() {
j += 1;
}
}
if j < bytes.len() && bytes[j] == b'_' {
return true;
}
if j < bytes.len()
&& bytes[j] == b'('
&& tuple_pattern_all_underscore(bytes, j) == Some(true)
{
return true;
}
i = j;
continue;
}
i += 1;
}
false
}
fn tuple_pattern_all_underscore(bytes: &[u8], start: usize) -> Option<bool> {
if start >= bytes.len() || bytes[start] != b'(' {
return None;
}
let mut depth = 0i32;
let mut k = start;
let mut any_binding = false;
let mut all_underscore = true;
while k < bytes.len() {
let b = bytes[k];
match b {
b'(' => {
depth += 1;
k += 1;
}
b')' => {
depth -= 1;
k += 1;
if depth == 0 {
if !any_binding {
return None;
}
return Some(all_underscore);
}
}
b',' | b' ' | b'\t' => {
k += 1;
}
b'=' => {
return None;
}
_ => {
if b == b'_' || b.is_ascii_alphabetic() {
let s = k;
while k < bytes.len() && is_ident_byte(bytes[k]) {
k += 1;
}
let word = &bytes[s..k];
if word == b"mut" || word == b"ref" {
continue;
}
let mut m = k;
while m < bytes.len() && (bytes[m] == b' ' || bytes[m] == b'\t') {
m += 1;
}
if m < bytes.len() {
let nb = bytes[m];
if nb == b'(' || nb == b'{' {
return None;
}
if nb == b':' && m + 1 < bytes.len() && bytes[m + 1] == b':' {
return None;
}
}
any_binding = true;
if !word.starts_with(b"_") {
all_underscore = false;
}
} else {
return None;
}
}
}
}
None
}
fn is_ident_byte(b: u8) -> bool {
b.is_ascii_alphanumeric() || b == b'_'
}
fn scan_for_ignored_tests(root: &Path, dir: &Path, offenders: &mut Vec<(PathBuf, usize, String)>) {
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
if !content.contains("#[ignore") {
return;
}
for (idx, line) in content.lines().enumerate() {
let trimmed = line.trim_start();
if trimmed.starts_with("#[ignore]") || trimmed.starts_with("#[ignore =") {
offenders.push((rel.to_path_buf(), idx + 1, line.to_string()));
}
}
});
}
fn scan_for_vendor_directories(
root: &Path,
dir: &Path,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
let read = match fs::read_dir(dir) {
Ok(r) => r,
Err(_) => return,
};
for entry in read.flatten() {
let path = entry.path();
let name = path.file_name().and_then(OsStr::to_str).unwrap_or("");
if (name.starts_with('.') && name != ".github")
|| name == "target"
|| name.starts_with("target-")
|| name == "node_modules"
|| name == "__pycache__"
|| name == "pydeps"
|| name == "site-packages"
|| name == "venv"
|| name == "dist"
|| name == "build"
|| name == "site"
{
continue;
}
if !path.is_dir() {
continue;
}
if name == "vendor" {
let rel = path.strip_prefix(root).unwrap_or(&path).to_path_buf();
offenders.push((
rel,
1,
"vendored crates are forbidden; depend on crates.io or `git = \"…\"` in Cargo.toml"
.to_string(),
));
continue;
}
scan_for_vendor_directories(root, &path, offenders);
}
}
const MAX_TRACKED_FILE_LINES: usize = 10_000;
static REPO_FILES: OnceLock<Vec<PathBuf>> = OnceLock::new();
fn collect_repo_files(root: &Path) -> &'static [PathBuf] {
REPO_FILES
.get_or_init(|| read_git_index_tracked_files(root))
.as_slice()
}
fn cluster_leak_needles() -> [String; 2] {
let needle_a = format!("projects{}standard", "/");
let needle_b = format!("{}BATCH", "S");
[needle_a, needle_b]
}
fn scan_for_cluster_infra_leaks(root: &Path) {
let needles = cluster_leak_needles();
let mut offenders: Vec<(PathBuf, usize, String)> = Vec::new();
for rel in collect_repo_files(root) {
let path = root.join(rel);
let content = match fs::read(&path) {
Ok(bytes) => bytes,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => continue,
Err(_) => continue,
};
let text = match std::str::from_utf8(&content) {
Ok(text) => text,
Err(_) => continue,
};
for (lineno, line) in text.lines().enumerate() {
for needle in &needles {
if line.contains(needle.as_str()) {
offenders.push((rel.clone(), lineno + 1, needle.clone()));
}
}
}
}
if offenders.is_empty() {
return;
}
eprintln!(
"\n=== BANNED cluster/SLURM INFRA LEAK in tracked file(s) ===\n\
No tracked file may contain the absolute cluster scratch path segment or the \
SLURM batch directive keyword. These are cluster-local infra leaks; cluster/sbatch \
scripts belong under /Users/user/, not in the repo. Offenders:"
);
for (rel, lineno, needle) in &offenders {
eprintln!(
" {}:{} contains banned string `{}`",
rel.display(),
lineno,
needle
);
println!(
"cargo:warning=banned cluster/SLURM infra leak: {}:{} contains `{}`",
rel.display(),
lineno,
needle
);
}
std::process::exit(1);
}
fn locate_git_index(root: &Path) -> PathBuf {
let git = root.join(".git");
let meta = fs::metadata(&git).unwrap_or_else(|err| {
panic!(
"failed to stat {} for tracked-file audit: {err}",
git.display()
)
});
if meta.is_dir() {
return git.join("index");
}
let pointer = fs::read_to_string(&git)
.unwrap_or_else(|err| panic!("failed to read worktree pointer {}: {err}", git.display()));
let gitdir = pointer
.lines()
.next()
.and_then(|line| line.strip_prefix("gitdir:"))
.map(|rest| rest.trim())
.unwrap_or_else(|| panic!("worktree pointer at {} missing gitdir line", git.display()));
let gitdir_path = if Path::new(gitdir).is_absolute() {
PathBuf::from(gitdir)
} else {
root.join(gitdir)
};
gitdir_path.join("index")
}
fn read_git_index_tracked_files(root: &Path) -> Vec<PathBuf> {
let index_path = locate_git_index(root);
let bytes = fs::read(&index_path).unwrap_or_else(|err| {
panic!(
"failed to read git index for tracked-file audit ({}): {err}",
index_path.display()
)
});
parse_git_index(&bytes).unwrap_or_else(|err| {
panic!(
"failed to parse git index at {}: {err}",
index_path.display()
)
})
}
fn parse_git_index(bytes: &[u8]) -> Result<Vec<PathBuf>, String> {
if bytes.len() < 12 {
return Err(format!("index too short for header: {} bytes", bytes.len()));
}
if &bytes[0..4] != b"DIRC" {
return Err(format!("bad signature {:?}", &bytes[0..4]));
}
let version = u32::from_be_bytes(bytes[4..8].try_into().expect("4-byte slice"));
if !matches!(version, 2 | 3 | 4) {
return Err(format!("unsupported index version {version}"));
}
let count = u32::from_be_bytes(bytes[8..12].try_into().expect("4-byte slice")) as usize;
let mut out: Vec<PathBuf> = Vec::with_capacity(count);
let mut pos = 12usize;
let mut prev_path: Vec<u8> = Vec::new();
for entry_idx in 0..count {
let entry_start = pos;
if bytes.len() < pos + 62 {
return Err(format!("truncated entry {entry_idx} fixed header"));
}
let flags = u16::from_be_bytes(bytes[pos + 60..pos + 62].try_into().expect("2-byte slice"));
let entry_mode =
u32::from_be_bytes(bytes[pos + 24..pos + 28].try_into().expect("4-byte slice"));
let is_gitlink = (entry_mode & 0o170000) == 0o160000;
pos += 62;
let extended = (flags & 0x4000) != 0;
if extended {
if version < 3 {
return Err(format!("entry {entry_idx} has extended flag in v{version}"));
}
if bytes.len() < pos + 2 {
return Err(format!("truncated entry {entry_idx} extended flags"));
}
pos += 2;
}
let stage = ((flags >> 12) & 0x3) as u8;
let name_len_hint = (flags & 0x0FFF) as usize;
let path_bytes: Vec<u8>;
if version == 4 {
let (chop, consumed) = decode_index_varint(&bytes[pos..])
.map_err(|e| format!("entry {entry_idx} varint: {e}"))?;
pos += consumed;
let keep = prev_path.len().checked_sub(chop).ok_or_else(|| {
format!(
"entry {entry_idx} v4 underflow: prev={} chop={chop}",
prev_path.len()
)
})?;
let nul_offset = bytes[pos..]
.iter()
.position(|b| *b == 0)
.ok_or_else(|| format!("entry {entry_idx} missing NUL after v4 suffix"))?;
let mut p = Vec::with_capacity(keep + nul_offset);
p.extend_from_slice(&prev_path[..keep]);
p.extend_from_slice(&bytes[pos..pos + nul_offset]);
pos += nul_offset + 1;
path_bytes = p;
} else {
let name_end = if name_len_hint < 0x0FFF
&& bytes.len() >= pos + name_len_hint + 1
&& bytes[pos + name_len_hint] == 0
{
pos + name_len_hint
} else {
pos + bytes[pos..]
.iter()
.position(|b| *b == 0)
.ok_or_else(|| format!("entry {entry_idx} missing NUL terminator"))?
};
path_bytes = bytes[pos..name_end].to_vec();
pos = name_end;
let raw = pos - entry_start;
let pad = if raw % 8 == 0 { 8 } else { 8 - (raw % 8) };
pos += pad;
}
prev_path = path_bytes.clone();
if stage != 0 {
continue;
}
if is_gitlink {
continue;
}
let path_str = std::str::from_utf8(&path_bytes)
.map_err(|_| format!("entry {entry_idx} path is not UTF-8"))?;
out.push(PathBuf::from(path_str));
}
Ok(out)
}
fn decode_index_varint(buf: &[u8]) -> Result<(usize, usize), String> {
let mut consumed = 0usize;
if consumed >= buf.len() {
return Err("empty buffer".to_string());
}
let mut c = buf[consumed];
consumed += 1;
let mut value = (c & 0x7F) as usize;
while c & 0x80 != 0 {
if consumed >= buf.len() {
return Err("truncated varint".to_string());
}
value += 1;
value <<= 7;
c = buf[consumed];
consumed += 1;
value |= (c & 0x7F) as usize;
}
Ok((value, consumed))
}
fn scan_for_oversized_tracked_files(root: &Path, offenders: &mut Vec<(PathBuf, usize, String)>) {
for rel in collect_repo_files(root) {
let path = root.join(rel);
let line_count = match count_file_lines(&path) {
Ok(line_count) => line_count,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => continue,
Err(err) => {
panic!(
"failed to read repo file for line-count audit: {}: {err}",
rel.display()
)
}
};
if line_count > MAX_TRACKED_FILE_LINES {
offenders.push((
rel.clone(),
line_count,
format!("{line_count} lines; limit is {MAX_TRACKED_FILE_LINES}"),
));
}
}
}
fn count_file_lines(path: &Path) -> std::io::Result<usize> {
let file = fs::File::open(path)?;
let mut reader = std::io::BufReader::new(file);
let mut buf = [0_u8; 64 * 1024];
let mut line_count = 0usize;
loop {
let read = reader.read(&mut buf)?;
if read == 0 {
return Ok(line_count);
}
line_count += buf[..read].iter().filter(|byte| **byte == b'\n').count();
}
}
fn is_mechanical_part_path(rel: &Path) -> bool {
if let Some(stem) = rel.file_stem().and_then(|s| s.to_str()) {
let is_part_n = stem
.strip_prefix("part_")
.is_some_and(|rest| !rest.is_empty() && rest.bytes().all(|b| b.is_ascii_digit()));
if is_part_n {
return true;
}
}
for comp in rel.components() {
if let std::path::Component::Normal(os) = comp {
if let Some(name) = os.to_str() {
if name == "split_parts" || name.ends_with("_parts") {
return true;
}
}
}
}
false
}
fn scan_for_mechanical_part_files(root: &Path, offenders: &mut Vec<(PathBuf, usize, String)>) {
for rel in collect_repo_files(root) {
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
continue;
}
if !is_mechanical_part_path(rel) {
continue;
}
offenders.push((
rel.clone(),
0,
"mechanical line-count split; decompose by cohesive concern into descriptively-named \
modules — this is a HARD ban, no grandfathering"
.to_string(),
));
}
}
struct ScannedFile {
rel: PathBuf,
content: String,
}
static SCANNABLE_FILES: OnceLock<Vec<ScannedFile>> = OnceLock::new();
fn visit_files(root: &Path, dir: &Path, visitor: &mut dyn FnMut(&Path, &str)) {
let dir_rel = dir
.strip_prefix(root)
.expect("scanner directory must be under the manifest root");
for file in scannable_files(root) {
if !dir_rel.as_os_str().is_empty() && !file.rel.starts_with(dir_rel) {
continue;
}
visitor(&file.rel, &file.content);
}
}
fn scannable_files(root: &Path) -> &'static [ScannedFile] {
SCANNABLE_FILES
.get_or_init(|| {
let mut files = Vec::new();
collect_scannable_files(root, root, &mut files);
files
})
.as_slice()
}
fn collect_scannable_files(root: &Path, dir: &Path, files: &mut Vec<ScannedFile>) {
let read = match fs::read_dir(dir) {
Ok(r) => r,
Err(_) => return,
};
for entry in read.flatten() {
let path = entry.path();
let name = path.file_name().and_then(OsStr::to_str).unwrap_or("");
if path
.strip_prefix(root)
.ok()
.is_some_and(|rel| rel.starts_with("bench/runtime/pydeps"))
{
continue;
}
if (name.starts_with('.') && name != ".github")
|| name == "target"
|| name.starts_with("target-")
|| name == "node_modules"
|| name == "__pycache__"
|| name == "pydeps"
|| name == "site-packages"
|| name == "venv"
|| name == "dist"
|| name == "build"
|| name == "site"
{
continue;
}
if path.is_dir() {
collect_scannable_files(root, &path, files);
continue;
}
let ext = path.extension().and_then(OsStr::to_str).unwrap_or("");
let basename = path.file_name().and_then(OsStr::to_str).unwrap_or("");
let scannable = matches!(
ext,
"rs" | "py" | "toml" | "yml" | "yaml" | "sh" | "bash" | "json"
) || basename == "build.rs"
|| basename == "Makefile";
if !scannable {
continue;
}
println!("cargo:rerun-if-changed={}", path.display());
let content = match fs::read_to_string(&path) {
Ok(s) => s,
Err(_) => continue,
};
let rel = path
.strip_prefix(root)
.expect("scanned file must be under the manifest root")
.to_path_buf();
files.push(ScannedFile { rel, content });
}
}
fn scan_for_underscore_fn_args(
root: &Path,
dir: &Path,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
if !content.contains("fn ") {
return;
}
let lines: Vec<&str> = content.lines().collect();
let stripped_lines = strip_file_lines(content);
let n = lines.len();
let mut idx = 0usize;
while idx < n {
let stripped = stripped_lines
.get(idx)
.map(String::as_str)
.unwrap_or(lines[idx]);
if !line_has_keyword(stripped, "fn") {
idx += 1;
continue;
}
let Some(fn_pos) = locate_fn_keyword(stripped) else {
idx += 1;
continue;
};
let after_fn = &stripped[fn_pos + 2..];
let trimmed_after = after_fn.trim_start();
let first_byte = trimmed_after.as_bytes().first().copied();
let is_definition =
matches!(first_byte, Some(b) if b.is_ascii_alphabetic() || b == b'_');
if !is_definition {
idx += 1;
continue;
}
let (sig_start, sig_end_line, sig_end_col_excl) =
match find_fn_body_at_stripped(&stripped_lines, idx) {
Some((_, (open, _close))) => {
let open_line = &stripped_lines[open];
let col = open_line.find('{').unwrap_or(open_line.len());
(idx, open, col)
}
None => {
let mut paren: i32 = 0;
let mut brack: i32 = 0;
let mut found: Option<(usize, usize)> = None;
let limit = (idx + 64).min(n);
'outer: for (rel, sj) in stripped_lines[idx..limit].iter().enumerate() {
let j = idx + rel;
for (k, b) in sj.as_bytes().iter().enumerate() {
match *b {
b'(' => paren += 1,
b')' => paren -= 1,
b'[' => brack += 1,
b']' => brack -= 1,
b';' if paren == 0 && brack == 0 => {
found = Some((j, k));
break 'outer;
}
b'{' if paren == 0 && brack == 0 => {
break 'outer;
}
_ => {}
}
}
}
match found {
Some((j, k)) => (idx, j, k),
None => {
idx += 1;
continue;
}
}
}
};
let mut sig_text = String::new();
let mut line_offsets: Vec<(usize, usize)> = Vec::new();
for (rel, stripped_line) in stripped_lines[sig_start..=sig_end_line].iter().enumerate()
{
let j = sig_start + rel;
let part = if j == sig_end_line {
&stripped_line[..sig_end_col_excl]
} else {
stripped_line.as_str()
};
line_offsets.push((sig_text.len(), j));
sig_text.push_str(part);
sig_text.push('\n');
}
let sig_bytes = sig_text.as_bytes();
let paren_open = {
let mut ang: i32 = 0;
let mut found: Option<usize> = None;
for (k, &b) in sig_bytes.iter().enumerate() {
match b {
b'<' => ang += 1,
b'>' => {
if ang > 0 {
ang -= 1;
}
}
b'(' if ang == 0 => {
found = Some(k);
break;
}
_ => {}
}
}
match found {
Some(p) => p,
None => {
idx = sig_end_line + 1;
continue;
}
}
};
let Some(close_rel) = find_matching_paren(&sig_bytes[paren_open + 1..]) else {
idx = sig_end_line + 1;
continue;
};
let params_inner = &sig_text[paren_open + 1..paren_open + 1 + close_rel];
let inner_bytes = params_inner.as_bytes();
let mut angle: i32 = 0;
let mut paren_d: i32 = 0;
let mut brack_d: i32 = 0;
let mut start_byte: usize = 0;
let mut params: Vec<(usize, usize)> = Vec::new();
let mut k = 0usize;
while k < inner_bytes.len() {
let b = inner_bytes[k];
match b {
b'(' => paren_d += 1,
b')' => paren_d -= 1,
b'[' => brack_d += 1,
b']' => brack_d -= 1,
b'<' => angle += 1,
b'>' => {
if angle > 0 {
angle -= 1;
}
}
b',' if angle == 0 && paren_d == 0 && brack_d == 0 => {
params.push((start_byte, k));
start_byte = k + 1;
}
_ => {}
}
k += 1;
}
if start_byte <= inner_bytes.len() {
params.push((start_byte, inner_bytes.len()));
}
for (ps, pe) in params {
let raw_param = ¶ms_inner[ps..pe];
let mut p = raw_param.trim_start();
while p.starts_with("#[") {
if let Some(close) = p.find(']') {
p = p[close + 1..].trim_start();
} else {
break;
}
}
loop {
let before = p;
if p.starts_with("&mut ") {
p = p[5..].trim_start();
} else if p.starts_with('&') {
p = p[1..].trim_start();
} else if p.starts_with("mut ") {
p = p[4..].trim_start();
}
if p == before {
break;
}
}
let pb = p.as_bytes();
if pb.is_empty() {
continue;
}
if pb.iter().all(|c| c.is_ascii_whitespace()) {
continue;
}
let mut end = 0usize;
while end < pb.len() && (pb[end] == b'_' || pb[end].is_ascii_alphanumeric()) {
end += 1;
}
if end == 0 {
continue;
}
let name = &p[..end];
let rest = p[end..].trim_start();
if !rest.starts_with(':') {
continue;
}
if name == "_" {
continue;
}
if name.starts_with('_') {
let type_after_colon = rest[1..].trim_start();
if type_after_colon.starts_with("Python<") {
continue;
}
let name_off_in_param = raw_param.find(name).unwrap_or(0);
let abs = paren_open + 1 + ps + name_off_in_param;
let mut hit_line = sig_start;
for (off, ln) in &line_offsets {
if *off <= abs {
hit_line = *ln;
} else {
break;
}
}
let raw = lines.get(hit_line).copied().unwrap_or("");
offenders.push((rel.to_path_buf(), hit_line + 1, raw.to_string()));
}
}
idx = sig_end_line + 1;
}
});
}
fn locate_fn_keyword(stripped: &str) -> Option<usize> {
let bytes = stripped.as_bytes();
let mut i = 0usize;
while i + 2 <= bytes.len() {
if &bytes[i..i + 2] == b"fn" {
let before_ok = i == 0 || !is_ident_byte(bytes[i - 1]);
let after_ok = i + 2 == bytes.len() || !is_ident_byte(bytes[i + 2]);
if before_ok && after_ok {
return Some(i);
}
}
i += 1;
}
None
}
fn scan_for_useless_tests(root: &Path, dir: &Path, offenders: &mut Vec<(PathBuf, usize, String)>) {
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
if !content.contains("#[test]") {
return;
}
let lines: Vec<&str> = content.lines().collect();
let stripped_lines = strip_file_lines(content);
let n = lines.len();
let local_fns = index_local_fns(&lines, &stripped_lines);
let mut i = 0usize;
while i < n {
let s = stripped_lines
.get(i)
.map(String::as_str)
.unwrap_or(lines[i]);
if !s.contains("#[test]") {
i += 1;
continue;
}
let mut has_should_panic = s.contains("#[should_panic");
let mut back = i;
while back > 0 {
back -= 1;
let prev = stripped_lines
.get(back)
.map(String::as_str)
.unwrap_or(lines[back]);
let pt = prev.trim();
if pt.is_empty() || pt.starts_with("//") {
continue;
}
if pt.starts_with("#[") || pt.starts_with("#![") {
if prev.contains("#[should_panic") {
has_should_panic = true;
}
continue;
}
break;
}
let mut j = i + 1;
while j < n {
let sj = stripped_lines
.get(j)
.map(String::as_str)
.unwrap_or(lines[j]);
let t = sj.trim();
if t.is_empty() {
j += 1;
continue;
}
if t.starts_with("//") {
j += 1;
continue;
}
if t.starts_with("#[") || t.starts_with("#![") {
if sj.contains("#[should_panic") {
has_should_panic = true;
}
j += 1;
continue;
}
if line_has_keyword(sj, "fn") {
break;
}
j = n;
break;
}
if j >= n {
i += 1;
continue;
}
if has_should_panic {
i = j + 1;
continue;
}
let Some((_sig, (open, close))) = find_fn_body_at_stripped(&stripped_lines, j) else {
i = j + 1;
continue;
};
let found =
test_body_reaches_assertion(&lines, &stripped_lines, open, close, &local_fns);
if !found {
let raw = lines.get(i).copied().unwrap_or("");
if rel
.to_string_lossy()
.contains("pyffi_fitted_family_roundtrip_bug")
{
eprintln!(
"DEBUG useless_test: file={} open={} close={}",
rel.display(),
open,
close
);
for k in open..=close {
let raw_l = lines.get(k).copied().unwrap_or("");
let strp = stripped_lines.get(k).map(String::as_str).unwrap_or(raw_l);
eprintln!(" L{}: RAW=[{}]", k + 1, raw_l);
eprintln!(" STR=[{}]", strp);
}
}
offenders.push((rel.to_path_buf(), i + 1, raw.to_string()));
}
i = close + 1;
}
});
}
fn line_contains_assertion_helper_macro(stripped: &str) -> bool {
let bytes = stripped.as_bytes();
let n = bytes.len();
let mut i = 0usize;
while i < n {
if bytes[i] != b'!' {
i += 1;
continue;
}
let next = bytes.get(i + 1).copied();
if !matches!(next, Some(b'(') | Some(b'[') | Some(b'{')) {
i += 1;
continue;
}
let mut start = i;
while start > 0 {
let b = bytes[start - 1];
if b == b'_' || b.is_ascii_alphanumeric() {
start -= 1;
} else {
break;
}
}
if start == i {
i += 1;
continue;
}
let name = &stripped[start..i];
if name.starts_with("assert_")
|| name.starts_with("expect_")
|| name.starts_with("require_")
|| name.starts_with("ensure_")
{
return true;
}
i += 1;
}
false
}
fn line_contains_assertion_helper_call(stripped: &str) -> bool {
let bytes = stripped.as_bytes();
let n = bytes.len();
let mut i = 0usize;
while i < n {
if bytes[i] != b'(' {
i += 1;
continue;
}
if i > 0 && bytes[i - 1] == b'!' {
i += 1;
continue;
}
let mut start = i;
while start > 0 {
let b = bytes[start - 1];
if b == b'_' || b.is_ascii_alphanumeric() {
start -= 1;
} else {
break;
}
}
if start == i {
i += 1;
continue;
}
let name = &stripped[start..i];
if name.starts_with("assert_")
|| name.starts_with("expect_")
|| name.starts_with("require_")
|| name.starts_with("ensure_")
{
return true;
}
i += 1;
}
false
}
fn line_contains_propagating_question(stripped: &str) -> bool {
let bytes = stripped.as_bytes();
let n = bytes.len();
let mut i = 0usize;
while i < n {
if bytes[i] == b'?' {
let mut k = i + 1;
while k < n && bytes[k] == b' ' {
k += 1;
}
if k == n {
return true;
}
let c = bytes[k];
if matches!(c, b';' | b',' | b'.' | b')') {
return true;
}
}
i += 1;
}
false
}
const HISTORY_LEDGER_FILENAME: &str = "ban_history.txt";
const HISTORY_MARKERS: &[&str] = &["unimplemented!(", "todo!(", "unreachable!(", "panic!("];
const HISTORY_BODY_REJECT_MACROS: &[&str] = &[
"unimplemented!(",
"todo!(",
"unreachable!(",
"panic!(",
"assert!(false",
"process::exit(",
"process::abort(",
];
const HISTORY_MIN_SUBSTANTIVE_BODY_LINES: usize = 2;
fn collect_git_history_marker_functions(
manifest_dir: &Path,
) -> std::collections::BTreeMap<(String, String), Vec<String>> {
let mut out: std::collections::BTreeMap<(String, String), Vec<String>> =
std::collections::BTreeMap::new();
let git_contents = git_head_files_containing(manifest_dir, HISTORY_MARKERS);
for (rel_str, content) in git_contents {
if rel_str == "build.rs" || !rel_str.ends_with(".rs") {
continue;
}
let rel = Path::new(&rel_str);
let lines: Vec<&str> = content.lines().collect();
let stripped_lines = strip_file_lines(&content);
let mask = compute_test_mask(&content, rel);
for (idx, line) in lines.iter().enumerate() {
if mask.get(idx).copied().unwrap_or(false) {
continue;
}
let stripped = strip_strings_and_comments(line);
for &marker in HISTORY_MARKERS {
if !stripped.contains(marker) {
continue;
}
if let Some((sig, _)) = find_enclosing_fn(&lines, &stripped_lines, idx) {
let kind = marker.trim_end_matches('(').to_string();
let entry = out.entry((rel_str.clone(), sig)).or_default();
if !entry.contains(&kind) {
entry.push(kind);
}
break;
}
}
}
}
out
}
fn run_unimplemented_history_audit(
manifest_dir: &Path,
violations: &mut Vec<(PathBuf, usize, String, String)>,
) {
let ledger_path = manifest_dir.join(HISTORY_LEDGER_FILENAME);
println!("cargo:rerun-if-changed={}", ledger_path.display());
let mut current: std::collections::BTreeMap<(String, String), (PathBuf, usize, Vec<String>)> =
std::collections::BTreeMap::new();
let mut file_contents: std::collections::BTreeMap<String, String> =
std::collections::BTreeMap::new();
visit_files(manifest_dir, manifest_dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
file_contents.insert(rel_str.clone(), content.to_string());
let lines: Vec<&str> = content.lines().collect();
let stripped_lines = strip_file_lines(content);
let mask = compute_test_mask(content, rel);
for (idx, line) in lines.iter().enumerate() {
if mask.get(idx).copied().unwrap_or(false) {
continue;
}
let stripped = strip_strings_and_comments(line);
for &marker in HISTORY_MARKERS {
if !stripped.contains(marker) {
continue;
}
if let Some((sig, (open, _close))) = find_enclosing_fn(&lines, &stripped_lines, idx)
{
let kind = marker.trim_end_matches('(').to_string();
let entry = current
.entry((rel_str.clone(), sig.clone()))
.or_insert_with(|| (rel.to_path_buf(), open + 1, Vec::new()));
if !entry.2.contains(&kind) {
entry.2.push(kind);
}
break;
}
}
}
});
let mut previous = load_history_ledger(&ledger_path);
for (key, kinds) in collect_git_history_marker_functions(manifest_dir) {
previous.entry(key).or_insert(kinds);
}
let mut next_ledger: std::collections::BTreeMap<(String, String), Vec<String>> =
std::collections::BTreeMap::new();
for ((file, sig), (_, _, kinds)) in ¤t {
next_ledger.insert((file.clone(), sig.clone()), kinds.clone());
}
for ((file, sig), prev_kinds) in &previous {
if current.contains_key(&(file.clone(), sig.clone())) {
continue;
}
let state = match file_contents.get(file) {
None => HistoryBodyState::FnAbsent,
Some(c) => body_state_for_signature(c, sig),
};
match state {
HistoryBodyState::FnAbsent | HistoryBodyState::Substantive => {
}
HistoryBodyState::Trivial {
fn_open_line,
snippet,
} => {
violations.push((
PathBuf::from(file),
fn_open_line + 1,
sig.clone(),
format!(
"marker(s) [{}] removed but body still trivial / panic-shaped — first body line: {}",
prev_kinds.join(","),
snippet,
),
));
next_ledger.insert((file.clone(), sig.clone()), prev_kinds.clone());
}
}
}
save_history_ledger(&ledger_path, &next_ledger);
}
fn load_history_ledger(path: &Path) -> std::collections::BTreeMap<(String, String), Vec<String>> {
let mut out: std::collections::BTreeMap<(String, String), Vec<String>> =
std::collections::BTreeMap::new();
let content = match fs::read_to_string(path) {
Ok(c) => c,
Err(_) => return out,
};
for line in content.lines() {
let trimmed = line.trim_end();
if trimmed.is_empty() || trimmed.starts_with('#') {
continue;
}
let parts: Vec<&str> = trimmed.splitn(3, '\t').collect();
if parts.len() != 3 {
continue;
}
let file = parts[0].to_string();
let sig = parts[1].to_string();
let kinds: Vec<String> = parts[2]
.split(',')
.filter(|s| !s.is_empty())
.map(|s| s.to_string())
.collect();
out.insert((file, sig), kinds);
}
out
}
fn save_history_ledger(
path: &Path,
ledger: &std::collections::BTreeMap<(String, String), Vec<String>>,
) {
let mut out = String::new();
out.push_str(
"# Persistent audit of `unimplemented!(` / `todo!(` / `unreachable!(`\n\
# sites. Auto-managed by build.rs — do NOT hand-edit. Each non-comment\n\
# line is tab-separated:\n\
# <relative_path>\\t<normalized_fn_signature>\\t<comma_marker_kinds>\n\
# When an entry disappears from the source tree, build.rs inspects the\n\
# enclosing function's body. Trivial bodies (under a few code lines)\n\
# and bodies that still contain any panic-shape macro fail the build,\n\
# so deleting a `unimplemented!` without writing a real implementation\n\
# is caught. Legitimately-implemented removals auto-prune.\n\
#\n\
# Concurrent branches that both remove markers will produce additive\n\
# line-level diff conflicts that resolve by union — the next build\n\
# then re-validates each surviving entry.\n",
);
for ((file, sig), kinds) in ledger {
out.push_str(file);
out.push('\t');
out.push_str(sig);
out.push('\t');
out.push_str(&kinds.join(","));
out.push('\n');
}
match fs::read_to_string(path) {
Ok(existing) if existing == out => return,
_ => {}
}
if fs::write(path, out).is_err() {
}
}
enum HistoryBodyState {
FnAbsent,
Trivial {
fn_open_line: usize,
snippet: String,
},
Substantive,
}
fn body_state_for_signature(content: &str, target_sig: &str) -> HistoryBodyState {
let lines: Vec<&str> = content.lines().collect();
let stripped_lines = strip_file_lines(content);
let mut idx = 0;
while idx < lines.len() {
let stripped = stripped_lines
.get(idx)
.map(String::as_str)
.unwrap_or(lines[idx]);
if !line_has_keyword(&stripped, "fn") {
idx += 1;
continue;
}
if let Some((sig, (open, close))) = find_fn_body_at_stripped(&stripped_lines, idx) {
if sig == target_sig {
let mut code_lines = 0;
let mut first_snippet: Option<String> = None;
for raw in lines.iter().take(close + 1).skip(open) {
let s = strip_strings_and_comments(raw);
let t = s.trim();
if t.is_empty() {
continue;
}
if t.chars().all(|c| matches!(c, '{' | '}' | ' ')) {
continue;
}
for &m in HISTORY_BODY_REJECT_MACROS {
if s.contains(m) {
return HistoryBodyState::Trivial {
fn_open_line: open,
snippet: raw.trim().chars().take(120).collect::<String>(),
};
}
}
if first_snippet.is_none() {
first_snippet = Some(raw.trim().chars().take(120).collect::<String>());
}
code_lines += 1;
}
if code_lines < HISTORY_MIN_SUBSTANTIVE_BODY_LINES {
return HistoryBodyState::Trivial {
fn_open_line: open,
snippet: first_snippet.unwrap_or_else(|| "<empty body>".to_string()),
};
}
return HistoryBodyState::Substantive;
}
idx = close + 1;
continue;
}
idx += 1;
}
HistoryBodyState::FnAbsent
}
fn find_enclosing_fn(
lines: &[&str],
stripped_lines: &[String],
at_line: usize,
) -> Option<(String, (usize, usize))> {
let mut start = at_line + 1;
while start > 0 {
start -= 1;
let stripped = stripped_lines
.get(start)
.map(String::as_str)
.unwrap_or(lines[start]);
if !line_has_keyword(&stripped, "fn") {
continue;
}
if let Some((sig, (open, close))) = find_fn_body_at_stripped(stripped_lines, start)
&& open <= at_line
&& at_line <= close
{
return Some((sig, (open, close)));
}
}
None
}
fn find_fn_body_at_stripped(
stripped_lines: &[String],
fn_line: usize,
) -> Option<(String, (usize, usize))> {
let mut depth: i32 = 0;
let mut body_open: Option<usize> = None;
for (j, s) in stripped_lines.iter().enumerate().skip(fn_line) {
for b in s.bytes() {
match b {
b'{' => {
depth += 1;
if body_open.is_none() {
body_open = Some(j);
}
}
b'}' => {
depth -= 1;
if depth == 0
&& let Some(open) = body_open
{
let mut sig = String::new();
for (k, ss) in stripped_lines
.iter()
.enumerate()
.take(open + 1)
.skip(fn_line)
{
let cut = if k == open {
ss.find('{').unwrap_or(ss.len())
} else {
ss.len()
};
sig.push_str(&ss[..cut]);
sig.push(' ');
}
let normalized = sig.split_whitespace().collect::<Vec<_>>().join(" ");
return Some((normalized, (open, j)));
}
}
_ => {}
}
}
}
None
}
const MAX_DELEGATION_DEPTH: usize = 4;
fn line_is_assertion_shaped(line_s: &str) -> bool {
line_s.contains("assert!(")
|| line_s.contains("assert_eq!(")
|| line_s.contains("assert_ne!(")
|| line_s.contains("debug_assert!(")
|| line_s.contains("debug_assert_eq!(")
|| line_s.contains("debug_assert_ne!(")
|| line_s.contains("panic!(")
|| line_s.contains("unreachable!(")
|| line_s.contains("unimplemented!(")
|| line_s.contains("todo!(")
|| line_contains_propagating_question(line_s)
|| line_contains_assertion_helper_macro(line_s)
|| line_contains_assertion_helper_call(line_s)
}
fn fn_name_from_sig(sig: &str) -> Option<String> {
let mut toks = sig.split_whitespace();
while let Some(t) = toks.next() {
if t == "fn" {
let next = toks.next()?;
let name: String = next
.chars()
.take_while(|c| *c == '_' || c.is_ascii_alphanumeric())
.collect();
return if name.is_empty() { None } else { Some(name) };
}
}
None
}
fn index_local_fns(lines: &[&str], stripped_lines: &[String]) -> Vec<(String, usize, usize)> {
let mut out = Vec::new();
let n = lines.len();
let mut i = 0usize;
while i < n {
let s = stripped_lines
.get(i)
.map(String::as_str)
.unwrap_or(lines[i]);
if line_has_keyword(s, "fn")
&& let Some((sig, (open, close))) = find_fn_body_at_stripped(stripped_lines, i)
&& let Some(name) = fn_name_from_sig(&sig)
{
out.push((name, open, close));
}
i += 1;
}
out
}
fn collect_called_idents(stripped: &str, out: &mut Vec<String>) {
let bytes = stripped.as_bytes();
let n = bytes.len();
let mut i = 0usize;
while i < n {
if bytes[i] != b'(' {
i += 1;
continue;
}
if i > 0 && bytes[i - 1] == b'!' {
i += 1;
continue;
}
let mut start = i;
while start > 0 {
let b = bytes[start - 1];
if b == b'_' || b.is_ascii_alphanumeric() {
start -= 1;
} else {
break;
}
}
if start < i {
out.push(stripped[start..i].to_string());
}
i += 1;
}
}
fn cosmetic_dodge_line_is_owed_signal(line: &str) -> bool {
let Some(text) = line_comment_text(line) else {
return false;
};
comment_text_is_owed_work(&text)
}
fn cosmetic_dodge_commit_src_files(manifest_dir: &Path, sha: &str) -> Vec<String> {
let parents = match Command::new("git")
.arg("-C")
.arg(manifest_dir)
.arg("rev-list")
.arg("--parents")
.arg("-n1")
.arg(sha)
.output()
{
Ok(o) if o.status.success() => o,
_ => return Vec::new(),
};
let parents_text = String::from_utf8_lossy(&parents.stdout);
let token_count = parents_text.split_whitespace().count();
if token_count != 2 {
return Vec::new();
}
let output = match Command::new("git")
.arg("-C")
.arg(manifest_dir)
.arg("diff")
.arg("--name-only")
.arg(format!("{sha}^"))
.arg(sha)
.output()
{
Ok(o) if o.status.success() => o,
_ => return Vec::new(),
};
let text = String::from_utf8_lossy(&output.stdout);
let mut out = Vec::new();
for rel in text.lines() {
let rel = rel.trim();
if rel.is_empty() {
continue;
}
let rel_norm = rel.replace('\\', "/");
if !rel_norm.starts_with("src/") || !rel_norm.ends_with(".rs") {
continue;
}
let rel_path = Path::new(rel);
if rel_path_is_skipped_for_scans(rel_path) || !rel_path_is_scannable(rel_path) {
continue;
}
out.push(rel.to_string());
}
out
}
fn cosmetic_dodge_blob_at(manifest_dir: &Path, treeish: &str, rel: &str) -> Option<String> {
let output = Command::new("git")
.arg("-C")
.arg(manifest_dir)
.arg("show")
.arg(format!("{treeish}:{rel}"))
.output()
.ok()?;
if !output.status.success() {
return None;
}
String::from_utf8(output.stdout).ok()
}
fn run_cosmetic_wording_dodge_audit(
manifest_dir: &Path,
violations: &mut Vec<(PathBuf, usize, String, String)>,
) {
let log = match Command::new("git")
.arg("-C")
.arg(manifest_dir)
.arg("log")
.arg(format!("-n{TO_DO_HISTORY_GIT_DEPTH}"))
.arg("--no-merges")
.arg("--format=%H")
.output()
{
Ok(o) if o.status.success() => o,
_ => return,
};
let log_text = match String::from_utf8(log.stdout) {
Ok(t) => t,
Err(_) => return,
};
for sha in log_text.lines() {
let sha = sha.trim();
if sha.is_empty() {
continue;
}
for rel in cosmetic_dodge_commit_src_files(manifest_dir, sha) {
let diff = match Command::new("git")
.arg("-C")
.arg(manifest_dir)
.arg("diff")
.arg("-U0")
.arg(format!("{sha}^"))
.arg(sha)
.arg("--")
.arg(&rel)
.output()
{
Ok(o) if o.status.success() => o,
_ => continue,
};
let diff_text = String::from_utf8_lossy(&diff.stdout);
let mut removed_signal_lines: Vec<String> = Vec::new();
for line in diff_text.lines() {
if line.starts_with("---") || line.starts_with("+++") {
continue;
}
if let Some(body) = line.strip_prefix('-')
&& cosmetic_dodge_line_is_owed_signal(body)
{
removed_signal_lines.push(body.to_string());
}
}
if removed_signal_lines.is_empty() {
continue;
}
let Some(before) = cosmetic_dodge_blob_at(manifest_dir, &format!("{sha}^"), &rel) else {
continue;
};
let Some(after) = cosmetic_dodge_blob_at(manifest_dir, sha, &rel) else {
continue;
};
let Some(current) = std::fs::read_to_string(manifest_dir.join(&rel)).ok() else {
continue;
};
let signal_lines = |blob: &str| -> Vec<String> {
blob.lines()
.filter(|l| cosmetic_dodge_line_is_owed_signal(l))
.map(|l| l.trim().to_string())
.collect::<Vec<_>>()
};
let signal_absent_in = |blob: &str| -> bool {
let present = signal_lines(blob);
removed_signal_lines
.iter()
.any(|r| !present.iter().any(|a| a == r.trim()))
};
if !signal_absent_in(&after) || !signal_absent_in(¤t) {
continue;
}
let code_before = normalized_file_code_without_comments(&before);
if code_before != normalized_file_code_without_comments(&after)
|| code_before != normalized_file_code_without_comments(¤t)
{
continue;
}
let reason = format!(
"cosmetic wording dodge: an owed-work/deferral note was reworded or deleted but \
no code changed (file {rel}, commit {short}) — the work was NOT done, only the \
wording. Do the real work or restore the honest note; rewording to satisfy \
build.rs is banned.",
short = &sha[..sha.len().min(9)],
);
violations.push((
PathBuf::from(&rel),
0,
reason,
removed_signal_lines
.first()
.map(|l| l.trim().to_string())
.unwrap_or_default(),
));
}
}
}
fn git_head_files_containing(
manifest_dir: &Path,
needles: &[&str],
) -> std::collections::BTreeMap<String, String> {
if needles.is_empty() {
return std::collections::BTreeMap::new();
}
let mut cmd = Command::new("git");
cmd.arg("-C")
.arg(manifest_dir)
.arg("grep")
.arg("-z")
.arg("-l");
for needle in needles {
cmd.arg("-e").arg(needle);
}
cmd.arg("HEAD").arg("--");
let output = match cmd.output() {
Ok(output) => output,
Err(_) => return std::collections::BTreeMap::new(),
};
if !output.status.success() {
return std::collections::BTreeMap::new();
}
let mut rels = Vec::new();
for raw in output.stdout.split(|b| *b == 0) {
if raw.is_empty() {
continue;
}
let spec = match String::from_utf8(raw.to_vec()) {
Ok(spec) => spec,
Err(_) => continue,
};
let Some(rel) = spec.strip_prefix("HEAD:") else {
continue;
};
let rel_path = Path::new(rel);
if rel_path_is_skipped_for_scans(rel_path) || !rel_path_is_scannable(rel_path) {
continue;
}
rels.push(rel.to_string());
}
git_show_head_files(manifest_dir, &rels)
}
fn git_show_head_files(
manifest_dir: &Path,
rels: &[String],
) -> std::collections::BTreeMap<String, String> {
let mut out = std::collections::BTreeMap::new();
if rels.is_empty() {
return out;
}
let mut child = match Command::new("git")
.arg("-C")
.arg(manifest_dir)
.arg("cat-file")
.arg("--batch")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
{
Ok(child) => child,
Err(_) => return out,
};
{
let stdin = child
.stdin
.as_mut()
.expect("git cat-file stdin must be piped");
for rel in rels {
writeln!(stdin, "HEAD:{rel}").expect("failed to write git cat-file query");
}
}
let output = match child.wait_with_output() {
Ok(output) => output,
Err(_) => return out,
};
if !output.status.success() {
return out;
}
let bytes = output.stdout;
let mut pos = 0usize;
for rel in rels {
let Some(header_len) = bytes[pos..].iter().position(|b| *b == b'\n') else {
break;
};
let header_end = pos + header_len;
let header = match std::str::from_utf8(&bytes[pos..header_end]) {
Ok(header) => header,
Err(_) => break,
};
let Some(size_text) = header.split_whitespace().nth(2) else {
break;
};
let Ok(size) = size_text.parse::<usize>() else {
break;
};
let content_start = header_end + 1;
let content_end = content_start + size;
if content_end > bytes.len() {
break;
}
if let Ok(content) = String::from_utf8(bytes[content_start..content_end].to_vec()) {
out.insert(rel.clone(), content);
}
pos = content_end;
if pos < bytes.len() && bytes[pos] == b'\n' {
pos += 1;
}
}
out
}
fn rel_path_is_skipped_for_scans(rel: &Path) -> bool {
if rel.starts_with("bench/runtime/pydeps") {
return true;
}
for component in rel.components() {
let name = component.as_os_str().to_string_lossy();
if name.starts_with('.')
|| name == "target"
|| name.starts_with("target-")
|| name == "node_modules"
|| name == "__pycache__"
|| name == "pydeps"
|| name == "site-packages"
|| name == "venv"
|| name == "dist"
|| name == "build"
|| name == "site"
{
return true;
}
}
false
}
fn rel_path_is_scannable(rel: &Path) -> bool {
let ext = rel.extension().and_then(OsStr::to_str).unwrap_or("");
let basename = rel.file_name().and_then(OsStr::to_str).unwrap_or("");
matches!(
ext,
"rs" | "py" | "toml" | "yml" | "yaml" | "sh" | "bash" | "json"
) || basename == "build.rs"
|| basename == "Makefile"
}
const TO_DO_HISTORY_LEDGER_FILENAME: &str = "todo_history.txt";
const FN_ANCHOR_PREFIX: &str = "fn ";
const FILE_ANCHOR: &str = "file";
const MIN_REWORD_DESCRIPTION_LEN: usize = 24;
const TO_DO_HISTORY_GIT_DEPTH: usize = 120;
#[derive(Clone)]
struct ToDoHistorySite {
file: String,
anchor: String,
site: String,
line_no: usize,
}
fn run_todo_marker_history_audit(
manifest_dir: &Path,
needle: &str,
violations: &mut Vec<(PathBuf, usize, String, String)>,
) {
let ledger_path = manifest_dir.join(TO_DO_HISTORY_LEDGER_FILENAME);
println!("cargo:rerun-if-changed={}", ledger_path.display());
let current = collect_current_todo_history_sites(manifest_dir, needle);
let mut next_ledger: std::collections::BTreeMap<(String, String, String), ToDoHistorySite> =
std::collections::BTreeMap::new();
for site in current.values() {
next_ledger.insert(
(site.file.clone(), site.anchor.clone(), site.site.clone()),
site.clone(),
);
}
let git_contents = git_head_files_containing(manifest_dir, &[needle]);
let mut previous = load_todo_history_ledger(&ledger_path);
for (rel, content) in &git_contents {
let rel_path = Path::new(rel);
for site in collect_todo_history_sites_from_content(rel_path, content, needle).into_values()
{
previous
.entry((site.file.clone(), site.anchor.clone(), site.site.clone()))
.or_insert(site);
}
}
for (key, site) in collect_reworded_marker_sites_from_git_history(manifest_dir, needle) {
previous.entry(key).or_insert(site);
}
let mut current_contents: std::collections::BTreeMap<String, String> =
std::collections::BTreeMap::new();
visit_files(manifest_dir, manifest_dir, &mut |rel, content| {
current_contents.insert(
rel.to_string_lossy().replace('\\', "/"),
content.to_string(),
);
});
for (key, previous_site) in &previous {
if current.contains_key(key) {
continue;
}
let Some(current_content) = current_contents.get(&previous_site.file) else {
continue;
};
let git_content = git_contents.get(&previous_site.file).map(String::as_str);
if let Some((line_no, reason)) =
removed_todo_site_violation(current_content, git_content, previous_site, needle)
{
violations.push((
PathBuf::from(&previous_site.file),
line_no,
reason,
previous_site.site.clone(),
));
next_ledger.insert(key.clone(), previous_site.clone());
}
}
save_todo_history_ledger(&ledger_path, &next_ledger);
}
fn collect_current_todo_history_sites(
manifest_dir: &Path,
needle: &str,
) -> std::collections::BTreeMap<(String, String, String), ToDoHistorySite> {
let mut out = std::collections::BTreeMap::new();
visit_files(manifest_dir, manifest_dir, &mut |rel, content| {
for site in collect_todo_history_sites_from_content(rel, content, needle).into_values() {
out.insert(
(site.file.clone(), site.anchor.clone(), site.site.clone()),
site,
);
}
});
out
}
fn collect_todo_history_sites_from_content(
rel: &Path,
content: &str,
needle: &str,
) -> std::collections::BTreeMap<(String, String, String), ToDoHistorySite> {
let mut out = std::collections::BTreeMap::new();
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return out;
}
if !content.contains(needle) {
return out;
}
let is_rust = rel.extension().and_then(OsStr::to_str) == Some("rs");
let lines: Vec<&str> = content.lines().collect();
let stripped_lines = if is_rust {
strip_file_lines(content)
} else {
Vec::new()
};
for (idx, line) in lines.iter().enumerate() {
if !line.contains(needle) {
continue;
}
let anchor = if is_rust {
find_enclosing_fn(&lines, &stripped_lines, idx)
.map(|(sig, _)| format!("{FN_ANCHOR_PREFIX}{sig}"))
.unwrap_or_else(|| FILE_ANCHOR.to_string())
} else {
FILE_ANCHOR.to_string()
};
let site = normalize_history_site_line(line);
let entry = ToDoHistorySite {
file: rel_str.clone(),
anchor,
site,
line_no: idx + 1,
};
out.insert(
(entry.file.clone(), entry.anchor.clone(), entry.site.clone()),
entry,
);
}
out
}
fn normalize_history_site_line(line: &str) -> String {
line.split_whitespace()
.collect::<Vec<_>>()
.join(" ")
.replace('\t', " ")
.chars()
.take(240)
.collect()
}
fn normalize_marker_text(text: &str) -> String {
let mut out = String::with_capacity(text.len());
let mut prev_space = true;
for ch in text.chars() {
if ch.is_ascii_alphanumeric() {
for low in ch.to_lowercase() {
out.push(low);
}
prev_space = false;
} else if !prev_space {
out.push(' ');
prev_space = true;
}
}
while out.ends_with(' ') {
out.pop();
}
out
}
fn marker_description(site_line: &str, needle: &str) -> Option<String> {
let pos = site_line.find(needle)?;
let after = site_line[pos + needle.len()..].trim_start();
let after = match after.strip_prefix('(') {
Some(rest) => match rest.find(')') {
Some(close) => &rest[close + 1..],
None => rest,
},
None => after,
};
let desc = normalize_marker_text(after);
if desc.is_empty() { None } else { Some(desc) }
}
fn line_is_comment_lead(line: &str) -> bool {
let t = line.trim_start();
t.starts_with("//") || (t.starts_with('#') && !t.starts_with("#["))
}
const MIN_REWORD_SIGNIFICANT_TOKENS: usize = 5;
const REWORD_CONTAINMENT_THRESHOLD: f64 = 0.75;
struct CommentBlock {
start_line: usize,
tokens: std::collections::HashSet<String>,
lower_text: String,
}
fn reword_is_stopword(t: &str) -> bool {
const STOP: &[&str] = &[
"the", "and", "for", "this", "that", "with", "from", "into", "over", "each", "can",
"will", "its", "are", "was", "were", "has", "have", "had", "not", "but", "use", "uses",
"used", "via", "per", "out", "off", "all", "any", "one", "two", "new", "old", "should",
"would", "could", "may", "might", "must", "then", "than", "they", "them", "when", "where",
"which", "while", "here", "there", "only", "also", "still", "yet", "now", "later", "our",
"your", "their", "been", "being", "such", "some", "more", "most", "less", "few",
];
STOP.contains(&t)
}
fn reword_significant_tokens(text: &str) -> Vec<String> {
normalize_marker_text(text)
.split(' ')
.filter(|t| t.len() >= 3 && !reword_is_stopword(t))
.map(|t| t.to_string())
.collect()
}
fn token_set_containment(
needle_tokens: &[String],
haystack: &std::collections::HashSet<String>,
) -> f64 {
if needle_tokens.is_empty() {
return 0.0;
}
let hit = needle_tokens
.iter()
.filter(|t| haystack.contains(*t))
.count();
hit as f64 / needle_tokens.len() as f64
}
fn comment_block_has_deferral_cue(lower_text: &str) -> bool {
use std::sync::OnceLock;
static CUES: OnceLock<Vec<String>> = OnceLock::new();
let cues = CUES.get_or_init(|| {
vec![
format!("{}{}", "to", "do"),
format!("{}{}", "fix", "me"),
format!("{}-{}", "follow", "up"),
format!("{}{}", "follow", "up"),
format!("{}{}", "de", "fer"),
format!("{}{}", "stop", "gap"),
format!("{}{}", "place", "holder"),
format!("{}{}", "w", "ip"),
format!("{}{}", "t", "bd"),
"revisit".to_string(),
"punt".to_string(),
"eventually".to_string(),
"someday".to_string(),
"pending".to_string(),
"unimplemented".to_string(),
"incomplete".to_string(),
"stub".to_string(),
"not yet".to_string(),
"for now".to_string(),
"to be done".to_string(),
"to be implemented".to_string(),
"come back".to_string(),
"needs to".to_string(),
"remains to".to_string(),
"yet to".to_string(),
format!("not wired {}", "into"),
format!("not wired {}", "through"),
format!("not yet {}", "wired"),
format!("deferred to a {}", "follow"),
format!("left to a {}", "follow"),
]
});
cues.iter().any(|c| lower_text.contains(c.as_str()))
}
fn comment_blocks_without_marker(content: &str, needle: &str) -> Vec<CommentBlock> {
let lines: Vec<&str> = content.lines().collect();
let mut out = Vec::new();
let mut i = 0usize;
while i < lines.len() {
if !line_is_comment_lead(lines[i]) {
i += 1;
continue;
}
let start = i;
let mut joined = String::new();
loop {
while i < lines.len() && line_is_comment_lead(lines[i]) {
joined.push(' ');
joined.push_str(lines[i]);
i += 1;
}
let mut j = i;
while j < lines.len() && lines[j].trim().is_empty() {
j += 1;
}
if j > i && j < lines.len() && line_is_comment_lead(lines[j]) {
i = j;
} else {
break;
}
}
if joined.contains(needle) {
continue;
}
out.push(CommentBlock {
start_line: start + 1,
tokens: reword_significant_tokens(&joined).into_iter().collect(),
lower_text: joined.to_lowercase(),
});
}
out
}
fn reworded_marker_remnant_survives(
current_content: &str,
previous_site: &ToDoHistorySite,
needle: &str,
) -> Option<usize> {
let description = marker_description(&previous_site.site, needle)?;
if description.len() >= MIN_REWORD_DESCRIPTION_LEN {
for (idx, line) in current_content.lines().enumerate() {
if line.contains(needle) || !line_is_comment_lead(line) {
continue;
}
if normalize_marker_text(line).contains(&description) {
return Some(idx + 1);
}
}
}
let needle_tokens = reword_significant_tokens(&description);
if needle_tokens.len() >= MIN_REWORD_SIGNIFICANT_TOKENS {
for block in comment_blocks_without_marker(current_content, needle) {
if token_set_containment(&needle_tokens, &block.tokens) >= REWORD_CONTAINMENT_THRESHOLD
&& comment_block_has_deferral_cue(&block.lower_text)
{
return Some(block.start_line);
}
}
}
None
}
fn collect_reworded_marker_sites_from_git_history(
manifest_dir: &Path,
needle: &str,
) -> std::collections::BTreeMap<(String, String, String), ToDoHistorySite> {
let mut out = std::collections::BTreeMap::new();
let output = match Command::new("git")
.arg("-C")
.arg(manifest_dir)
.arg("log")
.arg(format!("-n{TO_DO_HISTORY_GIT_DEPTH}"))
.arg(format!("-G{needle}"))
.arg("-p")
.arg("--no-color")
.arg("-U0")
.arg("--format=%n")
.arg("--")
.arg(".")
.output()
{
Ok(o) if o.status.success() => o,
_ => return out,
};
let text = match String::from_utf8(output.stdout) {
Ok(t) => t,
Err(_) => return out,
};
fn flush(
current_file: &Option<String>,
removed: &mut Vec<String>,
added: &mut Vec<String>,
needle: &str,
out: &mut std::collections::BTreeMap<(String, String, String), ToDoHistorySite>,
) {
if let Some(rel) = current_file {
let rel_path = Path::new(rel);
let scannable = rel != "build.rs"
&& !rel_path_is_skipped_for_scans(rel_path)
&& rel_path_is_scannable(rel_path);
if scannable {
for removed_line in removed.iter() {
if !removed_line.contains(needle) {
continue;
}
let Some(desc) = marker_description(removed_line, needle) else {
continue;
};
let exact_relabel = desc.len() >= MIN_REWORD_DESCRIPTION_LEN
&& added.iter().any(|added_line| {
!added_line.contains(needle)
&& normalize_marker_text(added_line).contains(&desc)
});
let pooled: String = added
.iter()
.filter(|a| !a.contains(needle))
.map(|a| a.as_str())
.collect::<Vec<_>>()
.join(" ");
let needle_tokens = reword_significant_tokens(&desc);
let bag: std::collections::HashSet<String> =
reword_significant_tokens(&pooled).into_iter().collect();
let fuzzy_relabel = needle_tokens.len() >= MIN_REWORD_SIGNIFICANT_TOKENS
&& token_set_containment(&needle_tokens, &bag)
>= REWORD_CONTAINMENT_THRESHOLD
&& comment_block_has_deferral_cue(&pooled.to_lowercase());
if exact_relabel || fuzzy_relabel {
let site = ToDoHistorySite {
file: rel.clone(),
anchor: FILE_ANCHOR.to_string(),
site: normalize_history_site_line(removed_line),
line_no: 0,
};
out.insert(
(site.file.clone(), site.anchor.clone(), site.site.clone()),
site,
);
}
}
}
}
removed.clear();
added.clear();
}
let mut current_file: Option<String> = None;
let mut removed: Vec<String> = Vec::new();
let mut added: Vec<String> = Vec::new();
for line in text.lines() {
if line.starts_with("diff --git ") {
flush(¤t_file, &mut removed, &mut added, needle, &mut out);
current_file = None;
continue;
}
if let Some(rest) = line.strip_prefix("+++ b/") {
flush(¤t_file, &mut removed, &mut added, needle, &mut out);
let rel = rest.trim();
current_file = if rel == "/dev/null" {
None
} else {
Some(rel.to_string())
};
continue;
}
if line.starts_with("@@") {
flush(¤t_file, &mut removed, &mut added, needle, &mut out);
continue;
}
if line.starts_with("---") || line.starts_with("+++") {
continue;
}
if let Some(body) = line.strip_prefix('-') {
removed.push(body.to_string());
} else if let Some(body) = line.strip_prefix('+') {
added.push(body.to_string());
}
}
flush(¤t_file, &mut removed, &mut added, needle, &mut out);
out
}
fn removed_todo_site_violation(
current_content: &str,
git_content: Option<&str>,
previous_site: &ToDoHistorySite,
needle: &str,
) -> Option<(usize, String)> {
if let Some(line_no) = reworded_marker_remnant_survives(current_content, previous_site, needle)
{
return Some((
line_no,
"marker removed but its description survives reworded under a different \
label (rename-evasion) — implement the work or delete the whole note; \
relabelling the marker does not resolve it"
.to_string(),
));
}
if let Some(sig) = previous_site.anchor.strip_prefix(FN_ANCHOR_PREFIX) {
if let Some(git_content) = git_content {
if normalized_fn_body_code_without_comments(current_content, sig)
== normalized_fn_body_code_without_comments(git_content, sig)
{
return Some((
line_for_history_anchor(current_content, &previous_site.anchor),
"marker removed but the enclosing function's code is unchanged from git HEAD"
.to_string(),
));
}
}
return match body_state_for_signature(current_content, sig) {
HistoryBodyState::FnAbsent | HistoryBodyState::Substantive => None,
HistoryBodyState::Trivial {
fn_open_line,
snippet,
} => Some((
fn_open_line + 1,
format!("marker removed but enclosing function is still trivial: {snippet}"),
)),
};
}
if let Some(git_content) = git_content
&& normalized_file_code_without_comments(current_content)
== normalized_file_code_without_comments(git_content)
{
return Some((
previous_site.line_no,
"marker removed but file code is unchanged from git HEAD".to_string(),
));
}
None
}
fn line_for_history_anchor(content: &str, anchor: &str) -> usize {
let Some(sig) = anchor.strip_prefix(FN_ANCHOR_PREFIX) else {
return 1;
};
let lines: Vec<&str> = content.lines().collect();
let stripped_lines = strip_file_lines(content);
let mut idx = 0usize;
while idx < lines.len() {
let stripped = stripped_lines
.get(idx)
.map(String::as_str)
.unwrap_or(lines[idx]);
if line_has_keyword(&stripped, "fn")
&& let Some((found_sig, (open, _close))) =
find_fn_body_at_stripped(&stripped_lines, idx)
&& found_sig == sig
{
return open + 1;
}
idx += 1;
}
1
}
fn normalized_fn_body_code_without_comments(content: &str, target_sig: &str) -> Option<String> {
let lines: Vec<&str> = content.lines().collect();
let stripped_lines = strip_file_lines(content);
let mut idx = 0usize;
while idx < lines.len() {
let stripped = stripped_lines
.get(idx)
.map(String::as_str)
.unwrap_or(lines[idx]);
if line_has_keyword(stripped, "fn")
&& let Some((sig, (open, close))) = find_fn_body_at_stripped(&stripped_lines, idx)
{
if sig == target_sig {
let mut body = String::new();
for line in stripped_lines.iter().take(close + 1).skip(open) {
body.push_str(line);
body.push('\n');
}
return Some(normalize_code_text(&body));
}
idx = close + 1;
continue;
}
idx += 1;
}
None
}
fn normalized_file_code_without_comments(content: &str) -> String {
normalize_code_text(&strip_file_lines(content).join("\n"))
}
fn normalize_code_text(content: &str) -> String {
content.split_whitespace().collect::<Vec<_>>().join(" ")
}
fn load_todo_history_ledger(
path: &Path,
) -> std::collections::BTreeMap<(String, String, String), ToDoHistorySite> {
let mut out = std::collections::BTreeMap::new();
let content = match fs::read_to_string(path) {
Ok(c) => c,
Err(_) => return out,
};
for line in content.lines() {
let trimmed = line.trim_end();
if trimmed.is_empty() || trimmed.starts_with('#') {
continue;
}
let parts: Vec<&str> = trimmed.splitn(4, '\t').collect();
if parts.len() != 4 {
continue;
}
let line_no = parts[3].parse::<usize>().unwrap_or(1);
let site = ToDoHistorySite {
file: parts[0].to_string(),
anchor: parts[1].to_string(),
site: parts[2].to_string(),
line_no,
};
out.insert(
(site.file.clone(), site.anchor.clone(), site.site.clone()),
site,
);
}
out
}
fn save_todo_history_ledger(
path: &Path,
ledger: &std::collections::BTreeMap<(String, String, String), ToDoHistorySite>,
) {
let mut out = String::new();
out.push_str(
"# Persistent audit of TO-DO comment/marker sites.\n\
# Auto-managed by build.rs — do NOT hand-edit. Each non-comment\n\
# line is tab-separated:\n\
# <relative_path>\\t<anchor>\\t<normalized_marker_line>\\t<line_no>\n\
# When an entry disappears from the source tree, build.rs inspects\n\
# the enclosing function or file and also compares against git HEAD.\n\
# Deleting the marker while leaving code unchanged keeps failing.\n",
);
for site in ledger.values() {
out.push_str(&site.file);
out.push('\t');
out.push_str(&site.anchor);
out.push('\t');
out.push_str(&site.site.replace('\t', " "));
out.push('\t');
out.push_str(&site.line_no.to_string());
out.push('\n');
}
match fs::read_to_string(path) {
Ok(existing) if existing == out => return,
_ => {}
}
let _ = fs::write(path, out);
}
fn test_body_reaches_assertion(
lines: &[&str],
stripped_lines: &[String],
open: usize,
close: usize,
local_fns: &[(String, usize, usize)],
) -> bool {
let mut visited: Vec<usize> = vec![open];
body_reaches_assertion(
lines,
stripped_lines,
open,
close,
local_fns,
&mut visited,
MAX_DELEGATION_DEPTH,
)
}
fn body_reaches_assertion(
lines: &[&str],
stripped_lines: &[String],
open: usize,
close: usize,
local_fns: &[(String, usize, usize)],
visited: &mut Vec<usize>,
depth: usize,
) -> bool {
for k in open..=close {
let line_s = stripped_lines
.get(k)
.map(String::as_str)
.unwrap_or_else(|| lines.get(k).copied().unwrap_or(""));
if line_is_assertion_shaped(line_s) {
return true;
}
}
if depth == 0 {
return false;
}
let mut callees: Vec<String> = Vec::new();
for k in open..=close {
let line_s = stripped_lines
.get(k)
.map(String::as_str)
.unwrap_or_else(|| lines.get(k).copied().unwrap_or(""));
collect_called_idents(line_s, &mut callees);
}
for callee in &callees {
for (name, h_open, h_close) in local_fns {
if name != callee || visited.contains(h_open) {
continue;
}
visited.push(*h_open);
let reached = body_reaches_assertion(
lines,
stripped_lines,
*h_open,
*h_close,
local_fns,
visited,
depth - 1,
);
if reached {
return true;
}
}
}
false
}
fn dodge_name_substrings() -> &'static [&'static str] {
&[
"discard_",
"_discard_",
"swallow_",
"_swallow_",
"_for_fixed_lambda",
"_for_fixed_arg",
"_for_unused",
"_for_no_op",
"_no_op_",
"silence_",
"ignore_unused",
"eat_unused",
"consume_unused",
"intentionally_unused",
"placeholder_for_",
"dummy_for_",
]
}
fn scan_for_dodge_named_fns(
root: &Path,
dir: &Path,
offenders: &mut Vec<(PathBuf, usize, String, String)>,
) {
let needles = dodge_name_substrings();
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
if !content.contains("fn ") {
return;
}
let stripped_lines = strip_file_lines(content);
for (idx, line) in content.lines().enumerate() {
let stripped = stripped_lines.get(idx).map(String::as_str).unwrap_or(line);
if !line_has_keyword(stripped, "fn") {
continue;
}
let Some(fn_pos) = locate_fn_keyword(stripped) else {
continue;
};
let bytes = stripped.as_bytes();
let mut j = fn_pos + 2;
while j < bytes.len() && bytes[j].is_ascii_whitespace() {
j += 1;
}
if j >= bytes.len() {
continue;
}
if !(bytes[j].is_ascii_alphabetic() || bytes[j] == b'_') {
continue;
}
let name_start = j;
while j < bytes.len() && is_ident_byte(bytes[j]) {
j += 1;
}
if j == name_start {
continue;
}
let name = &stripped[name_start..j];
let lower = name.to_ascii_lowercase();
for needle in needles {
if lower.contains(needle) {
offenders.push((
rel.to_path_buf(),
idx + 1,
name.to_string(),
line.to_string(),
));
break;
}
}
}
});
}
fn scan_for_noop_self_consuming_fns(
root: &Path,
dir: &Path,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
if !content.contains("fn ") {
return;
}
let lines: Vec<&str> = content.lines().collect();
let stripped_lines = strip_file_lines(content);
let n = lines.len();
let mut i = 0usize;
while i < n {
let s = stripped_lines
.get(i)
.map(String::as_str)
.unwrap_or(lines[i]);
if !line_has_keyword(s, "fn") {
i += 1;
continue;
}
let Some((sig, (open, close))) = find_fn_body_at_stripped(&stripped_lines, i) else {
i += 1;
continue;
};
if !first_param_is_by_value_self(&sig) {
i = open + 1;
continue;
}
if fn_body_is_empty(&stripped_lines, open, close) {
offenders.push((rel.to_path_buf(), i + 1, lines[i].to_string()));
}
i = close + 1;
}
});
}
fn first_param_is_by_value_self(sig: &str) -> bool {
let bytes = sig.as_bytes();
let mut i = 0usize;
let mut fn_pos: Option<usize> = None;
while i + 2 <= bytes.len() {
if &bytes[i..i + 2] == b"fn"
&& (i == 0 || !is_ident_byte(bytes[i - 1]))
&& (i + 2 == bytes.len() || !is_ident_byte(bytes[i + 2]))
{
fn_pos = Some(i);
break;
}
i += 1;
}
let Some(fp) = fn_pos else {
return false;
};
let mut j = fp + 2;
while j < bytes.len() && bytes[j].is_ascii_whitespace() {
j += 1;
}
if j >= bytes.len() || !(bytes[j].is_ascii_alphabetic() || bytes[j] == b'_') {
return false;
}
while j < bytes.len() && is_ident_byte(bytes[j]) {
j += 1;
}
while j < bytes.len() && bytes[j].is_ascii_whitespace() {
j += 1;
}
if j < bytes.len() && bytes[j] == b'<' {
let mut depth: i32 = 0;
while j < bytes.len() {
match bytes[j] {
b'<' => depth += 1,
b'>' => {
depth -= 1;
if depth == 0 {
j += 1;
break;
}
}
_ => {}
}
j += 1;
}
}
while j < bytes.len() && bytes[j].is_ascii_whitespace() {
j += 1;
}
if j >= bytes.len() || bytes[j] != b'(' {
return false;
}
let params_start = j + 1;
let Some(end) = find_matching_paren(&bytes[params_start..]) else {
return false;
};
let params = &sig[params_start..params_start + end];
let first = first_top_level_segment(params);
let first_trim = first.trim();
if first_trim.is_empty() {
return false;
}
if first_trim.starts_with('&') {
return false;
}
let after_mut = first_trim
.strip_prefix("mut ")
.map(str::trim_start)
.unwrap_or(first_trim);
if after_mut == "self" {
return true;
}
if let Some(rest) = after_mut.strip_prefix("self") {
if let Some(&b) = rest.as_bytes().first()
&& is_ident_byte(b)
{
return false;
}
let r = rest.trim_start();
if let Some(tail) = r.strip_prefix(':') {
let ty = tail.trim_start();
if ty.starts_with('&') {
return false;
}
return !ty.is_empty();
}
}
false
}
fn first_top_level_segment(params: &str) -> &str {
let bytes = params.as_bytes();
let mut angle: i32 = 0;
let mut paren: i32 = 0;
let mut bracket: i32 = 0;
let mut i = 0usize;
while i < bytes.len() {
match bytes[i] {
b'<' => angle += 1,
b'>' => {
if angle > 0 {
angle -= 1;
}
}
b'(' => paren += 1,
b')' => {
if paren > 0 {
paren -= 1;
}
}
b'[' => bracket += 1,
b']' => {
if bracket > 0 {
bracket -= 1;
}
}
b',' if angle == 0 && paren == 0 && bracket == 0 => {
return ¶ms[..i];
}
_ => {}
}
i += 1;
}
params
}
fn fn_body_is_empty(stripped_lines: &[String], open: usize, close: usize) -> bool {
if open > close || open >= stripped_lines.len() || close >= stripped_lines.len() {
return false;
}
let open_line = stripped_lines[open].as_str();
let Some(open_brace) = open_line.find('{') else {
return false;
};
if open == close {
let tail = &open_line[open_brace + 1..];
let Some(close_brace) = tail.rfind('}') else {
return false;
};
return tail[..close_brace].chars().all(char::is_whitespace);
}
let open_tail = &open_line[open_brace + 1..];
if !open_tail.chars().all(char::is_whitespace) {
return false;
}
for line in &stripped_lines[open + 1..close] {
if !line.chars().all(char::is_whitespace) {
return false;
}
}
let close_line = stripped_lines[close].as_str();
let Some(close_brace) = close_line.rfind('}') else {
return false;
};
close_line[..close_brace].chars().all(char::is_whitespace)
}
fn scan_for_stub_function_bodies(
root: &Path,
dir: &Path,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
if !content.contains("fn ") {
return;
}
let mask = compute_test_mask(content, rel);
let trait_def_mask = compute_trait_def_mask(content);
let lines: Vec<&str> = content.lines().collect();
let stripped_lines = strip_file_lines(content);
let n = lines.len();
let mut i = 0usize;
while i < n {
let s = stripped_lines
.get(i)
.map(String::as_str)
.unwrap_or(lines[i]);
if !line_has_keyword(s, "fn") {
i += 1;
continue;
}
if mask.get(i).copied().unwrap_or(false) {
i += 1;
continue;
}
if trait_def_mask.get(i).copied().unwrap_or(false) {
i += 1;
continue;
}
if fn_signature_ends_with_semicolon(&stripped_lines, i) {
i += 1;
continue;
}
let Some((sig, (open, close))) = find_fn_body_at_stripped(&stripped_lines, i) else {
i += 1;
continue;
};
let Some(param_count) = signature_param_count(&sig) else {
i = close + 1;
continue;
};
if param_count < 2 {
i = close + 1;
continue;
}
let body = extract_body_text(&stripped_lines, open, close);
if body_is_trivial_sentinel(&body) {
offenders.push((rel.to_path_buf(), i + 1, lines[i].to_string()));
}
i = close + 1;
}
});
}
fn scan_for_noop_sentinel_control_flow(
root: &Path,
dir: &Path,
offenders: &mut Vec<(PathBuf, usize, String)>,
) {
visit_files(root, dir, &mut |rel, content| {
let rel_str = rel.to_string_lossy().replace('\\', "/");
if rel_str == "build.rs" {
return;
}
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
if !content.contains("fn ") {
return;
}
let mask = compute_test_mask(content, rel);
let lines: Vec<&str> = content.lines().collect();
let stripped_lines = strip_file_lines(content);
let n = lines.len();
let mut i = 0usize;
while i < n {
let s = stripped_lines
.get(i)
.map(String::as_str)
.unwrap_or(lines[i]);
if !line_has_keyword(s, "fn") {
i += 1;
continue;
}
if mask.get(i).copied().unwrap_or(false) {
i += 1;
continue;
}
if fn_signature_ends_with_semicolon(&stripped_lines, i) {
i += 1;
continue;
}
let Some((sig, (open, close))) = find_fn_body_at_stripped(&stripped_lines, i) else {
i += 1;
continue;
};
let Some(param_count) = signature_param_count(&sig) else {
i = close + 1;
continue;
};
if param_count < 2 {
i = close + 1;
continue;
}
let body = extract_body_text(&stripped_lines, open, close);
if body_has_noop_sentinel_control_flow(&body) {
offenders.push((rel.to_path_buf(), i + 1, lines[i].to_string()));
}
i = close + 1;
}
});
}
fn fn_signature_ends_with_semicolon(stripped_lines: &[String], fn_line: usize) -> bool {
let mut paren: i32 = 0;
let mut brack: i32 = 0;
let mut angle: i32 = 0;
let limit = (fn_line + 64).min(stripped_lines.len());
for line in &stripped_lines[fn_line..limit] {
for &b in line.as_bytes() {
match b {
b'(' => paren += 1,
b')' => paren -= 1,
b'[' => brack += 1,
b']' => brack -= 1,
b'<' => angle += 1,
b'>' => {
if angle > 0 {
angle -= 1;
}
}
b';' if paren == 0 && brack == 0 => return true,
b'{' if paren == 0 && brack == 0 => return false,
_ => {}
}
}
}
false
}
fn signature_param_count(sig: &str) -> Option<usize> {
let bytes = sig.as_bytes();
let mut i = 0usize;
let mut fn_pos: Option<usize> = None;
while i + 2 <= bytes.len() {
if &bytes[i..i + 2] == b"fn"
&& (i == 0 || !is_ident_byte(bytes[i - 1]))
&& (i + 2 == bytes.len() || !is_ident_byte(bytes[i + 2]))
{
fn_pos = Some(i);
break;
}
i += 1;
}
let fp = fn_pos?;
let mut j = fp + 2;
while j < bytes.len() && bytes[j].is_ascii_whitespace() {
j += 1;
}
if j >= bytes.len() || !(bytes[j].is_ascii_alphabetic() || bytes[j] == b'_') {
return None;
}
while j < bytes.len() && is_ident_byte(bytes[j]) {
j += 1;
}
let mut k = j;
while k < bytes.len() && bytes[k].is_ascii_whitespace() {
k += 1;
}
if k < bytes.len() && bytes[k] == b'<' {
let mut ang: i32 = 0;
while k < bytes.len() {
match bytes[k] {
b'<' => ang += 1,
b'>' => {
ang -= 1;
if ang == 0 {
k += 1;
break;
}
}
_ => {}
}
k += 1;
}
}
let mut ang2: i32 = 0;
let mut open: Option<usize> = None;
while k < bytes.len() {
match bytes[k] {
b'<' => ang2 += 1,
b'>' => {
if ang2 > 0 {
ang2 -= 1;
}
}
b'(' if ang2 == 0 => {
open = Some(k);
break;
}
_ => {}
}
k += 1;
}
let op = open?;
let inner_start = op + 1;
let end_rel = find_matching_paren(&bytes[inner_start..])?;
let inner = &sig[inner_start..inner_start + end_rel];
if inner.trim().is_empty() {
return Some(0);
}
let mut count = 0usize;
let mut a: i32 = 0;
let mut p: i32 = 0;
let mut br: i32 = 0;
let mut seen_nonws = false;
for &c in inner.as_bytes() {
match c {
b'<' => {
a += 1;
seen_nonws = true;
}
b'>' => {
if a > 0 {
a -= 1;
}
seen_nonws = true;
}
b'(' => {
p += 1;
seen_nonws = true;
}
b')' => {
p -= 1;
seen_nonws = true;
}
b'[' => {
br += 1;
seen_nonws = true;
}
b']' => {
br -= 1;
seen_nonws = true;
}
b',' if a == 0 && p == 0 && br == 0 => {
if seen_nonws {
count += 1;
}
seen_nonws = false;
}
x if !(x as char).is_whitespace() => seen_nonws = true,
_ => {}
}
}
if seen_nonws {
count += 1;
}
Some(count)
}
fn extract_body_text(stripped_lines: &[String], open: usize, close: usize) -> String {
if open > close || close >= stripped_lines.len() {
return String::new();
}
let mut parts: Vec<String> = Vec::new();
for k in open..=close {
let line = stripped_lines[k].as_str();
let segment: &str = if k == open && k == close {
let after_open = line.find('{').map(|p| p + 1).unwrap_or(line.len());
let before_close = line[after_open..]
.rfind('}')
.map(|p| after_open + p)
.unwrap_or(line.len());
&line[after_open..before_close]
} else if k == open {
let after_open = line.find('{').map(|p| p + 1).unwrap_or(line.len());
&line[after_open..]
} else if k == close {
let before_close = line.rfind('}').unwrap_or(line.len());
&line[..before_close]
} else {
line
};
let t = segment.trim();
if !t.is_empty() {
parts.push(t.to_string());
}
}
parts.join(" ").trim().to_string()
}
fn body_is_trivial_sentinel(body: &str) -> bool {
let after_prologue = strip_validation_prologue(body);
let mut s = after_prologue.trim();
if let Some(stripped) = s.strip_suffix(';') {
s = stripped.trim_end();
}
if s.is_empty() {
return false;
}
if matches!(
s,
"None"
| "Ok(())"
| "Default::default()"
| "Vec::new()"
| "vec![]"
| "()"
| "HashMap::new()"
| "BTreeMap::new()"
| "HashSet::new()"
| "BTreeSet::new()"
| "VecDeque::new()"
| "String::new()"
| "Some(Default::default())"
| "true"
| "false"
| "\"\""
) {
return true;
}
if let Some(prefix) = s.strip_suffix("::default()")
&& is_path_like(prefix)
{
return true;
}
if let Some(inner) = s.strip_prefix("Some(").and_then(|r| r.strip_suffix(')'))
&& let Some(prefix) = inner.strip_suffix("::default()")
&& is_path_like(prefix)
{
return true;
}
if let Some(inner) = s.strip_prefix("Err(").and_then(|r| r.strip_suffix(')'))
&& err_arg_is_string_literal(inner.trim())
{
return true;
}
if matches!(
s,
"Array1::zeros(0)" | "Array2::zeros((0, 0))" | "Array3::zeros((0, 0, 0))"
) {
return true;
}
if is_bare_numeric_literal(s) {
return true;
}
false
}
fn body_has_noop_sentinel_control_flow(body: &str) -> bool {
let s = body.trim();
if s.is_empty() {
return false;
}
if leading_if_return_preserves_sentinel(s) {
return true;
}
if whole_if_else_preserves_sentinel(s) {
return true;
}
if whole_match_preserves_sentinel(s) {
return true;
}
if leading_discard_or_read_then_sentinel(s) {
return true;
}
if whole_predicate_then_trivial_sentinel(s) {
return true;
}
if contains_predicate_then_trivial_sentinel_return(s) {
return true;
}
false
}
fn leading_if_return_preserves_sentinel(s: &str) -> bool {
let Some((returned, rest)) = strip_leading_if_return_guard_with_expr(s) else {
return false;
};
let Some(returned_key) = trivial_sentinel_key(returned) else {
return false;
};
let Some(tail_key) = trivial_sentinel_key(rest) else {
return false;
};
returned_key == tail_key
}
fn whole_if_else_preserves_sentinel(s: &str) -> bool {
let Some((then_body, else_body, rest)) = parse_leading_if_else_blocks(s) else {
return false;
};
if !rest.trim().is_empty() {
return false;
}
let Some(then_key) = trivial_sentinel_key(then_body) else {
return false;
};
let Some(else_key) = trivial_sentinel_key(else_body) else {
return false;
};
then_key == else_key
}
fn whole_match_preserves_sentinel(s: &str) -> bool {
let Some((inside, rest)) = parse_leading_match_block(s) else {
return false;
};
if !rest.trim().is_empty() {
return false;
}
let Some(arms) = split_match_arms(inside) else {
return false;
};
let mut key: Option<String> = None;
let mut arm_count = 0usize;
for arm in arms {
let Some((_, expr)) = arm.split_once("=>") else {
return false;
};
let Some(expr_key) = trivial_sentinel_key(expr.trim().trim_end_matches(',')) else {
return false;
};
if let Some(existing) = &key {
if existing != &expr_key {
return false;
}
} else {
key = Some(expr_key);
}
arm_count += 1;
}
arm_count >= 2 && key.is_some()
}
fn leading_discard_or_read_then_sentinel(s: &str) -> bool {
let rest = strip_leading_drop_call(s)
.or_else(|| strip_leading_wildcard_assignment(s))
.or_else(|| strip_leading_read_only_statement(s));
rest.is_some_and(|tail| trivial_sentinel_key(tail).is_some())
}
fn whole_predicate_then_trivial_sentinel(s: &str) -> bool {
let mut expr = s.trim();
if let Some(stripped) = expr.strip_suffix(';') {
expr = stripped.trim_end();
}
predicate_then_trivial_sentinel_expr(expr)
}
fn predicate_then_trivial_sentinel_expr(expr: &str) -> bool {
let expr = expr.trim();
for method in [".then(", ".then_some("] {
let Some((predicate, arg)) = split_whole_method_call_arg(expr, method) else {
continue;
};
if predicate_is_read_only_empty_check(predicate) && then_arg_is_trivial_sentinel(arg) {
return true;
}
}
false
}
fn contains_predicate_then_trivial_sentinel_return(s: &str) -> bool {
let mut search_from = 0usize;
while let Some(rel) = s[search_from..].find("return") {
let pos = search_from + rel;
let before = if pos == 0 {
None
} else {
s.as_bytes().get(pos - 1).copied()
};
let after = s.as_bytes().get(pos + "return".len()).copied();
if before.map_or(true, |b| !is_ident_byte(b))
&& after.is_some_and(|b| b.is_ascii_whitespace())
{
let expr_start = pos + "return".len();
if let Some((expr, _)) = split_leading_statement(&s[expr_start..])
&& predicate_then_trivial_sentinel_expr(expr)
{
return true;
}
}
search_from = pos + "return".len();
}
false
}
fn split_whole_method_call_arg<'a>(expr: &'a str, method: &str) -> Option<(&'a str, &'a str)> {
let call_start = expr.find(method)?;
let arg_start = call_start + method.len();
let close_rel = find_matching_paren(&expr.as_bytes()[arg_start..])?;
if !expr[arg_start + close_rel + 1..].trim().is_empty() {
return None;
}
Some((
expr[..call_start].trim(),
expr[arg_start..arg_start + close_rel].trim(),
))
}
fn predicate_is_read_only_empty_check(predicate: &str) -> bool {
let p = trim_balanced_outer_parens(predicate.trim());
if p.is_empty() || p.contains('!') {
return false;
}
p.ends_with(".is_empty()") || predicate_is_zero_comparison(p)
}
fn trim_balanced_outer_parens(mut s: &str) -> &str {
loop {
let trimmed = s.trim();
if !trimmed.starts_with('(') || !trimmed.ends_with(')') {
return trimmed;
}
let inner = &trimmed[1..trimmed.len() - 1];
if find_matching_paren(inner.as_bytes()).is_some() {
return trimmed;
}
s = inner;
}
}
fn predicate_is_zero_comparison(predicate: &str) -> bool {
let Some((left, right)) = predicate.split_once("==") else {
return false;
};
let left = left.trim();
let right = right.trim();
(right == "0" && read_only_zero_compare_operand(left))
|| (left == "0" && read_only_zero_compare_operand(right))
}
fn read_only_zero_compare_operand(operand: &str) -> bool {
let op = operand.trim();
!op.is_empty()
&& !op.contains('=')
&& !op.contains('!')
&& op
.bytes()
.all(|b| is_ident_byte(b) || b == b'.' || b == b'(' || b == b')')
}
fn then_arg_is_trivial_sentinel(arg: &str) -> bool {
let a = arg.trim();
if a.is_empty() {
return false;
}
if trivial_sentinel_key(a).is_some() || expression_is_empty_array_constructor(a) {
return true;
}
if let Some(body) = a.strip_prefix("||") {
let body = body.trim();
return trivial_sentinel_key(body).is_some() || expression_is_empty_array_constructor(body);
}
matches!(
a,
"Vec::new"
| "String::new"
| "HashMap::new"
| "BTreeMap::new"
| "HashSet::new"
| "BTreeSet::new"
| "VecDeque::new"
| "Default::default"
)
}
fn expression_is_empty_array_constructor(expr: &str) -> bool {
let compact: String = expr.chars().filter(|c| !c.is_whitespace()).collect();
compact.contains("::zeros(0)")
|| compact.contains("::zeros((0,")
|| compact.contains("::from_shape_vec((0,")
|| compact.contains("::from_shape_fn((0,")
}
fn trivial_sentinel_key(expr: &str) -> Option<String> {
let mut s = expr.trim();
if let Some(rest) = s.strip_prefix("return ") {
s = rest.trim();
}
if let Some(stripped) = s.strip_suffix(';') {
s = stripped.trim_end();
}
if return_expr_is_trivial_sentinel(s) {
return Some(collapse_ascii_whitespace(s));
}
None
}
fn collapse_ascii_whitespace(s: &str) -> String {
let mut out = String::new();
let mut last_was_space = false;
for ch in s.chars() {
if ch.is_whitespace() {
if !last_was_space {
out.push(' ');
last_was_space = true;
}
} else {
out.push(ch);
last_was_space = false;
}
}
out.trim().to_string()
}
fn parse_leading_if_else_blocks(s: &str) -> Option<(&str, &str, &str)> {
let after_if = s.strip_prefix("if ")?;
let open_in_after_if = find_top_level_open_brace(after_if)?;
let then_start = open_in_after_if + 1;
let then_close_rel = find_matching_brace(&after_if.as_bytes()[then_start..])?;
let then_body = &after_if[then_start..then_start + then_close_rel];
let after_then = after_if[then_start + then_close_rel + 1..].trim_start();
let after_else = after_then.strip_prefix("else")?.trim_start();
if !after_else.starts_with('{') {
return None;
}
let else_body_start = 1usize;
let else_close_rel = find_matching_brace(&after_else.as_bytes()[else_body_start..])?;
let else_body = &after_else[else_body_start..else_body_start + else_close_rel];
let rest = &after_else[else_body_start + else_close_rel + 1..];
Some((then_body, else_body, rest))
}
fn parse_leading_match_block(s: &str) -> Option<(&str, &str)> {
let after_match = s.strip_prefix("match ")?;
let open = find_top_level_open_brace(after_match)?;
let body_start = open + 1;
let close_rel = find_matching_brace(&after_match.as_bytes()[body_start..])?;
let body = &after_match[body_start..body_start + close_rel];
let rest = &after_match[body_start + close_rel + 1..];
Some((body, rest))
}
fn find_top_level_open_brace(s: &str) -> Option<usize> {
let bytes = s.as_bytes();
let mut paren: i32 = 0;
let mut brack: i32 = 0;
let mut angle: i32 = 0;
let mut i = 0usize;
while i < bytes.len() {
match bytes[i] {
b'(' => paren += 1,
b')' => paren -= 1,
b'[' => brack += 1,
b']' => brack -= 1,
b'<' => angle += 1,
b'>' => {
if angle > 0 {
angle -= 1;
}
}
b'{' if paren == 0 && brack == 0 && angle == 0 => return Some(i),
_ => {}
}
i += 1;
}
None
}
fn find_matching_brace(bytes: &[u8]) -> Option<usize> {
let mut depth: i32 = 1;
let mut i = 0usize;
while i < bytes.len() {
match bytes[i] {
b'{' => depth += 1,
b'}' => {
depth -= 1;
if depth == 0 {
return Some(i);
}
}
_ => {}
}
i += 1;
}
None
}
fn split_match_arms(inside: &str) -> Option<Vec<&str>> {
let mut arms = Vec::new();
let bytes = inside.as_bytes();
let mut start = 0usize;
let mut paren: i32 = 0;
let mut brack: i32 = 0;
let mut brace: i32 = 0;
let mut angle: i32 = 0;
let mut i = 0usize;
while i < bytes.len() {
match bytes[i] {
b'(' => paren += 1,
b')' => paren -= 1,
b'[' => brack += 1,
b']' => brack -= 1,
b'{' => brace += 1,
b'}' => brace -= 1,
b'<' => angle += 1,
b'>' => {
if angle > 0 {
angle -= 1;
}
}
b',' if paren == 0 && brack == 0 && brace == 0 && angle == 0 => {
let arm = inside[start..i].trim();
if !arm.is_empty() {
arms.push(arm);
}
start = i + 1;
}
_ => {}
}
i += 1;
}
let tail = inside[start..].trim();
if !tail.is_empty() {
arms.push(tail);
}
if arms.is_empty() { None } else { Some(arms) }
}
fn strip_leading_read_only_statement(s: &str) -> Option<&str> {
let (statement, rest) = split_leading_statement(s)?;
if expression_statement_is_read_only_noop(statement.trim()) {
Some(rest)
} else {
None
}
}
fn split_leading_statement(s: &str) -> Option<(&str, &str)> {
let bytes = s.as_bytes();
let mut paren: i32 = 0;
let mut brack: i32 = 0;
let mut brace: i32 = 0;
let mut angle: i32 = 0;
let mut i = 0usize;
while i < bytes.len() {
match bytes[i] {
b'(' => paren += 1,
b')' => paren -= 1,
b'[' => brack += 1,
b']' => brack -= 1,
b'{' => brace += 1,
b'}' => brace -= 1,
b'<' => angle += 1,
b'>' => {
if angle > 0 {
angle -= 1;
}
}
b';' if paren == 0 && brack == 0 && brace == 0 && angle == 0 => {
return Some((&s[..i], &s[i + 1..]));
}
_ => {}
}
i += 1;
}
None
}
fn expression_statement_is_read_only_noop(statement: &str) -> bool {
let s = statement.trim();
if s.is_empty() || s.contains('=') || s.contains('!') {
return false;
}
let known_read_calls = [
".len()",
".is_empty()",
".capacity()",
".nrows()",
".ncols()",
".shape()",
".dim()",
".raw_dim()",
"std::mem::size_of_val(",
"core::mem::size_of_val(",
];
known_read_calls.iter().any(|needle| s.contains(needle))
}
fn strip_validation_prologue(body: &str) -> &str {
let mut s = body.trim_start();
loop {
if let Some(rest) = strip_leading_assert_call(s) {
s = rest.trim_start();
continue;
}
if let Some(rest) = strip_leading_if_return_guard(s) {
s = rest.trim_start();
continue;
}
if let Some(rest) = strip_leading_drop_call(s) {
s = rest.trim_start();
continue;
}
if let Some(rest) = strip_leading_wildcard_assignment(s) {
s = rest.trim_start();
continue;
}
break;
}
s
}
fn strip_leading_assert_call(s: &str) -> Option<&str> {
for name in ["assert", "assert_eq", "assert_ne", "assert_matches"] {
let Some(after_name) = s.strip_prefix(name) else {
continue;
};
let after_bang = after_name.strip_prefix('!')?;
let after_open_ws = after_bang.trim_start();
let (open, close) = match after_open_ws.as_bytes().first()? {
b'(' => (b'(', b')'),
b'[' => (b'[', b']'),
b'{' => (b'{', b'}'),
_ => return None,
};
let after_open = &after_open_ws[1..];
let bytes = after_open.as_bytes();
let mut depth: i32 = 1;
let mut i = 0usize;
while i < bytes.len() {
let b = bytes[i];
if b == open {
depth += 1;
} else if b == close {
depth -= 1;
if depth == 0 {
let after = after_open[i + 1..].trim_start();
return after.strip_prefix(';');
}
}
i += 1;
}
return None;
}
None
}
fn strip_leading_if_return_guard(s: &str) -> Option<&str> {
strip_leading_if_return_guard_with_expr(s).map(|(_, rest)| rest)
}
fn strip_leading_if_return_guard_with_expr(s: &str) -> Option<(&str, &str)> {
let after_if = s.strip_prefix("if ")?;
let bytes = after_if.as_bytes();
let mut paren: i32 = 0;
let mut brack: i32 = 0;
let mut i = 0usize;
let open_brace = loop {
if i >= bytes.len() {
return None;
}
match bytes[i] {
b'(' => paren += 1,
b')' => paren -= 1,
b'[' => brack += 1,
b']' => brack -= 1,
b'{' if paren == 0 && brack == 0 => break i,
_ => {}
}
i += 1;
};
let rest_after_brace = &after_if[open_brace + 1..];
let bytes = rest_after_brace.as_bytes();
let mut depth: i32 = 1;
let mut i = 0usize;
while i < bytes.len() {
match bytes[i] {
b'{' => depth += 1,
b'}' => {
depth -= 1;
if depth == 0 {
let inside = rest_after_brace[..i].trim();
if inside.starts_with("return ")
&& inside.ends_with(';')
&& count_top_level_semicolons(inside) == 1
{
let ret_expr = inside["return ".len()..inside.len() - 1].trim();
if return_expr_is_trivial_sentinel(ret_expr) {
return Some((ret_expr, &rest_after_brace[i + 1..]));
}
}
return None;
}
}
_ => {}
}
i += 1;
}
None
}
fn count_top_level_semicolons(s: &str) -> usize {
let bytes = s.as_bytes();
let mut paren: i32 = 0;
let mut brack: i32 = 0;
let mut brace: i32 = 0;
let mut angle: i32 = 0;
let mut count = 0usize;
let mut i = 0usize;
while i < bytes.len() {
match bytes[i] {
b'(' => paren += 1,
b')' => paren -= 1,
b'[' => brack += 1,
b']' => brack -= 1,
b'{' => brace += 1,
b'}' => brace -= 1,
b'<' => angle += 1,
b'>' => {
if angle > 0 {
angle -= 1;
}
}
b';' if paren == 0 && brack == 0 && brace == 0 && angle == 0 => {
count += 1;
}
_ => {}
}
i += 1;
}
count
}
fn return_expr_is_trivial_sentinel(expr: &str) -> bool {
let s = expr.trim();
if matches!(
s,
"None"
| "Ok(())"
| "Default::default()"
| "Vec::new()"
| "vec![]"
| "()"
| "HashMap::new()"
| "BTreeMap::new()"
| "HashSet::new()"
| "BTreeSet::new()"
| "VecDeque::new()"
| "String::new()"
| "Some(Default::default())"
| "true"
| "false"
| "\"\""
| "Array1::zeros(0)"
| "Array2::zeros((0, 0))"
| "Array3::zeros((0, 0, 0))"
) {
return true;
}
if let Some(prefix) = s.strip_suffix("::default()")
&& is_path_like(prefix)
{
return true;
}
if let Some(inner) = s.strip_prefix("Some(").and_then(|r| r.strip_suffix(')'))
&& let Some(prefix) = inner.strip_suffix("::default()")
&& is_path_like(prefix)
{
return true;
}
if let Some(inner) = s.strip_prefix("Ok(").and_then(|r| r.strip_suffix(')'))
&& matches!(
inner.trim(),
"()" | "Array1::zeros(0)" | "Array2::zeros((0, 0))" | "Array3::zeros((0, 0, 0))"
)
{
return true;
}
is_bare_numeric_literal(s)
}
fn strip_leading_drop_call(s: &str) -> Option<&str> {
let after_open = s.strip_prefix("drop(")?;
let bytes = after_open.as_bytes();
let mut depth: i32 = 1;
let mut i = 0usize;
while i < bytes.len() {
match bytes[i] {
b'(' => depth += 1,
b')' => {
depth -= 1;
if depth == 0 {
let after = after_open[i + 1..].trim_start();
return after.strip_prefix(';');
}
}
_ => {}
}
i += 1;
}
None
}
fn strip_leading_wildcard_assignment(s: &str) -> Option<&str> {
let after_underscore = s.strip_prefix('_')?;
if after_underscore
.as_bytes()
.first()
.is_some_and(|b| is_ident_byte(*b))
{
return None;
}
let rest = after_underscore.trim_start().strip_prefix('=')?;
if rest.as_bytes().first() == Some(&b'=') {
return None;
}
let rest = rest.trim_start();
let bytes = rest.as_bytes();
let mut paren: i32 = 0;
let mut brack: i32 = 0;
let mut brace: i32 = 0;
let mut i = 0usize;
while i < bytes.len() {
match bytes[i] {
b'(' => paren += 1,
b')' => paren -= 1,
b'[' => brack += 1,
b']' => brack -= 1,
b'{' => brace += 1,
b'}' => brace -= 1,
b';' if paren == 0 && brack == 0 && brace == 0 => {
return Some(&rest[i + 1..]);
}
_ => {}
}
i += 1;
}
None
}
fn is_path_like(s: &str) -> bool {
let s = s.trim();
if s.is_empty() {
return false;
}
s.bytes()
.all(|b| is_ident_byte(b) || b == b':' || b == b'<' || b == b'>' || b == b',' || b == b' ')
}
fn err_arg_is_string_literal(arg: &str) -> bool {
let bytes = arg.as_bytes();
if bytes.is_empty() || bytes[0] != b'"' {
return false;
}
let mut i = 1usize;
while i < bytes.len() {
if bytes[i] == b'\\' && i + 1 < bytes.len() {
i += 2;
continue;
}
if bytes[i] == b'"' {
i += 1;
let tail = arg[i..].trim();
return tail.is_empty()
|| tail == ".into()"
|| tail == ".to_string()"
|| tail == ".to_owned()";
}
i += 1;
}
false
}
fn is_bare_numeric_literal(s: &str) -> bool {
let bytes = s.as_bytes();
if bytes.is_empty() {
return false;
}
let mut i = 0usize;
let mut saw_digit = false;
while i < bytes.len() && (bytes[i].is_ascii_digit() || bytes[i] == b'_') {
if bytes[i].is_ascii_digit() {
saw_digit = true;
}
i += 1;
}
if !saw_digit {
return false;
}
if i < bytes.len() && bytes[i] == b'.' {
i += 1;
while i < bytes.len() && (bytes[i].is_ascii_digit() || bytes[i] == b'_') {
i += 1;
}
}
while i < bytes.len() && is_ident_byte(bytes[i]) {
i += 1;
}
i == bytes.len()
}
fn scan_for_src_items_used_only_by_tests(
root: &Path,
offenders: &mut Vec<(PathBuf, usize, String, String)>,
unreferenced_pub_scoped: &mut Vec<(PathBuf, usize, String, String)>,
) {
const EXEMPT_NAMES: &[&str] = &[
"new",
"default",
"iter",
"len",
"is_empty",
"clone",
"from",
"into",
"as_ref",
"as_mut",
"next",
"build",
"with",
"to_string",
"display",
"fmt",
"index",
"borrow",
"drop",
"main",
"deref",
"deref_mut",
"hash",
"eq",
"ne",
"cmp",
"partial_cmp",
"iter_mut",
"into_iter",
"as_slice",
"as_str",
];
struct SrcFile {
rel: PathBuf,
content: String,
mask: Vec<bool>,
stripped: Vec<String>,
trait_impl: Vec<bool>,
}
let mut src_files: Vec<SrcFile> = Vec::new();
let mut test_contents: Vec<(PathBuf, String)> = Vec::new();
visit_files(root, root, &mut |rel, content| {
if rel.extension().and_then(OsStr::to_str) != Some("rs") {
return;
}
let rel_str = rel.to_string_lossy().replace('\\', "/");
let is_test = rel_str.starts_with("tests/")
|| rel_str.starts_with("bench/")
|| rel_str.starts_with("benches/")
|| path_matches_crates_test(&rel_str);
if is_test {
test_contents.push((rel.to_path_buf(), content.to_string()));
return;
}
let is_src = rel_str.starts_with("src/")
|| (rel_str.starts_with("crates/") && rel_str.contains("/src/"));
if !is_src {
return;
}
let mask = compute_test_mask(content, rel);
let stripped = strip_file_lines(content);
let trait_impl = compute_trait_impl_mask(content);
src_files.push(SrcFile {
rel: rel.to_path_buf(),
content: content.to_string(),
mask,
stripped,
trait_impl,
});
});
let mut defs: Vec<(usize, usize, String, Visibility)> = Vec::new();
for (fi, sf) in src_files.iter().enumerate() {
for (idx, stripped) in sf.stripped.iter().enumerate() {
if sf.mask.get(idx).copied().unwrap_or(false) {
continue;
}
let trimmed = stripped.trim_start();
let (vis, rest) = strip_leading_visibility(trimmed);
if matches!(vis, Visibility::Public) {
continue;
}
let rest = strip_leading_item_modifiers(rest);
let Some(ident) = extract_item_ident(rest) else {
continue;
};
if ident.starts_with('_') || ident.len() <= 2 {
continue;
}
if EXEMPT_NAMES.contains(&ident.as_str()) {
continue;
}
if sf.trait_impl.get(idx).copied().unwrap_or(false) {
continue;
}
defs.push((fi, idx, ident, vis));
}
}
if defs.is_empty() {
return;
}
let mut per_file_tokens: Vec<std::collections::HashSet<String>> =
Vec::with_capacity(src_files.len());
for sf in &src_files {
let mut set: std::collections::HashSet<String> = std::collections::HashSet::new();
for (idx, stripped) in sf.stripped.iter().enumerate() {
if sf.mask.get(idx).copied().unwrap_or(false) {
continue;
}
extract_ident_tokens_into(stripped, &mut set);
}
per_file_tokens.push(set);
}
let mut defining_file_token_lines: Vec<Vec<std::collections::HashSet<String>>> =
Vec::with_capacity(src_files.len());
for sf in &src_files {
let mut v: Vec<std::collections::HashSet<String>> = Vec::with_capacity(sf.stripped.len());
for (idx, stripped) in sf.stripped.iter().enumerate() {
let mut set: std::collections::HashSet<String> = std::collections::HashSet::new();
if !sf.mask.get(idx).copied().unwrap_or(false) {
extract_ident_tokens_into(stripped, &mut set);
}
v.push(set);
}
defining_file_token_lines.push(v);
}
let mut test_first_hit: std::collections::HashMap<String, PathBuf> =
std::collections::HashMap::new();
for (rel, content) in &test_contents {
let mut local: std::collections::HashSet<String> = std::collections::HashSet::new();
for line in content.lines() {
let stripped = strip_strings_and_comments(line);
extract_ident_tokens_into(&stripped, &mut local);
}
for tok in local {
test_first_hit.entry(tok).or_insert_with(|| rel.clone());
}
}
let mut pub_use_idents: std::collections::HashSet<String> = std::collections::HashSet::new();
for sf in &src_files {
let rel_str = sf.rel.to_string_lossy().replace('\\', "/");
let is_lib_root = rel_str == "src/lib.rs"
|| rel_str.ends_with("/src/lib.rs")
|| rel_str == "src/main.rs"
|| rel_str.ends_with("/src/main.rs");
if !is_lib_root {
continue;
}
for stripped in &sf.stripped {
collect_pub_use_idents(stripped, &mut pub_use_idents);
}
}
for (fi, line_idx, ident, vis) in defs {
if pub_use_idents.contains(&ident) {
continue;
}
let test_hint = test_first_hit.get(&ident).cloned();
let mut prod_consumer = false;
for (other_fi, set) in per_file_tokens.iter().enumerate() {
if other_fi == fi {
continue;
}
if set.contains(&ident) {
prod_consumer = true;
break;
}
}
if !prod_consumer {
let token_lines = &defining_file_token_lines[fi];
for (li, toks) in token_lines.iter().enumerate() {
if li == line_idx {
continue;
}
if toks.contains(&ident) {
prod_consumer = true;
break;
}
}
}
if prod_consumer {
continue;
}
let sf = &src_files[fi];
let raw = sf.content.lines().nth(line_idx).unwrap_or("").to_string();
match (test_hint, vis) {
(Some(hint_path), _) => {
let hint = format!(
"{} (test ref: {})",
ident,
hint_path.to_string_lossy().replace('\\', "/")
);
offenders.push((sf.rel.clone(), line_idx + 1, hint, raw));
}
(None, Visibility::PubScoped) => {
unreferenced_pub_scoped.push((sf.rel.clone(), line_idx + 1, ident.clone(), raw));
}
(None, _) => {
}
}
}
}
#[derive(Clone, Copy)]
enum Visibility {
Private,
Public,
PubScoped,
}
fn strip_leading_visibility(trimmed: &str) -> (Visibility, &str) {
if let Some(rest) = trimmed.strip_prefix("pub(") {
let bytes = rest.as_bytes();
let mut depth = 1i32;
let mut i = 0usize;
while i < bytes.len() {
match bytes[i] {
b'(' => depth += 1,
b')' => {
depth -= 1;
if depth == 0 {
let after = rest[i + 1..].trim_start();
return (Visibility::PubScoped, after);
}
}
_ => {}
}
i += 1;
}
return (Visibility::PubScoped, "");
}
if let Some(rest) = trimmed.strip_prefix("pub ") {
return (Visibility::Public, rest.trim_start());
}
if trimmed == "pub" {
return (Visibility::Public, "");
}
(Visibility::Private, trimmed)
}
fn strip_leading_item_modifiers(mut s: &str) -> &str {
loop {
let before = s;
if let Some(rest) = s.strip_prefix("unsafe ") {
s = rest.trim_start();
continue;
}
if let Some(rest) = s.strip_prefix("async ") {
s = rest.trim_start();
continue;
}
if let Some(rest) = s.strip_prefix("default ") {
s = rest.trim_start();
continue;
}
if s.strip_prefix("const fn ").is_some() {
return &s[6..];
}
if let Some(rest) = s.strip_prefix("extern ") {
let r = rest.trim_start();
if r.starts_with('"') {
if let Some(end) = r[1..].find('"') {
s = r[end + 2..].trim_start();
continue;
}
}
s = r;
continue;
}
if s == before {
return s;
}
}
}
fn extract_item_ident(s: &str) -> Option<String> {
for kw in [
"fn ", "struct ", "enum ", "const ", "static ", "type ", "trait ",
] {
if let Some(rest) = s.strip_prefix(kw) {
let rest = rest.trim_start();
let bytes = rest.as_bytes();
if bytes.is_empty() {
return None;
}
if !(bytes[0].is_ascii_alphabetic() || bytes[0] == b'_') {
return None;
}
let mut end = 0usize;
while end < bytes.len() && is_ident_byte(bytes[end]) {
end += 1;
}
if end == 0 {
return None;
}
return Some(rest[..end].to_string());
}
}
None
}
fn extract_ident_tokens_into(stripped: &str, out: &mut std::collections::HashSet<String>) {
let bytes = stripped.as_bytes();
let n = bytes.len();
let mut i = 0usize;
while i < n {
let b = bytes[i];
if b.is_ascii_alphabetic() || b == b'_' {
let s = i;
while i < n && is_ident_byte(bytes[i]) {
i += 1;
}
out.insert(stripped[s..i].to_string());
} else if b.is_ascii_digit() {
while i < n && (is_ident_byte(bytes[i]) || bytes[i] == b'.') {
i += 1;
}
} else {
i += 1;
}
}
}
fn collect_pub_use_idents(stripped: &str, out: &mut std::collections::HashSet<String>) {
let t = stripped.trim_start();
let rest = if let Some(r) = t.strip_prefix("pub use ") {
r
} else if let Some(r) = t.strip_prefix("pub(crate) use ") {
r
} else {
return;
};
let rest = rest.trim_end().trim_end_matches(';').trim();
collect_use_tree_idents(rest, out);
}
fn collect_use_tree_idents(tree: &str, out: &mut std::collections::HashSet<String>) {
if let Some(brace_start) = tree.find('{') {
let prefix = &tree[..brace_start];
let inside = &tree[brace_start + 1..];
let close = match inside.rfind('}') {
Some(p) => p,
None => return,
};
let inside = &inside[..close];
let mut depth = 0i32;
let mut start = 0usize;
let bytes = inside.as_bytes();
for (i, &b) in bytes.iter().enumerate() {
match b {
b'{' => depth += 1,
b'}' => depth -= 1,
b',' if depth == 0 => {
let seg = inside[start..i].trim();
if !seg.is_empty() {
let combined = format!("{}{}", prefix, seg);
collect_use_tree_idents(&combined, out);
}
start = i + 1;
}
_ => {}
}
}
let tail = inside[start..].trim();
if !tail.is_empty() {
let combined = format!("{}{}", prefix, tail);
collect_use_tree_idents(&combined, out);
}
return;
}
let path = tree.trim();
if path.is_empty() || path == "*" || path.ends_with("::*") {
return;
}
if let Some(as_pos) = path.rfind(" as ") {
let alias = path[as_pos + 4..].trim().trim_end_matches(',').trim();
if !alias.is_empty() && alias != "_" {
out.insert(alias.to_string());
}
return;
}
let last = path.rsplit("::").next().unwrap_or(path).trim();
if !last.is_empty() && last != "*" && last != "self" {
out.insert(last.to_string());
}
}