diff --git a/CHANGELOG.md b/CHANGELOG.md index 88a2fc4..36f253d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ process. - Fixed clippy warnings - [breaking] Changed guard functions return type from Result<(),_> to Result - [breaking] Changed action functions return type from () to Result +- [breaking] Disallow guards mutable access to the context ## [v0.6.0] - 2022-11-02 diff --git a/examples/async.rs b/examples/async.rs index e13bbe0..b8f2816 100644 --- a/examples/async.rs +++ b/examples/async.rs @@ -22,19 +22,19 @@ pub struct Context { #[async_trait] impl StateMachineContext for Context { - fn guard3(&mut self) -> Result { + fn guard3(&self) -> Result { println!("`guard3` called from async context"); Ok(true) } - async fn guard2(&mut self) -> Result { + async fn guard2(&self) -> Result { println!("`guard2` called from async context"); let mut lock = self.lock.write().await; *lock = false; Ok(true) } - fn guard1(&mut self) -> Result { + fn guard1(&self) -> Result { println!("`guard1` called from sync context"); Ok(true) } diff --git a/examples/event_with_data.rs b/examples/event_with_data.rs index ea50a92..367543b 100644 --- a/examples/event_with_data.rs +++ b/examples/event_with_data.rs @@ -21,7 +21,7 @@ statemachine! { pub struct Context; impl StateMachineContext for Context { - fn guard(&mut self, event_data: &MyEventData) -> Result { + fn guard(&self, event_data: &MyEventData) -> Result { Ok(event_data == &MyEventData(42)) } diff --git a/examples/event_with_mutable_data.rs b/examples/event_with_mutable_data.rs index c2c8368..2f9ec92 100644 --- a/examples/event_with_mutable_data.rs +++ b/examples/event_with_mutable_data.rs @@ -21,7 +21,7 @@ statemachine! { pub struct Context; impl StateMachineContext for Context { - fn guard(&mut self, event_data: &mut MyEventData) -> Result { + fn guard(&self, event_data: &mut MyEventData) -> Result { event_data.0 = 55; Ok(true) } diff --git a/examples/event_with_reference_data.rs b/examples/event_with_reference_data.rs index 8e69480..c2e0791 100644 --- a/examples/event_with_reference_data.rs +++ b/examples/event_with_reference_data.rs @@ -21,7 +21,7 @@ statemachine! { pub struct Context; impl StateMachineContext for Context { - fn guard1(&mut self, event_data: &[u8]) -> Result { + fn guard1(&self, event_data: &[u8]) -> Result { // Only ok if the slice is not empty Ok(!event_data.is_empty()) } @@ -31,7 +31,7 @@ impl StateMachineContext for Context { Ok(()) } - fn guard2(&mut self, event_data: &MyReferenceWrapper) -> Result { + fn guard2(&self, event_data: &MyReferenceWrapper) -> Result { Ok(*event_data.0 > 9000) } diff --git a/examples/ex3.rs b/examples/ex3.rs index 10c3a36..cfb3143 100644 --- a/examples/ex3.rs +++ b/examples/ex3.rs @@ -18,12 +18,12 @@ statemachine! { pub struct Context; impl StateMachineContext for Context { - fn guard(&mut self) -> Result { + fn guard(&self) -> Result { // Always ok Ok(true) } - fn guard_fail(&mut self) -> Result { + fn guard_fail(&self) -> Result { // Always fail Ok(false) } diff --git a/examples/guard_action_syntax.rs b/examples/guard_action_syntax.rs index 77d43e0..0fc4491 100644 --- a/examples/guard_action_syntax.rs +++ b/examples/guard_action_syntax.rs @@ -27,7 +27,7 @@ pub struct Context; impl StateMachineContext for Context { // Guard1 has access to the data from Event1 - fn guard1(&mut self, _event_data: &MyEventData) -> Result { + fn guard1(&self, _event_data: &MyEventData) -> Result { todo!() } @@ -37,7 +37,7 @@ impl StateMachineContext for Context { } // Guard2 has access to the data from State2 - fn guard2(&mut self, _state_data: &MyStateData) -> Result { + fn guard2(&self, _state_data: &MyStateData) -> Result { todo!() } diff --git a/examples/guard_action_syntax_with_temporary_context.rs b/examples/guard_action_syntax_with_temporary_context.rs index a062575..4f8b2de 100644 --- a/examples/guard_action_syntax_with_temporary_context.rs +++ b/examples/guard_action_syntax_with_temporary_context.rs @@ -28,7 +28,7 @@ pub struct Context; impl StateMachineContext for Context { // Guard1 has access to the data from Event1 - fn guard1(&mut self, temp_context: &mut u16, _event_data: &MyEventData) -> Result { + fn guard1(&self, temp_context: &mut u16, _event_data: &MyEventData) -> Result { *temp_context += 1; Ok(true) @@ -46,7 +46,7 @@ impl StateMachineContext for Context { } // Guard2 has access to the data from State2 - fn guard2(&mut self, temp_context: &mut u16, _state_data: &MyStateData) -> Result { + fn guard2(&self, temp_context: &mut u16, _state_data: &MyStateData) -> Result { *temp_context += 1; Ok(true) diff --git a/examples/guard_custom_error.rs b/examples/guard_custom_error.rs index e6f9839..e2d71d8 100644 --- a/examples/guard_custom_error.rs +++ b/examples/guard_custom_error.rs @@ -35,7 +35,7 @@ pub struct Context; impl StateMachineContext for Context { type GuardError = GuardError; // Guard1 has access to the data from Event1 - fn guard1(&mut self, _event_data: &MyEventData) -> Result { + fn guard1(&self, _event_data: &MyEventData) -> Result { Err(GuardError::Custom) } @@ -45,7 +45,7 @@ impl StateMachineContext for Context { } // Guard2 has access to the data from State2 - fn guard2(&mut self, _state_data: &MyStateData) -> Result { + fn guard2(&self, _state_data: &MyStateData) -> Result { todo!() } diff --git a/examples/named_async.rs b/examples/named_async.rs index ac03063..ea939c2 100644 --- a/examples/named_async.rs +++ b/examples/named_async.rs @@ -23,12 +23,12 @@ pub struct Context { #[async_trait] impl AsyncSimpleStateMachineContext for Context { - fn guard1(&mut self) -> Result { + fn guard1(&self) -> Result { println!("`guard1` called from sync context"); Ok(true) } - async fn guard2(&mut self) -> Result { + async fn guard2(&self) -> Result { println!("`guard2` called from async context"); let mut lock = self.lock.write().await; *lock = false; diff --git a/examples/named_ex3.rs b/examples/named_ex3.rs index 062ce30..cac36b4 100644 --- a/examples/named_ex3.rs +++ b/examples/named_ex3.rs @@ -19,12 +19,12 @@ statemachine! { pub struct Context; impl LoopingWithGuardsStateMachineContext for Context { - fn guard(&mut self) -> Result { + fn guard(&self) -> Result { // Always ok Ok(true) } - fn guard_fail(&mut self) -> Result { + fn guard_fail(&self) -> Result { // Always fail Ok(false) } diff --git a/examples/state_machine_logger.rs b/examples/state_machine_logger.rs index 09a5d7c..5fea6da 100644 --- a/examples/state_machine_logger.rs +++ b/examples/state_machine_logger.rs @@ -30,7 +30,7 @@ pub struct Context; impl StateMachineContext for Context { // Guard1 has access to the data from Event1 - fn guard1(&mut self, event_data: &MyEventData) -> Result { + fn guard1(&self, event_data: &MyEventData) -> Result { Ok(event_data.0 % 2 == 0) } @@ -41,7 +41,7 @@ impl StateMachineContext for Context { } // Guard2 has access to the data from State2 - fn guard2(&mut self, state_data: &MyStateData) -> Result { + fn guard2(&self, state_data: &MyStateData) -> Result { Ok(state_data.0 % 2 == 0) } diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index affd452..dd8e686 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -327,7 +327,7 @@ pub fn generate_code(sm: &ParsedStateMachine) -> proc_macro2::TokenStream { guard_list.extend(quote! { #[allow(missing_docs)] #[allow(clippy::result_unit_err)] - #is_async fn #guard <#all_lifetimes> (&mut self, #temporary_context #state_data #event_data) -> Result; + #is_async fn #guard <#all_lifetimes> (&self, #temporary_context #state_data #event_data) -> Result; }); }; Ok(()) diff --git a/tests/test.rs b/tests/test.rs index 65a1c48..df81a33 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -48,15 +48,15 @@ fn multiple_lifetimes() { struct Context; impl StateMachineContext for Context { - fn guard1(&mut self, _event_data: &X) -> Result { + fn guard1(&self, _event_data: &X) -> Result { Ok(true) } - fn guard2(&mut self, _state_data: &X, _event_data: &Y) -> Result { + fn guard2(&self, _state_data: &X, _event_data: &Y) -> Result { Ok(true) } - fn guard3(&mut self, _event_data: &Z) -> Result { + fn guard3(&self, _event_data: &Z) -> Result { Ok(true) } @@ -146,7 +146,7 @@ fn async_guards_and_actions() { struct Context; #[smlang::async_trait] impl StateMachineContext for Context { - async fn guard1(&mut self) -> Result { + async fn guard1(&self) -> Result { Ok(true) } @@ -186,10 +186,10 @@ fn guard_expressions() { attempts: u32, } impl StateMachineContext for Context { - fn valid_entry(&mut self, e: &Entry) -> Result { + fn valid_entry(&self, e: &Entry) -> Result { Ok(e.0 == self.password) } - fn too_many_attempts(&mut self, _e: &Entry) -> Result { + fn too_many_attempts(&self, _e: &Entry) -> Result { Ok(self.attempts >= 3) } fn reset(&mut self) -> Result<(), ()> { @@ -260,7 +260,7 @@ fn guarded_transition_before_unguarded() { pub enabled: bool, } impl StateMachineContext for Context { - fn guard(&mut self) -> Result { + fn guard(&self) -> Result { Ok(self.enabled) } @@ -294,7 +294,7 @@ fn guard_errors() { pub guard_errors: bool, } impl StateMachineContext for Context { - fn guard(&mut self) -> Result { + fn guard(&self) -> Result { if self.guard_errors { Err(()) } else {