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

"undeclared lifetime" when derive Deserialize for an enum with both flatten and 'static fields #2371

Closed
Mingun opened this issue Feb 5, 2023 · 4 comments · Fixed by #2383

Comments

@Mingun
Copy link
Contributor

Mingun commented Feb 5, 2023

The following code panics with the error:

use serde::Deserialize;

#[derive(Deserialize)]
struct Nested {
    float: f64,
}

#[derive(Deserialize)]
#[serde(tag = "tag")]
enum InternallyTagged {
    Flatten {
        #[serde(flatten)]
        nested: Nested,
        string: &'static str,
    },
}

Commenting out any of fields lead to successful compilation.

Output:

Compiling playground v0.0.1 (/playground)
error[E0261]: use of undeclared lifetime name `'de`
 --> src/lib.rs:8:10
  |
8 | #[derive(Deserialize)]
  |          ^^^^^^^^^^^
  |          |
  |          undeclared lifetime
  |          lifetime `'de` is missing in item created through this procedural macro
  |
  = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
  = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider making the bound lifetime-generic with a new `'de` lifetime
  |
8 | #[derive(for<'de> Deserialize)]
  |          ++++++++
help: consider making the bound lifetime-generic with a new `'de` lifetime
  |
8 | #[derive(for<'de> Deserialize)]
  |          ++++++++
help: consider introducing lifetime `'de` here
  |
8 | #[derive(Deserialize<'de>)]
  |                     +++++

For more information about this error, try `rustc --explain E0261`.
error: could not compile `playground` due to previous error

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=b3e592812a43c300e2d247c9ac0b0033

@Teajey
Copy link

Teajey commented Feb 18, 2023

Since &'static str usually represents a string embedded in the binary of your program I don't think it's possible to or even makes sense to Deserialize one? Surely what you want to do is this:

#[derive(Deserialize)]
#[serde(tag = "tag")]
enum InternallyTagged<'a> {
    Flatten {
        #[serde(flatten)]
        nested: Nested,
        string: &'a str,
    },
}

@Mingun
Copy link
Contributor Author

Mingun commented Feb 19, 2023

Of course, this will not work, but serde in that case usually returns an error from Deserialize::deserialize phase instead of incorrect code generation. Moreover, as I said, if you comment nested field, this code is compiled.

So I think it should either:

  • always generate compiler error when you try to implement Deserialize with 'static fields
  • or never generate such an error

@Mingun
Copy link
Contributor Author

Mingun commented Feb 25, 2023

Of course, this will not work

Actually, I'm not right here. Of course, this will work if you try to deserialize a static string into a type (i.e. you just create a read-only struct around read-only string embedded in binary). This will not work if you try to deserialize heap-allocated string.

@Mingun
Copy link
Contributor Author

Mingun commented Feb 25, 2023

The problem in the DeserializeSeed implementation for the visitor for the deserialized type. The derive generates the following code:

impl DeserializeSeed<'static> for Visitor {
    type Value = InternallyTagged;

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,// <-- Error here
    {
        deserializer.deserialize_map(self)
    }
}

The cleaned generated code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=6c5e32bd6cef06756b0806be7447f827

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