These are chat archives for rust-lang/rust

14th
Jun 2018
Farzeen
@happycoder97
Jun 14 2018 00:09

I was trying to run some unit tests using gtk-rs. Even though I specified cargo test -- --test-threads=1, gtk::init().unwrap() panics with the following message:

Attempted to initialize GTK from two different threads.

Looks like although cargo is running tests two sequentially, it is running different tests in different threads and run those threads one after another. How to disable this?

Björn Lindström
@bkhl
Jun 14 2018 02:51
happycoder97, cargo test -- --test-threads=1
Thibault Delor
@thibaultdelor
Jun 14 2018 02:53
In Rust it's the compiler that complains, with C++ it's the colleagues - @vorner
Quote of the week I believe :smile:
Farzeen
@happycoder97
Jun 14 2018 02:55
Yeah.. that was a good one :D
@bkhl already tried that :(
Thibault Delor
@thibaultdelor
Jun 14 2018 02:59
When it’s not your colleagues, it’s your customers in your bug tracker ^^
Farzeen
@happycoder97
Jun 14 2018 03:01
:+1:
Thibault Delor
@thibaultdelor
Jun 14 2018 03:03
@happycoder97 Can you send your whole code?
Thibault Delor
@thibaultdelor
Jun 14 2018 03:15
Can you just ignore the error? I mean if it’s already initialised, all good
Farzeen
@happycoder97
Jun 14 2018 03:15
It panics : (
Thibault Delor
@thibaultdelor
Jun 14 2018 03:18
does it panics because you unwrap
or before the unwrap
Farzeen
@happycoder97
Jun 14 2018 03:19
Oh.. right!
May be I need not unwrap.
Let me try that and see if it works.
Thibault Delor
@thibaultdelor
Jun 14 2018 03:21
I would be surprise if it still panic if you remove unwrap
but if it does you can always catch and ignore
Farzeen
@happycoder97
Jun 14 2018 03:21
It panics even without unwrap
Thibault Delor
@thibaultdelor
Jun 14 2018 03:22
yuk
Farzeen
@happycoder97
Jun 14 2018 03:22
gtk is not thread safe. So gtk-rs panics if it is used in multiple threads
Is there anyway to make cargo test run in a single thread?
Instead of spawning multiple threads sequentially to appear like single thread?
Or running different test functions in its own process would be fine too
(I haven't pushed the version without unwrap.)
Thibault Delor
@thibaultdelor
Jun 14 2018 03:31
@happycoder97 rust-lang/cargo#5438
Farzeen
@happycoder97
Jun 14 2018 03:33
Oh.. I'm running arch linux. looks like it affects linux too.
Farzeen
@happycoder97
Jun 14 2018 03:49

Oh.. I'm running arch linux. looks like it affects linux too.

It doesn't. It only causes problems while testing in Linux. On Mac, it causes problems during cargo run too.

Thibault Delor
@thibaultdelor
Jun 14 2018 03:58
oh gosh good luck with that
To answer your question about if it can run on the main thread, the answer is no
If you want the details:
Farzeen
@happycoder97
Jun 14 2018 04:00
Oopsie :)
Thibault Delor
@thibaultdelor
Jun 14 2018 04:02
I guess It would be fairly straight forward to implement a configuration option for it
Farzeen
@happycoder97
Jun 14 2018 04:02
I just found a workaround. There's a crate rusty-fork, which provides a macro that wraps around test fns and then executes cargo test fn_name, essentially making each test run in its own process.
Thibault Delor
@thibaultdelor
Jun 14 2018 04:02
ha ha here you go
Farzeen
@happycoder97
Jun 14 2018 04:03
:)
trsh
@trsh
Jun 14 2018 05:47
fn back_process(&self, node: &NodeData) -> Box<Future<Item = (), Error = String>> {
    let mut node_inputs = node.inputs.iter();
    let ping_til_done = loop_fn(node_inputs, |_| {
      Ok::<_, String>(Loop::Break(()))
    });
     Box::new(ping_til_done)
}
I have narrowed down this code, that gives me an error
210 | /let xx = /Box::new(ping_til_done)
| ^^^^^^^^^^^^^^^^^^^^^^^ lifetime 'static required
With no further explanations. What can I make of this?
Fredrik Portström
@portstrom
Jun 14 2018 06:44
@trsh You're probably putting something in the box that does't have a static lifetime, and the function is declared as returning a box with static lifetime. Anyway, you should be returning impl Future<_> rather than Box<Future<_>> since Rust 1.26. https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
trsh
@trsh
Jun 14 2018 06:52
@portstrom hmm... that node: &NodeData comes from a box object with static ref
Fredrik Portström
@portstrom
Jun 14 2018 06:52
I'm more thinking of what comes out of loop_fn.
trsh
@trsh
Jun 14 2018 06:55
@portstrom if I dont push node_inputs to loop_fn closure, everything fine
But I need that data
Cloning iter also doesn't help
Fredrik Portström
@portstrom
Jun 14 2018 06:57
So you're iterating over something and saving the iterator? But you didn't show in the code you posted how you do that. Doing it with iterdoesn't work, because it borrows the data, which doesn't have a static lifetime. Doing it with into_iter works, because the data is moved and owned by the iterator, so the data lives as long as the iterator.
trsh
@trsh
Jun 14 2018 07:02
error: internal compiler error: unexpected panic

note: the compiler unexpectedly panicked. this is a bug.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports

note: rustc 1.26.2 (594fb253c 2018-06-01) running on x86_64-unknown-linux-gnu

note: compiler flags: -C debuginfo=2 -C incremental --crate-type lib

note: some of the compiler flags provided by cargo are hidden
:D
into_iter killed it all finally
I guess i can't try to own a iter, that is from are ref of a box
Fredrik Portström
@portstrom
Jun 14 2018 07:05
That's never happened to me. Anyway, what the compiler probably means is that you're taking the node by reference, so you can't call into_iter on it. It's quite a broad limitation: You can't put any reference in a future that has a lifetime shorter than the entire system driving the futures.
trsh
@trsh
Jun 14 2018 07:09
If I take that ref from a box, it should be 'static liftime
Fredrik Portström
@portstrom
Jun 14 2018 07:11
Your box isn't static unless you declare it as a global variable (const or static).
What you frequently want to do in async programs is Rc<Box<_>>. That way you can clone the box so different futures can own it at the same time. The box is freed when the last owner drops it.
Michal 'vorner' Vaner
@vorner
Jun 14 2018 07:12
Why the double-indirection? Rc is a pointer too, you can convert a box into RC
Fredrik Portström
@portstrom
Jun 14 2018 07:14
My mistake. Confused it with Rc<RefCell<_>>. Don't do double indirection. Rc replaces Box.
trsh
@trsh
Jun 14 2018 07:16
Actually it doesn't care about Future
Just dies at into_iter
Will try to reproduce on playground
Fredrik Portström
@portstrom
Jun 14 2018 07:19
I'd appreciate that.
trsh
@trsh
Jun 14 2018 07:36
can't
When I remove some funcs that call this func, the panic is gone
basically I would need to paste all source
Another strange one appears
error[E0507]: cannot move out of borrowed content --> manu/src/impls/nodes/processor/engine.rs:82:24 | 82 | let node_inputs = &node.inputs.into_iter(); | ^^^^ cannot move out of borrowed content
But its barrowed
Dmitriy
@dpogretskiy
Jun 14 2018 07:38
it's into_iter() i believe
Fredrik Portström
@portstrom
Jun 14 2018 07:38
That's what I told I would expect. You can't call into_iter on a reference.
Dmitriy
@dpogretskiy
Jun 14 2018 07:38
try iter()
trsh
@trsh
Jun 14 2018 07:39
@dpogretskiy that inital plan, but then I cant feed it to a future
non static >> lalal
Dmitriy
@dpogretskiy
Jun 14 2018 07:40
yeah, because trying to use references inside futures, leads to data-races
you have some data somewhere, then refer to it somewhere else, put it inside of future executor that throws them between threads
and then try to read and mutate it in different threads, and there you go!
C++ wasteland :laughing:
trsh
@trsh
Jun 14 2018 07:42
@dpogretskiy so whats the right schema. Clone everything before feeding to future?
Dmitriy
@dpogretskiy
Jun 14 2018 07:43
that's a possibility
also you can use Arc<_>
Fredrik Portström
@portstrom
Jun 14 2018 07:43
Use Rc, not Arc, unless you need to share a value between multiple threads.
Dmitriy
@dpogretskiy
Jun 14 2018 07:43
if you need to mutate something, you use Arc<Mutex<_>> but it's a bad thing to do in futures
@portstrom it's futures, they need to be Send + Sync i believe
trsh
@trsh
Jun 14 2018 07:44
Well look at this ex:
fn forward_process(&self, node: &NodeData) -> Box<Future<Item = (), Error = String> + 'static> {
    let nodes = &self.processData.as_ref().expect("Nodes are empty").nodes;

    let connection_nodes_flat = node
      .outputs
      .iter()
      .flat_map(|output| {
        output
          .connections
          .iter()
          .flat_map(|c| {
            let c_node = nodes
              .get(&c.node.to_string())
              .expect("Unknown output connection node");

            vec![self.back_process(c_node), self.forward_process(c_node)]
          })
          .collect::<Vec<_>>()
      })
      .collect::<FuturesOrdered<_>>();

    Box::new(connection_nodes_flat.for_each(|_| Ok(())))
  }
