#Motivation
struct Foo<'r> {
i: Box<Baz>,
b: Bar<'r>,
}
struct Baz;
struct Bar<'r> {
i: &'r Baz,
}
let boxed_baz = Box::new(Baz{});
let boxed_ref: &Baz = boxed_baz.as_ref();
let f = Foo{i: boxed_baz, b: Bar{i: boxed_ref}};
Which results in:
error[E0505]: cannot move out of `boxed_baz` because it is borrowed
> src/main.rs:51:20

50  let boxed_ref: &Baz = boxed_baz.as_ref();
  borrow of `boxed_baz` occurs here
51  let f = Foo{i: boxed_baz, b: Bar{i: boxed_ref}};
 ^^^^^^^^^ move out of `boxed_baz` occurs here
A more real example would look like this
struct Device;
struct CommandBuffer {
device: &Device,
// ...
}
// Does not work because Rust does not allow internal pointers
struct Something {
device: Device,
command_buffer: CommandBuffer,
}
The workaround for this problem is to fallback to Arc
struct Device;
struct CommandBuffer {
device: Arc<Device>,
// ...
}
struct Something {
device: Arc<Device>,
command_buffer: CommandBuffer,
}
Arc imposes the following drawback
 Atomic counter
 Ignores Rust’s lifetime system
#Solution
Add a builtin trait to allow moves even with active borrows.
unsafe impl<T> BorrowMove<&T> for Box<T> {}
If Rust encounters a borrow of type &T
that is linked to a Box<T>
, it will allow the box to be moved to a equal or larger lifetime.
Rust will still refuse to move Box<T>
for every other active borrow, this includes &Box<T>
.
#Problems
Unsure how this will interact with custom alloactors.
#Closing thoughts
This is not really a well crated RFC. I encountered the problem recently while designing vulkan wrapper.
The proposed solution is probably too optmistic and will have some problems. The main goal for the prerfc is to see if moving should be allowed for some types that have active borrows.