From 202285f9ab86d1382a7bb476fdbe1fd700627281 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Thu, 13 May 2021 10:34:24 +0800 Subject: [PATCH] Disallow pure setters. --- CHANGELOG.md | 1 + codegen/src/function.rs | 14 ++++++++++++++ tests/plugins.rs | 16 +++++++++++++--- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 323a7cc4..74c50c1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ Enhancements ------------ * Registering a custom syntax now only requires specifying whether the `Scope` is adjusted (i.e. whether variables are added or removed). This allows more flexibility for cases where the number of new variables declared depends on internal logic. +* Putting a `pure` attribute on a plugin property setter now raises a syntax error. Version 0.20.1 diff --git a/codegen/src/function.rs b/codegen/src/function.rs index 1d3029cf..8fc8c93b 100644 --- a/codegen/src/function.rs +++ b/codegen/src/function.rs @@ -550,6 +550,13 @@ impl ExportedFn { "property setter cannot return any value", )) } + // 3c. Property setters cannot be pure. + FnSpecialAccess::Property(Property::Set(_)) if params.pure.is_some() => { + return Err(syn::Error::new( + params.pure.unwrap(), + "property setter cannot be pure", + )) + } // 4a. Index getters must take the subject and the accessed "index" as arguments. FnSpecialAccess::Index(Index::Get) if self.arg_count() != 2 => { return Err(syn::Error::new( @@ -580,6 +587,13 @@ impl ExportedFn { "index setter cannot return any value", )) } + // 5b. Index setters cannot be pure. + FnSpecialAccess::Index(Index::Set) if params.pure.is_some() => { + return Err(syn::Error::new( + params.pure.unwrap(), + "index setter cannot be pure", + )) + } _ => {} } diff --git a/tests/plugins.rs b/tests/plugins.rs index e42c4c73..42aadcb7 100644 --- a/tests/plugins.rs +++ b/tests/plugins.rs @@ -31,15 +31,17 @@ mod test { } #[rhai_fn(name = "test", name = "hi")] - #[inline(always)] pub fn len(array: &mut Array, mul: INT) -> INT { (array.len() as INT) * mul } #[rhai_fn(name = "+")] - #[inline(always)] pub fn funky_add(x: INT, y: INT) -> INT { x / 2 + y * 2 } + #[rhai_fn(pure)] + pub fn no_effect(_array: &mut Array, _value: INT) { + // do nothing to array + } } } @@ -82,7 +84,15 @@ fn test_plugins_package() -> Result<(), Box> { reg_functions!(engine += greet::single(INT, bool, char)); #[cfg(not(feature = "no_object"))] - assert_eq!(engine.eval::("let a = [1, 2, 3]; a.foo")?, 1); + { + assert_eq!(engine.eval::("let a = [1, 2, 3]; a.foo")?, 1); + engine.consume("const A = [1, 2, 3]; A.no_effect(42);")?; + + assert!( + matches!(*engine.consume("const A = [1, 2, 3]; A.test(42);").expect_err("should error"), + EvalAltResult::ErrorAssignmentToConstant(x, _) if x == "array") + ) + } assert_eq!(engine.eval::(r#"hash("hello")"#)?, 42); assert_eq!(engine.eval::(r#"hash2("hello")"#)?, 42);