From 24d36a08a6f912c3a1e7e83c08d843d4263a24be Mon Sep 17 00:00:00 2001 From: Brummel Date: Mon, 30 Mar 2026 11:50:08 +0200 Subject: [PATCH] Refactor 'again' type check to use unify This change replaces a manual type check for the `again` function with a call to the generic `unify` function. This improves consistency and leverages existing type-checking logic. A new test case `test_again_type_mismatch` has been added to specifically verify that type mismatches in `again` calls are caught at compile time, preventing potential infinite loops. --- src/ast/compiler/type_checker.rs | 12 ++---------- tests/error_recovery.rs | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/ast/compiler/type_checker.rs b/src/ast/compiler/type_checker.rs index 21342c6..2fefbd4 100644 --- a/src/ast/compiler/type_checker.rs +++ b/src/ast/compiler/type_checker.rs @@ -1513,16 +1513,8 @@ impl TypeChecker { self.check_node(args, ctx, diag) }; - if let Some(expected_ty) = &ctx.current_params_ty - && !expected_ty.is_assignable_from(&args_typed.ty) - { - diag.push_error( - format!( - "Type mismatch in 'again' call: expected {}, but got {}", - expected_ty.display_compact(), args_typed.ty.display_compact() - ), - Some(node.identity.clone()), - ); + if let Some(expected_ty) = &ctx.current_params_ty { + self.unify(expected_ty.clone(), args_typed.ty.clone(), diag); } ( diff --git a/tests/error_recovery.rs b/tests/error_recovery.rs index 1eb4aa9..fea1a84 100644 --- a/tests/error_recovery.rs +++ b/tests/error_recovery.rs @@ -160,3 +160,17 @@ fn test_error_recovery_multiple_errors() { .any(|m| m.contains("no matching overload")) ); } + +#[test] +fn test_again_type_mismatch() { + let env = Environment::new(); + // (again "text") should fail: parameter n is int (from call site), not string. + // Without this check, the program would loop forever. + let result = env.run_script( + r#"(do (def f (fn [n] (if (= n 0) n (again "text")))) (f 3))"#, + ); + assert!( + result.is_err(), + "again with wrong type should be a compile error, not an infinite loop" + ); +}