I created a library to deal with digraphs: nodes that link (reference counted) to zero or one other nodes (as in linked lists, but in a digraph a node can be linked to by more than one node).
I am trying to use my library to create a list with a current node:
struct ListWithPointer<'a> {
pub nodes: DigraphNodeRef<String>,
pub current_node: Option<&'a mut DigraphNodeRef<String>>,
}
current_node points to a link in the list.
Now I am trying to move current node to the next element of the list (or to the beginning if the list ended):
fn next_node<'a>(this: &'a mut ListWithPointer<'a>) {
if this.current_node.is_some() {
this.current_node.iter_mut().for_each(|a| {
(*a).as_rc_mut().iter_mut()
.for_each(|rc| this.current_node = Some(&mut Arc::get_mut(rc).unwrap().next));
});
} else {
this.current_node = Some(&mut this.nodes);
}
}
but whatever I do, it fails with an error like:
error[E0500]: closure requires unique access to `this.current_node` but it is already borrowed
--> src/lib.rs:150:51
|
148 | fn next_node<'a>(this: &'a mut ListWithPointer<'a>) {
| -- lifetime `'a` defined here
149 | if this.current_node.is_some() {
150 | this.current_node.iter_mut().for_each(|a| {
| ---------------------------- ^^^ closure construction occurs here
| |
| borrow occurs here
| argument requires that `this.current_node` is borrowed for `'a`
151 | (*a).as_rc_mut().iter_mut()
152 | .for_each(|rc| this.current_node = Some(&mut Arc::get_mut(rc).unwrap().next));
| ----------------- second borrow occurs due to use of `this.current_node` in closure
Help to rewrite without errors.
Here is the library code:
use std::sync::Arc;
#[derive(Clone)]
pub struct DigraphNode<T> {
pub next: DigraphNodeRef<T>, // I made it `pub` to be able `item.next.next()` to remove an item from the middle.
data: T,
}
impl<T> DigraphNode<T> {
fn new(next: DigraphNodeRef<T>, data: T) -> Self {
Self { next, data }
}
}
pub struct DigraphNodeRef<T> {
rc: Option<Arc<DigraphNode<T>>>,
}
impl<T> DigraphNodeRef<T> {
pub fn new() -> Self {
Self {
rc: None
}
}
pub fn from_node(value: DigraphNode<T>) -> Self {
Self::from(Some(Arc::new(value)))
}
pub fn from(rc: Option<Arc<DigraphNode<T>>>) -> Self {
Self {
rc
}
}
pub fn as_rc(&self) -> &Option<Arc<DigraphNode<T>>> {
&self.rc
}
pub fn as_rc_mut(&mut self) -> &mut Option<Arc<DigraphNode<T>>> {
&mut self.rc
}
pub fn is_none(&self) -> bool {
self.rc.is_none()
}
pub fn remove(&mut self) -> bool {
if let Some(rc) = self.rc.clone() {
self.rc = rc.next.rc.clone();
true
} else {
false
}
}
pub fn prepend(&mut self, value: T) -> Self {
let new_node = DigraphNode::new(self.clone(), value);
let new_node_ref = DigraphNodeRef::from_node(new_node);
*self = new_node_ref.clone();
new_node_ref
}
pub fn node(&self) -> Option<DigraphNode<T>>
where T: Clone
{
self.rc.clone().map(|node| (*node).clone())
}
/// TODO: Should return a reference.
pub fn data(&self) -> Option<T>
where T: Clone
{
self.rc.clone().map(|node| (*node).data.clone())
}
pub fn values(self) -> DigraphNodeValuesIterator<T> {
DigraphNodeValuesIterator {
underlying: self.clone()
}
}
}
impl<T> Clone for DigraphNodeRef<T> {
fn clone(&self) -> Self {
Self { rc: self.rc.clone() }
}
}
impl<T> Iterator for DigraphNodeRef<T> {
type Item = Arc<DigraphNode<T>>;
fn next(&mut self) -> Option<Self::Item> {
if let Some(rc) = self.rc.clone() {
self.rc = rc.next.rc.clone();
Some(rc.clone())
} else {
None
}
}
}
pub struct DigraphNodeValuesIterator<T> {
underlying: DigraphNodeRef<T>,
}
impl<T: Clone> Iterator for DigraphNodeValuesIterator<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.underlying.next().map(|node| node.data.clone())
}
}
In Rust the mutable access is ensured to be exclusive, i.e. if you hold a reference, some other code can't grab a mutable reference.
Problem is this line:
this.current_node.iter_mut().for_each(...)
It grabs a mutable access to current_node, so it can't regain it again down the line.
Not to mention that iterating over Option is a strange decision.
If you want to move current_node to a different place, I'd try to reorganize your code such that reads are separate from writes, and they are performed in a sequence, instead of trying to do it in one go:
// detach the current_node for moving
if let Some(current_node_to_move) = this.current_node.take() {
let new_current_node_ref: &mut ... = ... // find new location logic
new_current_node_ref.replace(current_node_to_move);
} else {
...
}
Here in line 1 it does a write None update to current_node via this, but immediately relinquishes the mutable reference. Line 2 does a read (search), but also grabs a mutable reference to a new location. Line 3 writes to this location.
To get the linked list implementation right, I recommend https://rust-unofficial.github.io/too-many-lists/
Related
I haven't found an answer to this in other questions.
I have reduced my problem to the following:
use std::sync::RwLock;
pub fn main() {
iter_lock().for_each(|v| {
println!("{}", v);
});
}
fn get_lock<'a>() -> &'a RwLock<Vec<u32>> {
static mut lock: RwLock<Vec<u32>> = RwLock::new(Vec::new());
unsafe { &lock }
}
fn iter_lock<'a>() -> impl std::iter::Iterator<Item = &'a u32> {
get_lock().read().unwrap().iter()
}
playground
The code above will not compile and give the following error:
error[E0515]: cannot return reference to temporary value
--> src/main.rs:15:5
|
15 | get_lock().read().unwrap().iter()
| --------------------------^^^^^^^
| |
| returns a reference to data owned by the current function
| temporary value created here
|
= help: use `.collect()` to allocate the iterator
Note that the static mut is not necessary in the code above, but I need it because I need to define a variable inside of an impl block.
I need to return an iterator, not a Vec because I am trying to avoid any allocations, and this function will always be used to iterate.
How can I solve this issue? I'm not afraid of using unsafe code, so unsafe suggestions are also welcome.
You can try something like this:
use std::sync::{RwLock, RwLockReadGuard};
pub fn main() {
let data = Data::new(&[1, 2, 3]);
data.iter().for_each(|x| println!("{:?}", x));
}
struct Data {
inner: RwLock<Vec<u32>>,
}
impl Data {
fn new(vec: &[u32]) -> Self {
Self {
inner: RwLock::new(vec.to_vec()),
}
}
fn iter(&self) -> Iter<'_> {
let d = self.inner.read().unwrap();
Iter::new(d)
}
}
struct Iter<'a> {
inner: RwLockReadGuard<'a, Vec<u32>>,
current_index: usize,
}
impl<'a> Iter<'a> {
pub fn new(inner: RwLockReadGuard<'a, Vec<u32>>) -> Iter<'a> {
Self {
inner,
current_index: 0,
}
}
}
impl Iterator for Iter<'_> {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if self.current_index >= self.inner.len() {
return None;
}
let item = &self.inner[self.current_index];
self.current_index += 1;
Some(*item)
}
}
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.
I want to implement a Iterator for a struct so easily loop over an inner field but I can't get it to work.
The return from IterWrapper::next() is faulty.
Maybe there is an easier solution to accomplish this.
struct Wrapper {
pub items: Vec<String>
}
struct IterWrapper<'a> {
inner: &'a std::slice::Iter<'a, String>,
}
impl<'a> Iterator for IterWrapper<'a> {
type Item = &'a String;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next();
}
}
impl Wrapper {
fn iter<'a>(&'a self) -> IterWrapper<'a> {
IterWrapper {
inner: &self.items.iter(),
}
}
}
fn main() {
let w = Wrapper {
items: vec![String::from("test1"), String::from("test2")]
};
for item in w.iter() {
println!("{}", item);
}
}
error[E0308]: mismatched types
--> src/main.rs:13:27
|
13 | fn next(&mut self) -> Option<Self::Item> {
| ---- ^^^^^^^^^^^^^^^^^^ expected enum `std::option::Option`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
14 | self.inner.next();
| - help: consider removing this semicolon
|
= note: expected enum `std::option::Option<&std::string::String>`
found unit type `()`
There are a couple changes that you have to make:
struct Wrapper {
pub items: Vec<String>
}
struct IterWrapper<'a> {
// this needs to own the iterator, not a reference to it
// in order to avoid returning a borrowed value
inner: std::slice::Iter<'a, String>,
}
impl<'a> Iterator for IterWrapper<'a> {
type Item = &'a String;
fn next(&mut self) -> Option<Self::Item> {
// no semicolon here so the result is implicitly returned
// your old error happened because the semicolon causes the value to not be returned
self.inner.next()
}
}
impl Wrapper {
fn iter<'a>(&'a self) -> IterWrapper<'a> {
IterWrapper {
// give the iterator, not the reference to it
inner: self.items.iter(),
}
}
}
fn main() {
let w = Wrapper {
items: vec![String::from("test1"), String::from("test2")]
};
for item in w.iter() {
println!("{}", item);
}
}
I have a struct that lazily load data into an inner vector (but for the example this is ommited). Then I am implementing IntoIterator and Iterator for the IntoIterator type:
struct EntryOwned(u32);
struct Entry<'a>(&'a u32);
impl<'a> EntryOwned {
fn to_entry(&'a self) -> Entry<'a> {
Entry(&self.0)
}
}
struct LazyStruct {
cache: Vec<EntryOwned>,
}
impl<'a> LazyStruct {
fn new(data: Vec<EntryOwned>) -> LazyStruct {
Self {
cache: data,
}
}
fn get_entry(&'a self, index: usize) -> Option<Entry<'a>> {
match self.cache.get(index) {
Some(entry_owned) => Some(entry_owned.to_entry()),
None => None,
}
}
}
impl<'a> IntoIterator for &'a mut LazyStruct {
type Item = Entry<'a>;
type IntoIter = LazyStructIter<'a>;
fn into_iter(self) -> Self::IntoIter {
LazyStructIter {
inner: self,
current_index: 0,
}
}
}
struct LazyStructIter<'a> {
inner: &'a mut LazyStruct,
current_index: usize,
}
impl<'a> LazyStructIter<'a> {
fn next_item(&'a mut self) -> Option<Entry<'a>> {
if self.current_index > self.inner.cache.len() {
return None;
}
let ret = self.inner.get_entry(self.current_index);
self.current_index += 1;
ret
}
}
impl<'a> Iterator for LazyStructIter<'a> {
type Item = Entry<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.next_item()
}
}
Which yields me to a lifetime issue:
Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:64:14
|
64 | self.next_item()
| ^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 63:5...
--> src/main.rs:63:5
|
63 | / fn next(&mut self) -> Option<Self::Item> {
64 | | self.next_item()
65 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:64:9
|
64 | self.next_item()
| ^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 60:6...
--> src/main.rs:60:6
|
60 | impl<'a> Iterator for LazyStructIter<'a> {
| ^^
note: ...so that the types are compatible
--> src/main.rs:64:14
|
64 | self.next_item()
| ^^^^^^^^^
= note: expected `&mut LazyStructIter<'_>`
found `&mut LazyStructIter<'a>`
The lifetime of the references should be bind to the LazyStruct, but I cannot change the Iter trait do not accept any lifetime specifier.
I have already check some answers to similar issues:
Iterator returning items by reference, lifetime issue
How do I write an iterator that returns references to itself?
EDIT: The Entry is a more complex data structure and it is not possible to copy it. I have to bind it to a specific lifetime since it contains references to things.
One of them points that the iterator should hold a reference to the original collection instead of owning it since it is not allowed to return a reference with the self lifetime. But I could't make it work.
So, how should I play the references here?
Here is the playground example
You can't.
You require that each item returned by next() has a reference with a lifetime tied to the
existence of the LazyStructIter iterator.
This it is not possible with the Iterator interface:
pub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
But it would be possible with a trait defined as:
trait FakeIterator<'a> {
type Item;
fn next(&'a mut self) -> std::option::Option<Self::Item>;
}
impl<'a> FakeIterator<'a> for LazyStructIter<'a> {
type Item = Entry<'a>;
fn next(&'a mut self) -> Option<Self::Item> {
self.next_item()
}
}
Tha capability to have a kind of iterator which returns items borrowing from self is the goal of
RFC 1598 - GAT.
See also this article for a collection of workarounds about this topic.
Generally you don't need to specify lifetimes in rust unless 1 of two things is true, the reference is bound to an owner that isn't known, or a reference that is static. Rust says it expected '_ lifetime, which means it understands the ownership and borrows on its own.
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c54f5f2f24e635dcfaa0fcbf69fa4ce0
struct EntryOwned(u32);
struct Entry(u32);
impl EntryOwned {
fn to_entry(&self) -> Entry {
Entry(self.0)
}
}
struct LazyStruct {
cache: Vec<EntryOwned>,
}
impl LazyStruct {
fn new(data: Vec<EntryOwned>) -> LazyStruct {
Self {
cache: data,
}
}
fn get_entry(&self, index: usize) -> Option<Entry> {
match self.cache.get(index) {
Some(entry_owned) => Some(entry_owned.to_entry()),
None => None,
}
}
}
impl IntoIterator for LazyStruct {
type Item = Entry;
type IntoIter = LazyStructIter;
fn into_iter(self) -> Self::IntoIter {
LazyStructIter {
inner: self,
current_index: 0,
}
}
}
struct LazyStructIter {
inner: LazyStruct,
current_index: usize,
}
impl LazyStructIter {
fn next_item(&mut self) -> Option<Entry> {
if self.current_index > self.inner.cache.len() {
return None;
}
let ret = self.inner.get_entry(self.current_index);
self.current_index += 1;
ret
}
}
impl Iterator for LazyStructIter {
type Item = Entry;
fn next(&mut self) -> Option<Self::Item> {
self.next_item()
}
}
fn main() {
// let json_data = r#"{"item_1" : 10, "item_2" : 100, "item_3" : 1000}"#;
// if let Ok(data) = serde_json::from_str::<A>(json_data) {
// println!("{:?}", data);
// }
// else if let Ok(data) = serde_json::from_str::<B>(json_data) {
// println!("{:?}", data);
// }
for _ in 0..0 {
println!("foo");
}
}
After removing the lifetime specifications, it compiles fine and runs.
The program below compiles and runs if Rc is replaced with Box. Why doesn't it compile when using reference counting? This is a question about the difference between Rc<T> and Box<T>.
use std::rc::Rc;
#[derive(Debug, Clone)]
pub enum ILst {
Nil,
Cons(i32, Rc<ILst>),
}
impl ILst {
pub fn new() -> Self {
ILst::Nil
}
pub fn cons(self, item: i32) -> Self {
ILst::Cons(item, Rc::new(self))
}
pub fn car(&self) -> Option<i32> {
match *self {
ILst::Cons(u, ref _v) => Some(u),
ILst::Nil => None,
}
}
pub fn cdr(&self) -> Self {
match *self {
ILst::Cons(_u, ref v) => *v.clone(),
ILst::Nil => ILst::Nil,
}
}
}
fn main() {
let list = ILst::new().cons(17).cons(29);
let rest = list.cdr();
println!("list = {:?}", rest);
}
error[E0507]: cannot move out of borrowed content
--> src/main.rs:27:38
|
27 | ILst::Cons(_u, ref v) => *v.clone(),
| ^^^^^^^^^^ cannot move out of borrowed content
The solution seems to be to replace
*v.clone()
with
Rc::deref(v).clone()
and then add the line
use::ops::Deref;
to the beginning of the program.