Dmitriy
@dpogretskiy
Jun 14 2018 07:44
try to not mutate data in futures, since there is no need to, generally
Arc, can do the trick tho
trsh
@trsh
Jun 14 2018 07:44
It this BAD?
Dmitriy
@dpogretskiy
Jun 14 2018 07:45
Mutex'es inside futures?
Real bad!
trsh
@trsh
Jun 14 2018 07:45
No I mean the code I pasted
Dmitriy
@dpogretskiy
Jun 14 2018 07:46
it depends on what are you trying to achieve
Fredrik Portström
@portstrom
Jun 14 2018 07:47
@dpogretskiy I use Rc with futures.
Dmitriy
@dpogretskiy
Jun 14 2018 07:47
back_process and forward_process are too damn mysterious names
trsh
@trsh
Jun 14 2018 07:48
What achieve is my problem. i mean code wise. Looks like this gona blow?
because u said don't use Refs in Futures.. I have 3 usages
Well.. only for fn param
Dmitriy
@dpogretskiy
Jun 14 2018 07:52
I mean, i can't get the big picture
Fredrik Portström
@portstrom
Jun 14 2018 07:53
If you don't care to collect the results, it would be simpler to just spawn each future onto the executor than create all these FuturesUnorderedto combine them.
Dmitriy
@dpogretskiy
Jun 14 2018 07:53
futures are not for parallelization, but are for async stuff
which is not the same really
trsh
@trsh
Jun 14 2018 07:55
@portstrom why? I can just do collect on futures_ordered, and it wild exactly do that
Fredrik Portström
@portstrom
Jun 14 2018 07:56
You're nesting collect inside collect and then some flat map inside flat map and your code is hard to read.
Dmitriy
@dpogretskiy
Jun 14 2018 07:56
) -> Box<Future<Item = (), Error = String> + 'static> {
that specifically says you don't care what are results
Fredrik Portström
@portstrom
Jun 14 2018 07:57
I also wonder what's the point of using futures. Does the node processing now need some asynchronous IO?
Dmitriy
@dpogretskiy
Jun 14 2018 07:57
and it only would wail, if any of futures will fail
same stands for futures_unordered
i have no idea if you can even make it 'static
trsh
@trsh
Jun 14 2018 07:58
Box is static by default
I can remove that mark
Dmitriy
@dpogretskiy
Jun 14 2018 07:59
there are no references inside Future and Box
other then Box itself, which doesn't care about lifetimes, other then Box'es itself
:smirk:
trsh
@trsh
Jun 14 2018 08:03
Maybe I should just wait() everywhere, and screw these fancy future functions
Fredrik Portström
@portstrom
Jun 14 2018 08:04
What do you need to wait for?
trsh
@trsh
Jun 14 2018 08:05
example: node 1 gives output x To node 2, node 2 using x fetches some online resource, when done, moves to node3 for processing
It's called visual block programming
Fredrik Portström
@portstrom
Jun 14 2018 08:06
For fetching online resources you should definitely use futures. They are however not easy to learn, and I would suggest practicing the basics before trying to do anything too fancy. It took me weeks to properly understand futures.
trsh
@trsh
Jun 14 2018 08:07
I already went trough basics.
I sink my case is really demanding, with recursions and loops and stuff, so not sure Rust + Futures is actually ready for that
Fredrik Portström
@portstrom
Jun 14 2018 08:08
Reading the basics isn't the same as practicing the basics using futures in a real program.
trsh
@trsh
Jun 14 2018 08:08
It's more hacking not coding now
Id o create this code peace by peace, and test it.. and now stuck with some errors, thats all
The biggest problem is referencing some Self (struct) stuff to futures.. sure I do not want to pass anyting trough functions, what would make them large and ugly
Fredrik Portström
@portstrom
Jun 14 2018 08:13
It's difficult to give advice without knowing more about the program you're developing, but I guess you wouldn't pass anything too recursive between futures, but have a central store of nodes where you reference them by ID, and use an Rc to let multiple futures own a handle to the store.
trsh
@trsh
Jun 14 2018 08:14
yes this is my central store
pub struct Engine {
  pub id: String,
  processData: Option<Box<ProcessData>>,
Data that needs to be acessed is boxed
Fredrik Portström
@portstrom
Jun 14 2018 08:15
What's the reason for boxing it?
trsh
@trsh
Jun 14 2018 08:16
I want it to be owned by Engine
Because its Huge data
When I pass it to Engine I want it to be moved to it, and just used by it
I have imp with ::new, and there i do that
Fredrik Portström
@portstrom
Jun 14 2018 08:18
It's owned by Engine no matter whether it's boxed. If you box the engine with Rc there's no need for another box.
trsh
@trsh
Jun 14 2018 08:22
engine::new(hugeData) > hugeData still lives here VS engine::new(Box::new(HugeData)) > hugeData is moved to engine
Fredrik Portström
@portstrom
Jun 14 2018 08:23
How huge is the data anyway? I guess it's stored in collections, and each collection is just a few bytes, no matter the size of its contents.
trsh
@trsh
Jun 14 2018 08:23
Json.
Desciptor of every node
and those connections
Can be small and Huge, depends on visual code
Fredrik Portström
@portstrom
Jun 14 2018 08:24
That's all boxed by the collection types anyway.
Vec is 24 bytes no matter how much data it contains. HashMap is 40 bytes no matter how much data it contains.
trsh
@trsh
Jun 14 2018 08:33
@portstrom u suggest to use Rc instead of box? And the clone references to futures where needed?
Like fetching central data for all nodes and it's futures
Also you mentioned RefCell
Fredrik Portström
@portstrom
Jun 14 2018 08:35
I don't know what data your futures need to access. Do they need the Engine or just the ProcessData? If Engine, then the box is irrelevant, and you can wrap Engine in Rc. If ProcessData, use Rc instead of Box.
RefCell is if you need mutability.
trsh
@trsh
Jun 14 2018 08:35
ProcessData for read-only data, and Engine to call recursive futures
Fredrik Portström
@portstrom
Jun 14 2018 08:36
It's good to avoid RefCell whenever possible, because even just to read something from a RefCell you need to explicitly borrow it by calling the borrow function, and you get a Ref struct, not a plain reference.
trsh
@trsh
Jun 14 2018 08:38
Thats the thing with recursion, you NEED to access It's self (Engine) in futures
Fredrik Portström
@portstrom
Jun 14 2018 08:39
You may not need recursion.
trsh
@trsh
Jun 14 2018 08:40
I kind of don't how to avoid it in my impl
Of nodes, as idea
Fredrik Portström
@portstrom
Jun 14 2018 08:40
You can probably store a flat collection of nodes referenced by ID. Each node just contains the ID of other nodes, not a hierarchy of owned nodes.
trsh
@trsh
Jun 14 2018 08:42
flat means collect by iter, and then iter over that iter to process
double job
Anyway, recursion should not be a Red flag for advanced programming lng
Fredrik Portström
@portstrom
Jun 14 2018 08:45
In the first code you posted, I saw you do some memoized calculation for each node. If you want to do that, have a collection if ID to Option<futures::future::Shared<_>> mappings in your store. Whenever you need something from some node, check the option. If None create the future, clone it and put it in the store. If Some, clone the future from the store.
trsh
@trsh
Jun 14 2018 08:54
back_process?
Shared fut could be actually usefull
trsh
@trsh
Jun 14 2018 09:00
Can shared fut take arguments?
Fredrik Portström
@portstrom
Jun 14 2018 09:00
What do you mean? You just create a future as usual and then wrap it in Shared.
trsh
@trsh
Jun 14 2018 09:01
Otherwise I see no point for it, I ahve other code for dont re-calcing
Ahh, well yeah, in recursion it could create Future with same logic, if same node is accessed
Fredrik Portström
@portstrom
Jun 14 2018 09:03
The point of it is to avoid race conditions. If node B asks node A to compute itself, and then node C also asks node A to compute itself before the already requested computation is finished, then you may have a race condition. If you have a shared future, both node B and C will wait for the same computation to complete.
trsh
@trsh
Jun 14 2018 09:03
So it could get usefull to kind of Cache it.. but thats not my major problem :D
Ok
AS I use streaming, as guys mentioned yesterday here, I actually don now have to care about conurrency
B will ask for A, and wait to finish and then process C, that will ask A
trsh
@trsh
Jun 14 2018 09:09
It a bit dumb, and will slow down the node process, but for now it's ok
Fredrik Portström
@portstrom
Jun 14 2018 09:11
I doubt there's a benefit in doing it the dumb way when you have such a great framework for asynchronous programming available.
trsh
@trsh
Jun 14 2018 09:12
Deadlines
For now the biggest question is if Futures can do recursions at all
Will try some mini example
Fredrik Portström
@portstrom
Jun 14 2018 09:14
My point was to show that when doing a good asynchronous design, it may not be recursive anymore. So instead of trying to fit asynchronous programming into the mindset of recursive programming and having to solve difficult problems of mixing the two approaches, go for fully embracing asynchronous programming right away.
Michal 'vorner' Vaner
@vorner
Jun 14 2018 09:15
You can do recursive with something like Box<Future>.
trsh
@trsh
Jun 14 2018 09:16
@vorner its a guess or you have done it?
Michal 'vorner' Vaner
@vorner
Jun 14 2018 09:16
Or semantically tail-recursive ‒ spawn a new future instead of the old one. The result can be taken out by oneshot.
I haven't done it, but I know I could if I really wanted to. I just never had the reason.
trsh
@trsh
Jun 14 2018 09:17
Or semantically tail-recursive ‒ spawn a new future instead of the old one. The result can be taken out by oneshot sorry but this is Chinese to be
Michal 'vorner' Vaner
@vorner
Jun 14 2018 09:19
I haven't read what exact problem you try to solve. Some recursive algorithms can be optimized with so called tail recursion. You can do that manually by not calling into the inner future, but by spawning it instead and being done yourself.
But I don't know if that's applicable.
trsh
@trsh
Jun 14 2018 09:20
@vorner any example or doc? Sounds interesting
Fredrik Portström
@portstrom
Jun 14 2018 09:21
He never described what exact problem he tries to solve, so we're just discussing hypothetical ideas.
Michal 'vorner' Vaner
@vorner
Jun 14 2018 09:21
No. It's just creative combining of general principles. And as I said, I've never had any need for these crazy things.
trsh
@trsh
Jun 14 2018 09:22
@portstrom so your suggestion is to flattern a VEC with correct execution order, then from it create Futures by avoiding repeating ones with shared?
Still sounds difficult
But kind of falling for this idea
Fredrik Portström
@portstrom
Jun 14 2018 09:24
That includes some additional details I didn't actually suggest.
trsh
@trsh
Jun 14 2018 09:25
:D
ok ok
Tnx guys
With all this info I can defenetly do the job
Denis Lisov
@tanriol
Jun 14 2018 09:26
@trsh Can your visual block programs contain loops? How are they controlled?
trsh
@trsh
Jun 14 2018 09:30
@tanriol no Loops for now, just ff
But i have to make a check for that
It should throw invalid Flow schema err to end-user
Denis Lisov
@tanriol
Jun 14 2018 09:32
The "for now" sounds worrying. How about "generator" nodes that produce outputs without changes in inputs? These are kinds of special cases you need to think about when planning the engine.
trsh
@trsh
Jun 14 2018 09:34
@tanriol its not that serious. Not really for programming. Just that in the system Im building end-users can have small control over data flow
With logic nodes
Im NOT making an Universal Rust visual programming engine. Im to dumb for it now
And to Poor, as nobody would pay for it if I decide to make one
:D
Fredrik Portström
@portstrom
Jun 14 2018 09:41

Now I finally understand the general problem better, so I can begin to suggest a solution instead of just pointing out tiny details in the code.

As I have understood it, it's an acyclical dependency graph, where there is one root node (or several root nodes, doesn't change the complexity of the problem), where each node computes something, which may be asynchronous, and depends of the result of the computation of each upstream node in the graph. The graph is read-only.

The solution I would explore is to use synchronous functions and recursion for setting up futures, and then the futures would resolve themselves without any intervention. The futures don't need to know anything about the graph, so you avoid having to bring recursion into the asynchronous code.

trsh
@trsh
Jun 14 2018 09:44
Yes yes. I think im cutting my code down 2 times right now
Fredrik Portström
@portstrom
Jun 14 2018 09:45
The functions that set up the futures carry with them a map from node id to shared future. To create the future of a node, look up the futures for all dependencies in the map. If found, clone them. If not found, recurse into creating the futures for those nodes, then clone them and put in the map. Then join the futures of all dependencies and chain the computation function of the current node and return the resulting future.
trsh
@trsh
Jun 14 2018 09:46
btw for map
hashMap or Btree
Any expierence?
Fredrik Portström
@portstrom
Jun 14 2018 09:47
Good question. Btree if you need it to be sorted. Otherwise I guess it's all about performance, and someone probably knows better than me the performance characteristics of each.
trsh
@trsh
Jun 14 2018 09:48
Someone Google? :D
Well as the both operate in same manner, I can experiment
Sylwester Rąpała
@xoac
Jun 14 2018 09:54
How to get value from Hashmap?
trsh
@trsh
Jun 14 2018 09:54
.get(&key)
and unwrap
Sylwester Rąpała
@xoac
Jun 14 2018 09:54
if let Entry::Occupied(tx) = self.dev_tx_pair.entry(frame.frame_nr()) {
    // if we do, we sending frame there
    tx.send(frame);
}
dev_tx_pair is a HashMap
trsh
@trsh
Jun 14 2018 09:55
if suspect that key can be invalid, heck the result before unwrap
Sylwester Rąpała
@xoac
Jun 14 2018 09:56

