#[cfg(test)]
mod tests {
    use crate::mir::MirInstruction;
    use crate::parser::NyashParser;

    // Regression for predecessor mis-selection on nested if inside loop in PHI-off mode
    // Path: cond == true && cond2 == false should observe inner else assignment at merge.
    #[test]
    fn nested_if_inside_loop_edges_copy_from_exiting_blocks() {
        // Force PHI-off
        std::env::set_var("NYASH_MIR_NO_PHI", "1");

        let code = r#"
            x = 0
            i = 0
            loop (i < 1) {
                i = i + 1
                if (1 == 1) {
                    if (1 == 0) {
                        x = 1
                    } else {
                        x = 2
                    }
                }
            }
            return x
        "#;

        let ast = NyashParser::parse_from_string(code).expect("parse");
        let mut compiler = crate::mir::MirCompiler::new();
        let result = compiler.compile(ast).expect("compile");

        // Find return block/value id
        let f = result.module.functions.get("main").expect("main");
        let (ret_block, out_v) = f
            .blocks
            .iter()
            .find_map(|(bid, bb)| match &bb.terminator {
                Some(MirInstruction::Return { value: Some(v) }) => Some((*bid, *v)),
                _ => None,
            })
            .expect("ret block");

        // Every predecessor must carry a Copy to the merged value in PHI-off mode
        let preds: Vec<_> = f
            .blocks
            .get(&ret_block)
            .unwrap()
            .predecessors
            .iter()
            .copied()
            .collect();
        assert!(!preds.is_empty(), "ret must have predecessors");
        for p in preds {
            let bb = f.blocks.get(&p).unwrap();
            let has_copy = bb
                .instructions
                .iter()
                .any(|inst| matches!(inst, MirInstruction::Copy { dst, .. } if *dst == out_v));
            assert!(
                has_copy,
                "missing Copy to merged value in predecessor {:?}",
                p
            );
        }
        // ret block must not contain Copy to out_v
        let merge_has_copy = f
            .blocks
            .get(&ret_block)
            .unwrap()
            .instructions
            .iter()
            .any(|inst| matches!(inst, MirInstruction::Copy { dst, .. } if *dst == out_v));
        assert!(
            !merge_has_copy,
            "merge/ret must not contain Copy to merged value"
        );
    }
}
