Lifetime parameter in function call has conflicting requirements - rust

I have a Screen struct which holds two mutable slices for buffers and one for a canvas:
pub struct Screen<'a> {
pub canvas: Canvas<'a>,
pub buffers: [Vec<u32>; 2],
pub index: usize,
}
Methods to borrow the buffers and a method do swap and write them:
impl<'a> Screen<'a> {
pub fn get_buf(&'a self) -> &[u32] {
self.buffers[self.index].as_slice()
}
pub fn get_mut_buf(&mut self) -> &mut [u32] {
self.buffers[self.index].as_mut_slice()
}
pub fn swap_buffers(&mut self) {
self.canvas.copy_from_slice(self.get_buf());
self.bufnum += 1;
if self.bufnum == self.buffers.len() {
self.bufnum = 0;
}
}
}
The issue here is that, as answered in another thread (Cannot infer correct lifetime when borrowing index of slice and field of a struct at once), the compiler can't see self.buffers and self.canvas as different things, so I tried to assign a new 'b lifetime to buffers, but it resulted in it having conflicting requirements somehow:
struct Screen<'a, 'b> {
pub canvas: &'a mut [u32],
pub buffers: [&'b mut [u32]; 2],
pub bufnum: usize,
}
impl<'a, 'b> Screen<'a, 'b> {
pub fn get_buf(&self) -> &'b [u32] {
self.buffers[self.bufnum]
}
pub fn get_mut_buf(&mut self) -> &'b mut [u32] {
&mut self.buffers[self.bufnum]
}
pub fn swap_buffers(&mut self) {
self.canvas.copy_from_slice(self.get_buf());
self.bufnum += 1;
if self.bufnum == self.buffers.len() {
self.bufnum = 0;
}
}
}
How can I solve this problem and still be able to use get_but and get_mut_buf?

Use your original struct.
match self {
Screen { index, buffers, index } => {
// the parts are separate &mut references here
....
}
}

Related

Rust mutably borrowed lifetime issue

This is en excerpt from my actual code, but the issue is the same. I cannot borrow the staging_buffer in Buffer::from_data as mutable, and I cannot figure out why this is the case. Why isn't the mutable borrow of the Memory<'a> from the staging_Buffer released when the block is finished?
Note that the u32 reference in the Device struct is just a dummy, and in practice is a non-copyable type.
pub struct Device<'a> {
id: &'a u32,
}
impl<'a> Device<'a> {
pub fn new(id: &'a u32) -> Self {
Self { id }
}
}
pub struct Memory<'a> {
device: &'a Device<'a>,
}
impl<'a> Memory<'a> {
pub fn new(device: &'a Device) -> Self {
Self { device }
}
pub fn map(&mut self) {}
pub fn unmap(&mut self) {}
pub fn copy_from_host<T>(&self, _slice: &[T]) {}
}
impl<'a> Drop for Memory<'a> {
fn drop(&mut self) {}
}
pub struct Buffer<'a> {
device: &'a Device<'a>,
memory: Memory<'a>,
}
impl<'a> Buffer<'a> {
pub fn new(device: &'a Device) -> Self {
let buffer_memory = Memory::new(device);
Self {
device,
memory: buffer_memory,
}
}
pub fn from_data<T: Copy>(device: &'a Device, _data: &[T]) -> Self {
let mut staging_buffer = Buffer::new(device);
{
let staging_buffer_memory = staging_buffer.memory_mut();
staging_buffer_memory.map();
staging_buffer_memory.unmap();
}
let buffer = Self::new(device);
staging_buffer.copy_to_buffer(&buffer);
buffer
}
pub fn memory(&self) -> &Memory {
&self.memory
}
pub fn memory_mut(&'a mut self) -> &mut Memory {
&mut self.memory
}
fn copy_to_buffer(&self, _dst_buffer: &Buffer) {
//
}
}
impl<'a> Drop for Buffer<'a> {
fn drop(&mut self) {}
}
fn main() {
let id = 5;
let device = Device::new(&id);
let _buffer = Buffer::new(&device);
}
Okay, I finally figured it out!
The error here is actually in your implementation of memory_mut, and not in the rest of the code (although I agree that the lifetimes and references are making things harder than they need to be).
One way to see that this is the issue is to just mutably borrow memory directly, like so.
...
pub fn from_data<T: Copy>(device: &'a Device, _data: &[T]) -> Self {
let mut staging_buffer = Buffer::new(device);
{
// Don't use the stagin_buffer_memory variable
// let staging_buffer_memory = staging_buffer.memory_mut();
staging_buffer.memory.map();
staging_buffer.memory.unmap();
}
let buffer = Self::new(device);
staging_buffer.copy_to_buffer(&buffer);
buffer
}
...
but instead you can fix memory_mut by rewriting it like this:
...
pub fn memory_mut(&mut self) -> &mut Memory<'a> {
&mut self.memory
}
...
In this case the implementation of from_data works as it should.
I am not very confident with this, but I think it is due to the fact that the same lifetime annotation 'a is used everywhere.
Then, when lifetimes are considered by the borrow-checker, some are supposed to be equivalent (because of the same annotation) although they are not.
A lifetime is indeed necessary for the reference id in Device.
Another is needed for the reference device in Memory but this is not necessarily the same as the previous.
Then, I propagated these distinct lifetimes all over the code.
A Rust expert could probably explain this better than me.
pub struct Device<'i> {
id: &'i u32,
}
impl<'i> Device<'i> {
pub fn new(id: &'i u32) -> Self {
Self { id }
}
}
pub struct Memory<'d, 'i> {
device: &'d Device<'i>,
}
impl<'d, 'i> Memory<'d, 'i> {
pub fn new(device: &'d Device<'i>) -> Self {
Self { device }
}
pub fn map(&mut self) {}
pub fn unmap(&mut self) {}
pub fn copy_from_host<T>(
&self,
_slice: &[T],
) {
}
}
impl<'d, 'i> Drop for Memory<'d, 'i> {
fn drop(&mut self) {}
}
pub struct Buffer<'d, 'i> {
device: &'d Device<'i>,
memory: Memory<'d, 'i>,
}
impl<'d, 'i> Buffer<'d, 'i> {
pub fn new(device: &'d Device<'i>) -> Self {
let buffer_memory = Memory::new(device);
Self {
device,
memory: buffer_memory,
}
}
pub fn from_data<T: Copy>(
device: &'d Device<'i>,
_data: &[T],
) -> Self {
let mut staging_buffer = Buffer::new(device);
{
let staging_buffer_memory = staging_buffer.memory_mut();
staging_buffer_memory.map();
staging_buffer_memory.unmap();
}
let buffer = Self::new(device);
staging_buffer.copy_to_buffer(&buffer);
buffer
}
pub fn memory(&self) -> &Memory<'d, 'i> {
&self.memory
}
pub fn memory_mut(&mut self) -> &mut Memory<'d, 'i> {
&mut self.memory
}
fn copy_to_buffer(
&self,
_dst_buffer: &Buffer,
) {
//
}
}
impl<'d, 'i> Drop for Buffer<'d, 'i> {
fn drop(&mut self) {}
}
fn main() {
let id = 5;
let device = Device::new(&id);
let _buffer = Buffer::new(&device);
}

How to iterate over an Rc<RefCell<T>> that returns raw mutable references

I have a Vec<Rc<RefCell<MyStruct>>> member on a struct and I have an external library function that expects to be handed an Iterator with an Item that is a &'a mut dyn LibTrait which I have as a member inside MyStruct. I can't figure out how to get a raw &mut from out of the Rc<RefCell<MyStruct>> in my iterator even though I know the Vec member that holds it will stick around for longer than either the iterator or the function that gets passed the iterator.
The library looks like this:
struct Lib {}
trait LibTrait {
fn run(&mut self);
}
impl Lib {
pub fn lib_func<'a, Iter>(&mut self, trait_iter: Iter)
where
Iter: Iterator<Item = &'a mut dyn LibTrait>,
{
...
}
}
Here's my latest attempt where I tried to create a temp Vec to hold RefMut's to all the MyStructs so that those refs are owned for the whole time that the &mut would be inside the iterator and lib function. (This code complains about "cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements".)
struct TraitImpl {
dummy: f32,
}
impl LibTrait for TraitImpl {
fn run(&mut self) {
self.dummy += 1.0;
}
}
struct MyStruct {
my_impl: TraitImpl,
num: f32,
}
type MutStructSlice<'a> = &'a mut [&'a mut MyStruct];
struct TraitIterator<'a> {
my_structs: MutStructSlice<'a>,
index: usize,
}
impl<'a> TraitIterator<'a> {
fn new(my_structs: MutStructSlice<'a>) -> Self {
Self {
my_structs,
index: 0,
}
}
}
impl<'a> Iterator for TraitIterator<'a> {
type Item = &'a mut dyn LibTrait;
fn next(&mut self) -> Option<&'a mut dyn LibTrait> {
if self.index >= self.my_structs.len() {
return None;
}
Some(&mut self.my_structs[self.index].my_impl)
}
}
struct Data {
data: Vec<Rc<RefCell<MyStruct>>>,
lib: Lib,
}
impl Data {
fn do_stuff(&mut self) {
let mut struct_refs: Vec<RefMut<MyStruct>> = self
.data
.iter_mut()
.map(|s_rc| s_rc.borrow_mut())
.collect();
let mut structs_raw_refs: Vec<&mut MyStruct> =
struct_refs.iter_mut().map(|s_ref| &mut **s_ref).collect();
self.lib.lib_func(TraitIterator::new(&mut structs_raw_refs));
}
}
Here's the playground
Is there some way around this given that I can't change the library and I need to have Rc<RefCell<>>'s to the data?
I think you're overcomplicating this. You don't need a custom iterator, you can do this with .map():
fn do_stuff(&mut self) {
let mut struct_refs: Vec<RefMut<MyStruct>> = self.data
.iter_mut()
.map(|s_rc| s_rc.borrow_mut())
.collect();
self.lib.lib_func(struct_refs.iter_mut().map(|s_ref| &mut s_ref.my_impl as &mut dyn LibTrait));
}
You get the error you did because implementing Iterator for &mut T is inherently unsafe. See How to implement Iterator yielding mutable references.

How to set the lifetime on these structures?

I am trying to make an Iterator which filters out certain moves from a movelist. In order not to take ownership of the returned moves, they get referenced. However, when doing that, the missing lifetime specifier compiler error appears. As I have a chain of structs, I thought the first step to solve the problem was to start putting lifetimes on MoveFilter and then onto it's type Item in IntoIterator. However there it complains the usage of an undeclared lifetime.
Code:
pub struct GameMove {
pub from: usize,
pub to: usize,
pub move_type: GameMoveType,
pub piece_type: PieceType,
}
#[derive(PartialEq, Clone, Debug)]
pub enum GameMoveType {
Quiet,
Capture(PieceType),
}
#[derive(PartialEq, Clone, Debug)]
pub enum PieceType {
King,
Pawn
}
pub fn match_move_type(move_type: &GameMoveType) -> usize {
match move_type {
GameMoveType::Quiet => 0,
GameMoveType::Capture(_) => 1,
}
}
pub struct MoveFilter<'a> {
legal_moves: Vec<GameMove>,
move_type: GameMoveType,
}
impl IntoIterator for MoveFilter {
type Item = &'a GameMove;
type IntoIter = MoveFilterIterator;
fn into_iter(self) -> Self::IntoIter {
MoveFilterIterator {
legal_moves: self.legal_moves,
move_type: match_move_type(&self.move_type),
index: 0,
}
}
}
pub struct MoveFilterIterator {
legal_moves: Vec<GameMove>,
move_type: usize,
index: usize,
}
impl Iterator for MoveFilterIterator {
type Item = &GameMove;
fn next(&mut self) -> Option<&GameMove> {
while self.index < self.legal_moves.len() {
if match_move_type(&self.legal_moves[self.index].move_type) == self.move_type {
Some(&self.legal_moves[self.index])
} else {
self.index += 1;
}
}
None
}
}
There is a discrepancy between your
method fn into_iter(self: MoveFilter) that takes ownership of MoveFilter
and
the method fn next(&mut self) -> Option<&GameMove> that only wants to hand out immutable references to GameMoves. Who is supposed to own the referenced GameMoves after your into_iter takes ownership of the MoveFilter and completely consumes it?
One way to fix it would be to implement IntoIterator for &'a MoveFilter, that does not take ownership of MoveFilter, and thus does not have to worry that all GameMoves are discarded while there are any references &'a GameMove floating around:
pub struct GameMove {
pub from: usize,
pub to: usize,
pub move_type: GameMoveType,
pub piece_type: PieceType,
}
#[derive(PartialEq, Clone, Debug)]
pub enum GameMoveType {
Quiet,
Capture(PieceType),
}
#[derive(PartialEq, Clone, Debug)]
pub enum PieceType {
King,
Pawn
}
pub fn match_move_type(move_type: &GameMoveType) -> usize {
match move_type {
GameMoveType::Quiet => 0,
GameMoveType::Capture(_) => 1,
}
}
pub struct MoveFilter {
legal_moves: Vec<GameMove>,
move_type: GameMoveType,
}
impl<'t> IntoIterator for &'t MoveFilter {
type Item = &'t GameMove;
type IntoIter = MoveFilterIterator<'t>;
fn into_iter(self) -> Self::IntoIter {
MoveFilterIterator {
legal_moves: &self.legal_moves[..],
move_type: match_move_type(&self.move_type),
index: 0,
}
}
}
pub struct MoveFilterIterator<'a> {
legal_moves: &'a [GameMove],
move_type: usize,
index: usize,
}
impl<'a> Iterator for MoveFilterIterator<'a> {
type Item = &'a GameMove;
fn next(&mut self) -> Option<&'a GameMove> {
while self.index < self.legal_moves.len() {
if match_move_type(&self.legal_moves[self.index].move_type) == self.move_type {
return Some(&self.legal_moves[self.index])
} else {
self.index += 1;
}
}
None
}
}
Another possible solution would be to leave your IntoIterator for MoveFilter as-is, but then change Item = &GameMove to Item = GameMove. This would give you a destructive iterator that moves the MoveFilter and that can be used only once, but I assume that's not what you wanted when you began with type Item = &GameMove. Implementing it seems a bit more awkward, because it's not entirely trivial to remove single elements from a vector, and I didn't quite understand what that while-loop was doing there.

