Skip to content
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

look through references to improve externally tagged enum generation #178

Open
lsh opened this issue Jan 26, 2023 · 4 comments
Open

look through references to improve externally tagged enum generation #178

lsh opened this issue Jan 26, 2023 · 4 comments

Comments

@lsh
Copy link
Contributor

lsh commented Jan 26, 2023

This is a possible solution to some of the gnarly Vega code generation. Several of the more complex types end up with many VariantN layers (like @ahl mentioned in #165).

For example we have:

#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum AlignValueVariant0ItemSubtype1Subtype1Subtype0 {
    Variant0(SignalRef),
    Variant1 {
        value: AlignValueVariant0ItemSubtype1Subtype1Subtype0Variant1Value,
    },
    Variant2 {
        field: Field,
    },
    Variant3 {
        range: AlignValueVariant0ItemSubtype1Subtype1Subtype0Variant3Range,
    },
}

It might be okay to replace instances of that enum with something like Box<dyn AsVegaAlign>.

@ahl
Copy link
Collaborator

ahl commented Jan 26, 2023

In that specific case, I think we could generate better code if we picked apart the referenced SignalRef type:

#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum AlignValueVariant0ItemSubtype1Subtype1Subtype0 {
    Signal(String),
    Value(AlignValueVariant0ItemSubtype1Subtype1Subtype0Variant1Value),
    Field(Field),
    Range(AlignValueVariant0ItemSubtype1Subtype1Subtype0Variant3Range),
}

This uses the default serde "external" enum tagging.

The downside (such as it is) is that this would no longer use the SignalRef type. Perhaps this could be mitigated by

impl TryFrom<AlignValueVariant0ItemSubtype1Subtype1Subtype0> for SignalRef {
    type Error = &'static str;
    fn try_from(value: AlignValueVariant0ItemSubtype1Subtype1Subtype0) {
        match value {
            AlignValueVariant0ItemSubtype1Subtype1Subtype0::Signal(signal) => Ok(Self { signal }),
            _ => Err("nope!"),
        }
    }
}

What do you think? Internally I think we'd do something like annotating each variant's IR to say "this is actually a type that we picked apart so offer up a TryFrom for this case".

@ahl
Copy link
Collaborator

ahl commented Jan 26, 2023

The vega spec also seems to have many duplicated structures that might be nice to consolidate, though that would require us to figure out an appropriate name for the type. The current naming is, effectively, path dependent, and while not the nicest at least is simple to construct.

@ahl ahl changed the title Allow for Trait as Enum Argument look through references to improve externally tagged enum generation Apr 24, 2023
@ahl
Copy link
Collaborator

ahl commented Apr 27, 2023

This turns out to be quite a pain in the neck right now. It may need to wait for #195 (in particular see "Separate mutable and immutable structures")

ahl added a commit that referenced this issue Apr 27, 2023
We currently "expand" or "look through" referenced types for internally
tagged enums, but don't for externally tagged enums. There is more we
could do to be clever in both cases.

We want to preserve types rather than expanding them, but there's also
some opportunities to do a better job of naming enum variants.

This kicked over some inconsistencies and accidents with varied use of
`get_object` and `schema_is_named`

So far this has cleaned up some grotty code, but there's more we can
do to tidy it up.
@ahl
Copy link
Collaborator

ahl commented Sep 6, 2023

Another idea:

#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum AlignValueVariant0ItemSubtype1Subtype1Subtype0 {
    Value(AlignValueVariant0ItemSubtype1Subtype1Subtype0Variant1Value),
    Field(Field),
    Range(AlignValueVariant0ItemSubtype1Subtype1Subtype0Variant3Range),
    #[untagged]
    SignalRef(SignalRef),
}

per serde-rs/serde#2403

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants