Hello,
recently I encountered this example
#[test]
fn foo() {
let s = "abcd".to_string();
let mut it: Chars = s.chars();
let r_it: &mut Chars = &mut it;
let mut peek: Peekable<&mut Chars> = r_it.peekable();
assert_eq!(peek.next(), Some('a'));
assert_eq!(r_it.next(), Some('b'));
assert_eq!(it.next(), Some('c'));
}
and I wonder why is it possible? Typically I would assume that only one mutable reference can exist.
After this in analogy with an Iterator
trait I tried to implement the following that might leak a reference
trait Leakable {
fn leak(self) -> Leak<Self>
where
Self: Sized,
{
Leak::new(self)
}
fn change(&mut self);
}
#[derive(Clone)]
struct Leak<T: Leakable> {
val: T,
}
impl<T: Leakable> Leak<T> {
fn new(val: T) -> Leak<T> {
Leak { val }
}
}
impl<T: Leakable> Leakable for Leak<T> {
fn change(&mut self) {
self.val.change()
}
}
#[derive(Debug)]
struct Bar {
val: i32,
}
impl Leakable for Bar {
fn change(&mut self) {
self.val += 1;
}
}
#[test]
fn bar() {
let mut i: i32 = 5;
let mut bar: Bar = Bar { val: i };
let r_bar: &mut Bar = &mut bar;
let mut leak: Leak<Bar> = r_bar.leak();
leak.change();
assert_eq!(leak.val.val, 6);
assert_eq!(r_bar.val, 6);
assert_eq!(bar.val, 6);
}
However in contrast with the iterator the leak
in bar()
has a type of Leak<Bar>
and not Leak<&mut Bar>
as with the iterator example, where peek
has a type peek: Peekable<&mut Chars>
. And here is my second question why is the type of leak
different from the type of peek
?
Accordingly as I would expect due to the type Leak<Bar>
the code fails to compile with the error
error[E0507]: cannot move out of `*r_bar` which is behind a mutable reference
--> test.rs:590:35
|
590 | let mut leak: Leak<Bar> = r_bar.leak();
| ^^^^^^^^^^^^ move occurs because `*r_bar` has type `Bar`, which does not implement the `Copy` trait
Can anybody explain me what is happening here.
Thanks.