pub fn parse_from_file(file_path: impl Into<PathBuf>) -> Params {
let file = File::open(file_path.into()).unwrap();
let reader = BufReader::new(file);
let params: Params = serde_json::from_reader(reader).unwrap();
params
}
but got
--> src/params.rs:74:30
|
74 | let params: Params = serde_json::from_reader(reader).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough
|
= note: `Params` must implement `Deserialize<'0>`, for any lifetime `'0`...
= note: ...but it actually implements `Deserialize<'static>`
In general, it is not possible to deserialize into a &'static str.
If you have a &'static str to be parsed to begin with, and the serialization format doesn't use escaping, then it might be possible. But if you are trying to deserialize from a reader, then it's simply not possible (the underlying value has to be stored somewhere).
Speaking as someone who's recently gained a lot of experience with Box::leak() (it does have valid use cases):
You could do that, and then you'd have yourself a fine memory leak that's next to impossible to fix.
In this case the better option is to change the Params type — i.e. the one that contains the &'static str field — or, if that's not possible, to create a fit-for-purpose set of types to which you can easily deserialize, starting with ParamsOwned which has the same fields as Params except that instead of &'static str fields it has String fields.
Use Cow<'static, str> instead of &'static str if you really need to assign &'static str to it sometime. Decoding will use String, which it can properly free. Using heap-allocated and leaked string does not give you any performance advantage over using heap-allocated and not leaked String.
&'static str makes sense only for predefined strings hardcoded into the program. But if your field can have only one of predefined strings, then don't even bother with str, and use an enum instead. This is easy to deserialize (serde will match enum fields by name) and efficient to store.
The derive macro detects fields with the shape &'a str and automatically borrows. The resulting trait implementation will them be Deserialize<'de> where 'de: 'a or in the special case of 'static it is Deserialize<'static>.
This makes it incompatible with DeserializeOwned as used by from_reader.
You can trick the derive macro by hiding the fact that you have a &'static str.
Alternatively, create the Deserializer with serde_json::Deserializer::from_reader and call Params::deserialize(deserializer) instead of using from_reader.
That's not really a solution, though, and there's no good reason for using it. You should just follow @kornel's suggestion. Your approach based on leaking is not better than any alternative (it's worse than the Cow in that it leaks memory and abuses the type system by trying to shove owned data in a borrow-shaped hole, in particular).