typestate-rs icon indicating copy to clipboard operation
typestate-rs copied to clipboard

Default implementations don't work

Open jquesada2016 opened this issue 3 years ago • 2 comments

Given the following:

    use typestate::typestate;

    #[typestate]
    mod my_state {
        #[automaton]
        pub struct Automaton;

        #[state]
        pub struct State1(bool);

        pub trait State1: Sized {
            fn new() -> State1 {
                Automaton {
                    state: State1(true),
                }
            }

            fn to_state_2(mut self) -> State2 {
                Automaton {
                    state: State2(true),
                }
            }
        }

        #[state]
        pub struct State2(bool);

        pub trait State2: Sized {
            fn done(self) {}
        }
    }

    fn t() {
        use my_state::*;

        let s1 = Automaton::new();
    }

We get an error stating that State1State trait is in scope, but not implemented for Automaton<State1>.

If I instead implement the traits, all is well:

        #[automaton]
        pub struct Automaton;

        #[state]
        pub struct State1;

        pub trait State1 {
            fn new() -> State1;

            fn to_state_2(self) -> State2;
        }

        impl State1State for Automaton<State1> {
            fn new() -> Automaton<State1> {
                Automaton { state: State1 }
            }

            fn to_state_2(self) -> Automaton<State2> {
                Automaton { state: State2 }
            }
        }

        #[state]
        pub struct State2;

        pub trait State2 {
            fn done(self);
        }

        impl State2State for Automaton<State2> {
            fn done(self) {}
        }
    }

    fn t() {
        use my_state::*;

        let s1 = Automaton::new();
    }

jquesada2016 avatar Dec 14 '21 22:12 jquesada2016

Could you run cargo expand on your example?

https://github.com/dtolnay/cargo-expand

jmg-duarte avatar Dec 15 '21 12:12 jmg-duarte

Sure, he is the cargo-expand output:

mod _t {
    use typestate::typestate;
    ///```mermaid
    ///stateDiagram-v2
    ///[*] --> State1 : new
    ///State1 --> State2 : to_state_2
    ///State2 --> [*] : done
    ///```
    mod my_state {
        pub struct Automaton<State: AutomatonState> {
            pub state: State,
        }
        pub struct State1(bool);
        pub trait State1State: Sized {
            fn new() -> Automaton<State1> {
                Automaton {
                    state: State1(true),
                }
            }
            #[must_use]
            fn to_state_2(mut self) -> Automaton<State2> {
                Automaton {
                    state: State2(true),
                }
            }
        }
        pub struct State2(bool);
        pub trait State2State: Sized {
            fn done(self) {}
        }
        #[doc(hidden)]
        mod __private {
            pub trait AutomatonState {}
        }
        pub trait AutomatonState: __private::AutomatonState {}
        impl<__T: ?::core::marker::Sized> AutomatonState for __T where __T: __private::AutomatonState {}
        impl __private::AutomatonState for State1 {}
        impl __private::AutomatonState for State2 {}
    }
    fn t() {
        use my_state::*;
    }
}

jquesada2016 avatar Dec 15 '21 16:12 jquesada2016