ok, I got it but https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.get say:

The key may be any borrowed form of the map's key type, but Hash and Eq on the borrowed form must match those for the key type.

How to guarantee that?

and what return map[key] because it's not easy to get from docs
trsh
@trsh
Jun 14 2018 09:58
Same as Get, but I guess it will panic if key doesn't exist
Michal 'vorner' Vaner
@vorner
Jun 14 2018 09:59
Which is the same as the unwrap would do if the key didn't exist ;-)
trsh
@trsh
Jun 14 2018 09:59
Basically when you compile Rust will start cry, if you sumbit invalid key type
It knows everything :D
Even your darkest secrets
@portstrom still. IF nodes are [A,B,C], if I run them concurrently, and A asks fro C, and B asks for C, i understand that shared will resolve that C gets finished in time, But still it needs to ask, so it still Future executed inside Future
Fredrik Portström
@portstrom
Jun 14 2018 10:06
Future is not executed inside Future. Future is executed inside Executor. Executor takes care of all dependencies between futures.
trsh
@trsh
Jun 14 2018 10:07
Ok executor was wrong term. But sull A asks For B, so I must define this depency
And its recursion again?
Fredrik Portström
@portstrom
Jun 14 2018 10:10
My suggestion was that you use recursion to visit all nodes and set up the futures. But the futures will run without recursion. You do b.then(a). The executor will execute b until completion and then it executes a, sequentially, not recursively.
trsh
@trsh
Jun 14 2018 10:18
pretty much the code I have now actually. Just instead of streams a Join, ans shared futures to don't mess up.
trsh
@trsh
Jun 14 2018 10:24
will try now modify
trsh
@trsh
Jun 14 2018 10:33
Btw the crashes where because Low disk space
Fredrik Portström
@portstrom
Jun 14 2018 11:18
The difficult thing about shared futures is how to compose them. They wrap their errors in SharedError, so if I have a shared future and create another shared future using a combinator and make that future also shared, I get SharedError<SharedError<…>>. and_then becomes impossible.
Dmitriy
@dpogretskiy
Jun 14 2018 11:25
map_err every step, seems fun
trsh
@trsh
Jun 14 2018 11:25
Also having difficulties creating the map
error[E0308]: mismatched types
   --> manu/src/impls/nodes/processor/engine.rs:251:42
    |
