Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lifetime issue with From<&V> trait constraint

Tags:

rust

lifetime

The following code produces the lifetime errors below despite the fact that the V instance in question is owned.

use std::collections::hash_map::HashMap;
use std::cmp::Eq;
use std::hash::Hash;

trait Set<V> {
    fn set(&mut self, value: V) -> Option<V>;
}

impl<'a, K: Eq + Hash + From<&'a V>, V: 'a> Set<V> for HashMap<K, V> {
    fn set(&mut self, v: V) -> Option<V> {
        let k = K::from(&v);
        self.insert(k, v)
    }
}

The resulting errors ...

   |
9  | impl<'a, K: Eq + Hash + From<&'a V>, V: 'a> Set<V> for HashMap<K, V> {
   |      -- lifetime `'a` defined here
10 |     fn set(&mut self, v: V) -> Option<V> {
11 |         let k = K::from(&v);
   |                 --------^^-
   |                 |       |
   |                 |       borrowed value does not live long enough
   |                 argument requires that `v` is borrowed for `'a`
12 |         self.insert(k, v)
13 |     }
   |     - `v` dropped here while still borrowed

error[E0505]: cannot move out of `v` because it is borrowed
  --> src/lib.rs:12:24
   |
9  | impl<'a, K: Eq + Hash + From<&'a V>, V: 'a> Set<V> for HashMap<K, V> {
   |      -- lifetime `'a` defined here
10 |     fn set(&mut self, v: V) -> Option<V> {
11 |         let k = K::from(&v);
   |                 -----------
   |                 |       |
   |                 |       borrow of `v` occurs here
   |                 argument requires that `v` is borrowed for `'a`
12 |         self.insert(k, v)
   |                        ^ move out of `v` occurs here
like image 576
George Avatar asked Dec 23 '21 07:12

George


People also ask

Why is the option to continue with errors hidden in lifetime?

Fixed an issue causing the option "Continue with errors" to be hidden when staging applications using the LifeTime console. This issue occurred only in Cloud environments. (RPM-1558) The Installation Checklist for LifeTime 11.10.4 incorrectly states that the product requires ".NET Core 2.1 Runtime & Hosting Bundle for Windows".

What's new in lifetime?

You can now request database users in LifeTime to improve troubleshooting and manipulate data. These users are temporary and nominal, ensuring that only legitimate users can carry on with this privileged access to data. (RCVT-909) Fixed an issue causing the date filters on the Deployment Plans page to be displayed incorrectly.

Why is lifetime analytics not working in lifetime management console?

This issue was found in LifeTime Management Console - 11.7.3 (Build 778). (RLIT-4177) Wrong environment setting may prevent LifeTime Analytics to retrieve analytics data from that environment.

What is the rpd-3676 error in lifetime?

(RPD-3676) Fixed an issue that caused some errors, related to REST calls in the LifeTime environment, to be created in the Error Log without an error message. (RPD-4826) Fixed an issue that caused a deployment to become stuck in some specific situations.


Video Answer


1 Answers

Use a higher-rank trait bound denoted by for<'a>:

impl<K: Eq + Hash + for<'a> From<&'a V>, V> Set<V> for HashMap<K, V> {
    fn set(&mut self, v: V) -> Option<V> {
        self.insert(K::from(&v), v)
    }
}

See it working on the playground.

As a normal generic parameter, the lifetime 'a is determined by the caller, which would outlive the set() call itself. However, the life of v is only local to the function body, meaning any lifetime 'a used to call K::from() can outlive the content that may be contained in V. Just because v is an owned value doesn't mean it doesn't have lifetimes associated with it, it is generic after all. The compiler is doing its best, but its suggestion is not what you want.

Using a for<'a> From<&'a V> constraint means that the K::from() call will work for any lifetime, including the short function-local lifetime of v.

like image 131
kmdreko Avatar answered Dec 03 '22 14:12

kmdreko