How to handle this:

Hi,

I don't know how to work around a type that I don't know how to set. I challenge myself to implement a serialization lib to improve in the language and touch many of its areas.

All the following code has been massively simplified.
I use nightly.

The trait:

pub trait Serialize {
        type Input;

        type Nominative;

        fn serialize_value_nominative(&self, value: &mut Self::Nominative) {
                // helps me debug what I didn't implement yet.
                todo!()
        }
}

the macro for all the primitive type: u8, u16..
I only show u32 here:

#[macro_export]

macro_rules! primitive_implementation {
        ($T: ident, $ArchivedT: ident) => {
               

                impl Serialize for $T { // $T a u32 here
                        type Input = $ArchivedT;
                        type Nominative = $T;

                        fn serialize_value_nominative(
                                &self,
                                value: &mut Self::Nominative,
                        ) {

                                println!("return {:?} {:?}; (for  alignment {})", self, *value, std::mem::align_of_val(self));

                                *value = *self;

                              
                        }
                }
        };
}

called with:
primitive_implementation!(u32, Archivedu32);

The issue is when I implement tuples (other type have been successfully implemented and the serialization works). But Tuple potentially have different types in them and I have to treat the inner type(s) separately.
let's keep it simple and only take a tuple with 2 elements. It is (u32,u32) in my test, but it can be anything, really, as long as it is serializable:

#[derive(Default)]

pub struct ArchivedTuple2<A, B>
where
        A: Serialize,
        B: Serialize
{
        val: (A, B)
}

impl<A, B> Serialize for (A, B)
where
        A: Serialize + Debug,
        B: Serialize + Debug
{
        type Input = ArchivedTuple2<A, B>;
        type Nominative = (A, B);

        fn serialize_value(&self, value: &mut Self::Input) {

                println!("A is {:?}", type_name::<A>());

                println!("B is {:?}", type_name::<B>());

                println!("Self {:?} {:?}", self.0, self.1);

                let u = &mut value.val.0; // it's a u32 here in my test
                 // Since we are dealing with a (u32,u32) self.0 is a u32.
                 // So it should calls the u32 implementation above
                self.0.serialize_value_nominative(u);

                let u = &mut value.val.1; // it's a u32 here in my test

                self.1.serialize_value_nominative(u);
        }
}

Ok so now the real issue:
my variable u is of the wrong type.

expected `&mut <A as Serialize>::Nominative`, found `&mut A

So, in that test, I should get a &mut u32. A is just a generic type (could have named it anything), not an existing type.
But in my understanding, &mut A is in fact &mut u32 in that case, so already &mut <A as Serialize>::Nominative as well because A is a u32. :thinking:

I use an associated trait for serialize_value_nominative function to avoid generics.

But my knowledge to solve this ends here.

How to get that type ?

You'll need to specify the constraint on the impl:

impl<A, B> Serialize for (A, B)
where
    A: Serialize<Nominative=A> + Debug,
    B: Serialize<Nominative=B> + Debug,
2 Likes

Ahah and the moment you point my mistake, I realized that this change was suggested by my IDE.

Thanks a lot!