From 3ded62d836ca062fc19529d0c8a27e5a41b05339 Mon Sep 17 00:00:00 2001 From: Michael Schimmel Date: Fri, 6 Mar 2026 11:47:31 +0100 Subject: [PATCH] feat: Add --no-opt flag and a failing test case Introduce a --no-opt flag to disable compiler optimizations and add a new integration test case to reproduce a slot clash issue during inlining. --- src/bin/ast.rs | 4 ++-- src/integration_test.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/bin/ast.rs b/src/bin/ast.rs index 96fb8da..657ad8b 100644 --- a/src/bin/ast.rs +++ b/src/bin/ast.rs @@ -42,8 +42,8 @@ struct Cli { fn main() { let cli = Cli::parse(); - let env = Environment::new(); - // Use env.optimization setting if needed, though it's currently on by default + let mut env = Environment::new(); + env.optimization = !cli.no_opt; // Load libraries for lib_path in &cli.lib { diff --git a/src/integration_test.rs b/src/integration_test.rs index 29b4686..9fe22b2 100644 --- a/src/integration_test.rs +++ b/src/integration_test.rs @@ -756,4 +756,31 @@ mod tests { .any(|m| m.contains("Invalid arguments for function call")) ); } + + #[test] + fn test_optimizer_inlining_slot_clash_repro() { + let mut env = Environment::new(); + env.optimization = true; + + // This exactly mirrors err.myc structure. + // NOTE: We must use a dynamic call like (series :float) here. + // Simple constants like (def history 100) might be constant-folded or + // inlined as values by the optimizer before the slot-clash can occur. + // By using a series, we force the result into a local slot at runtime, + // which triggers the conflict when the inliner fails to remap slots correctly. + let source = r#" + (do + (def outer (fn [length] + (do + (def history (series :float)) + (fn [val] length) + ) + )) + ((outer 20) 5) + ) + "#; + + let res = env.run_script(source).unwrap(); + assert_eq!(format!("{}", res), "20"); + } }