rs-es icon indicating copy to clipboard operation
rs-es copied to clipboard

'static lifetimes in operations

Open AlexNav73 opened this issue 8 years ago • 2 comments

Hi, in my case, i need to use &'static str for index and doc type, but lifetimes in IndexOperation in such case, disallow me pass reference to doc with non-static lifetime. What i try to say:

const ES_INDEX_NAME: &'static str = "my_index";

pub trait EsDocument: Serialize + Deserialize {
    fn entity_type() -> &'static str;
}

pub fn index<'a, 'b, T>(&'a mut self, doc: &'b T) -> &'a mut IndexOperation<'a, 'b, T> 
    where T: EsDocument
{
    self.client.index(ES_INDEX_NAME, T::entity_type()).with_doc(doc)
}

In this example, lifetime 'b == 'static, because:

fn index<'a, 'b, E: Serialize>(&'a mut self, index: &'b str, doc_type: &'b str) -> IndexOperation<'a, 'b, E>
fn with_doc(&'b mut self, doc: &'b E) -> &'b mut Self

with_doc accepts &'b E (in our case &'static E) and passing doc: &'b T for 'b != 'static breaks borrow checker rules

For now, possible solution can be using mem::transmute to avoid this lifetime rules.

AlexNav73 avatar Feb 09 '17 10:02 AlexNav73

Thanks for the notification.

Do you have a larger example that demonstrates the problem? Perhaps something I can encapsulate in a test case?

In a simple case, using something like:

const INDEX_NAME: &'static str = "my_index";

fn test() {
   let mut client = create_client();
   client.index(INDEX_NAME, "type").with_doc(&make_document()).send();
}

works as you'd expect, because the lifetime is self-contained and all the parameters exceed what's required. But in your case you're returning the IndexOperation.

I expect the solution will be the same in all cases, but it would be good to have a reproducible test or example code to verify it.

benashford avatar Feb 11 '17 15:02 benashford

Here is example of code:

extern crate rs_es;
extern crate serde;

use rs_es::Client;
use rs_es::operations::index::IndexOperation;
use serde::Serialize;

const INDEX_NAME: &'static str = "my_index";

struct Wrapper(Client);

impl Wrapper {
    fn get_index_operation<'a, 'b, T: Serialize>(&self, doc: &'b T) -> &'a mut IndexOperation<'a, 'b, T> {
        self.0.index(INDEX_NAME, "type").with_doc(doc)
    }
}

fn main() { }

How can i set lifetimes to make it compile? Now it says:

main.rs|15 col 16 error 495| cannot infer an appropriate lifetime for autoref due to conflicting requirements
||    |
|| 15 |         self.0.index(INDEX_NAME, "type").with_doc(doc)
||    |                ^^^^^

AlexNav73 avatar Feb 12 '17 14:02 AlexNav73