I'm trying to deserialize a generic type T
in a function without requiring that T: DeserializeOwned
, but just that T: Deserialize
, i.e. I would like to permit it to borrow from the input. However I don't see a way to make this work. Consider this code:
use std::fmt;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct Foo<T> {
#[allow(dead_code)]
bar: T,
}
fn main() {
deserialize_and_print();
deserialize_generic_and_print::<Foo<&str>>();
}
fn deserialize_and_print() {
let s = r#"{ bar: "baz" }"#.to_string();
let foo: Foo<&str> = serde_json::from_str(&s).unwrap();
println!("{foo:?}");
}
fn deserialize_generic_and_print<T: fmt::Debug + Deserialize>() {
let s = r#"{ bar: "baz" }"#.to_string();
let foo: Foo<T> = serde_json::from_str(&s).unwrap();
println!("{foo:?}");
}
The non-generic function deserialize_and_print
works perfectly fine, but this code does not compile because the Deserialize
bound in deserialize_generic_and_print
is missing a lifetime.
But how can I fill out this lifetime? I don't want the caller to choose a lifetime and it certainly can't just be any lifetime. The way I think about it, I want to specify the lifetime of a local variable of the function, i.e. the lifetime of s
. But I'm not aware of any way to do that. Conceptually I want to write this basically:
// Note the lack of a generic lifetime parameter.
fn deserialize_generic_and_print<T: fmt::Debug + Deserialize<'s>>() {
's: {
let s = r#"{ bar: "qux" }"#.to_string();
let foo: Foo<T> = serde_json::from_str(&s).unwrap();
println!("{foo:?}");
}
}
If I try to just fill in a generic lifetime like this...
fn deserialize_generic_and_print<'s, T: fmt::Debug + Deserialize<'s>>() {
let s = r#"{ bar: "qux" }"#.to_string();
let foo: Foo<T> = serde_json::from_str(&s).unwrap();
println!("{foo:?}");
}
I get borrowed value does not live long enough
and s dropped here [at the end of the function] while still borrowed
, because the caller could in principle choose a lifetime that is longer than the lifetime of s
- but is there no way to restrict the caller to not allow any lifetime longer than a local variable of the function?
I'd like to know whether I am running up against some kind of misunderstanding or fundamental limitation of the borrow checker, or whether the issue is a lack of a way to specify that "local variable lifetime".