Here is a really simple attempt at a 2D Vec. I'm trying to add an element to the last entry in the top-level Vec:
fn main() {
let mut vec_2d = vec![vec![]];
if let Some(v) = vec_2d.last() {
v.push(1);
}
println!("{:?}", vec_2d);
}
I get this error:
error[E0596]: cannot borrow `*v` as mutable, as it is behind a `&` reference
--> src/main.rs:4:9
|
3 | if let Some(v) = vec_2d.last() {
| - help: consider changing this to be a mutable reference: `&mut std::vec::Vec<i32>`
4 | v.push(1);
| ^ `v` is a `&` reference, so the data it refers to cannot be borrowed as mutable
I've also tried Some(ref v) and Some(ref mut v) with the same results. I can't find any documentation that describes this error specifically. What is the right approach here?
An answer to a similar question recommends something more like Some(&mut v). Then I get these errors:
error[E0308]: mismatched types
--> src/main.rs:3:17
|
3 | if let Some(&mut v) = vec_2d.last() {
| ^^^^^^ types differ in mutability
|
= note: expected type `&std::vec::Vec<_>`
found type `&mut _`
= help: did you mean `mut v: &&std::vec::Vec<_>`?
If I try Some(&ref mut v) I get:
error[E0596]: cannot borrow data in a `&` reference as mutable
--> src/main.rs:3:18
|
3 | if let Some(&ref mut v) = vec_2d.last() {
| ^^^^^^^^^ cannot borrow as mutable
Grab a mutable reference to the last element with last_mut; no need to change patterns.
fn main() {
let mut vec_2d = vec![vec![]];
if let Some(v) = vec_2d.last_mut() {
v.push(1);
}
println!("{:?}", vec_2d);
}
A (much) more elegant solution for this particular case would be:
fn main() {
let vec_2d = vec![vec![1i32]];
println!("{:?}", vec_2d);
}
Related
I'm trying to return a Vector from a function. This happens in a loop and I need the values to exist outside of the loop. Since I perform the return multiple times and I only need the unique values, I thought I use a HashSet for this, in which I insert and then try to get a reference to the value in the next line.
I need a reference to the value in multiple other datastructures and don't want to duplicate the actual values. The values don't need to be mutable.
What I tried
use std::collections::HashSet;
fn main() {
let mut vec: Vec<&str> = Vec::new();
let mut books = HashSet::new();
for i in 0..5 {
// This could be a function call, which returns a vector of objects, which should all be
// stored centrally and uniquely in a HashSet
books.insert("A Dance With Dragons".to_string());
let mut reference: &str = books.get("A Dance With Dragons").unwrap();
// This would be done for multiple "refering" datastructures
vec.push(reference);
}
}
What I was expecting
Getting a pointer to the String in the HashSet for future use.
What actually happens
error[E0502]: cannot borrow `books` as mutable because it is also borrowed as immutable
--> src/main.rs:10:9
|
10 | books.insert("A Dance With Dragons".to_string());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
11 |
12 | let mut reference: &str = books.get("A Dance With Dragons").unwrap();
| --------------------------------- immutable borrow occurs here
13 | // This would be done for multiple "refering" datastructures
14 | vec.push(reference);
| ------------------- immutable borrow later used here
For more information about this error, try `rustc --explain E0502`.
warning: `set_test` (bin "set_test") generated 2 warnings
error: could not compile `set_test` due to previous error; 2 warnings emitted
I think I'm missing a very obvious solution to this...
Thanks in advance for helping.
You can't do this
use std::collections::HashSet;
fn main() {
let mut v: Vec<&str> = Vec::new();
let mut books = HashSet::new();
for i in 0..5 {
// this needs to borrow mutably
books.insert("A Dance With Dragons".to_string());
// this reference has to live as long as v
// so on the second iteration books is still borrowed
// which means you can't borrow it mutably any more.
let reference: &str = books.get("A Dance With Dragons").unwrap();
v.push(reference);
}
// v only goes out of scope here
}
You might find success in separating mutation and referencing like this:
fn main() {
let mut books = HashSet::new();
for i in 0..5 {
books.insert("A Dance With Dragons".to_string());
}
let v: Vec<&str> = books.iter().collect();
}
Or by using a Rc like pigeonhgands suggests.
fn main() {
let mut v: Vec<Rc<str>> = Vec::new();
let mut books = HashSet::new();
for i in 0..5 {
books.insert(Rc::new("A Dance With Dragons".to_string()));
// note: this clone is cheap cause it only clones the `Rc` not the whole String.
let reference = books.get("A Dance With Dragons").unwrap().clone();
v.push(reference);
}
}
The issue is that's the value in "book" could be removed and you try to save reference in a vector. It is a risk of null pointer.
You need to build book in imutable way, like this
use std::collections::HashSet;
fn main() {
let mut vec: Vec<&str> = Vec::new();
let books: HashSet<String> = vec!(
"A Dance With Dragons".to_string(),
"A Dance With Dragons".to_string()).into_iter().collect();
let reference: &str = books.get("A Dance With Dragons").unwrap();
vec.push(reference);
}
I am trying to pass a closure returning Future<Output=bool> to an async function and call this closure as an async predicate (something like an async .filter or other higher-order function).
This predicate receives its input as a reference. I found how to implement it for pure predicates that do not capture their environment:
type BoxFuture<'a, Out> = Pin<Box<dyn Future<Output=Out> + 'a + Send>>;
////////////////////////////////////////////////////////////////////////////////
// 1 -> Closure only uses the inner argument //
////////////////////////////////////////////////////////////////////////////////
/// Run the computation and check that its output is not empty
fn run1<'a>(expected: &'a [u8]) -> impl Future<Output=()> + 'a {
async move {
let is_ok = compute_and_check1(|b: &[u8]| Box::pin(async move {
b.len() > 0 // Only uses the inner argument
}));
let is_ok1 = is_ok.await;
dbg!(is_ok1);
}
}
/// Compute some bytes (may be complex / use async), then check their validity
/// with a user-supplied function, finally do some clean-up and return.
async fn compute_and_check1<F>(check: F) -> bool
where
F: for<'r> FnOnce(&'r [u8]) -> BoxFuture<'r, bool>
{
let bytes = [0u8; 128];
let is_ok = check(&bytes).await;
drop(bytes);
is_ok
}
Playground link
Supporting only non-capturing closures is quite limiting. I would like to use a closure that captures its environment. By changing the bounds of my compute_and_check function, I am able to pass a closure that uses its environment - but not its input:
type BoxFuture<'a, Out> = Pin<Box<dyn Future<Output=Out> + 'a + Send>>;
////////////////////////////////////////////////////////////////////////////////
// 2 -> Closure only uses the outer argument //
////////////////////////////////////////////////////////////////////////////////
/// Run the computation and assume that its output is not empty if `expected` is not empty
fn run2<'a>(expected: &'a [u8]) -> impl Future<Output=()> + 'a {
async move {
let is_ok = compute_and_check2(|b: &[u8]| Box::pin(async move {
expected.len() > 0 // Only uses the environment
}));
let is_ok2 = is_ok.await;
dbg!(is_ok2);
}
}
/// Compute some bytes (may be complex / use async), then check their validity
/// with a user-supplied function, finally do some clean-up and return.
async fn compute_and_check2<'a, F>(check: F) -> bool
where
F: for<'r> FnOnce(&'r [u8]) -> BoxFuture<'a, bool>
{
let bytes = [0u8; 128];
let is_ok = check(&bytes).await;
drop(bytes);
is_ok
}
Playground link
I can write an implementation where the closure uses its input, and one where the closure uses its environment. But not both at the same time.
How can I accept a Future-producing closure that uses references for both its input and environment?
What I would like to write is something like this:
type BoxFuture<'a, Out> = Pin<Box<dyn Future<Output=Out> + 'a + Send>>;
////////////////////////////////////////////////////////////////////////////////
// 3 -> Closure uses both the inner and outer arguments //
////////////////////////////////////////////////////////////////////////////////
/// Run the computation and check its output is the provided expected value
fn run3<'a>(expected: &'a [u8]) -> impl Future<Output=()> + 'a {
async move {
let is_ok = compute_and_check3(|b: &[u8]| Box::pin(async move {
b == expected // Uses both the input and environment
}));
let is_ok2 = is_ok.await;
dbg!(is_ok2);
}
}
/// Compute some bytes (may be complex / use async), then check their validity
/// with a user-supplied function, finally do some clean-up and return.
async fn compute_and_check3<'a, F>(check: F) -> bool
where
F: for<'r> FnOnce(&'r [u8]) -> BoxFuture<'r + 'a, bool>
{
let bytes = [0u8; 128];
let is_ok = check(&bytes).await;
drop(bytes);
is_ok
}
Playground link
This code does not compile because I am asking the closure to return BoxFuture<'r + 'a, bool> but this is not legal syntax:
error[E0226]: only a single explicit lifetime bound is permitted
--> src/main.rs:89:51
|
89 | F: for<'r> FnOnce(&'r [u8]) -> BoxFuture<'r + 'a, bool>
| ^^
From what I understand, the core of my issue is that I need to restrict my Higher-Ranked Trait Bound. Instead of "for any 'r", I want to say "for any 'r that does not outlive 'a" but I don't see how to write it down.
I tried to use two lifetimes and restrictions to my BoxFuture type alias, or define an auxilliary trait but I did not manage to solve this issue because I fail to apply restrictions on the HRTB lifetime.
For completness, here are the errors I get when passing my final closure to compute_and_check1 (only input) and compute_and_check2 (only environment):
Using compute_and_check1 (only input) playground link
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:17:67
|
17 | let is_ok = compute_and_check1(|b: &[u8]| Box::pin(async move {
| ___________________________________________________________________^
18 | | b == expected
19 | | }));
| |_____^
|
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 15:9...
--> src/main.rs:15:9
|
15 | fn run3<'a>(expected: &'a [u8]) -> impl Future<Output=()> + 'a {
| ^^
note: ...so that the types are compatible
--> src/main.rs:17:67
|
17 | let is_ok = compute_and_check1(|b: &[u8]| Box::pin(async move {
| ___________________________________________________________________^
18 | | b == expected
19 | | }));
| |_____^
= note: expected `(&[u8], &[u8])`
found `(&[u8], &'a [u8])`
note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the body at 17:36...
--> src/main.rs:17:36
|
17 | let is_ok = compute_and_check1(|b: &[u8]| Box::pin(async move {
| ____________________________________^
18 | | b == expected
19 | | }));
| |______^
note: ...so that the expression is assignable
--> src/main.rs:17:47
|
17 | let is_ok = compute_and_check1(|b: &[u8]| Box::pin(async move {
| _______________________________________________^
18 | | b == expected
19 | | }));
| |______^
= note: expected `Pin<Box<dyn Future<Output = bool> + Send>>`
found `Pin<Box<dyn Future<Output = bool> + Send>>`
Using compute_and_check2 (only environment) playground link
error: lifetime may not live long enough
--> src/main.rs:17:47
|
17 | let is_ok = compute_and_check2(|b: &[u8]| Box::pin(async move {
| ________________________________________-____-_^
| | | |
| | | return type of closure is Pin<Box<(dyn Future<Output = bool> + Send + '2)>>
| | let's call the lifetime of this reference `'1`
18 | | b == expected
19 | | }));
| |______^ returning this value requires that `'1` must outlive `'2`
I have also looked into the unboxed_closure nightly feature but did not manage to solve my issue. I would prefer my code to work on stable Rust but it is acceptable for my code to require nightly if it is the only solution.
I am trying to write a function that prints a vector. I am having some trouble in understanding how to pass a vector as a parameter. This is what I have so far:
fn vecprinter(v1: &mut Vec<u32>) -> Vec<u32> {
v1
}
fn main(){
let mut v1=vec![1,10,11,12,13];
println!("{:?}", vecprinter(v1));
}
However I am getting this error:
error[E0308]: mismatched types
--> main.rs:3:1
|
1 | fn vecprinter(v1: &mut Vec<u32>) -> Vec<u32> {
| -------- expected `std::vec::Vec<u32>` because of return type
2 |
3 | v1
| ^^
| |
| expected struct `std::vec::Vec`, found mutable reference
| help: try using a conversion method: `v1.to_vec()`
|
= note: expected struct `std::vec::Vec<u32>`
found mutable reference `&mut std::vec::Vec<u32>`
error[E0308]: mismatched types
--> main.rs:10:31
|
10 | println!("{:?}", vecprinter(v1));
| ^^
| |
| expected mutable reference, found struct `std::vec::Vec`
| help: consider mutably borrowing here: `&mut v1`
|
= note: expected mutable reference `&mut std::vec::Vec<u32>`
found struct `std::vec::Vec<{integer}>`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.
compiler exit status 1
What am I doing wrong?
You have two issues here.
Firs your vecprinter method takes a &mut Vec<u32 as a parameter, but you are passing it a Vec<u32> in your call to println!. To resolve this pass a mutable reference t to the vec instead:
println!("{:?}", vecprinter(&mut v1));
The second issue is with the return types of the vecprinter method. You are taking in a &mut Vec<u32> and expecting to return a Vec<u32>; however, when you return the value of v1 you are returning a &mut Vec<u32> rather than the expected Vec<u32>. Depending on your requirements you have two options.
Change the return type of the vecprinter method and pass a mutable reference:
fn vecprinter(v1: &mut Vec<u32>) -> &mut Vec<u32> {
v1
}
fn main(){
let mut v1=vec![1,10,11,12,13];
println!("{:?}", vecprinter(&mut v1));
}
or change the parameter value to take the vector rather than a reference:
fn vecprinter(v1: Vec<u32>) -> Vec<u32> {
v1
}
fn main(){
let mut v1=vec![1,10,11,12,13];
println!("{:?}", vecprinter(v1));
}
You wrote in your question:
I am trying to write a function that prints a vector.
But the function you wrote (no matter if it works or not) is not writing anything: it returns the given vector.
A function which would print something would look like this:
fn print_something(to_print: /*Some type*/) /*No return type*/ {
println!(/*...*/);
}
As you want to print a vector of u32, the prototype could be:
fn print_something(to_print: Vec<u32>) { /*...*/ }
But if you do that, the argument will be moved into the function and will become unusable outside of it. In order to improve this, you can pass the argument as a reference:
fn print_something(to_print: &Vec<u32>) { /*...*/ }
To handle more general cases (&Vec<u32> + &[u32]), you can still improve it like this:
fn print_something(to_print: &[u32]) { /*...*/ }
Now when you call this function, you have to add an ampersamp & to the given argument (unless it's already a reference):
print_something(&my_vector);
Finally, by gluing everything together, you have this:
fn print_vec(v: &[u32]) {
println!("{:?}", v);
}
fn main() {
let v = vec![1, 10, 11, 12, 13];
print_vec(&v);
// Because we changed "&Vec<u32>" to "&[u32]", the following is also
// possible:
let arr = &[1, 10, 11, 12, 13];
print_vec(arr);
}
I need to iterate over a vector of mutable references; here is a simplified reproduction:
trait Ticking {
fn tick(&mut self);
}
trait Fish {}
struct World<'a> {
fish: Vec<&'a mut dyn Fish>,
}
impl<'a> Ticking for World<'a> {
fn tick(&mut self) {
let _fish: &mut dyn Fish = self.fish[0];
//let _fish: &mut dyn Fish = self.fish.get_mut(0).expect("expected value");
}
}
struct Guppy<'a> {
n_ref: &'a usize,
}
impl<'a> Fish for Guppy<'a> {}
fn main() {
let mut guppy: Guppy = Guppy { n_ref: &5 };
let _world: World = World {
fish: vec![&mut guppy],
};
}
I received the following error:
error[E0596]: cannot borrow data in an index of `std::vec::Vec<&mut dyn Fish>` as mutable
--> src/main.rs:15:36
|
15 | let _fish: &mut dyn Fish = self.fish[0];
| ^^^^^^^^^^^^ cannot borrow as mutable
|
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `std::vec::Vec<&mut dyn Fish>`
I attempted to call get_mut directly and received a lifetime bound error:
error[E0277]: the trait bound `&'a mut (dyn Fish + 'a): Fish` is not satisfied
--> src/main.rs:13:36
|
13 | let _fish: &mut dyn Fish = self.fish.get_mut(0).expect("expected value");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Fish` is not implemented for `&'a mut (dyn Fish + 'a)`
|
= note: required for the cast to the object type `dyn Fish`
The compiler explanations were unhelpful in determine the root cause here.
You are (1) using the wrong syntax for indexing and (2) your type mismatches:
let _fish: &mut &mut dyn Fish = &mut self.fish[0];
// ^^^^ 2 ^^^^ 1
There's no reason to have an explicit type here anyway:
let _fish = &mut self.fish[0];
See also:
How can I use `index_mut` to get a mutable reference?
What is the return type of the indexing operation?
The compiler incorrectly chooses the Index trait over the IndexMut trait here, and gives a factually wrong error message. I filed a bug for this behaviour, but it turns out that this is actually fixed in the beta and nightly versions of Rust. Beta will be released as stable next week, so in the future your code will just work.
In the meantime, there are several ways of making the code work on the current stable version and older versions of Rust. The most succinct way is to force the compiler to choose IndexMut by adding &mut only on the right-hand side of the assignment:
let _fish: &mut dyn Fish = &mut self.fish[0];
The right-hand side has type &mut &mut dyn Fish now, so a deref coercion will be applied by the compiler. Alternatively, you can explicitly dereference the right-hand side, *&mut self.fish[0].
How do I call to_socket_addrs() on an array or vector in Rust? The following code does not compile:
extern crate ws;
use std::net::ToSocketAddrs;
fn main() {
let addrs = ["127.0.0.1:8889", "127.0.0.1:0"]
.iter()
.flat_map(|a| a.to_socket_addrs());
ws::listen(addrs, |out| move |msg| out.send(msg));
}
error[E0277]: the trait bound `std::iter::FlatMap<std::slice::Iter<'_, &str>, std::result::Result<std::vec::IntoIter<std::net::SocketAddr>, std::io::Error>, [closure#src/main.rs:7:19: 7:42]>: std::net::ToSocketAddrs` is not satisfied
--> src/main.rs:8:5
|
8 | ws::listen(addrs, |out| move |msg| out.send(msg));
| ^^^^^^^^^^ the trait `std::net::ToSocketAddrs` is not implemented for `std::iter::FlatMap<std::slice::Iter<'_, &str>, std::result::Result<std::vec::IntoIter<std::net::SocketAddr>, std::io::Error>, [closure#src/main.rs:7:19: 7:42]>`
|
= note: required by `ws::listen`
It took me two hours to understand the error because "trait X is not implemented for std::iter::FlatMap" reads like the problem is caused by flat_map, instead of the demands of ws::listen.
to_socket_addrs returns a Result containing an iterator. Result itself implements IntoIterator, so flat_map flattens the result, but not the inner iterator, you need to do that in an extra step:
use std::net::ToSocketAddrs;
fn main() {
let addrs = ["127.0.0.1:8889", "127.0.0.1:0"]
.iter()
.flat_map(|a| a.to_socket_addrs())
.flatten()
.collect::<Vec<_>>();
println!("addrs = {:?}!", addrs);
}