Search code examples
rustserde

requires that `'de` must outlive `'a`


I am stuck trying to implement deserialize and serialize traits for a struct. I just keep going down the route the compiler tells me to and getting stuck.

I start out with this struct:

#[derive(Serialize, Deserialize)]
struct FileMetadata {
  file_path: PathBuf,
  last_updated: SystemTime,
  mime_type: MediaType,
}

And get the following error: expected named lifetime parameter, help: consider introducing a named lifetime parameter.

So I do that:

#[derive(Serialize, Deserialize)]
struct FileMetadata<'a> {
  file_path: PathBuf,
  last_updated: SystemTime,
  mime_type: MediaType<'a>,
}

Which gives the following error: requires that 'demust outlive'a, help: consider adding the following bound: 'de: 'a.

So I do as it says:

#[derive(Serialize, Deserialize)]
struct FileMetadata<'a, 'de>
where
'de: 'a {
  file_path: PathBuf,
  last_updated: SystemTime,
  mime_type: MediaType<'a>,
}

Now I get two errors:

  1. cannot deserialize when there is a lifetime parameter called 'de
  2. unused parameter, help: consider removing 'de, referring to it in a field, or using a marker such as PhantomData.

I also tried to follow the advice of this post, but that leads down the same path.

I can solve the second error, but not the first one. I find the error very frustrating because the compiler sends me down a path and at the end gives me the error equivalent of "computer says no". What am I missing here and could someone explain me where I went wrong and how I can avoid these kinds of problems in the future.


Solution

  • This is a bug in version 0.19.15 of the mediatype crate. See https://github.com/picoHz/mediatype/pull/15.

    You can work around it like this:

    // [dependencies]
    // mediatype = "0.19"
    // serde = "1"
    // serde_derive = "1"
    
    use mediatype::MediaType;
    use serde::de::{Deserialize, Deserializer};
    use serde_derive::Deserialize;
    use std::path::PathBuf;
    use std::time::SystemTime;
    
    #[derive(Deserialize)]
    pub struct FileMetadata<'a> {
        pub file_path: PathBuf,
        pub last_updated: SystemTime,
        #[serde(borrow, deserialize_with = "mediatype_workaround")]
        pub mediatype: MediaType<'a>,
    }
    
    fn mediatype_workaround<'de: 'a, 'a, D>(deserializer: D) -> Result<MediaType<'a>, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s: &str = Deserialize::deserialize(deserializer)?;
        MediaType::parse(s).map_err(serde::de::Error::custom)
    }