Declaring a vector of trait objects with a lifetime parameter

I have a Widget trait parametrised on a context type:
trait Widget<C> {
fn f<'a>(&self, ctx: &'a mut C);
}
Some widgets whose context types are the same, but contain references so are parameterised:
struct Ctxt<'c> {
data: &'c u32,
}
struct W1 {}
struct W2 {}
impl<'c> Widget<Ctxt<'c>> for W1 { // and W2
fn f<'a>(&self, ctx: &'a mut Ctxt<'c>) {
unimplemented!()
}
}
I have a multi-widget which wants to store several of these:
struct WV {
widgets: Vec<Box<Widget<Ctxt<????>>>>,
}
impl<'c> Widget<Ctxt<'c>> for WV {
fn f<'a>(&self, ctx: &'a mut Ctxt<'c>) {
for w in &self.widgets {
w.f(ctx);
}
}
}
It looks like I need a Vec<Box<Widget<for<'c> Ctxt<'c>>>>; but you can't do that! Alternatively, only specifying the lifetime in the definition of f:
impl Widget<Ctxt> for W {
fn f<'a, 'c>(&self, ctx: &'a mut Ctxt<'c>) {
unimplemented!()
}
}
This doesn't work either (missing lifetime parameter for Ctxt).
The purpose of the context is to pass a mutable reference to something long-lived which is only needed during f; the &mut reference can't be stored in W1 etc. I don't really want to specify any lifetimes for Ctxt.
How can I store multiple implementers of the trait, which allow passing in a context containing references?
After a night's sleep, I think I have an answer. I can defer the selection of the Ctxt lifetime by indirecting through a new trait CtxtWidget, and impl<'c> Widget<Ctxt<'c>> for the new trait:
trait Widget<C> {
fn f<'a>(&self, ctx: &'a mut C);
}
struct W1 {}
struct W2 {}
struct Ctxt<'c> {
data: &'c u32,
}
trait CtxtWidget {
fn ctxt_f<'a, 'c>(&self, ctx: &'a mut Ctxt<'c>);
}
impl CtxtWidget for W1 {
fn ctxt_f<'a, 'c>(&self, ctx: &'a mut Ctxt<'c>) {
unimplemented!()
}
}
impl CtxtWidget for W2 {
fn ctxt_f<'a, 'c>(&self, ctx: &'a mut Ctxt<'c>) {
unimplemented!()
}
}
impl<'c> Widget<Ctxt<'c>> for Box<CtxtWidget> {
fn f<'a>(&self, ctx: &'a mut Ctxt<'c>) {
self.ctxt_f(ctx);
}
}
struct WV {
pub widgets: Vec<Box<CtxtWidget>>,
}
fn main() {
let mut wv = WV{widgets: Vec::new()};
wv.widgets.push(Box::new(W1{}));
wv.widgets.push(Box::new(W2{}));
let u = 65u32;
let mut ctxt = Ctxt{data: &u};
for widget in &wv.widgets {
widget.f(&mut ctxt);
}
}
(playground)
In effect CtxtWidget is roughly equivalent to for<'c> Widget<Ctxt<'c>>.
I'd still be interested in any other solutions (including intrusive changes if there's a better way to do this).

How would I create a handle manager in Rust?

pub struct Storage<T>{
vec: Vec<T>
}
impl<T: Clone> Storage<T>{
pub fn new() -> Storage<T>{
Storage{vec: Vec::new()}
}
pub fn get<'r>(&'r self, h: &Handle<T>)-> &'r T{
let index = h.id;
&self.vec[index]
}
pub fn set(&mut self, h: &Handle<T>, t: T){
let index = h.id;
self.vec[index] = t;
}
pub fn create(&mut self, t: T) -> Handle<T>{
self.vec.push(t);
Handle{id: self.vec.len()-1}
}
}
struct Handle<T>{
id: uint
}
I am currently trying to create a handle system in Rust and I have some problems. The code above is a simple example of what I want to achieve.
The code works but has one weakness.
let mut s1 = Storage<uint>::new();
let mut s2 = Storage<uint>::new();
let handle1 = s1.create(5);
s1.get(handle1); // works
s2.get(handle1); // unsafe
I would like to associate a handle with a specific storage like this
//Pseudo code
struct Handle<T>{
id: uint,
storage: &Storage<T>
}
impl<T> Handle<T>{
pub fn get(&self) -> &T;
}
The problem is that Rust doesn't allow this. If I would do that and create a handle with the reference of a Storage I wouldn't be allowed to mutate the Storage anymore.
I could implement something similar with a channel but then I would have to clone T every time.
How would I express this in Rust?
The simplest way to model this is to use a phantom type parameter on Storage which acts as a unique ID, like so:
use std::kinds::marker;
pub struct Storage<Id, T> {
marker: marker::InvariantType<Id>,
vec: Vec<T>
}
impl<Id, T> Storage<Id, T> {
pub fn new() -> Storage<Id, T>{
Storage {
marker: marker::InvariantType,
vec: Vec::new()
}
}
pub fn get<'r>(&'r self, h: &Handle<Id, T>) -> &'r T {
let index = h.id;
&self.vec[index]
}
pub fn set(&mut self, h: &Handle<Id, T>, t: T) {
let index = h.id;
self.vec[index] = t;
}
pub fn create(&mut self, t: T) -> Handle<Id, T> {
self.vec.push(t);
Handle {
marker: marker::InvariantLifetime,
id: self.vec.len() - 1
}
}
}
pub struct Handle<Id, T> {
id: uint,
marker: marker::InvariantType<Id>
}
fn main() {
struct A; struct B;
let mut s1 = Storage::<A, uint>::new();
let s2 = Storage::<B, uint>::new();
let handle1 = s1.create(5);
s1.get(&handle1);
s2.get(&handle1); // won't compile, since A != B
}
This solves your problem in the simplest case, but has some downsides. Mainly, it depends on the use to define and use all of these different phantom types and to prove that they are unique. It doesn't prevent bad behavior on the user's part where they can use the same phantom type for multiple Storage instances. In today's Rust, however, this is the best we can do.
An alternative solution that doesn't work today for reasons I'll get in to later, but might work later, uses lifetimes as anonymous id types. This code uses the InvariantLifetime marker, which removes all sub typing relationships with other lifetimes for the lifetime it uses.
Here is the same system, rewritten to use InvariantLifetime instead of InvariantType:
use std::kinds::marker;
pub struct Storage<'id, T> {
marker: marker::InvariantLifetime<'id>,
vec: Vec<T>
}
impl<'id, T> Storage<'id, T> {
pub fn new() -> Storage<'id, T>{
Storage {
marker: marker::InvariantLifetime,
vec: Vec::new()
}
}
pub fn get<'r>(&'r self, h: &Handle<'id, T>) -> &'r T {
let index = h.id;
&self.vec[index]
}
pub fn set(&mut self, h: &Handle<'id, T>, t: T) {
let index = h.id;
self.vec[index] = t;
}
pub fn create(&mut self, t: T) -> Handle<'id, T> {
self.vec.push(t);
Handle {
marker: marker::InvariantLifetime,
id: self.vec.len() - 1
}
}
}
pub struct Handle<'id, T> {
id: uint,
marker: marker::InvariantLifetime<'id>
}
fn main() {
let mut s1 = Storage::<uint>::new();
let s2 = Storage::<uint>::new();
let handle1 = s1.create(5);
s1.get(&handle1);
// In theory this won't compile, since the lifetime of s2
// is *slightly* shorter than the lifetime of s1.
//
// However, this is not how the compiler works, and as of today
// s2 gets the same lifetime as s1 (since they can be borrowed for the same period)
// and this (unfortunately) compiles without error.
s2.get(&handle1);
}
In a hypothetical future, the assignment of lifetimes may change and we may grow a better mechanism for this sort of tagging. However, for now, the best way to accomplish this is with phantom types.

Resources