I started with Rust recently and I working on small game, unfortunately, I'm having issues on implementing a simple mechanic due an error of multiple mutable borrows, for instance, the following code has an issue with a second mutable borrow
struct Margin {
x: f32,
y: f32,
h: f32,
w: f32,
}
struct Level {
margins: Vec<Margin>,
}
impl Level {
fn new() -> Self {
Level{
margins: vec![]
}
}
fn update(&mut self) {
// Add a new margin on each tick
self.margins.push(Margin {
x:0., y:0., w:100., h:0.5,
});
// Iterate over margins moving each one down a little
for (i, m) in self.margins.iter_mut().enumerate() {
m.y += 1.;
// Remove margins outside of the screen
if m.y > 640. {
self.margins.remove(i);
}
}
}
}
fn main() {
let mut l = Level::new();
l.update();
}
Error
Compiling playground v0.0.1 (/playground)
error[E0499]: cannot borrow `self.margins` as mutable more than once at a time
--> src/main.rs:31:17
|
26 | for (i, m) in self.margins.iter_mut().enumerate() {
| -----------------------------------
| |
| first mutable borrow occurs here
| first borrow later used here
...
31 | self.margins.remove(i);
| ^^^^^^^^^^^^ second mutable borrow occurs here
Found the useful method retain on the Vec and the code is fixed as follows:
struct Margin {
x: f32,
y: f32,
h: f32,
w: f32,
}
struct Level {
margins: Vec<Margin>,
}
impl Level {
fn new() -> Self {
Level{
margins: vec![]
}
}
fn update(&mut self) {
// Add a new margin on each tick
self.margins.push(Margin {
x:0., y:0., h:100., w:0.5,
});
// Iterate over margins moving each one down a little
for m in self.margins.iter_mut() {
m.y += 1.;
}
// Retains only the elements where y is lower than 640.
self.margins.retain(|v| v.y < 640.);
}
}
fn main() {
let mut l = Level::new();
l.update();
}
Answered based on a previous answer here Remove an element while iterationg over it
Related
I'm trying to learn rust making a game with SDL2. I have a struct GameEngine which has ownership of some variables to control the game state.
The method GameEngine::run() is responsible to manage the game loop. I want this method to do 2 things:
Check if some event is related to closing the game and in this case break the loop
For any other kind of event I want to call a method GameEngine::handle_event() to handle it
The problem is that the compiler is refusing to accept my code telling me I'm trying to borrow self as mutable more than once. The first borrow happen on this line:
let event_poll_iterator = self.event_pump.poll_iter();
and the second on this:
self.handle_event(event);
As I'm a newbie in Rust, I'm getting stuck in this error.
The complete code:
pub mod engine {
use std::time::Duration;
use sdl2::{EventPump, Sdl};
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::pixels::Color;
use sdl2::render::WindowCanvas;
fn get_canvas(sdl_context: &Sdl) -> WindowCanvas {
let video_subsystem = sdl_context.video().unwrap();
let window = video_subsystem
.window("SDL2 Snake Game", 800, 600)
.position_centered()
.opengl()
.build()
.map_err(|e| e.to_string()).unwrap();
let mut canvas = window.into_canvas().build().map_err(|e| e.to_string()).unwrap();
canvas.set_draw_color(Color::BLACK);
canvas
}
pub struct GameEngine {
context: Sdl,
event_pump: EventPump,
canvas: WindowCanvas,
}
impl GameEngine {
pub fn new() -> Self {
let context = sdl2::init().unwrap();
let canvas = get_canvas(&context);
let event_pump = context.event_pump().unwrap();
GameEngine { context, canvas, event_pump }
}
fn redraw(&mut self) {
self.canvas.clear();
self.canvas.present();
}
fn handle_event(&mut self, event: Event) {
todo!()
}
pub fn run(&mut self) {
'game_loop: loop {
let event_poll_iterator = self.event_pump.poll_iter();
for event in event_poll_iterator {
match event {
Event::Quit { .. }
| Event::KeyDown {
keycode: Some(Keycode::Escape),
..
} => break 'game_loop,
_ => {
self.handle_event(event);
}
}
}
self.redraw();
std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 30));
}
}
}
}
Edit
I could reproduce the same problem (I think) with a much smaller example:
struct List {
v: Vec<u32>
}
impl List {
fn increment(&mut self, x: &mut u32) {
*x += 1;
}
fn iter(&mut self) {
for x in &mut self.v {
self.increment(x);
}
}
}
fn main() {
let mut list = List { v: vec![1, 2, 3] };
list.iter();
assert!(list.v == vec![2, 3, 4]);
}
Error log:
λ cargo run
Compiling rustlings v4.7.1 (/home/luizalabs/repositories/rust/rustlings)
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/main.rs:12:13
|
11 | for x in &mut self.v {
| -----------
| |
| first mutable borrow occurs here
| first borrow later used here
12 | self.increment(x);
| ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
For more information about this error, try `rustc --explain E0499`.
error: could not compile `rustlings` due to previous error
The problem is, self.handle_event could modify whatever you are iterating over (in this case event_poll_iterator). If you are modifying what the iterator is iterating over, you might want to consider cloning the iterator. If self.handle_event isn't modifying the iterator, you have to show the borrow checker that you are not modifying the iterator. One option is to inline self.handle_event. Another option is to pass whatever you are modifying as mutable to self.handle_event. Here is a simple example of what is going on:
#[derive(Debug)]
struct Point {
x: i32,
y: i32
}
struct Points {
points: Vec<Point>,
num_points: usize
}
impl Points {
fn bar(&mut self, point: &mut Point) {
println!("{:?}", point)
}
fn foo(&mut self) {
for p in &mut self.points {
self.bar(p);
}
}
}
Inlining would change foo as such:
fn foo(&mut self) {
for p in &mut self.points {
println!("{:?}", p); // modified line
}
}
Tried to simplify your example
fn main() {
let i: i32 = 4326;
let b = i.to_le_bytes();
for i in 0..4 {
println!("{}", b[i]);
}
}
pub struct GameEngine {
event_pump: EventPump,
}
pub struct EventPump {
}
impl EventPump {
pub fn poll_iter(&mut self) -> Vec<i32> {
vec![0, 1, 2]
}
}
impl GameEngine {
pub fn new() -> Self {
GameEngine {
event_pump: EventPump { },
}
}
fn redraw(&mut self) {
}
fn handle_event(&mut self, _event: i32) {
todo!()
}
pub fn run(&mut self) {
loop {
let ep = self.event_pump.poll_iter();
let event_poll_iterator = ep.iter();
for event in event_poll_iterator {
match event {
_ => {
self.handle_event(*event);
}
}
}
self.redraw();
}
}
}
Hope without losing sense. Seems it compiled ok.
It changes Iter to vector instance but I'm not sure if that matters.
This question already has answers here:
How can I create my own data structure with an iterator that returns mutable references?
(1 answer)
How to implement Iterator yielding mutable references [duplicate]
(2 answers)
Closed 2 years ago.
I have a struct (Lines) containing a vec of Coordinates.
I'm trying to implement a non-consuming mutable iterator over non-overlapping sub-slices into this vector as &mut [Coordinate]. Each sub-slice would represent 1 line stored in Lines.
-edit: Additionally the lists of indices may be reordered without the vertices being moved. As such the lines in vertices cannot be assumed to be in the same order as the indices.
The implementation works for the immutable iterator (same implementation as below, but without muts)
https://play.rust-lang.org/?version=stable&mode=debug&edition=2015&gist=dc03530c82e8113ea532e5345dda4142
use std::ops::{Index, IndexMut};
#[derive(Debug)]
pub struct Coordinate {
x: u32,
y: u32,
}
/// SOA containing multiple line geometries
/// All coordinates of all the lines are stored contiguously in vertices
/// start_indices & end_indices both contain 1 entry for every geometry
#[derive(Debug)]
struct Lines {
vertices: Vec<Coordinate>,
start_indices: Vec<usize>,
end_indices: Vec<usize>,
}
impl Lines {
pub fn len(&self) -> usize {
self.start_indices.len()
}
fn iter_mut(&mut self) -> LinesIterMut {
LinesIterMut {
lines: self,
next_index: 0,
}
}
}
impl Index<usize> for Lines {
type Output = [Coordinate];
fn index(&self, index: usize) -> &Self::Output {
&self.vertices[self.start_indices[index]..self.end_indices[index]]
}
}
impl IndexMut<usize> for Lines {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.vertices[self.start_indices[index]..self.end_indices[index]]
}
}
pub struct LinesIterMut<'a> {
lines: &'a mut Lines,
next_index: usize,
}
impl<'a> Iterator for LinesIterMut<'a> {
type Item = &'a mut [Coordinate];
fn next(&mut self) -> Option<Self::Item> {
if self.next_index < self.lines.len() {
let current_index = self.next_index;
self.next_index += 1;
Some(&mut self.lines[current_index])
} else {
None
}
}
}
fn main() {
let mut my_lines = Lines {
vertices: vec![
Coordinate {
x: 1,
y: 2,
},
Coordinate {
x: 4,
y: 5,
},
],
start_indices: vec![0],
end_indices: vec![2],
};
for line in my_lines.iter_mut() {
line[0].y = 33;
println!("=> {:?}", line);
}
}
I get the following lifetime error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:54:23
|
54 | Some(&mut self.lines[current_index])
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 50:5...
--> src/main.rs:50:5
|
50 | fn next(&mut self) -> Option<Self::Item> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:54:23
|
54 | Some(&mut self.lines[current_index])
| ^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 47:6...
--> src/main.rs:47:6
|
47 | impl<'a> Iterator for LinesIterMut<'a> {
| ^^
note: ...so that the types are compatible
--> src/main.rs:50:46
|
50 | fn next(&mut self) -> Option<Self::Item> {
| ______________________________________________^
51 | | if self.next_index < self.lines.len() {
52 | | let current_index = self.next_index;
53 | | self.next_index += 1;
... |
57 | | }
58 | | }
| |_____^
= note: expected `Iterator`
found `Iterator`
How do I tell the compiler that the lifetime of the reference is related to Lines?
-edit: Using the link provided by #kmdreko : https://stackoverflow.com/a/60072822/13138916
I wrote this.
It works, but is this safe? How can I tell?
pub struct LinesIterMut<'a> {
lines: &'a mut Lines,
next_index: usize,
}
impl<'a> Iterator for LinesIterMut<'a> {
type Item = &'a mut [Coordinate];
fn next(&mut self) -> Option<Self::Item> {
if self.next_index < self.lines.len() {
let current_index = self.next_index;
self.next_index += 1;
Some(unsafe { std::mem::transmute(&mut self.lines[current_index]) }) // <<--- Only changed this line
} else {
None
}
}
}
I am working through examples in Rust by Example.
#[derive(Debug)]
struct Point {
x: f64,
y: f64,
}
#[derive(Debug)]
struct Rectangle {
p1: Point,
p2: Point,
}
fn main() {
let mut point: Point = Point { x: 0.3, y: 0.4 };
println!("point coordinates: ({}, {})", point.x, point.y);
let rectangle = Rectangle {
p1: Point { x: 1.0, y: 1.0 },
p2: point,
};
point.x = 0.5; // Why does the compiler not break here,
println!(" x is {}", point.x); // but it breaks here?
println!("rectangle is {:?} ", rectangle);
}
I get this error (Rust 1.25.0):
error[E0382]: use of moved value: `point.x`
--> src/main.rs:23:26
|
19 | p2: point,
| ----- value moved here
...
23 | println!(" x is {}", point.x);
| ^^^^^^^ value used here after move
|
= note: move occurs because `point` has type `Point`, which does not implement the `Copy` trait
I understand that I gave point to the Rectangle object and that is why I can no longer access it, but why does the compilation fail on the println! and not the assignment on the previous line?
What really happens
fn main() {
let mut point: Point = Point { x: 0.3, y: 0.4 };
println!("point coordinates: ({}, {})", point.x, point.y);
drop(point);
{
let mut point: Point;
point.x = 0.5;
}
println!(" x is {}", point.x);
}
It turns out that it's already known as issue #21232.
The problem is that the compiler allows partial reinitialization of a struct, but the whole struct is unusable after that. This happens even if the struct contains only a single field, and even if you only try to read the field you just reinitialized.
struct Test {
f: u32,
}
fn main() {
let mut t = Test { f: 0 };
let t1 = t;
t.f = 1;
println!("{}", t.f);
}
This is discussed in issue 21232
I am working through examples in Rust by Example.
#[derive(Debug)]
struct Point {
x: f64,
y: f64,
}
#[derive(Debug)]
struct Rectangle {
p1: Point,
p2: Point,
}
fn main() {
let mut point: Point = Point { x: 0.3, y: 0.4 };
println!("point coordinates: ({}, {})", point.x, point.y);
let rectangle = Rectangle {
p1: Point { x: 1.0, y: 1.0 },
p2: point,
};
point.x = 0.5; // Why does the compiler not break here,
println!(" x is {}", point.x); // but it breaks here?
println!("rectangle is {:?} ", rectangle);
}
I get this error (Rust 1.25.0):
error[E0382]: use of moved value: `point.x`
--> src/main.rs:23:26
|
19 | p2: point,
| ----- value moved here
...
23 | println!(" x is {}", point.x);
| ^^^^^^^ value used here after move
|
= note: move occurs because `point` has type `Point`, which does not implement the `Copy` trait
I understand that I gave point to the Rectangle object and that is why I can no longer access it, but why does the compilation fail on the println! and not the assignment on the previous line?
What really happens
fn main() {
let mut point: Point = Point { x: 0.3, y: 0.4 };
println!("point coordinates: ({}, {})", point.x, point.y);
drop(point);
{
let mut point: Point;
point.x = 0.5;
}
println!(" x is {}", point.x);
}
It turns out that it's already known as issue #21232.
The problem is that the compiler allows partial reinitialization of a struct, but the whole struct is unusable after that. This happens even if the struct contains only a single field, and even if you only try to read the field you just reinitialized.
struct Test {
f: u32,
}
fn main() {
let mut t = Test { f: 0 };
let t1 = t;
t.f = 1;
println!("{}", t.f);
}
This is discussed in issue 21232
I am working through examples in Rust by Example.
#[derive(Debug)]
struct Point {
x: f64,
y: f64,
}
#[derive(Debug)]
struct Rectangle {
p1: Point,
p2: Point,
}
fn main() {
let mut point: Point = Point { x: 0.3, y: 0.4 };
println!("point coordinates: ({}, {})", point.x, point.y);
let rectangle = Rectangle {
p1: Point { x: 1.0, y: 1.0 },
p2: point,
};
point.x = 0.5; // Why does the compiler not break here,
println!(" x is {}", point.x); // but it breaks here?
println!("rectangle is {:?} ", rectangle);
}
I get this error (Rust 1.25.0):
error[E0382]: use of moved value: `point.x`
--> src/main.rs:23:26
|
19 | p2: point,
| ----- value moved here
...
23 | println!(" x is {}", point.x);
| ^^^^^^^ value used here after move
|
= note: move occurs because `point` has type `Point`, which does not implement the `Copy` trait
I understand that I gave point to the Rectangle object and that is why I can no longer access it, but why does the compilation fail on the println! and not the assignment on the previous line?
What really happens
fn main() {
let mut point: Point = Point { x: 0.3, y: 0.4 };
println!("point coordinates: ({}, {})", point.x, point.y);
drop(point);
{
let mut point: Point;
point.x = 0.5;
}
println!(" x is {}", point.x);
}
It turns out that it's already known as issue #21232.
The problem is that the compiler allows partial reinitialization of a struct, but the whole struct is unusable after that. This happens even if the struct contains only a single field, and even if you only try to read the field you just reinitialized.
struct Test {
f: u32,
}
fn main() {
let mut t = Test { f: 0 };
let t1 = t;
t.f = 1;
println!("{}", t.f);
}
This is discussed in issue 21232