251 |     self.process_futures.insert(node.id, ff);
    |                                          ^^ expected struct `futures::future::Shared`, found reference
    |
    = note: expected type `futures::future::Shared<std::boxed::Box<futures::Future<Item=(), Error=std::string::String> + 'static>>`
               found type `&futures::future::Shared<std::boxed::Box<futures::Future<Item=(), Error=std::string::String>>>`
Fredrik Portström
@portstrom
Jun 14 2018 11:27
It would be nice to have an implementation of Shared for cloneable errors that simply clones them instead of wrapping them.
Zakarum
@omni-viral
Jun 14 2018 11:28
You can map_err(|err| (*err).clone)
If error is clonable
Fredrik Portström
@portstrom
Jun 14 2018 11:28
Now I have to do that every step.
trsh
@trsh
Jun 14 2018 11:28
I mean ff must tale also some args, so Have i push ownership to that self. process_futures
Dmitriy
@dpogretskiy
Jun 14 2018 11:28
ff.clone()
trsh
@trsh
Jun 14 2018 11:29
Its already cloned> let ff = &self.my_fut().shared().clone();
Dmitriy
@dpogretskiy
Jun 14 2018 11:30
remove & in &self :laughing:
trsh
@trsh
Jun 14 2018 11:30
Can move out of barrow blah blah
Dmitriy
@dpogretskiy
Jun 14 2018 11:30
let ff = self.my_fut().shared().clone();
let ff = &(self.my_fut().shared().clone());
trsh
@trsh
Jun 14 2018 11:31
The things is that clone here create some poiter to same future, and not clone it all
Dmitriy
@dpogretskiy
Jun 14 2018 11:31
is what you are doing
Shared is itself a pointer to some future
so you have a pointer to a pointer to a future
and map doesn't want to deal with pointers, it has different type
trsh
@trsh
Jun 14 2018 11:32
but as I said
let ff = self.my_fut().shared().clone();
    |              ^^^^ cannot move out of borrowed content
