I'm trying to make a type that wraps &mut u8
in a struct, in order to impose some additional invariants. In doing that, I realize I'm not able to make my struct follow the same borrow-checking rules as &mut
does. Playground link: Rust Playground.
Here's the issue. When I have a &mut u8
, I can pass it multiple times to a function:
fn f(r: &mut u8) {
*r = 1;
}
fn g(r: &mut u8) {
f(r);
f(r);
}
However, when I wrap my &mut u8
in a struct and try to do the same thing, I get a type error:
struct S<'a>(&'a mut u8);
fn f2(r: S) {
*r.0 = 1;
}
fn g2(r: S) {
f2(r);
f2(r); // FAILS
}
with error:
error[E0382]: use of moved value: `r`
--> src/lib.rs:18:8
|
16 | fn g2(r: S) {
| - move occurs because `r` has type `S<'_>`, which does not implement the `Copy` trait
17 | f2(r);
| - value moved here
18 | f2(r);
| ^ value used here after move
The type error on S
makes sense to me: I don't implement Clone on S
, so I can't use it after it is moved. My questions:
- How is
&mut
able to work around this issue? It doesn't implementClone
, but it can be used multiple times. - Is it possible to provide the same typechecking rules to my own structs? My fear is that
&mut
is imbued with some special rules that user-defined types have no access to.