Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

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?


In 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.


Except 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/8949ac0304660f53e1fbe2850...


Gtk-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.


So given that this isn't actually safe, you can presumably write some code that has undefined behaviour using this library for us?


Well 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.des...


I tried to test this by modifying the example on 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.


Looking 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.


I 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.


For 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.


Isn't it still undefined behaviour to do so, though?


Valgrind doesn't detect anything, so I guess GTK's reference counting does the right thing and doesn't prematurely free data still referenced somewhere else. It just doesn't show a window.


Yes, it's possible to write unsafe code that exhibits undefined behavior in Rust in general (not just through FFI and bindings such as this).


Sure, but this isn't unsafe code. Code using this library isn't written in an unsafe block, right? You just use it like any other Rust library?


It's unsafe to Rust. Rust has defined safety to mean a certain thing. In order to support FFI in general the Rust compiler must assume nothing about the safety guarantees of the other language, and therefore that it should be considered "unsafe" according to Rust.


If you're asking about gtk-rs, yes you use it just like a library. The only reason the unsafe block is there is because it does FFI. The Rust compiler inherently doesn't trust ffi calls. That doesn't mean necessarily that the call is actually unsafe.


If you write code that can be called without 'unsafe' then you are required to make that code safe. Whether you implement it using unsafe underneath is irrelevant.

The unsafe block is there because it does FFI, which hasn't actually been verified to be safe.


You're rephrasing exactly what I said:

> The Rust compiler inherently doesn't trust ffi calls. That doesn't mean necessarily that the call is actually unsafe.


unsafe{} means "hey compiler, you cannot verify but this is safe, but I have." This code should be safe to use, unless the human involved has messed something up, in which case, it's a bug.

It's more that the possibility for UB now exists, than it definitely does.


Maybe unsafe should be called assume_safe or presumably_safe or maybe_unsafe... People easily understand it wrong


We considered many things, but in the end, nothing is perfect.


> 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.


And not even all cells, just RefCell.


Why does cells even exist then?


Hi. 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

You didn't call anyone names but the sarcasm and patronizing tone aren't necessary.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: