[Solved] Why this triggers E0502

I think the immutable borrow drops at line 17, but it doesn't. Why? Thanks!

pub trait SomeTrait<'a, K> where K: 'a
{
  fn get_key(&'a self) -> K;
}

pub fn some_func<'a, K, T>(
  items: &'a mut Vec<T>
) 
where 
  T: SomeTrait<'a, K>,
  K: 'a
{
  {
    for item in items.iter() {
      let key = item.get_key(); // immutable borrow occurs here
      drop(key) // borrow dropped here
    }
  };

  items.clear(); // cannot borrow `*items` as mutable because it is also borrowed as immutable
}
fn get_key(&'a self) -> K;

This comes up from time to time on this forum - you almost never want to borrow self for the lifetime parameter of the type itself. This causes a borrow that essentially freezes the object when mutable borrows are in play. Drop the 'a from the get_key signature.

2 Likes

Thanks!
But I still don't know how to implement this trait properly:

struct SomeStruct {
    key: String
}

impl<'a> SomeTrait<'a, &'a str> for SomeStruct {
    fn get_key(&self) -> &'a str {
        self.key.as_ref()
    }
}

Gives me

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
  --> src/main.rs:29:18
   |
29 |         self.key.as_ref()
   |                  ^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 28:5...
  --> src/main.rs:28:5
   |
28 | /     fn get_key(&self) -> &'a str {
29 | |         self.key.as_ref()
30 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:29:9
   |
29 |         self.key.as_ref()
   |         ^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 27:1...
  --> src/main.rs:27:1
   |
27 | / impl<'a> SomeTrait<'a, &'a str> for SomeStruct {
28 | |     fn get_key(&self) -> &'a str {
29 | |         self.key.as_ref()
30 | |     }
31 | | }
   | |_^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:29:9
   |
29 |         self.key.as_ref()
   |         ^^^^^^^^^^^^^^^^^

Is this a trait you've defined? Are you sure you're not looking for something like this instead:

pub trait SomeTrait {
    type Key: ?Sized;

    fn get_key(&self) -> &Self::Key;
}

pub fn some_func<K, T>(items: &mut Vec<T>)
where
    T: SomeTrait<Key = K>,
{
    for item in items.iter() {
        let key = item.get_key();
    }

    items.clear();
}

struct SomeStruct {
    key: String,
}

impl SomeTrait for SomeStruct {
    type Key = str;
    fn get_key(&self) -> &Self::Key {
        &self.key
    }
}
1 Like

You are right. Thank you very much. :smiley: