Question on `from_str` complains about lifetime when coping with generics
BobAnkh opened this issue · 2 comments
I would like to read from file/string in a struct with generic, however I face the lifetime error.
The minimal reproduce code:
use ron;
use serde::{Deserialize, Serialize};
pub struct BarBuilder {
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Bar<T: Default> {
bar: T,
}
impl BarBuilder {
pub fn build<'de, T: Default + serde::de::Deserialize<'de>>(
self,
) -> Bar<T>{
let content = "Bar { bar: 1 }".to_string();
let bar = ron::de::from_str(&content).unwrap();
Bar { bar }
}
}
fn main() {
println!("Hello, world!");
}
The error msg:
$ cargo check
error[E0597]: `content` does not live long enough
--> src\main.rs:16:37
|
12 | pub fn build<'de, T: Default + serde::de::Deserialize<'de>>(
| --- lifetime `'de` defined here
...
16 | let bar = ron::de::from_str(&content).unwrap();
| ------------------^^^^^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `content` is borrowed for `'de`
17 | Bar { bar }
18 | }
| - `content` dropped here while still borrowed
For more information about this error, try `rustc --explain E0597`.
error: could not compile `demo` due to previous error
My dependencies in Cargo.toml:
[dependencies]
ron = "0.8"
serde = { version = "1.0", features = ["derive"] }
The same error occurs the same with from_reader
.
I wonder why this piece of code is not working in ron
while there is some way to bypass in toml
:
pub struct BarBuilder {
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Bar<T: Default> {
bar: T,
}
impl BarBuilder {
pub fn build<'de, T: Default + serde::de::Deserialize<'de> + Clone>(
self,
) -> Bar<T>{
let content = "bar = 1".to_string();
let configs: toml::value::Table = match toml::from_str(&content) {
Ok(t) => t,
Err(e) => {
panic!("Error: {}", e);
}
};
let configs: HashMap<String, T> = configs
.iter()
.map(|(k, v)| (k.to_owned(), v.to_owned().try_into().unwrap()))
.collect();
// let bar = toml::from_str(&content).unwrap();
Bar { bar: configs["bar"].clone() }
}
}
So I would like to know if there is one way for me to implement reading from ron within a genereic struct? Thank you!
I think the problem here is that while you define T: Deserialize<'de>
, the &str
you deserialise from has a different, shorter lifetime. You could either change the bound to T: DeserializeOwned
, or if T
might borrow data from the content string, pass content: &'de str
to the build
method itself.
The toml
version seems to work because you first deserialise into their Value
type and then clone that, erasing the lifetime requirement.
I hope this helps :)
@MomoLangenstein Really thank you for your suggestion! Switching to T: DeserializedOwned
works.