Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to express lifetime bounds in Rust when using references in trait methods

Here is a code snippet illustrating a lifetimes issue I ran into:

use std::collections::HashSet;

pub trait Store {
    fn put<'a, 'b: 'a>(&mut self, val: &'b str);
}


struct Hstore<'a> {
    hset: HashSet<&'a str>,
}

impl<'a> Store for Hstore<'a> {
    fn put<'b, 'c: 'b>(&mut self, val: &'c str) {
        self.hset.insert(val);
    }
}

My intention is to store referenced values passed by the trait in the struct as long as their lifetimes outlives that of the struct.

A get a compilation error:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

error: lifetime may not live long enough
  --> src/lib.rs:14:9
   |
12 | impl<'a> Store for Hstore<'a> {
   |      -- lifetime `'a` defined here
13 |     fn put<'b, 'c: 'b>(&mut self, val: &'c str) {
   |                -- lifetime `'c` defined here
14 |         self.hset.insert(val);
   |         ^^^^^^^^^^^^^^^^^^^^^ argument requires that `'c` must outlive `'a`
   |
   = help: consider adding the following bound: `'c: 'a`

How do I add this 'c: 'a bound? I tried several approaches which did not work.

Also why can’t the compile infer the life 'b in the implementation has the same lifetime validity as 'a.

>Solution :

You can make your trait generic over the lifetime.

pub trait Store<'a> {
    fn put(&mut self, val: &'a str);
}

Then you can easily implement it.

impl<'a> Store<'a> for Hstore<'a> {
    fn put(&mut self, val: &'a str) {
        self.hset.insert(val);
    }
}

This isn’t very common, but should work fine. The standard library trait Pattern is very similar, since it also has a method that incorporates a string slice into a type that escapes the function.

An alternative is to make the trait fully generic.

pub trait Store<T> {
    fn put(&mut self, val: T);
}

impl<'a> Store<&'a str> for Hstore<'a> {
    fn put(&mut self, val: &'a str) {
        self.hset.insert(val);
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading