-
Notifications
You must be signed in to change notification settings - Fork 210
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
Can't Derive ToVariant on generic type with constraint #957
Comments
Thanks for reporting. I'm not 100% sure how good the support for generics is in the derives. Did you already have a look with |
Okay, I learned a bit I installed nightly and i'm running through that code to try and understand what's up : #[derive(Debug, Clone, ToVariant)]
pub enum WorldChange<T: Entity> {
EntityMoved {
id: EntityId,
from: Position,
to: Position,
cost: f32,
},
EntitySentMessage {
from: EntityId,
to: EntityId,
msg: T::Message,
},
EntityStateChanged {
id: EntityId,
change: T::EntityChange,
},
EntityPlaced(EntityId, Position),
EntityUnplaced(EntityId),
EntityPassedTurn(EntityId),
} expands the bloc of code at the end of this comment: It was incredibly useful to pinpoint the bug ! expansion impl<T: Entity> ::gdnative::core_types::ToVariant for WorldChange<T: Entity>
where
T::Message: ::gdnative::core_types::ToVariant,
T::EntityChange: ::gdnative::core_types::ToVariant,
{
fn to_variant(&self) -> ::gdnative::core_types::Variant {
use ::gdnative::core_types::ToVariant;
use ::gdnative::core_types::FromVariant;
match &self {
WorldChange::EntityMoved { id, from, to, cost } => {
let __dict = ::gdnative::core_types::Dictionary::new();
let __key = ::gdnative::core_types::ToVariant::to_variant(
&::gdnative::core_types::GodotString::from("EntityMoved"),
);
let __value = {
let __dict = ::gdnative::core_types::Dictionary::new();
{
let __key = ::gdnative::core_types::GodotString::from("id")
.to_variant();
__dict.insert(&__key, &(id).to_variant());
}
{
let __key = ::gdnative::core_types::GodotString::from("from")
.to_variant();
__dict.insert(&__key, &(from).to_variant());
}
{
let __key = ::gdnative::core_types::GodotString::from("to")
.to_variant();
__dict.insert(&__key, &(to).to_variant());
}
{
let __key = ::gdnative::core_types::GodotString::from("cost")
.to_variant();
__dict.insert(&__key, &(cost).to_variant());
}
__dict.into_shared().to_variant()
};
__dict.insert(&__key, &__value);
::gdnative::core_types::ToVariant::to_variant(&__dict.into_shared())
}
WorldChange::EntitySentMessage { from, to, msg } => {
let __dict = ::gdnative::core_types::Dictionary::new();
let __key = ::gdnative::core_types::ToVariant::to_variant(
&::gdnative::core_types::GodotString::from("EntitySentMessage"),
);
let __value = {
let __dict = ::gdnative::core_types::Dictionary::new();
{
let __key = ::gdnative::core_types::GodotString::from("from")
.to_variant();
__dict.insert(&__key, &(from).to_variant());
}
{
let __key = ::gdnative::core_types::GodotString::from("to")
.to_variant();
__dict.insert(&__key, &(to).to_variant());
}
{
let __key = ::gdnative::core_types::GodotString::from("msg")
.to_variant();
__dict.insert(&__key, &(msg).to_variant());
}
__dict.into_shared().to_variant()
};
__dict.insert(&__key, &__value);
::gdnative::core_types::ToVariant::to_variant(&__dict.into_shared())
}
WorldChange::EntityStateChanged { id, change } => {
let __dict = ::gdnative::core_types::Dictionary::new();
let __key = ::gdnative::core_types::ToVariant::to_variant(
&::gdnative::core_types::GodotString::from("EntityStateChanged"),
);
let __value = {
let __dict = ::gdnative::core_types::Dictionary::new();
{
let __key = ::gdnative::core_types::GodotString::from("id")
.to_variant();
__dict.insert(&__key, &(id).to_variant());
}
{
let __key = ::gdnative::core_types::GodotString::from(
"change",
)
.to_variant();
__dict.insert(&__key, &(change).to_variant());
}
__dict.into_shared().to_variant()
};
__dict.insert(&__key, &__value);
::gdnative::core_types::ToVariant::to_variant(&__dict.into_shared())
}
WorldChange::EntityPlaced(__field_0, __field_1) => {
let __dict = ::gdnative::core_types::Dictionary::new();
let __key = ::gdnative::core_types::ToVariant::to_variant(
&::gdnative::core_types::GodotString::from("EntityPlaced"),
);
let __value = {
let __array = ::gdnative::core_types::VariantArray::new();
__array.push(&(__field_0).to_variant());
__array.push(&(__field_1).to_variant());
__array.into_shared().to_variant()
};
__dict.insert(&__key, &__value);
::gdnative::core_types::ToVariant::to_variant(&__dict.into_shared())
}
WorldChange::EntityUnplaced(__field_0) => {
let __dict = ::gdnative::core_types::Dictionary::new();
let __key = ::gdnative::core_types::ToVariant::to_variant(
&::gdnative::core_types::GodotString::from("EntityUnplaced"),
);
let __value = (__field_0).to_variant();
__dict.insert(&__key, &__value);
::gdnative::core_types::ToVariant::to_variant(&__dict.into_shared())
}
WorldChange::EntityPassedTurn(__field_0) => {
let __dict = ::gdnative::core_types::Dictionary::new();
let __key = ::gdnative::core_types::ToVariant::to_variant(
&::gdnative::core_types::GodotString::from("EntityPassedTurn"),
);
let __value = (__field_0).to_variant();
__dict.insert(&__key, &__value);
::gdnative::core_types::ToVariant::to_variant(&__dict.into_shared())
}
}
}
} |
Thanks for expanding, that helped me narrow down the problem! A fix is available in #961, could you see if it works for you? You can add a Git dependency in Cargo.toml with a branch name. |
Amazing thanks ! cargo expand generate code that impl ToVariant Correctly but #[method] now complains that all the struct deriving ToVariant don't satisfy the trait bound , I'm extremly puzzled to be honest ... What's extremely odd is that your test seems to be passing and i dont do anything differently, maybe i messed it up in Cargo.toml ? I used : |
I found it ! Oh my it was subtle (for me)!! Okay so a struct like this #[derive(Debug, Clone,ToVariant)]
pub struct Intent<T: Entity> {
pub emitter: EntityId,
pub action: Action<T>,
pub priority: i32,
} has a generated cargo expand like this impl<T: Entity> ::gdnative::core_types::ToVariant for Intent<T>
where
T: ::gdnative::core_types::ToVariant,
{
fn to_variant(&self) -> ::gdnative::core_types::Variant {
use ::gdnative::core_types::FromVariant;
use ::gdnative::core_types::ToVariant;
{
let Intent {
emitter,
action,
priority,
} = self;
{
let __dict = ::gdnative::core_types::Dictionary::new();
{
let __key = ::gdnative::core_types::GodotString::from("emitter").to_variant();
__dict.insert(
&__key,
&(emitter).to_variant(),
);
}
{
let __key = ::gdnative::core_types::GodotString::from("action").to_variant();
__dict.insert(
&__key,
&(action).to_variant(),
);
}
{
let __key = ::gdnative::core_types::GodotString::from("priority").to_variant();
__dict.insert(
&__key,
&(priority).to_variant(),
);
}
__dict.into_shared().to_variant()
}
}
}
} Note that Edit : maybe it wouldnt be so hard, the user would just have to write #[derive(ToVariant)]
MyStruct<T : ToVariant> /* ... */ if needed, but i guess we'd have to see if the error msg is nice, maybe leave that to me i'd like to help and try to improve the macros (plus i have a code base to test it right after so) |
Yeah, gladly! 😊 Maybe I'll merge the existing PR but keep this issue open; then you can use it as a base to address the |
961: Fixed ToVariant/FromVariant derive for generic types with bounds r=Bromeon a=Bromeon Fixes part of #957; but there's a separate problem with `where` clauses (see description). Co-authored-by: Jan Haller <[email protected]>
Hey, I'm having trouble launching the tests in test_derive.rs with |
Did you run It should create some dynamic library files (for example Otherwise feel free to use the CI for testing, just amend your commits and keep force-pushing ( |
Maybe related to #965 |
This is correct. Macros operate only at the token level, so any automatic bounds are at most guesses. Now that we have |
Hi !
I'm trying to get this to compile :
but it complains
this enum takes 1 generic argument but 0 generic arguments were supplied expected 1 generic argument
.Note that it doesn't complain for MyStruct, but it complains for any constraint MyStruct or MyStruct
it doesn't matter as well if T::Message impl ToVariant or not (which it does)
It would be nice to be able to constrain the type because my only other option is to impl ToVariant by myself which is not ideal.
The text was updated successfully, but these errors were encountered: