I have a struct with function remove
, and I want the remove
function to return new instance if actually removed or the same reference
But I get Cannot move
when trying to return *self
Is it possible?
From the errors I don’t think so, but then how Cow
is possible.
Code:
use std::collections::HashMap;
#[derive(Clone)]
struct Something {
data: HashMap<char, u16>,
}
impl Something {
fn new() -> Self {
return Something {
data: HashMap::new()
}
}
fn get(&self, c: char) -> Option<&u16> {
return self.data.get(&c);
}
fn add(&self, c: char, value: u16) -> Self {
let mut n = self.clone();
n.data.insert(c, value);
return n;
}
fn remove(&self, c: char) -> Self {
if !self.data.contains_key(&c) {
return *self; // <-- error[E0507]: cannot move out of `*self` which is behind a shared reference
}
let mut n = self.clone();
n.data.remove(&c);
return n;
}
}
fn main() {
let s = Something::new();
let s = s.add('a', 1);
let s = s.add('b', 2);
let s = s.remove('a');
// Should return the same instance as c is missing
let s = s.remove('c');
}
but If I change the remove
function to return &Self
then I can’t return a reference to a variable declared in the function:
fn remove(&self, c: char) -> &Self {
if !self.data.contains_key(&c) {
return self;
}
let mut n = self.clone();
n.data.remove(&c);
return &n; // <--- error[E0515]: cannot return reference to local variable `n`
}
I know I can avoid borrowing something
but I don’t want to move ownership:
// <--- self and not &self
fn remove(self, c: char) -> Self {
if !self.data.contains_key(&c) {
return self;
}
let mut n = self.clone();
n.data.remove(&c);
return n;
}
Because then the following will fail:
fn main() {
let s = Something::new();
let s = s.add('a', 1);
let s = s.add('b', 2);
let s1 = s.remove('a');
let s2 = s.remove('a'); // <-- error[E0382]: use of moved value: `s`
}