use std::collections::BTreeSet;
use crate::hir::common::{HirLabelId, HirProto, HirStmt};
use super::visit::{HirVisitor, visit_proto};
use super::walk::{HirRewritePass, rewrite_proto};
#[cfg(test)]
mod tests;
pub(super) fn remove_unused_labels_in_proto(proto: &mut HirProto) -> bool {
let referenced = collect_referenced_labels(proto);
let mut pass = DeadLabelPass {
referenced: &referenced,
};
rewrite_proto(proto, &mut pass)
}
struct DeadLabelPass<'a> {
referenced: &'a BTreeSet<HirLabelId>,
}
impl HirRewritePass for DeadLabelPass<'_> {
fn rewrite_block(&mut self, block: &mut crate::hir::common::HirBlock) -> bool {
let original_len = block.stmts.len();
block.stmts.retain(
|stmt| !matches!(stmt, HirStmt::Label(label) if !self.referenced.contains(&label.id)),
);
block.stmts.len() != original_len
}
}
fn collect_referenced_labels(proto: &HirProto) -> BTreeSet<HirLabelId> {
let mut collector = ReferencedLabelCollector::default();
visit_proto(proto, &mut collector);
collector.labels
}
#[derive(Default)]
struct ReferencedLabelCollector {
labels: BTreeSet<HirLabelId>,
}
impl HirVisitor for ReferencedLabelCollector {
fn visit_stmt(&mut self, stmt: &HirStmt) {
let HirStmt::Goto(goto_stmt) = stmt else {
return;
};
self.labels.insert(goto_stmt.target);
}
}