librasn / rasn

A Safe #[no_std] ASN.1 Codec Framework
Other
212 stars 50 forks source link

Traits for macro expansion not always correctly carried with generics when using Encode/Decode #193

Closed Nicceboy closed 1 week ago

Nicceboy commented 1 year ago

It seems that syntax matters for declaring generics and trait declarations.

I have the following struct:

#[derive(AsnType, Encode, Decode, Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[rasn(choice, automatic_tags)]
pub enum RPermissions<T: CertExtType> {
    Content(T::Req),
    All(()),
}

It does not compile, and if I expand Encode macro for example, CertExtType condition is not carried.

However, if I change syntax to following

#[derive(AsnType, Encode, Decode, Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[rasn(choice, automatic_tags)]
pub enum RPermissions<T>
where
    T: CertExtType,
{
    Content(T::Req),
    All(()),
}

Correct macro code is generated. I almost ended up writing custom functions, but noticed by accident. If someone else fights the same problem 😁 .

XAMPPRocky commented 1 year ago

Huh, the first code should work.

Nicceboy commented 1 year ago

Huh, the first code should work.

It seems to work when newtype style is used, for example

#[derive(AsnType, Debug, Decode, Encode, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[rasn(automatic_tags)]
pub struct ContributedExtensionBlocks<T: ContributedExtension>(
    SequenceOf<ContributedExtensionBlock<T>>,
);

Edit, nevermind, it won't. The compiler error was just hidden by other errors.

XAMPPRocky commented 2 months ago

@Nicceboy Is this still the case?

Nicceboy commented 2 months ago

Yeah, the commented in the following does not compile:

use rasn::prelude::*;

pub trait TestTrait: Encode + Decode + AsnType {
    type Req: Encode + Decode + AsnType;
}

#[derive(AsnType, Encode, Decode, Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct Hello(String);

// #[derive(AsnType, Encode, Decode, Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
// #[rasn(choice, automatic_tags)]
// pub enum TraitNotCarried<T: TestTrait> {
//     Maybe(T::Req),
//     MaybeNot(()),
// }

impl TestTrait for Hello {
    type Req = u8;
}

#[derive(AsnType, Encode, Decode, Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[rasn(choice, automatic_tags)]
pub enum TraitNotCarried<T>
where
    T: TestTrait,
{
    Maybe(T::Req),
    MaybeNot(()),
}

fn main() {
    let hello = Hello("world!".to_string());
    println!("{}", hello.0);
}