onyx-lang / onyx

✨ The compiler and developer toolchain for Onyx

Home Page:https://onyxlang.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Enums should implement hash()

alexspurling opened this issue · comments

It is currently not possible to create a Map or a Set using an enum as a key type because the compiler expects the key type to implement a hash() function. This is surprising because the underlying type of an enum is u32 which should be easy to translate to an i32 for purposes of generating a hash code.

Example code:

use core.map


Fruit :: enum {
    Apple; Banana; Carrot;
}

main :: () {
    m : Map(u32, str);
    m = map.make(u32, str);
    
    m2 : Map(Fruit, str);
    m2 = map.make(Fruit, str);
}

Error:

Failed to compile your code:

Line 38, column 16:
    Failed to satisfy constraint where t is of type 'Fruit'.
 38 |     { hash.hash(t) } -> u32;
                     ^ 
Line 19, column 66:
    Here is where the interface was used.
 19 | Map :: struct (Key_Type: type_expr, Value_Type: type_expr) where ValidKey(Key_Type) {
                                                                       ^~~~~~~~ 
Line 13, column 13:
    Here is the code that caused this constraint to be checked.
 13 |     m2 : Map(Fruit, str);
                  ^ 

A similar error occurs when trying to create a Set(Fruit).

I suggest an enhancement where all enums automatically implement hash() using the underlying data type if possible. If it's not possible to hash the underlying data type, then there should be an option to implement this function in the body of the enum in the same way as for structs.

I agree enums should have hash defined for them by default, so that's going to be fixed.

But just to mention, you can make this work manually in one of these two ways.

#inject
Fruit.hash :: (f: Fruit) -> u32 {
    return hash.hash(cast(u32) f);
}
#overload
hash.hash :: (f: Fruit) -> u32 {
    return hash.hash(cast(u32) f);
}