These are chat archives for rust-lang/rust

23rd
Mar 2019
Whether the build succeeds or not, I have apparently gotten the basis for a good Arch Linux Circle CI Rust build script for Docker Hub going
hello2dj
@hello2dj
Mar 23 14:21
hello, who can help me?
Why Universal Function Call is moved( on &mut T), but method call is borrowed?
Michal 'vorner' Vaner
@vorner
Mar 23 15:06
The basic idea is that . is „clever“ and picks the lowest access that is needed for it to work. So it desugars it to something like A::say(&mut c). On the other hand, with the UFC you clearly state that you want no borrowing to happen and function calls are not clever in that way, so it does what you say.
nbrr
@nbrr
Mar 23 17:06
(From Mutex::lock documentation example) Here c_mutex is an Arc<Mutex<{integer}>>. What is the trick here that allow to use Mutex<_>'s .lock directly on c_mutex? Is it thanks to Deref?
let mutex = Arc::new(Mutex::new(0));
let c_mutex = mutex.clone();

thread::spawn(move || {
    *c_mutex.lock().unwrap() = 10;
}).join().expect("thread::spawn failed");
Riley Cat
@WreckedAvent
Mar 23 18:31
Yes, . and Deref allow for some opaque de-referencing. So that's the same as writing
    *(*c_mutex).lock().unwrap() = 10;
which in turn is sugar for something like
    *Mutex::lock(&*c_mutex).unwrap() = 10;
Sam Johnson
@sam0x17
Mar 23 20:53
I am looking for a general way of having a chain (e.g. linked list) of structs that have mutable references to one-another, but still be able to externally access and mutate each struct in the list after they are all linked up. Any suggestions? Right now I am running into problems where once they are linked up (e.g. using a boxed reference) I am no longer able to access them
Denis Lisov
@tanriol
Mar 23 20:55
Arc and Mutex?
Sam Johnson
@sam0x17
Mar 23 20:56
e.g. something like:
let mut node1 = Node::new();
let mut node2 = Node::new();
let mut node3 = Node::new();
node1.set_target(node2);
node2.set_target(node3);
println!("{:?}", node2.some_method()); // borrowing issue typically occurs here
@tanriol so if I go that route, would I have to externally declare as an Arc<Node>?
or can that all be internal to the implementation
Denis Lisov
@tanriol
Mar 23 21:00
You can do in internally or externally, as you wish. If you remember the example we've discussed some time ago, it had a structure struct LimiterHandle { state: Rc<RefCell<LimiterState>> } specifically to make it accessible from more than one place.
Rc<RefCell<T>> is the single-threaded version of Arc<Mutex<T>>
Sam Johnson
@sam0x17
Mar 23 21:18
@tanriol yeah my problem now is I have a limiter whose target is another limiter, but once I set that as the target I can't access the second limiter at all because it has moved into the first limiter, so I need to do something like that LimiterHandle construct that you use internally in the limiter implementation, externally for each limiter
#[test]
fn test_passthrough_limiter_large_write() {
    let mut pas = Limiter::new(Passthrough);
    let mut acc = Limiter::new(Accumulator::new());
    acc.set_limit(Some(5));
    acc.on_limit(|ac| {
        match ac.total_limits() {
            1 => { assert_eq!(ac.transformer.slice(), [0, 1, 2, 3, 4]); },
            2 => { assert_eq!(ac.transformer.slice(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); },
            3 => { assert_eq!(ac.transformer.slice(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]);},
            _ => {}
        }
        Ok(())
    });
    pas.targets.push(Box::new(acc));
    pas.write(Bytes::from_static(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]));
    assert_eq!(acc.total_limits(), 2);
}
the assert_eq! line is not allowed because acc is moved into pas by the pas.targets.push(Bos::new(acc)); line
*Box
I could probably do something like pas.targets[0].total_limits() but that could get awkward with long chains so if possible I'd like to find a more general solution
Sam Johnson
@sam0x17
Mar 23 21:23
and actually that would need restructuring as well because targets is of type Writeable
Vec<Box<dyn Writable>> to be exact
Denis Lisov
@tanriol
Mar 23 21:28
In the example it was possible to take the limiter handle for a limiter before moving the limiter.
let mut acc = /* ... */; let acc_handle = acc.handle(); pas.targets.push(Box::new(acc)); acc_handle.total_limits()
Sam Johnson
@sam0x17
Mar 23 21:32
ohhhhh
thank you so much
that answers everything lol
@tanriol
oh wait except, isn't the handle a clone?
so it won't get changes if I do a write?
like if I want an accurate total_in number after some writes?
Denis Lisov
@tanriol
Mar 23 21:33
It clones the Rc, not whatever is inside it.
Sam Johnson
@sam0x17
Mar 23 21:34
oh gotcha, ok cool
then this works
thanks so much