I must maybe wrap it some vars
Dmitriy
@dpogretskiy
Jun 14 2018 11:33
what's my_fut signature?
trsh
@trsh
Jun 14 2018 11:33
Dummy future
fn my_fut(self) -> Box<Future<Item = (), Error = String>> {
    Box::new(ok(()))
  }
Dmitriy
@dpogretskiy
Jun 14 2018 11:34
my_fut(self) consumes self
everything magically doesn't make sense anymore :smile:
can it be my_fut(&self) ?
trsh
@trsh
Jun 14 2018 11:35
@portstrom have did you imagine storing shared Future in a Map?
@dpogretskiy seems to work
Dmitriy
@dpogretskiy
Jun 14 2018 11:36
yay
trsh
@trsh
Jun 14 2018 11:37
No slightest idea how this could work
Dmitriy
@dpogretskiy
Jun 14 2018 11:37
pub struct Shared<F: Future> {
    inner: Arc<Inner<F>>,
    waiter: usize,
}
this is the definition of Shared
trsh
@trsh
Jun 14 2018 11:37
I store in map some pointer, but to what..
Fredrik Portström
@portstrom
Jun 14 2018 11:39
Now I made an implementation the way I imagined it. Unfortunately it doesn't work in the playground because it has incompatible versions of futures and tokio-core. Since I had to run it locally, I also added real HTTP connections which are not supported in the playground.
http://play.rust-lang.org/?gist=58177cb182bb841547bf74d8ecce0f31
trsh
@trsh
Jun 14 2018 11:40
wow
trsh
@trsh
Jun 14 2018 11:50
set_up(context, a)
                .join(set_up(context, b))
