Json: from_str fine; from_reader expected bound lifetime parameter but found concrete

Created on 2 Jun 2017  路  2Comments  路  Source: serde-rs/json

This works fine:

#[macro_use]
extern crate serde_derive;
extern crate serde_json;
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;

#[derive(Debug, Deserialize)]
struct Foo<'a> {
    #[serde(borrow)]
    bar: &'a str,
}

fn main() {
    let deser: Foo = serde_json::from_str("{\"bar\": \"rab\"}").unwrap();
    println!("{:?}", deser);
}

but fails to compile if main is swapped for:

fn main() {
    let mut f = File::open("contents_as_above.json")?;
    let mut reader = BufReader::new(f);

    let deser: Foo = serde_json::from_reader(reader).unwrap();
    println!("{:?}", deser);
}

The error message is:

error[E0279]: the requirement for<'de> 'de : is not satisfied (expected bound lifetime parameter 'de, found concrete lifetime)
--> examples/one.rs:22:22
|
22 | let deser: Foo = serde_json::from_reader(reader).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: required because of the requirements on the impl of for<'de> _IMPL_DESERIALIZE_FOR_Foo::_serde::Deserialize<'de> for Foo<'_>
= note: required because of the requirements on the impl of _IMPL_DESERIALIZE_FOR_Foo::_serde::de::DeserializeOwned for Foo<'_>
= note: required by serde_json::from_reader

where the red underlining (^^^) should be under serde_json::from_reader, stopping short of its argument.

Incidentally, E0279 is not yet in the error index, and I'm not sure I understand it fully (e.g. isn't for<'de> 'de : syntactically incorrect; the second 'de should be a type?) - so apologies if this is just due to my misuse.

support

Most helpful comment

Check out https://serde.rs/lifetimes.html where it explains what the two different possible Deserialize trait bounds mean. In serde_json, from_str and from_reader require different bounds.

fn from_str<'a, T>(s: &'a str) -> Result<T>
    where T: Deserialize<'a>;

fn from_reader<R, T>(reader: R) -> Result<T>
    where R: Read,
          T: DeserializeOwned; // equivalent to T: for<'de> Deserialize<'de>

As explained on the site, the bound on from_str means that T can be deserialized from data of lifetime 'a, while the bound on from_reader means that T can be deserialized from data of any (even arbitrarily short) lifetime. The reason is data from a reader is not kept in memory so there is nothing to borrow from.

Your options are to change Foo to be able to deserialize from any lifetime (by not borrowing) or to memory-map the input file using memmap and use from_slice to deserialize from the resulting in-memory slice of the file.

Remember to thank Rust for catching this bug! The borrow checker saved you from successfully deserializing a Foo containing garbage data.

All 2 comments

Check out https://serde.rs/lifetimes.html where it explains what the two different possible Deserialize trait bounds mean. In serde_json, from_str and from_reader require different bounds.

fn from_str<'a, T>(s: &'a str) -> Result<T>
    where T: Deserialize<'a>;

fn from_reader<R, T>(reader: R) -> Result<T>
    where R: Read,
          T: DeserializeOwned; // equivalent to T: for<'de> Deserialize<'de>

As explained on the site, the bound on from_str means that T can be deserialized from data of lifetime 'a, while the bound on from_reader means that T can be deserialized from data of any (even arbitrarily short) lifetime. The reason is data from a reader is not kept in memory so there is nothing to borrow from.

Your options are to change Foo to be able to deserialize from any lifetime (by not borrowing) or to memory-map the input file using memmap and use from_slice to deserialize from the resulting in-memory slice of the file.

Remember to thank Rust for catching this bug! The borrow checker saved you from successfully deserializing a Foo containing garbage data.

I understand now, thank you for your help!

Remember to thank Rust for catching this bug! The borrow checker saved you from successfully deserializing a Foo containing garbage data.

:green_heart: Rust

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mnacamura picture mnacamura  路  6Comments

AerialX picture AerialX  路  5Comments

elliottslaughter picture elliottslaughter  路  5Comments

allan-simon picture allan-simon  路  6Comments

mfarrugi picture mfarrugi  路  4Comments