By realli


2017-04-22 02:48:17 8 Comments

I'm using serde and serde_json 1.0 to decode data from a base64 string:

fn from_base64_str<T: Deserialize>(string: &str) -> T {
    let slice = decode_config(string, URL_SAFE).unwrap();     
    serde_json::from_slice(&slice).unwrap()
}

When I compile, I got this:

error[E0106]: missing lifetime specifier
 --> src/main.rs:6:23
  |
6 | fn from_base64_str<T: Deserialize>(string: &str) -> T {
  |                       ^^^^^^^^^^^ expected lifetime parameter

Checking the serde doc, Deserialize is defined as:

pub trait Deserialize<'de>: Sized {

So I added the lifetime:

fn from_base64_str<'de, T: Deserialize<'de>>(string: &str) -> T {
    let slice = decode_config(string, URL_SAFE).unwrap();     
    serde_json::from_slice(&slice).unwrap()
}

The compiler then told me:

error: `slice` does not live long enough
  --> src/main.rs:11:29
   |
11 |     serde_json::from_slice(&slice).unwrap()
   |                             ^^^^^ does not live long enough
12 | }
   | - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'de as defined on the body at 9:64...
  --> src/main.rs:9:65
   |
9  |   fn from_base64_str<'de, T: Deserialize<'de>>(string: &str) -> T {
   |  _________________________________________________________________^ starting here...
10 | |     let slice = decode_config(string, URL_SAFE).unwrap();
11 | |     serde_json::from_slice(&slice).unwrap()
12 | | }
   | |_^ ...ending here

I only know the very basics of lifetimes in Rust, so I'm very confused by the 'de in trait Deserialize.

How can I fix the lifetime error in such function? I'm using Rust 1.18.0-nightly (452bf0852 2017-04-19)

2 comments

@dtolnay 2017-04-22 20:38:48

This section of the Serde website covers Deserialize bounds in detail.


There are two main ways to write Deserialize trait bounds, whether on an impl block or a function or anywhere else.

  • <'de, T> where T: Deserialize<'de>

    This means "T can be deserialized from some lifetime." The caller gets to decide what lifetime that is. Typically this is used when the caller also provides the data that is being deserialized from, for example in a function like serde_json::from_str. In that case the input data must also have lifetime 'de, for example it could be &'de str.

  • <T> where T: DeserializeOwned

    This means "T can be deserialized from any lifetime." The callee gets to decide what lifetime. Usually this is because the data that is being deserialized from is going to be thrown away before the function returns, so T must not be allowed to borrow from it. For example a function that accepts base64-encoded data as input, decodes it from base64, deserializes a value of type T, then throws away the result of base64 decoding. Another common use of this bound is functions that deserialize from an IO stream, such as serde_json::from_reader.

    To say it more technically, the DeserializeOwned trait is equivalent to the higher-rank trait bound for<'de> Deserialize<'de>. The only difference is DeserializeOwned is more intuitive to read. It means T owns all the data that gets deserialized.

@realli 2017-04-22 03:36:11

I found an answer from Serde issue 891: I should use DeserializeOwned instead of Deserialize.

Related Questions

Sponsored Content

1 Answered Questions

[SOLVED] Lifetime inference problem when implementing iterator with refs

1 Answered Questions

[SOLVED] Factory method: instance does not live long enough

  • 2015-05-02 20:24:30
  • W.K.S
  • 558 View
  • 1 Score
  • 1 Answer
  • Tags:   rust

2 Answered Questions

[SOLVED] How to include module from another file from the same project?

  • 2014-10-15 17:47:50
  • ave
  • 37399 View
  • 74 Score
  • 2 Answer
  • Tags:   rust

2 Answered Questions

1 Answered Questions

[SOLVED] Taking closures with explicit lifetimes as arguments in Rust

  • 2017-03-07 12:22:31
  • SphericalCow
  • 158 View
  • 1 Score
  • 1 Answer
  • Tags:   rust lifetime

2 Answered Questions

1 Answered Questions

[SOLVED] How can I explicitly specify a lifetime when implementing a trait?

  • 2015-02-18 01:33:48
  • nogoma
  • 155 View
  • 2 Score
  • 1 Answer
  • Tags:   rust lifetime

1 Answered Questions

[SOLVED] Unable to coerce &String to &str

  • 2015-02-15 14:02:16
  • Omar Abid
  • 230 View
  • 0 Score
  • 1 Answer
  • Tags:   string rust

1 Answered Questions

[SOLVED] Correctly setting lifetimes and mutability expectations in Rust

  • 2014-10-12 19:08:13
  • troutwine
  • 69 View
  • 1 Score
  • 1 Answer
  • Tags:   rust lifetime

Sponsored Content