Why is this field mutation allowed after drop? [duplicate] - rust

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

Related

How to push a item from a function parameter to a vector from a function parameter - Different lifetime issue

I need to push an item to a vector. But both of item and vector are function parameters.
Simple code to reproduce:-
struct Point {
x: i32,
y: i32
}
fn main(){
let points: Vec<&Point> = vec!();
let start_point = Point {x: 1, y:2};
fn fill_points<F>(points: &mut Vec<&F>, point: &F ){
// Some conditions and loops
points.push(point);
}
fill_points(&mut points, & start_point);
}
Error:-
|
13 | fn fill_points<F>(points: &mut Vec<&F>, point: &F ){
| -- -- these two types are declared with different lifetimes...
14 | // Some conditions
15 | points.push(point);
| ^^^^^ ...but data from `point` flows into `points` here
Playground URL:- https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=e1f2d738a22795ae11aab01ad8d00d96
You need to add a lifetime parameter:
struct Point {
x: i32,
y: i32,
}
fn main() {
let start_point = Point { x: 1, y: 2 };
let mut points: Vec<&Point> = vec![];
fn fill_points<'a, F>(points: &mut Vec<&'a F>, point: &'a F) {
// Some conditions
points.push(point);
}
fill_points(&mut points, &start_point);
}
(code simplified based the comment from #Stargateur)

Issues with a second borrow in rust

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

Temporary value does not live long enough

I'm having trouble with this code. I have no idea why it errors.
It's supposed to take camera input and then put that inside of a buffer struct, contained inside the putter struct.
extern crate rscam;
// use std::fs::File;
// use std::io::prelude::*;
const WIDTH: usize = 1280;
const HEIGHT: usize = 720;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Pyxel {
r: u8,
g: u8,
b: u8,
}
impl Pyxel {
fn new() -> Pyxel {
Pyxel { r: 0, g: 0, b: 0 }
}
}
#[repr(transparent)]
struct Buffer {
pyxels: [[Pyxel; WIDTH]; HEIGHT],
}
// impl Buffer {
// fn new(s: [[Pyxel; WIDTH]; HEIGHT]) -> Buffer {
// Buffer {
// pyxels: s,
// }
// }
// }
struct Putter {
x: usize,
y: usize,
buffer: &'static mut Buffer,
}
impl Putter {
fn put_pyxel(&mut self, r: u8, g: u8, b: u8) {
if self.x >= WIDTH {
self.move_down();
}
let col = self.x;
let row = self.y;
self.buffer.pyxels[row][col] = Pyxel { r: r, g: g, b: b };
self.x += 1;
}
fn move_down(&mut self) {
self.y += 1;
}
fn new() -> Putter {
Putter {
x: 0,
y: 0,
buffer: &mut Buffer {
pyxels: [[Pyxel::new(); WIDTH]; HEIGHT],
},
}
}
}
fn main() {
let mut camera = rscam::new("/dev/video0").unwrap();
camera
.start(&rscam::Config {
interval: (1, 30),
resolution: (1280, 720),
format: b"RGB3",
..Default::default()
})
.unwrap();
let frame = camera.capture().unwrap();
let mut putter = Putter::new();
}
It errors:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:65:20
|
57 | buffer: &mut Buffer {
| __________________________^
58 | | pyxels: [[Pyxel::new(); WIDTH]; HEIGHT],
59 | | },
| |_____________^ temporary value does not live long enough
60 | }
61 | }
| - temporary value only lives until here
|
= note: borrowed value must be valid for the static lifetime..
How do I use the buffer inside of the putter (structs)?
For the most part, I understand what this errors means, not how it works. I just need a workaround or a solution. Any help is appreciated. I could have written this better but im tired.
This is more or less logical error for me. You should carefully read about Rust ownership.
Consider thinking about how would your code work.
struct Putter {
x: usize,
y: usize,
buffer: &'static mut Buffer,
}
Buffer is a reference which you have lifetime equal to the lifetime of the program,
'static tells compiler that. Error message is pretty clear, you're creating temporary value in place and borrowing it. It will be destroyed right after exiting scope, so your reference will be pointing to invalid memory. Dangling references are prohibited in Rust. In language like C++ this example will compile fine, but will result in run-time error.
To fix this issue buffer should own value and struct design should be rethought while keeping attention to lifetimes.
struct Putter {
x: usize,
y: usize,
buffer: Buffer,
}

Why does Rust allow modification of a mutable struct after moving it into a closure? [duplicate]

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

Why does compilation not fail when a member of a moved value is assigned to?

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

Resources