These are chat archives for rust-lang/rust

3rd
Nov 2018
Kelly Thomas Kline
@kellytk
Nov 03 2018 01:43
If you're interested in Rust in the browser and a Friday night challenge I'm trying to figure out DenisKolodin/yew#418
Tom Cumming
@tomcumming
Nov 03 2018 12:39
hi guys, use_small_heuristics = "Off"/"Max" for rustfmt doesn't seem to have any effect. Anyone got this to work ?
synepis
@synepis
Nov 03 2018 13:03
Hi, I just stared learning Rust and am slightly confused about a piece of code.(not sure if there is a different beginners channel?). Question is in the comments, on line 17.
#[derive(Debug)]
struct Point { x: i32, y: i32 }

fn main() {
    let mut p1 = Point { x: 1, y: 2 };
    println!("p1: {:?}", p1);    // p1: Point { x: 1, y: 2 }
    p1.x = -1;
    println!("p1: {:?}", p1);    //  p1: Point { x: -1, y: 2 }

    let mut p2 = p1;
    println!("p2: {:?}", p2);    // p2: Point { x: -1, y: 2 }
    p2.x = 3;
    // println!("p1: {:?}", p1); // Cannot compile, p1 was already moved!
    p1.x = -11;                  // Compiles but what does it do?
    println!("p2: {:?}", p2);    // p2: Point { x: 3, y: 2 }
}
red75prime
@red75prime
Nov 03 2018 13:47
Probably it does nothing. Compiler allows to write into moved-out value, but you will not be able to read it anyway.
synepis
@synepis
Nov 03 2018 13:48
But isn't that a mutation of a moved reference?
I would expect the compiler to complain, or at least warn about it?
Sonia Malhotra
@torridiansonia_twitter
Nov 03 2018 13:57
Gentlemen, whats the best way to start and stop a thread from REST API (independent function calls)?
I am using global variable like so: static mut running: bool = false;
when the thread loop starts, setting it to true: unsafe { running = true };
Within loop checking if it was set to false: if !unsafe { running } {
break;
}
And then from stopping REST API, mutating it to false: unsafe { running = false };
unsafe call is bothering me to think, I am not doing it nicely, even though its working nice.
Is there a better pattern?
Edvin Malinovskis
@nCrazed
Nov 03 2018 14:39
torridiansonia_twitter: this would probably work https://doc.rust-lang.org/std/sync/mpsc/index.html
Sonia Malhotra
@torridiansonia_twitter
Nov 03 2018 14:50
@nCrazed rx, tx should in an case where thread call is from the parent that should stay in scope until process execution. But thread is being started and stopped from rest API end-point
I am anyways using channel to get results from the thread, but then starting it from one rest api end-point and after few minutes stopping from another end-point requires some shared state
thats what I meant with global variable
Edvin Malinovskis
@nCrazed
Nov 03 2018 14:54
well, you'd have similar approach, but the channels should help you get around the unsafe calls
clone the global receiver/sender into the relevant endpoint handlers
as well as the receiver into the thread when its created
I might be overlooking something here, but that would be my initial approach for removing the unusafe call
although, I guess in this case you could just wrap the boolean in Arc and call it a day
Sonia Malhotra
@torridiansonia_twitter
Nov 03 2018 15:04
@nCrazed I tried Arc::new(Mutex::new but since it would still be static mut, compiler required unsafe. Will try with channel clone method. Thanks.
Edvin Malinovskis
@nCrazed
Nov 03 2018 15:05
torridiansonia_twitter: does it have to be static? why not define it early in main() and clone from there?
Sonia Malhotra
@torridiansonia_twitter
Nov 03 2018 15:06
You mean pass it through the chain of call from the main?
Edvin Malinovskis
@nCrazed
Nov 03 2018 15:06
Sonia Malhotra
@torridiansonia_twitter
Nov 03 2018 15:08
That looks complicated to my setup. I have a lib that needs to implement start and stop call, return the receiver to the caller function invoked from Rest API to return the data to the frontend
and then another rest api can be called to stop the thread
so setting up channel in main and passing it through the rest api, and lib would cause problems in reusability I believe
Unless, I have really complicated the setup than required.
Ichoran
@Ichoran
Nov 03 2018 15:28
@synepsis - Yeah, that looks like highly undesirable behavior to me. I'd report it or look for a bug or a rationale for why it doesn't at least warn. Assigning to a moved-out (and therefore inaccessible) value is logically equivalent to assigning to a variable that isn't used, and it does warn on that.
Jonathan Steyfkens
@jonathansty
Nov 03 2018 15:52

Hi everyone,
I'm experiencing an issue with the drop order in rust. In this playground you can see that rust drops the owning struct first and then the members of that struct, why is the order like this?

I'm doing some graphics code that needs to free certain resources before destroying the context, now I've tried manually using std::mem::drop but that didn't call the implemented Drop trait of my abstractions

Ichoran
@Ichoran
Nov 03 2018 16:06
Usually when you create A, B, C and pack it into D with maybe some extra stuff, you need to uncreate it in the reverse order.
That explains why the drop order is what it is--it tries to undo the presumed process that created it (i.e. opposite order).
You can call the drop method yourself on the members before using std::mem::drop.
Are you sure it doesn't work, though?
Jonathan Steyfkens
@jonathansty
Nov 03 2018 16:09

A, B, C and pack it into D
I would expect the drop order to be C -> B -> A and then D, instead of D and then it's members.

For the manual drop method, I guess std::mem::drop tells rust to not drop it manually? I think I wasn't using it correctly in this case then

error[E0040]: explicit use of destructor method
   --> src/main.rs:462:28
    |
462 |             self.swapchain.drop();
    |                            ^^^^ explicit destructor calls not allowed

error: aborting due to previous error
Seems like you can't do explicit drop calls, I was using std::mem::drop like so:
            std::mem::drop(&self.swapchain);
Ichoran
@Ichoran
Nov 03 2018 16:11
Oh, I see, you can't call drop.
But D can be built from stuff that includes A, B, and C. So it might depend on them, so should be dropped first.
I see the problem, though. I'm not sure what the solution is.
synepis
@synepis
Nov 03 2018 16:15

@Ichoran OK, I will make a report for it (I assume on Github issues?)
I have one more strange question, when comparing structs things should be compared via PartialEq meaning by content (which you can derive or implement custom).
However, when comparing pointers with std::ptr::eq() it seems that the creation of new structs does not necessarily mean creation of new memory. Not sure if this is meant to behave as such, or it someone could depend on such an assumption.
See example below:

#[derive(Debug)]
struct Point { x: i32, y: i32 }

fn create_point(x: i32, y: i32) -> Point { Point{x, y} }

fn main() {
    let p1 = &Point{x:1, y:2};
    let p2 = p1;
    let p3 = &Point{x:1, y:2};
    let p4 = &create_point(1, 2);

    println!("\teq({:?}, {:?}) = {}", p1, p2, ptr::eq(p1, p2));
    println!("\teq({:?}, {:?}) = {}", p1, p3, ptr::eq(p1, p3));
    println!("\teq({:?}, {:?}) = {}", p1, p4, ptr::eq(p1, p4));
}

Output

eq(Point { x: 1, y: 2 }, Point { x: 1, y: 2 }) = true
eq(Point { x: 1, y: 2 }, Point { x: 1, y: 2 }) = true
eq(Point { x: 1, y: 2 }, Point { x: 1, y: 2 }) = false

I would expect p3 and p1 NOT to be pointing to the same memory
It feels there is a compiler optimization going on here...

Jonathan Steyfkens
@jonathansty
Nov 03 2018 16:15
yeah, I think I might have to revisit how I'm doing things. It's vulkan so all of the code is pretty much unsafe and I'm just passing raw handles around, the easiest solution for me right now is to manually implement functions on the resources I need to destroy and call these wherever I need to.
Denis Lisov
@tanriol
Nov 03 2018 16:16
If Rust dropped children first, the parent's drop would be able to access invalid (already dropped) children, which would be rather unsafe.
What destruction order do you need and why?
Jonathan Steyfkens
@jonathansty
Nov 03 2018 16:21

I need to destruct resources before destroying the a vulkan device. I've abstracted some of them away into a Swapchain while for testing sake I've got raw handles to others in my BaseApp. The BaseApp also has a handle to the device and instance.

When BaseApp drops I need to destruct the resources of Swapchain and the resources that BaseApp owns before destroying the device and instance.

As mentioned earlier I tried calling std::mem::drop but that didn't seem to work.
Denis Lisov
@tanriol
Nov 03 2018 16:27
So you have multiple children that keep raw handles to each other and you need them to be destructed in the right order, correct?
Jonathan Steyfkens
@jonathansty
Nov 03 2018 17:48
@tanriol yeah pretty much
Denis Lisov
@tanriol
Nov 03 2018 17:53
If you need to control the order between children only, you can change their order; otherwise, take a look at std::mem::ManuallyDrop
I'd probably take a look at why such manual control is needed, but this is probably a consequence of using the Vulkan API, isn't it?
Jonathan Steyfkens
@jonathansty
Nov 03 2018 19:00
Yeah, Vulkan expects all resources created from a certain device to be freed before the device. I'm just looking for solutions to make sure this is the case :)
Denis Lisov
@tanriol
Nov 03 2018 19:02
Well, I'd probably expect to have Rust-side wrappers for the resources which would contain an internal (reference-counted) reference to the device wrapper.
Jonathan Steyfkens
@jonathansty
Nov 03 2018 19:02
^ that's what I was probably going to do :)
Denis Lisov
@tanriol
Nov 03 2018 19:04
Or, possibly, to have the same guaranteed with lifetimes if resource creation/deletion happens on hot paths. However, AFAIK, in the Vulkan design it's expected to be a rare event.
Jonathan Steyfkens
@jonathansty
Nov 03 2018 19:05
Yeah in this case it is just an app with 1 vulkan device that destructs at the end of the application
verilog15
@verilog15
Nov 03 2018 23:21
Hi guys, Does Rust have anonymous features? I know that it has anonymous function, but does it contain anonymous variables,structs,enums,modules or types?
David Vo
@auscompgeek
Nov 03 2018 23:41
how on earth could variables be anonymous?