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

Data::try_from reached unreachable!(). #85

Closed
Luro02 opened this issue Dec 26, 2019 · 2 comments · Fixed by #123
Closed

Data::try_from reached unreachable!(). #85

Luro02 opened this issue Dec 26, 2019 · 2 comments · Fixed by #123

Comments

@Luro02
Copy link
Contributor

Luro02 commented Dec 26, 2019

The function Data::try_from has an unreachable!(), which will trigger, if you try to call this function with syn::Data::Union.

syn::Data::Union(_) => unreachable!(),

Because this is definitely reachable, it should be either replaced with an Error

Error::custom("Union structs are not supported.")
    .with_span(&body);

or exposed by the data struct.

This should definitely not panic, because it makes it unnecessarily difficult to find the problem and it would be nice to get a beautiful error, instead of this:

error: proc-macro derive panicked
 --> tests/test_union.rs:3:10
  |
3 | #[derive(ShortHand)]
  |          ^^^^^^^^^
  |
  = help: message: internal error: entered unreachable code

error: aborting due to previous error

error: could not compile `shorthand`.

To learn more, run the command again with --verbose.

Implementation

/// Attempt to convert from a [`syn::Data`] instance.
///
/// # Errors
///
/// This function will error, if `body` is [`syn::Data::Union`].
pub fn try_from(body: &syn::Data) -> Result<Self> {
    match *body {
        syn::Data::Enum(ref data) => {
            let mut items = Vec::with_capacity(data.variants.len());
            let mut errors = Vec::new();
            for v_result in data.variants.iter().map(FromVariant::from_variant) {
                match v_result {
                    Ok(val) => items.push(val),
                    Err(err) => errors.push(err),
                }
            }

            if !errors.is_empty() {
                Err(Error::multiple(errors))
            } else {
                Ok(Data::Enum(items))
            }
        }
        syn::Data::Struct(ref data) => Ok(Data::Struct(Fields::try_from(&data.fields)?)),
        syn::Data::Union(u) => Err(
            Error::custom("Union structs are not supported.")
                .with_span(&u.fields)
        ),
    }
}
error: Union structs are not supported.
 --> tests/test_union.rs:5:20
  |
5 |   union ExampleUnion {
  |  ____________________^
6 | |     f1: u32,
7 | |     f2: f32,
8 | | }
  | |_^

error: aborting due to previous error

error: could not compile `shorthand`.

To learn more, run the command again with --verbose.

I am not sure, if the span is correct, or if there shouldn't be any span attached to it and instead the docs show how to attach the correct span:

fn from_derive_input(input: &DeriveInput) {
    let data = Data::try_from(&input.data).map_err(|e| e.with_span(&input.ident))
}
error: Union structs are not supported.
 --> tests/test_union.rs:5:7
  |
5 | union ExampleUnion {
  |       ^^^^^^^^^^^^

error: aborting due to previous error

error: could not compile `shorthand`.

To learn more, run the command again with --verbose.

There is also

pub fn empty_from(src: &syn::Data) -> Self {

which should do the same as above, but this would be a breaking change, so it might be better to simply document, that this could panic, if called with Data::Union. I would also replace the unreachable!() with unreachable!("::darling::ast::Data::empty_from: Union structs are not supported.")


Another one is here (this can error?)

Data::Union(_) => unreachable!(),

@TedDriggs
Copy link
Owner

I wonder if it's possible to get the span of the union keyword for the error here.

@TedDriggs
Copy link
Owner

Finally getting around to implementing this; it turns out that leaving the span information off completely produces the most helpful error; it's pretty clear where the union is, but it's less clear which macro is objecting to the presence of a union. Otherwise, this is very straightforward.

TedDriggs added a commit that referenced this issue Feb 16, 2021
TedDriggs added a commit that referenced this issue Feb 16, 2021
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

Successfully merging a pull request may close this issue.

2 participants