Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default implementations don't work #26

Open
jquesada2016 opened this issue Dec 14, 2021 · 2 comments
Open

Default implementations don't work #26

jquesada2016 opened this issue Dec 14, 2021 · 2 comments

Comments

@jquesada2016
Copy link

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();
    }
@jmg-duarte
Copy link
Contributor

Could you run cargo expand on your example?

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

@jquesada2016
Copy link
Author

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::*;
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants