#Serialization of HashMap with Custom Key

44 messages ยท Page 1 of 1 (latest)

magic anchor
#

I'm trying to reflect a type:

#[derive(Component, Reflect, FromReflect)]
#[reflect(Component)]
struct Foo(HashMap<Id, X>);

where Id is:

#[derive(Clone, Copy, Hash, PartialEq, Eq, Reflect, FromReflect)]
#[reflect(Hash, PartialEq)]
pub struct Id(usize);

And yet this is panicking in bevy_reflect/src/map.rs:
thread 'main' panicked at 'the given key does not support hashing'

I've checked and my Id type is registered with App. Am I missing something else?

magic anchor
#

I have a really simple type:

#[derive(Clone, Copy, PartialEq, Eq, Reflect, FromReflect)]
#[reflect(Hash)]
pub struct Id(u64);

And I'm trying to store this into a HashMap as keys, but Bevy is just not having it, giving me "the given key does not support hashing" when trying to serialize. I've tried using #[reflect(Hash, PartialEq, Debug)] too, and same thing (the ID type implements Debug manually).

#

The Id type itself is being perfectly serialized in other places. And I can get around the problem by just storing a HashMap<u64, T>

#

But I don't get why this isn't working

cerulean dock
#

It panics at serialization or deserialization?

magic anchor
#

Serialization

#

Do I need to do anything besides .register_type::<Id>().register_type::<HashMap<Id, T>>() during build phase?

cerulean dock
#

Well, generally the only time you get the the given key does not support hashing error is when attempting to insert a dynamic type into a map

#

I'm guessing there's some part of your code or Bevy's code that's cloning the key before the serialization

#

Since Reflect::clone_value will often introduce these dynamic types

magic anchor
#

i can't see where it would do that.
copy pasted snippets from my code:

This is the ID type:

#[derive(Clone, Copy, PartialEq, Eq, Reflect, FromReflect)]
#[reflect(Hash)]
pub struct Tag(u64);

This is my container component:

#[derive(Component, Default, Reflect)]
#[reflect(Component)]
pub struct Layout {
    // TODO: This should be a map of tags to enclosures
    enclosures: HashMap<u64, Enclosure>,
}

Tag is being registered as such:

app.register_type::<Tag>();

And Layout is being registered as such:

app.register_type::<Layout>()
    .register_type::<HashMap<u64, Enclosure>>()
    .register_type::<Enclosure>()

The Enclosure type does do dynamic allocation, since it contains a Vec. But that's the value type:

#[derive(Reflect, FromReflect)]
pub struct Enclosure {
    entities: Vec<Entity>,
    limit: usize,
}
#

There is no boxing or anything crazy happening

#

If I change u64 to Tag in the hashmap, I get the panic

cerulean dock
#

And there are no instances of clone_value or clone_dynamic in your code?

magic anchor
#

Nope

#

๐Ÿ˜„

cerulean dock
#

Oh wait what version is this?

magic anchor
#

i've learned my lesson to just work around boxed/dynamic types in bevy, since it gave me so much pain, so it's all static

#

0.10.1

cerulean dock
#

Oh gotcha

magic anchor
#

wait

cerulean dock
#

Yeah this is a bug on latest

#

There's a fix in 0.11-dev

magic anchor
#

Ahhh

#

Ok

cerulean dock
#

Essentially we weren't properly handling clone_dynamic for HashMap

#

It was calling clone_value on the keys but not converting them back to their concrete types using FromReflect

#

But it should be fixed now (for the 0.11 release in a few weeks)

magic anchor
#

ok sweet thanks!

#

at least i'm not insane ๐Ÿ˜„

cerulean dock
#

Yeah haha it's not you

#

But if you're able to, I would confirm that 0.11 fixes your issue

#

If it doesn't there may be some other bug or issue happening that would be nice to address before 0.11

magic anchor
#

Yah I'll leave a TODO and get around to it when 0.11 rolls out

#

Oh you mean before 0.11

#

I'll see if I can upgrade

cerulean dock
#

Yeah before (if you have time)

#

Doesn't have to be much, just a verification it's working

#

Also, quick question: are you using scenes for serialization?

magic anchor
#

Yup

#

I'm using my own save library, which uses scenes under the hood

cerulean dock
#

Okay cool then yeah that should be the issue