Need vector slices to live longer - vector

Is there any way to get the slices of this vector to last long enough so that I can use them in this kind of circular structure?
fn populate_chain(file_path: &str) -> HashMap<String, HashSet<&String>> {
println!("loading...");
let time = util::StopWatch::new();
let mut words = HashMap::new();
{
let f = |mut x: Vec<String>| {
let word = x.pop().unwrap();
words.insert(word, HashSet::new());
};
Csv::process_rows(f, file_path, "\t");
}
let col: Vec<(String, HashSet<&String>)> = words.clone().into_iter().collect();
let m: usize = col.len() - 1;
for i in 0..m {
let ref k: String = col[i].0;
for j in i..m {
let ref nk: String = col[j].0;
if check_link(k, nk) {
words.get_mut(k).unwrap().insert(nk);
words.get_mut(nk).unwrap().insert(k);
}
}
}
time.print_time();
words
}
I'm using the double for loops to chain words together which are related so that they can be quickly looked up later.
Here are the compiler errors...
error: `col` does not live long enough
--> src/main.rs:28:29
|
28 | let ref k: String = col[i].0;
| ^^^ does not live long enough
...
40 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the block at 13:72...
--> src/main.rs:13:73
|
13 | fn populate_chain(file_path: &str) -> HashMap<String, HashSet<& String>>{
| ^
error: `col` does not live long enough
--> src/main.rs:30:34
|
30 | let ref nk: String = col[j].0;
| ^^^ does not live long enough
...
40 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the block at 13:72...
--> src/main.rs:13:73
|
13 | fn populate_chain(file_path: &str) -> HashMap<String, HashSet<& String>>{
|

I can tell you from your function signature that you're going to have big problems trying to write this function, at least if you want it to contain non-empty HashSets in the result.
fn populate_chain(file_path: &str) -> HashMap<String, HashSet<&String>>
This function signature has references in it; they have elided lifetimes. If you make the inferred lifetimes explicit, it would look like this:
fn populate_chain<'a>(file_path: &'a str) -> HashMap<String, HashSet<&'a String>>
In other words: This function claims that, given some string slice with lifetime 'a, it will give back a collection that holds String objects with lifetime 'a.
But you have no means for allocating such String objects within your code. :(
So, you're stuck; no matter what you put into that function body, you're not going to be able to supply an implementation that returns a non-trivial result with respect to the HashSets.
However, all is not lost. You could, for example, revise your function so that it also takes as an additional parameter a reference to a TypedArena with an appropriate lifetime, and then allocate the strings there. Another (simpler) option would be to use HashSet<String> instead of HashSet<&String>...

Related

Add value to a HashSet in Rust and add a reference to it to another datastructure

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);
}

executing method on variable pointer moves the variable itself?

I'm using the rusqlite crate and am doing some queries, basically i'm just trying to check the length of the query results before trying to proceed, however I'm running into error[E0382]: use of moved value: key_rows whilst trying to compile, I don't understand since i'm borrowing a reference to the variable so it wouldn't move it's local in memory?
Maybe it's due to the method i'm calling on the variable's pointer?
Full compiler error:
error[E0382]: use of moved value: `key_rows`
--> src/handle.rs:126:16
|
108 | let key_rows = key_stmt.query_map(&[(":key", key.as_str())], |row| {
| -------- move occurs because `key_rows` has type `MappedRows<'_, [closure#src/handle.rs:108:66: 113:6]>`, which does not implement the `Copy` trait
...
117 | if(&key_rows.count() == &0){
| ------- `key_rows` moved due to this method call
...
126 | for row in key_rows {
| ^^^^^^^^ value used here after move
|
note: this function takes ownership of the receiver `self`, which moves `key_rows`
Erroneous code:
let mut key_stmt = conn.prepare("SELECT id , key FROM key_table WHERE key = :key;").unwrap();
let key_rows = key_stmt.query_map(&[(":key", key.as_str())], |row| {
Ok(Table {
id: row.get(0)?,
payload: row.get(1)?,
})
}).unwrap();
//Checking that the key exists:
if(&key_rows.count() == &0){
panic!("Can't find the key...")
}
//Putting in a default value since the compiler is worried.
let mut reference_id : i32 = 0;
//For loop is nessessary since MappedRow type cannot be indexed regularly (weird)
for row in key_rows {
reference_id = row.unwrap().id;
println!("{:?}", reference_id.to_string());
}
You aren't borrowing key_rows then checking the count, but rather calling key_rows.count(), then borrowing the result.
Iterator#count consumes the entire iterator, returning how many elements were traversed.
let mut reference_id = key_rows.next().unwrap_or_else(|| panic!("Can't find the key..."));
// Remove the code past this point if you are only expecting one, or the first value.
for row in key_rows {
reference_id = row.unwrap().id;
println!("{:?}", reference_id.to_string());
}

How could the result of Arc::clone have a 'static lifetime?

Let's begin with a canonical example of Arc
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let msg = Arc::new(Mutex::new(String::new()));
let mut handles = Vec::new();
for _ in 1..10 {
let local_msg = Arc::clone(&msg);
handles.push(thread::spawn(move || {
let mut locked = local_msg.lock().unwrap();
locked.push_str("hello, world\n");
}));
}
for handle in handles {
handle.join().unwrap();
}
println!("{}", msg.lock().unwrap());
}
This compiles and runs as expected. Then I realized maybe the Mutex doesn't have to live on the heap and started wondering if I can get rid of Arc and just use a shared reference to a Mutex allocated on the stack. Here is my attempt
use std::sync::Mutex;
use std::thread;
fn main() {
let msg = Mutex::new(String::new());
let mut handles = Vec::new();
for _ in 1..10 {
let local_msg = &msg;
handles.push(thread::spawn(move || {
let mut locked = local_msg.lock().unwrap();
locked.push_str("hello, world\n");
}));
}
for handle in handles {
handle.join().unwrap();
}
println!("{}", msg.lock().unwrap());
}
This one doesn't compile, though
error[E0597]: `msg` does not live long enough
--> src/main.rs:8:25
|
8 | let local_msg = &msg;
| ^^^^ borrowed value does not live long enough
9 | handles.push(thread::spawn(move || {
| ______________________-
10 | | let mut locked = local_msg.lock().unwrap();
11 | | locked.push_str("hello, world\n");
12 | | }));
| |__________- argument requires that `msg` is borrowed for `'static`
...
20 | }
| - `msg` dropped here while still borrowed
error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.
error: could not compile `hello`
To learn more, run the command again with --verbose.
The compiler complains that local_msg doesn't have a 'static lifetime. Well, it doesn't, so the error makes sense. However, this implies the variable let local_msg = Arc::clone(&msg); in the first snippet has 'static lifetime, otherwise I should get a similar error.
Questions:
How could Arc::clone(&msg) get a 'static lifetime? The value it points to isn't known at compile-time, and could die before the whole program exits.
As a bonus, what about other heap-backed smart pointers like Box and Rc? Do they all have a 'static lifetime because the borrow checker ensures that as long as these pointers are visible, then the addresses they point to are always valid?
The thing the compiler is looking for is a lifetime bound. A lifetime bound of 'a doesn't mean “this type is a reference with lifetime 'a”, but rather “all of the references this type contains have lifetimes of at least 'a”.
(When a lifetime bound is written explicitly, it looks like where T: 'a.)
Thus, any type which does not contain any references (or rather, has no lifetime parameters) automatically satisfies the 'static lifetime bound. If T: 'static, then Arc<T>: 'static (and the same for Box and Rc).
How could Arc::clone(&msg) get a 'static lifetime? The value it points to isn't known at compile-time, and could die before the whole program exits.
It does not point to the value using a reference, so it's fine. The type of your value is Arc<Mutex<String>>; there are no lifetime parameters here because there are no references. If it were, hypothetically, Arc<'a, Mutex<String>> (a lifetime parameter which Arc doesn't actually have), then that type would not satisfy the bound.
The job of Arc (or Rc or Box) is to own the value it points to. Ownership is not a reference and thus not subject to lifetimes.
However, if you had the type Arc<Mutex<&'a str>> then that would not satisfy the bound, because it contains a reference which is not 'static.

How to use an async closure both capturing and accepting references

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.

How to call to_socket_addrs on a collection of addresses?

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);
}

Resources