This is the depency part right?
Fredrik Portström
@portstrom
Jun 14 2018 11:50
Right
trsh
@trsh
Jun 14 2018 11:51
Cool example. Tnx!
trsh
@trsh
Jun 14 2018 11:58
nodes: &'a [Node<'a>]
this kind of thing I havent seen
[]
Good to know
@portstrom , @dpogretskiy hi-5 :D
trsh
@trsh
Jun 14 2018 12:32
Bt how to deal with this crap
error[E0308]: mismatched types
   --> manu/src/impls/nodes/processor/engine.rs:266:42
    |
266 |     self.process_futures.insert(node.id, ff.clone());
    |                                          ^^^^^^^^^^ expected trait futures::Future, found struct `futures::AndThen`
    |
    = note: expected type `futures::future::Shared<std::boxed::Box<futures::Future<Item=(), Error=std::string::String> + 'static>>`
               found type `futures::future::Shared<std::boxed::Box<futures::AndThen
AndThen is IntoFuture
Tom Cumming
@tomcumming
Jun 14 2018 12:35
whats the type of self.process_futures?
trsh
@trsh
Jun 14 2018 12:37
Expected one
process_futures: HashMap<usize, Shared<Box<Future<Item = (), Error = String>>>>,
I know it's messy, I will later split in types
trsh
@trsh
Jun 14 2018 12:47
Eh no, it's becouse of 2 return I guess
Anyway, should run
trsh
@trsh
Jun 14 2018 12:53
Neeeded some casting, never mind
Miguel Duarte
@malduarte
Jun 14 2018 14:01
Hi everyone... is there a way to compare function references? Assume cipher_original is a function let fun = cipher_original; assert_eq!(fun, cipher_original);
This currently fails with error[E0369]: binary operation == cannot be applied to type the function type
Michal 'vorner' Vaner
@vorner
Jun 14 2018 14:26
I believe you can take reference of it, turn that reference into raw pointer and compare that.
Zakarum
@omni-viral
Jun 14 2018 14:26
PartialEq is implemented for function pointers in form of fn(Args...) -> Ret
What you try to compare is function type, not a pointer
Try to rewrite as let fun: fn(Args...) -> Ret = cipher_original
replacing Args... and Ret with actual types
trsh
@trsh
Jun 14 2018 15:19
SO how do I run some self funcs in future closure? :D
let ff: Box<Future<Item = Vec<IOData>, Error = String>> =
      Box::new(join_all(kaka).map_err(|e| e.to_string()).and_then(|ots| {
        Rc::clone(&self.workers).worker_mapper(11);
        ok(vec![])
      }));
Aint working with rc
Dmitriy
@dpogretskiy
Jun 14 2018 15:20
try binding some with lets, one per line
let rc = Rc::clone(&self.workers);
let xx = rc.worker_mapper(11);
and such
trsh
@trsh
Jun 14 2018 15:23
I declared it outside.. And then added move to |ots|
Kind of compiled
Dmitriy
@dpogretskiy
Jun 14 2018 15:23
there is a chance it will work
trsh
@trsh
Jun 14 2018 15:24
there is a chance it will work
:D
Well move takes ownership of rc
But mystery is why it doesn't work defined right inside
I will trust the compiler :D
however, you are likely to run into problems because the FooMut and BarMut types are different
Dmitriy
@dpogretskiy
Jun 14 2018 15:32
@Diggsey it wasn't me, i know how [x] access works :)
who it was tho.. i can't find
Diggory Blake
@Diggsey
Jun 14 2018 15:33
I think they deleted their message
hence the confusion :P
@Diggsey This implementation does get the mutable referenced struct. But I can't access the individual attributes of such struct.
println!("{}", ent1.x[0])
By accessing the mutable struct variables in the spring_force generic function, I get error[E0609]: no fieldxon type<T as GetMut<'a>>::MutParts`` error
Dmitriy
@dpogretskiy
Jun 14 2018 19:45
because it's not any concrete MutParts
just some MutParts
so it doesn't have x
Dmitriy
@dpogretskiy
Jun 14 2018 19:50
this works, since spring_force operates on the notion of GetMut only
and main tells it what GetMut specifically to use there.
i guess your idea is that all implementations of GetMut has something that has x, but it's not how it works really
@dineshadepu check it out :smirk: