Skip to content

Instantly share code, notes, and snippets.

@muhamadazmy
Last active March 5, 2019 09:37
Show Gist options
  • Save muhamadazmy/55c7f662f589eec21f93990fecc921a9 to your computer and use it in GitHub Desktop.
Save muhamadazmy/55c7f662f589eec21f93990fecc921a9 to your computer and use it in GitHub Desktop.
No idea why this doesn't build
struct Cache {}
impl Cache {
fn new() -> Cache {
Cache {}
}
fn get(&mut self, key: &u32) -> Option<&str> {
None
}
fn put(&mut self, key: u32, value: String) {}
}
struct Data {
cache: Cache,
}
impl Data {
fn new() -> Data {
Data { cache: Cache {} }
}
fn get(&mut self, k: u32) -> &str {
if let Some(v) = self.cache.get(&k) {
return v;
}
let s = String::from("cached");
self.cache.put(k, s);
self.cache.get(&k).unwrap()
}
}
fn main() {
let mut data = Data::new();
data.get(100);
}
/*
## cargo build output
Compiling functions v0.1.0 (/home/azmy/Projects/functions)
error[E0499]: cannot borrow `self.cache` as mutable more than once at a time
--> src/main.rs:31:9
|
24 | fn get(&mut self, k: u32) -> &str {
| - let's call the lifetime of this reference `'1`
25 | if let Some(v) = self.cache.get(&k) {
| ---------- first mutable borrow occurs here
26 | return v;
| - returning this value requires that `self.cache` is borrowed for `'1`
...
31 | self.cache.put(k, s);
| ^^^^^^^^^^ second mutable borrow occurs here
error[E0499]: cannot borrow `self.cache` as mutable more than once at a time
--> src/main.rs:32:9
|
24 | fn get(&mut self, k: u32) -> &str {
| - let's call the lifetime of this reference `'1`
25 | if let Some(v) = self.cache.get(&k) {
| ---------- first mutable borrow occurs here
26 | return v;
| - returning this value requires that `self.cache` is borrowed for `'1`
...
32 | self.cache.get(&k).unwrap()
| ^^^^^^^^^^ second mutable borrow occurs here
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0499`.
error: Could not compile `functions`.
To learn more, run the command again with --verbose.
*/
@yaymukund
Copy link

yaymukund commented Mar 5, 2019

The if let is obscuring the problem. I think this is what's going on?:

fn get(&mut self, k: u32) -> &str {
  let maybe_thing = self.cache.get(&k);
  
  if let Some(v) = maybe_thing {
    return v;
  }

  let s = String::from("cached");

  // oh no! maybe_thing still has ownership!
  self.cache.put(k, s);
  self.cache.get(&k).unwrap()
}

@muhamadazmy
Copy link
Author

Weirdly enough, this also doesn't work

impl Data {

    fn create(&mut self, k: u32) -> &str {
        let s = String::from("cached");

        self.cache.put(k, s);
        self.cache.get(&k).unwrap()
    }

    fn get(&mut self, k: u32) -> &str {
        if let Some(v) = self.cache.get(&k) {
            return v;
        }

        self.create(k)
    }
}

With this error

error[E0499]: cannot borrow `*self` as mutable more than once at a time
  --> src/main.rs:36:9
   |
31 |     fn get(&mut self, k: u32) -> &str {
   |            - let's call the lifetime of this reference `'1`
32 |         if let Some(v) = self.cache.get(&k) {
   |                          ---------- first mutable borrow occurs here
33 |             return v;
   |                    - returning this value requires that `self.cache` is borrowed for `'1`
...
36 |         self.create(k)
   |         ^^^^ second mutable borrow occurs here

error: aborting due to previous error

For more information about this error, try `rustc --explain E0499`.
error: Could not compile `functions`.

To learn more, run the command again with --verbose.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment