rhaiscript / rhai

Rhai - An embedded scripting language for Rust.
https://crates.io/crates/rhai
Apache License 2.0
3.63k stars 174 forks source link

Registered enum types can't be used with assert_eq in Rhai #843

Closed Hodkinson closed 4 months ago

Hodkinson commented 4 months ago

I registered an enum as described here: https://rhai.rs/book/patterns/enums.html

It works as described, I can use the enum (and pass it as an argument), so it seems the type is registered:

assert!(MyEnum::Foo == MyEnum::Foo)

however I cannot check for equality using assert_eq!:

assert_eq!(MyEnum::Foo, MyEnum::Foo);

ERROR: Runtime error: unknown types in assertion: left was example::MyEnum, right was example::MyEnum (line 22, position 9)

schungx commented 4 months ago

Well, you know that but Rhai doesn't. Unless you define the == operator for that enum type, Rhai can only assume that one opaque object is not the same as another...

So the solution is to define the comparison operators on your type.

Hodkinson commented 4 months ago

I did that: here's the full macro I used:

macro_rules! create_enum_module {
    ($module:ident : $typ:ty => $($variant:ident),+) => {
        #[export_module]
        pub mod $module {
            $(
                #[allow(non_upper_case_globals)]
                pub const $variant: $typ = <$typ>::$variant;
            )*

            #[rhai_fn(global, name = "to_string", name = "to_debug", pure)]
            pub fn to_string(my_enum: &mut $typ) -> String {
                format!("{my_enum:?}")
            }

            #[rhai_fn(global, name = "==", pure)]
            pub fn eq(my_enum: &mut $typ, my_enum2: $typ) -> bool {
                my_enum == &my_enum2
            }

            #[rhai_fn(global, name = "!=", pure)]
            pub fn neq(my_enum: &mut $typ, my_enum2: $typ) -> bool {
                my_enum != &my_enum2
            }
        }
    };
}
Hodkinson commented 4 months ago

I also tried defining the comparison operators directly on the enum type itself but I had the same error. Although the == comparison works when they are defined, using within assert_eq fails.

schungx commented 4 months ago

May I ask whether you derived PartialEq for your type?

EDIT: Probably yes since you can use == in Rust ..

schungx commented 4 months ago

Can you post your exact aasert_eq call?

It seems like you are comparing with the results of a script call.

Hodkinson commented 4 months ago

I tried various ways of calling it, always the same result:

assert_eq!(MyEnum::Foo,MyEnum::Foo); assert_eq!(MyEnum::Foo,m.method_that_returns_enum_foo());

Edit: I might have found the issue, am checking now

Hodkinson commented 4 months ago

My bad - I had forgotten that I had defined the assert_eq call myself, I had thought this was within rhai. I patched the assert_eq call to handle this extra type and now it works as expected. Thank you for the quick response. 🙏🏻