Reputation: 15799
How do I tell the compiler that one lifetime must outlive another?
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
pub struct Tokens<'a> {
buffer: String,
list: Vec<Token<'a>>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Token<'a> {
term: &'a str,
}
yields
error: lifetime may not live long enough
--> src/pipeline/tokenizers/test.rs:6:5
|
3 | #[derive(Serialize, Deserialize, Debug)]
| ----------- lifetime `'de` defined here
4 | pub struct Tokens<'a> {
| -- lifetime `'a` defined here
5 | buffer: String,
6 | list: Vec<Token<'a>>,
| ^^^^ requires that `'de` must outlive `'a`
|
= help: consider adding the following bound: `'de: 'a`
In the code above, the token.term: &str will always refer to a slice of tokens.buffer. I'm not sure how to specify that relationship. I'm also not sure how to add the requested bound.
Will this even work? If so, what's the magic syntax?
Upvotes: 3
Views: 243
Reputation: 58785
You can use the attribute, #[serde(borrow)]
, which makes the generated Deserialize
implementation borrow the data.
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
pub struct Tokens<'a> {
buffer: String,
#[serde(borrow)]
list: Vec<Token<'a>>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Token<'a> {
term: &'a str,
}
See:
Upvotes: 4
Reputation: 70297
You can't add constraints to a derive
implementation. You could write the entire Deserialize
implementation yourself and put the constraint in the usual place. But fortunately, serde
thought of this use case. If you indicate to serde
that the data should be borrowed from the deserializer, it will put the constraint in for you.
#[derive(Serialize, Deserialize, Debug)]
pub struct Tokens<'a> {
buffer: String,
#[serde(borrow)]
list: Vec<Token<'a>>,
}
Upvotes: 4