These are chat archives for rust-lang/rust

8th
Jun 2018
VJ
@00imvj00
Jun 08 2018 00:27 UTC
@omni-viral and can we early drop static variable?
Zakarum
@omni-viral
Jun 08 2018 06:02 UTC
  1. Just like you did it. funcname::<'lifetime>
  1. static X: Mutex<Option<T>> = ... and then X.lock().take()
How to go around
I need to populate that m. This just an narrowed example
Denis Lisov
@tanriol
Jun 08 2018 07:48 UTC
@trsh Don't see any good ways, at least without NLL. Are you sure you really need this?
@tanriol yes. Whats NLL?
Fredrik Portström
@portstrom
Jun 08 2018 07:51 UTC
@trsh I don't understand why you make references of everything, and even references of references. Removing all the & signs, the code works: https://play.rust-lang.org/?gist=0e55df6f6420eb3df4165deaa0c296f6
Denis Lisov
@tanriol
Jun 08 2018 07:52 UTC
Non-lexical lifetimes, a future change in lifetime rules. It will be much more flexible, but at the moment it's nightly only.
@portstrom in my real code I am looping a vector
And parts for vector are references
Fredrik Portström
@portstrom
Jun 08 2018 07:54 UTC
@trsh It would be helpful to have some example code that is more similar to the real code.
Denis Lisov
@tanriol
Jun 08 2018 07:54 UTC
Could you please show or describe the real problem your code is trying to solve?
Well its long. I can paste a fragment that gives me headaches > https://pastebin.com/kqCGRZzt
error[E0499]: cannot borrow `*self` as mutable more than once at a time
  --> manu/src/applications/api/sockets/workers/processor/engine.rs:53:19
   |
53 |         let out = self.back_process(&nn);
   |                   ^^^^ mutable borrow starts here in previous iteration of loop
...
63 |     }
   |     - mutable borrow ends here
If I could undrestand the problem
..
Denis Lisov
@tanriol
Jun 08 2018 08:02 UTC
What's the signature of self.back_process?
fn back_process(&mut self, node: &Value) -> &Vec<Option<Value>> {
I narrowed the code down > https://pastebin.com/XNk0TH3y
Denis Lisov
@tanriol
Jun 08 2018 08:13 UTC
(a) at least in the current state, the function does not need to take &mut self as it does not mutate anything
@tanriol sorry I removed part accidentally > self.nodes_output.insert(*id, new_outputs);
The point is that I do need it mutable
Seems like when I want to return recursively a reference, eveything goes to hell
Denis Lisov
@tanriol
Jun 08 2018 08:18 UTC
What's the type of nodes_output?
nodes_output: HashMap<u64, Vec<Option<Value>>>,
Fredrik Portström
@portstrom
Jun 08 2018 08:20 UTC
@trsh There are some things that make the code more difficult to read, such as looping through a range of numbers and using as an index when you could do for input in inputs.iter() { and for c in connections.iter() {, and making a reference for nid and out_index just to dereference it on the next line, when you could simply remove the & and *.
@portstrom yeah, Im working on that. See last link
Denis Lisov
@tanriol
Jun 08 2018 08:21 UTC
So your idea is that nodes_output is append-only, Vecs inside are not mutated at all and thus keeping the references shall be safe. The problem is that the compiler does not know that.
When you call a method on &mut self, it assumes that could do anything... including, for example, dropping all data from node_outputs, which would make the references invalid.
hmm
So what could be the solution? I partly understood the point
Denis Lisov
@tanriol
Jun 08 2018 08:26 UTC
Is this part expected to be performance critical?
Fredrik Portström
@portstrom
Jun 08 2018 08:26 UTC
What type are self.nodes and self.nodes_output?
btw if I remove out_data.push(val);, the code compiles. The problem is that in 1st loop, the reference is barowed and not ready for next loops. as the compiler says
Fredrik Portström
@portstrom
Jun 08 2018 08:28 UTC
There's surely a solution, if I just get enough information to reproduce the error in the playground.
Denis Lisov
@tanriol
Jun 08 2018 08:28 UTC
The problem is that you collect references in out_data while, possibly, mutating underlying data.
@tanriol perf is critical :/
Denis Lisov
@tanriol
Jun 08 2018 08:29 UTC
The most trivial is to make nodes_output: HashMap<u64, Vec<Arc<Option<Value>>>> and clone the Arcs, but may be a performance problem if this code is hot.
Maybe I have to write code 0 and do it otherwise
Denis Lisov
@tanriol
Jun 08 2018 08:46 UTC
An alternate option with a tiny bit of unsafe (probably safe, but I don't know enough to be absolutely sure) is to make a wrapper around HashMap<Vec<T>> that can only be indexed to a slice, not a reference to the Vec, but allows insertion with &self
...looks like Aovec from the aovec crates already is such a wrapper.
Or passing the hashmap as param for the function
ugly and simple
Fredrik Portström
@portstrom
Jun 08 2018 08:51 UTC
I would probably go with passing a mutable reference to the hash map to the function.
Denis Lisov
@tanriol
Jun 08 2018 08:53 UTC
Does it actually work? I doubt so.
I think yes, but having moving problems value used here after move
When I pass let out = self.back_process(nn, ss); ss is moved so can't use later in code
Fredrik Portström
@portstrom
Jun 08 2018 08:55 UTC
I would like to show in the sandbox how it works if I could just get the type of self.nodes and the missing code that creates new_outputs.
I can reproduce in small example
Fredrik Portström
@portstrom
Jun 08 2018 08:56 UTC
I recommend using serde_derive rather than working on serde_json::Value. https://github.com/serde-rs/json#parsing-json-as-strongly-typed-data-structures
nodes is nodes: Option<&'a Value>,
@portstrom par of data will be static (predictable), par dynamic
So I cant glue it to a struct, I guess
Denis Lisov
@tanriol
Jun 08 2018 08:59 UTC
You're trying to keep references into a HashMap and mutate it at the same time. Not gonna fly. If it did, I'd consider it a bug.
Fredrik Portström
@portstrom
Jun 08 2018 09:02 UTC
Derived deserializers allow mixing predictable fields with unpredictable fields. I just can't find the documentation for that feature right now.
Maybe have to ditch the HashMap
ghh
Then I will need todo loops, to find the index
tnx
will read about Aovec
Zakarum
@omni-viral
Jun 08 2018 09:07 UTC
What's the best way to match on either lifetime parameter or type parameter inside < > in macro?
@tanriol is there a way to get the value from Vec as non-reference? make a copy?
Michal 'vorner' Vaner
@vorner
Jun 08 2018 09:14 UTC
.clone()
@vorner so clone allocates new memory?
Dmitriy
@dpogretskiy
Jun 08 2018 09:15 UTC
if you clone value it depends
Michal 'vorner' Vaner
@vorner
Jun 08 2018 09:15 UTC
It can. It depends on what type it is called on. For example, .clone on Arc just increases the reference count.
Fredrik Portström
@portstrom
Jun 08 2018 09:18 UTC
@portstrom good point
tnx
@vorner tnx for info
Will try to fix that code now
Btw I only use hashTree for fast index lookup. Maybe there something as fast as and even better.
?
Mutable hashMap keeping references
Denis Lisov
@tanriol
Jun 08 2018 09:44 UTC
You're not keeping references to something the HashMap owns in this example.
Fredrik Portström
@portstrom
Jun 08 2018 09:46 UTC
I see you have IDs for everything. You could put IDs instead of references in all data structures, and that would solve the problem of self-referencing data structures.
@tanriol can u quick make the example throw that error. so i better understand?
Denis Lisov
@tanriol
Jun 08 2018 09:52 UTC
Gotcha, tnx
If I barrow the reference of hashMap, I can further mess with it
@portstrom id based approach works like a charm. Instead of reference I pass id, and do not need to barrow references in loop
I mean other problems arrise, but getting further
:D
I mean besides removing brackets :D
Michal 'vorner' Vaner
@vorner
Jun 08 2018 12:18 UTC
@trsh: That thing looks somewhat suspicious and you probably want to avoid this situation in your design. But if you really need to do something like that, you need to either have something like Rc instead of „plain“ data, or put the i outside into an option, or like this:
Ok, clear tnx
@vorner still I dont understand. If this > https://play.rust-lang.org/?gist=4cf7320195675955ee7f3a11d1961951&version=stable&mode=debug > is bad design. How do I do it correctly. How do I fill hashMap with references?
Whats the correct Rust Way?
you can do this
in both cases you don't fill hashmap with references, since values are just copied into it
Zakarum
@omni-viral
Jun 08 2018 13:27 UTC
@trsh You you actually need to fill HashMap with references you must ensure that HasMap is dropped before any of referenced values
@dpogretskiy In your example you make HashMap<usize, &i32>
Dmitriy
@dpogretskiy
Jun 08 2018 13:28 UTC
@omni-viral yeah, my bad, i was too fast :smile:
use std::collections::HashMap;

fn main(){
    let gg: Vec<i32> = vec![1,2,3];
    let mut ss: HashMap<usize, &i32> = HashMap::new();

    for i in 0..gg.len() {
      let v = &gg[i];
      ss.insert(i, v);
    }
}
Zakarum
@omni-viral
Jun 08 2018 13:28 UTC
If you will replace iter() with into_iter() then it will br HashMap<usize, i32>
Dmitriy
@dpogretskiy
Jun 08 2018 13:29 UTC
this actually works
Zakarum
@omni-viral
Jun 08 2018 13:29 UTC
This is the same as example above that uses collect
Dmitriy
@dpogretskiy
Jun 08 2018 13:29 UTC
since scope item are dropped in reverse create order
Zakarum
@omni-viral
Jun 08 2018 13:29 UTC
But written manually
@dpogretskiy Not entirely. They have scope started at let and ended simulteneously
Drop wil be executed in any order
Dmitriy
@dpogretskiy
Jun 08 2018 13:31 UTC
but it doesn't compile that way, funny enough
use std::collections::HashMap;

fn main(){
    let gg: Vec<i32> = vec![1,2,3];

    let refs = gg.iter().enumerate().collect::<HashMap<usize, &i32>>();
    println!("{:?}", refs);
}
so this also works
Tom Sellman
@tsellman
Jun 08 2018 13:34 UTC
@omni-viral is this note in the original compiler error incorrect then? "= note: values in a scope are dropped in the opposite order they are created"
Zakarum
@omni-viral
Jun 08 2018 13:35 UTC
Maybe something changed :/
Maybe I mess that up with struct fields drop order...
Zakarum
@omni-viral
Jun 08 2018 13:44 UTC
Anyway HashMap::drop never tries to dereference stored references. So it is safe to drop it last
Hmmm
And what in the hell did the order change for a magic?
Dropping happens in reverse to definitions?
From error I concluded, that the LOOP is int's own scope, and all references are dropped in the end of it
Dmitriy
@dpogretskiy
Jun 08 2018 13:57 UTC
nah, it's only vec is dropped prior to hash map, which is a lifetime error
i mean, there can be some awkward stuff in Drop definition, so there should be strict rule on drop order.
and creation order vs reverse create order makes sense, since there is higher probability of predicating new values on older ones, and not reverse :)
Btw thanks for the input
The vector I want to put in hash is dependent on some index.
Dmitriy
@dpogretskiy
Jun 08 2018 14:20 UTC
use std::collections::HashMap;

fn get_big_vec(index: i32) -> Vec<i32> {
    vec![1, 2, 3]
}

fn main() {
    let vecs = (0..2)
        .map(|id| get_big_vec(id).to_vec())
        .collect::<Vec<_>>();
    let ss = vecs.iter()
        .flat_map(|v| v.iter().enumerate())
        .collect::<HashMap<usize, &i32>>();

    println!("{:?}", ss);
}
it depends on where you wan't to enumerate them
on top level or bottom level
use std::collections::HashMap;

fn get_big_vec(index: i32) -> Vec<i32> {
    vec![1, 2, 3]
}

fn main() {
    let vecs = (0..2)
        .map(|id| get_big_vec(id).to_vec())
        .collect::<Vec<_>>();

    let ss = vecs.iter()
        .flat_map(|v| v.iter())
        .enumerate()
        .collect::<HashMap<usize, &i32>>();

    println!("{:?}", ss);
}
{0: 1, 2: 3, 5: 3, 3: 1, 4: 2, 1: 2}
this is last one
if enumerate is inside you get {1: 2, 0: 1, 2: 3} as you start from 0 for each vec you get from get_big_vec(id)
look at flat_map closely, it's very useful when you deal with nested stuff
Gotchya! And loops stay the same
Dmitriy
@dpogretskiy
Jun 08 2018 14:25 UTC
yeah, you just need to pin your vecs in place before you do anything with them
Will try this in my project
Lesson learned
I come from python, js, ts.. so its bit alien to me.. even after a lot of reading and expirmenting
@dpogretskiy SPASIBO pacan! :D
Dmitriy
@dpogretskiy
Jun 08 2018 14:27 UTC
take your time, it's somewhat alien to all mortals :laughing:
I apologies if your not from rus, just your name...
Dmitriy
@dpogretskiy
Jun 08 2018 14:28 UTC
I am, what can i say, nice meme breh
:smile:
Ash
@ashthespy
Jun 08 2018 14:42 UTC

Hello again! I have a question about the source of the documentation on docs.rs.

For example - I am using the futures crate (futures = "0.1.8") but the docs don't seem to match the available functions.

Even though I believe I am using 0.1.8 when I attempt Sender::poll_complete() the compiler complains that it's not implemented,
Dmitriy
@dpogretskiy
Jun 08 2018 15:07 UTC
So you do something like Sended::poll_complete(&mut sender)
or something like sender.poll_complete()
where sender happens to be mut
pub struct Sender;

trait Poll {
    fn poll_complete(&mut self) -> Result<(), ()>;
}

impl Poll for Sender {
    fn poll_complete(&mut self) -> Result<(), ()> {
        Ok(())
    }
}

fn main() {
    let mut sender = Sender;

    Sender::poll_complete(&mut sender);
    sender.poll_complete();
}
Dmitriy
@dpogretskiy
Jun 08 2018 15:12 UTC
both of those are valid, but Sender::poll_complete(); doesn't exists
If not just check Cargo.lock for exact versions of your libraries
@dpogretskiy still it all goes to hell if you must work with pointers > https://play.rust-lang.org/?gist=b72c916468b7c7a8fdccb8d0345cdbd9&version=stable&mode=debug
Dmitriy
@dpogretskiy
Jun 08 2018 15:15 UTC
yeah, as i said, you need to pin your vectors in place first
don't create references to them in lambdas, cause then literally anything can happen to that vectors :)
Fredrik Portström
@portstrom
Jun 08 2018 15:25 UTC
@trsh You're creating a reference to a value that is discarded at the end of the closure and moving the reference out of the closure. That's not something that should be done.
Ash
@ashthespy
Jun 08 2018 15:54 UTC
@dpogretskiy thanks for the tip with the cargo.lock!
Ash
@ashthespy
Jun 08 2018 16:03 UTC
How does one poke the sender to actually send something?
Ash
@ashthespy
Jun 08 2018 16:12 UTC

When I call it form my

thread::spawn(move || {

}

I end up with a

thread '<unnamed>' panicked at 'no Task is currently running', /home/ash/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.17/src/task_impl/mod.rs:44:9
dovreshef
@dovreshef
Jun 08 2018 21:04 UTC
Where can see usage of failure with errorkind? I'm having a hard understanding it