[BUG] derive Introspect doesn't work in embedded generics
Describe the bug A clear and concise description of what the bug is. derive Introspect doesn't work in embedded generics
To Reproduce Steps to reproduce the behavior:
#[derive(Introspect, Serde, Copy, Drop)]
struct A<T>{
a: T,
b: u64
}
#[derive(Introspect, Serde, Copy, Drop)]
struct B<T>{
a: A<T>,
b: u64
}
failed with
error: Variable not dropped.
--> gg.cairo[impls]:8:16
c: core::serde::Serde::deserialize(ref serialized)?,
^**********************************************^
note: the variable needs to be dropped due to the divergence here:
--> gg.cairo[impls]:9:16
d: core::serde::Serde::deserialize(ref serialized)?,
^**********************************************^
note: Trait has no implementation in context: core::traits::Drop::<kingdom_lord::gg::A::<T>>
note: Trait has no implementation in context: core::traits::Destruct::<kingdom_lord::gg::A::<T>>
error: Variable not dropped.
-->gg.cairo[impls]:8:16
c: core::serde::Serde::deserialize(ref serialized)?,
^**********************************************^
note: the variable needs to be dropped due to the potential panic here:
-->gg.cairo[impls]:9:16
d: core::serde::Serde::deserialize(ref serialized)?,
^*********************************************^
note: Trait has no implementation in context: core::traits::Drop::<kingdom_lord::gg::A::<T>>
note: Trait has no implementation in context: core::traits::Destruct::<kingdom_lord::gg::A::<T>>
note: Trait has no implementation in context: core::traits::PanicDestruct::<kingdom_lord::gg::A::<T>>
Expected behavior Build should work,
Screenshots If applicable, add screenshots to help explain your problem.
Additional context Add any other context about the problem here.
Hi @zsluedem !
Thanks for the bug report !
After some investigations, this is not a Dojo bug but a strange behaviour in Cairo. I tried to compile the following Cairo code outside Dojo and I get the same error:
#[derive(Serde, Copy, Drop)]
struct A<T> {
a: T,
}
#[derive(Serde, Copy, Drop)]
struct B<T> {
a: A<T>,
b: u8
}
But, if I move the a field of struct B at the end of the struct, it compiles properly.
On a same idea, this code does not compile:
#[derive(Serde, Copy, Drop)]
struct A<T> {
a: T,
}
#[derive(Serde, Copy, Drop)]
struct C<T> {
c: T,
}
#[derive(Serde, Copy, Drop)]
struct B<T> {
b: u8
a: A<T>,
c: C<T>
}
I continue the investigation to know if it's a known limitation, a bug to fix or if there is a specific syntax for these cases.
@tarrencev could you assign this issue to me please ?
After some investigations, here is the solution: your struct A must implement the Destruct trait as follow:
#[derive(Serde, Copy, Drop, Introspect, Destruct)]
struct A<T> {
a: T
}
#[derive(Serde, Copy, Drop, Introspect)]
struct B<T> {
a: A<T>,
b: u8
}
It also works for the example with the struct C but this struct C has also to implement the Destruct trait.
Tested with the spawn-and-move example and it compiles !
#[derive(Introspect, Serde, Copy, Drop)] struct A<T>{ a: T, b: u64 }
#[derive(Introspect, Serde, Copy, Drop)] struct B<T>{ a: A<T>, b: u64 }
I thought derive Drop would also implement Destruct. Interesting solution.