From e39911650ad75903907a61539f25a5919c305e87 Mon Sep 17 00:00:00 2001 From: Liam Date: Fri, 31 Jul 2026 02:34:30 -0400 Subject: [PATCH 1/2] Compare functions by identity --- src/evaluator.rs | 2 ++ src/function.rs | 8 +++++--- tests/integration.rs | 29 +++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/evaluator.rs b/src/evaluator.rs index 6b45263..ac7c0b1 100644 --- a/src/evaluator.rs +++ b/src/evaluator.rs @@ -289,6 +289,7 @@ impl<'a> Evaluator<'a> { Ok(Value::Function(Function::UserDefined { body: body.clone(), environment: self.environment.clone(), + identity: Rc::new(()), name: None, parameters: parameters.clone(), })) @@ -447,6 +448,7 @@ impl<'a> Evaluator<'a> { let function = Function::UserDefined { body: body.clone(), environment: self.environment.clone(), + identity: Rc::new(()), name: Some(name.clone()), parameters: params.clone(), }; diff --git a/src/function.rs b/src/function.rs index d1736da..a94d9fd 100644 --- a/src/function.rs +++ b/src/function.rs @@ -10,6 +10,7 @@ pub enum Function<'src> { UserDefined { body: Vec>, environment: Environment<'src>, + identity: Rc<()>, name: Option, parameters: Vec, }, @@ -37,6 +38,7 @@ impl<'src> Function<'src> { environment, name, parameters, + .. } => { let call_environment = Environment::with_parent(environment.clone()); @@ -98,9 +100,9 @@ impl PartialEq for Function<'_> { match (self, other) { (Self::Builtin { name: a, .. }, Self::Builtin { name: b, .. }) => a == b, ( - Self::UserDefined { name: Some(a), .. }, - Self::UserDefined { name: Some(b), .. }, - ) => a == b, + Self::UserDefined { identity: a, .. }, + Self::UserDefined { identity: b, .. }, + ) => Rc::ptr_eq(a, b), _ => false, } } diff --git a/tests/integration.rs b/tests/integration.rs index bc913d3..c5e0173 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -1316,6 +1316,35 @@ fn function_arity_is_checked_before_arguments() -> Result { .run() } +#[test] +fn function_equality_uses_identity() -> Result { + Test::new()? + .program(indoc! { + " + anonymous = fn() {} + alias = anonymous + + println(anonymous == anonymous) + println(anonymous == alias) + println(anonymous == fn() {}) + + fn foo() { + return 1 + } + + original = foo + + fn foo() { + return 2 + } + + println(original == foo) + " + }) + .expected_stdout(Exact("true\ntrue\nfalse\nfalse\n")) + .run() +} + #[test] fn function_call_as_argument() -> Result { Test::new()? From 244dfeab1d1c7746c95c7c1ad43304d5f5c8b49e Mon Sep 17 00:00:00 2001 From: Liam Date: Fri, 31 Jul 2026 02:37:21 -0400 Subject: [PATCH 2/2] Order function equality test --- tests/integration.rs | 58 ++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/tests/integration.rs b/tests/integration.rs index c5e0173..6b3841d 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -1316,35 +1316,6 @@ fn function_arity_is_checked_before_arguments() -> Result { .run() } -#[test] -fn function_equality_uses_identity() -> Result { - Test::new()? - .program(indoc! { - " - anonymous = fn() {} - alias = anonymous - - println(anonymous == anonymous) - println(anonymous == alias) - println(anonymous == fn() {}) - - fn foo() { - return 1 - } - - original = foo - - fn foo() { - return 2 - } - - println(original == foo) - " - }) - .expected_stdout(Exact("true\ntrue\nfalse\nfalse\n")) - .run() -} - #[test] fn function_call_as_argument() -> Result { Test::new()? @@ -1383,6 +1354,35 @@ fn function_calling_builtin() -> Result { .run() } +#[test] +fn function_equality_uses_identity() -> Result { + Test::new()? + .program(indoc! { + " + anonymous = fn() {} + alias = anonymous + + println(anonymous == anonymous) + println(anonymous == alias) + println(anonymous == fn() {}) + + fn foo() { + return 1 + } + + original = foo + + fn foo() { + return 2 + } + + println(original == foo) + " + }) + .expected_stdout(Exact("true\ntrue\nfalse\nfalse\n")) + .run() +} + #[test] fn function_modifying_outer_scope() -> Result { Test::new()?