5 ms·
How does a pointer-soup toolkit like GTK work with Rust? For example, this code: let button = Button::new_with_label("Click me!"); window.add(&button);
by ridiculous_fish 9y ago
How does a pointer-soup toolkit like GTK work with Rust? For example, this code:
let button = Button::new_with_label("Click me!");
window.add(&button);
button.connect_clicked(|_| {
println!("Clicked!");
});
We just mutated the button (connect_clicked) while the window holds a reference to it. Isn't that disallowed in Rust? How do the GTK types interoperate with Rust ownership?
- nialv7 9y agoIn Rust there is this concept called interior mutability. Which allows the user to mutate something through a shared reference (&T). You might want to say "hold on, how can this be safe?" The trick here is that there are runtime checks to make sure only one reference is used for mutation. Oh, did you believe all checks needed to make Rust memory safe is done at compile time? Well that's too bad.
- yorwba 9y agoExcept this isn't guaranteed to be safe, because the implementation [1] just calls GTK in an unsafe block: fn add<P: IsA<Widget>>(&self, widget: &P) { unsafe { ffi::gtk_container_add(self.to_glib_none().0, widget.to_glib_none().0); } } Oh, did you believe that Rust always does checks to ensure memory safety? Well that's too bad. Unsafe blocks are for exactly those situations where the compiler can't prove safety at compile time, giving you an escape hatch to say "this really is safe, I know what I'm doing". There are some runtime-checked abstractions built on this, but they can't help you when interacting with non-Rust code. [1] https://github.com/gtk-rs/gtk/blob/8949ac0304660f53e1fbe28503a970d5d75bae91/src/auto/container.rs#L111 https://github.com/gtk-rs/gtk/blob/8949ac0304660f53e1fbe2850...
- alphaalpha101 9y agoSo given that this isn't actually safe, you can presumably write some code that has undefined behaviour using this library for us?
- ridiculous_fish 9y agoWell that's the question, isn't it? Here's one scenario that might invoke UB: create a top level widget, call destroy() [1] on it, then use the widget. Does that invoke UB? If not, why not - how does Rust's ownership model interact with the GTK one? [1] http://gtk-rs.org/docs/gtk/trait.WidgetExt.html#tymethod.destroy http://gtk-rs.org/docs/gtk/trait.WidgetExt.html#tymethod.des...
- yorwba 9y agoI tried to test this by modifying the example on http://gtk-rs.org http://gtk-rs.org so that the window would be destroyed immediately after creation. When I ran it under valgrind, there were lots of memory access violations. (Valgrind: "Go fix your program!") I thought that would settle the matter, but then I ran the unmodified code, and it generated essentially the same error messages. Filing a bug report right now.
- jcranmer 9y agoLooking at your bug report, the first few errors are in g_object code and have absolutely nothing to do with Rust, let alone gtk-rs. (It is known that jemalloc, Rust's allocator, doesn't play nicely with valgrind, but not even that is in play). Given that the stacks start with dbus, none of these errors are relevant to gtk-rs.
- yorwba 9y agoI did not get any similar errors on other GTK apps I tested, so I'm relatively confident that it is at least somewhat related to the way gtk-rs does things. I do not seriously expect any Rust code to directly violate memory safety, but calling C code in GTK incorrectly can still have the same effect.
- yorwba 9y agoFor those still watching this thread: the memory accesses were correct, valgrind just couldn't handle the jemalloc allocator. Using the system allocator instead, even destroying the window before using it does not lead to invalid accesses.
- imperioland 9y agoGtk-rs owner here: the unsafe block is "simply" because rust considers all FFI calls as unsafe. We strongly rely on GTK's functionalities in order to make its usage safer. After you can always break the world if you want.
- deleted 9y ago[deleted]
- fredmorcos 9y ago> Oh, did you believe all checks needed to make Rust memory safe is done at compile time? Well that's too bad. Actually yes. You can write all the programs you want without runtime borrow checking, but it's inconvenient. Runtime borrow checking happens _only_ when you use cells.
- steveklabnik 9y agoAnd not even all cells, just RefCell.
- nialv7 9y agoWhy does cells even exist then?
- humanrebar 9y agoHi. Can we take the tone down a notch? > When disagreeing, please reply to the argument instead of calling names. "That is idiotic; 1 + 1 is 2, not 3" can be shortened to "1 + 1 is 2, not 3." https://news.ycombinator.com/newsguidelines.html https://news.ycombinator.com/newsguidelines.html You didn't call anyone names but the sarcasm and patronizing tone aren't necessary.