Need some help of E495

Hi guys, I have a special requirement of giving out &'a mut T. The code is below, and I get the error E495. What I am thinking is:

isn't &'a mut i32 which come from self.table.get_mut(k) should binding the lifetime with the &'a mut HashMap<i32, i32> instead of &mut self?

How can I make it happen? Like, send out the &'a mut i32, ignore &mut self and fix the E495?

/// update to whole version below

Update on 8/12/2021:

This is full version of my code:

use std::collections::HashMap;

struct HashMapWrap {
    table: HashMap<i32, i32>,
}

impl<'a> HashMapWrap {
    fn get_mut(&mut self, k: &i32) -> Option<&mut i32> {
        self.table.get_mut(k)
    }
}

struct HashMapWrapIterMut<'a> {
    temp_k: i32,
    data: &'a mut HashMapWrap,
}

impl<'a> Iterator for HashMapWrapIterMut<'a> {
    type Item = LeakResult<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        Some(LeakResult {
            v: self.data.get_mut(&self.temp_k).unwrap(),
        })
    }
}

struct LeakResult<'a> {
    v: &'a mut i32,
}

I want to hold a &'a mut i32, come from HashMapWrap inside LeakResult as the Item of Iterator. How can I do it?

Thanks guys.

note that 'b: 'a reads "'b outlives 'a"; which I think is the opposite of what you're attempting.

Unfortunately, I don't think what you are attempting is sound - if it worked, client code could call leak_out twice with the same parameter and get two mutual references to the same value. The compiler is preventing that.

Perhaps you can provide more context for what you are trying to accomplish?

1 Like

Yes, you are right. I delete that post. Let me clean my mind and give more context/detail about what I want to do. Thank you.

Doing:

impl<'a> HashMapWrap<'a> {
-    fn leak_out(&mut self, k: &i32) -> Option<&'a mut i32> {
+    fn leak_out(&mut self, k: &i32) -> Option<&mut i32> {
        self.table.get_mut(k)

seems to work. I don't know your exact use case, but the following one works with this change:

fn main() {
    let mut map = HashMap::new();
    map.insert(2, 32);
    
    let mut wrap = HashMapWrap { table: &mut map };
    let leak = wrap.leak_out(&2).unwrap();
    
    let leakresult = LeakResult { v: leak };
}

Playground link


It seems like you're trying to write out the explicit lifetimes instead of using the elided lifetimes. In that case, the equivalent of

impl<'a> HashMapWrap<'a> {
    fn leak_out(&mut self, k: &i32) -> Option<&mut i32> { 

would be

impl<'a> HashMapWrap<'a> {
    // This is the same function as the above leak_out function,
    // just with more explicit lifetimes.
    fn leak_out<'f>(&'f mut self, k: &i32) -> Option<&'f mut i32> {

You want the mutable borrow of self to last as long as the mutable borrow, &'f mut i32, is still active/live.

1 Like

Hi, I just update the whole version of my demo code. If you are still interested, that's what I am trying to implement now. Mostly Iterator trait

Thanks for your reply. Sorry about the confuse of my demo code. I just update my demo code, it is truly I want to implement. Implement Iterator trait stuck me.

I can use unsafe block to implement this feature, but do we have safe methods to do the same thing?

impl<'a> Iterator for HashMapWrapIterMut<'a> {

     fn next(&mut self) -> Option<Self::Item> {
         Some(LeakResult {
-            v: self.data.get_mut(&self.temp_k).unwrap(),
+            v: unsafe {
+                (self.data.get_mut(&self.temp_k).unwrap() as *mut i32)
+                    .as_mut()
+                    .unwrap()
+            },
         })
     }
 }

Your unsafe code is incorrect because it lets the caller get two mutable references to the same item. You can do this:

struct HashMapWrapIterMut<'a> {
    temp_k: i32,
    data: Option<&'a mut HashMapWrap>,
}

impl<'a> Iterator for HashMapWrapIterMut<'a> {
    type Item = LeakResult<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        match self.data.take() {
            Some(data) => Some(LeakResult {
                v: data.get_mut(&self.temp_k).unwrap(),
            }),
            None => None,
        }
    }
}

playground

1 Like

Brilliant! Thanks, never thought about can use Option::take in this case.

Also, if you don't mind I ask, could you give more details about caller get two mutable references to the same item? I don't use unsafe often, just curious about how does it happen. Thank you

Sure. Mutable references are guaranteed to have exclusive access to the thing they point to. Check out Rust: A unique perspective for more info.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.