10

I tried to derive serde::Deserialize for a struct containing a reference to a Path. This yielded an error message which doesn't occur if you replace &'a Path with &'a str. What causes the different behaviours of #[derive(Deserialize)]?

Playground

#!/bin/cargo script //! ```cargo //! [dependencies] //! serde_derive="1.0" //! serde="1.0" //! ``` extern crate serde_derive; use serde_derive::*; #[derive(Deserialize)] struct A<'a> { a: &'a std::path::Path, //a: &'a str, } fn main() {} 
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'de` due to conflicting requirements --> src/main.rs:7:5 | 7 | a: &'a std::path::Path, | ^ | note: first, the lifetime cannot outlive the lifetime 'de as defined on the impl at 5:10... --> src/main.rs:5:10 | 5 | #[derive(Deserialize)] | ^^^^^^^^^^^ = note: ...so that the types are compatible: expected _IMPL_DESERIALIZE_FOR_A::_serde::de::SeqAccess<'_> found _IMPL_DESERIALIZE_FOR_A::_serde::de::SeqAccess<'de> note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 6:10... --> src/main.rs:6:10 | 6 | struct A<'a> { | ^^ = note: ...so that the types are compatible: expected _IMPL_DESERIALIZE_FOR_A::_serde::Deserialize<'_> found _IMPL_DESERIALIZE_FOR_A::_serde::Deserialize<'_> error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'de` due to conflicting requirements --> src/main.rs:7:5 | 7 | a: &'a std::path::Path, | ^ | note: first, the lifetime cannot outlive the lifetime 'de as defined on the impl at 5:10... --> src/main.rs:5:10 | 5 | #[derive(Deserialize)] | ^^^^^^^^^^^ = note: ...so that the types are compatible: expected _IMPL_DESERIALIZE_FOR_A::_serde::de::MapAccess<'_> found _IMPL_DESERIALIZE_FOR_A::_serde::de::MapAccess<'de> note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 6:10... --> src/main.rs:6:10 | 6 | struct A<'a> { | ^^ = note: ...so that the types are compatible: expected _IMPL_DESERIALIZE_FOR_A::_serde::Deserialize<'_> found _IMPL_DESERIALIZE_FOR_A::_serde::Deserialize<'_> 

Strangely enough, the code compiles if the struct contains both fields _a: &'a Path and _b: &'a str... At this point I think this is a bug.

4
  • Use a: PathBuf Commented May 31, 2019 at 11:54
  • @FrenchBoiethios thanks for the recommendation, but I can afford to be stubborn on this one :) Commented May 31, 2019 at 11:59
  • 1
    Hm, I looked at the impls of Deserialize for &'a str and &'a Path and everything looks the same for both cases except for a type conversion via AsRef, but that's in the body of PathVisitor and that should long be typechecked when this error occurs. It looks like it might even be a bug in the lifetime inference. Commented May 31, 2019 at 12:25
  • @JanHudec thanks for investigating this. I filed a bug report, just in case. A faulty lifetime inference engine does sound nasty, so I hope it's not that ^^ Commented May 31, 2019 at 13:00

1 Answer 1

12

Add an attribute to the field: #[serde(borrow)]. That will indicate to serde that it should be borrowing the value. You must provide this attribute for every borrow except for &str and &[u8].

Source: https://serde.rs/lifetimes.html#borrowing-data-in-a-derived-impl

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.