Hacker News new | ask | show | jobs
by btown 3942 days ago
One might argue that "guaranteeing your web browser doesn't have memory leaks" is a "hard problem." Ergo https://github.com/servo/servo . I agree, though, that the problems you mention are all ones where I'd love to see a greenfield programming language with as much attention to detail and support as Rust has.
2 comments

(Rust doesn't guarantee an absence of leaks, actually. Just memory safety.)
It's still really hard to leak in Rust though. Affine types and all.
In what conditions could Rust code leak memory, excluding the use of unsafe code? What are the technical reasons you can't guarantee an absence of leaks?

  >  What are the technical reasons you can't guarantee an absence of leaks?
Well, 'leak' is one of those things that's easy for a programmer to understand, but a hard thing for a computer to understand, because it's really about intent. How long did you intend for some resource to live? Any global value is, in some sense, a leak. We had a long discussion about this, and, at least currently, we couldn't come up with a formal enough definition of 'leak' to even start tackling the problem of "how do we solve leaks." (It is entirely possible that I am unaware about research on this topic... but given that solving leaks wasn't a goal of Rust, fixing it would just be gravy anyway. You have to choose your battles, and Rust certainly isn't perfect.)

As for how safe Rust can leak:

    let x = Box::new(5);
    std::mem::forget(x);
which can itself just be implemented in safe code:

    use std::cell::RefCell;
    use std::rc::Rc;

    fn forget<T>(val: T) {
        struct Foo<T>(T, RefCell<Option<Rc<Foo<T>>>>);
        let x = Rc::new(Foo(val, RefCell::new(None)));
        *x.1.borrow_mut() = Some(x.clone());
    }
or something like "I have a thread that is holding the receiving end of a channel that infinitely loops without reading anything off," in which case anything sent down that channel leaks.
That's a very intriguing block of code there. I'd like to think that while Rust may not have been designed to guarantee that leaks are prevented, it so happens that anything that could leak memory sticks out like a sore thumb in code review, since the code to get something to leak needs to be explicit. I'd consider a global variable or a channel that has the possibility of not reading all its values to follow that pattern. Whereas it's much easier to get something "stuck" in memory without a reference in C++. But you're absolutely right that memory safety does not at all imply "leak" safety, nor is the latter well defined at all!
Cycles of reference counted objects.

It is technically possible to guarantee the absence of leaks by introducing a `?Leak` trait to the language. There was a point in time when many wanted Rust to go that way, but it was ultimately decided against (it complicates other things).

Note that the trait-based scheme referenced here would only prohibit specific kinds of memory leaks. "Leaking", in its broadest usage, isn't a solvable problem in a Turing-complete language since an infinite loop can be considered a leak.
Interesting. How does Rust prevent the cyclic reference counting issues that led Chrome to adopt Oilpan?
In Servo, DOM nodes are Rust values managed entirely by the SpiderMonkey GC, and clever (and evolving) techniques are used to teach Rust to integrate reliably with SpiderMonkey. Rust has the flexibility (or will) to safely integrate external GC systems.
do you know enough about low-level computer architecture to speculate if mild-to-moderate changes would be warranted in things like, e.g., cache sizes on CPUs? Branch prediction was implemented on generalizations drawn in research papers analyzing procedural codes. I'm wondering if the concurrency abstraction will add a significant working-set to the runtime that adversely impacts existing prediction algorithms. For example, predicting in a for loop is one thing, but when the target of the branch is always some new portion of memory (graphic, text, etc), it'll always be a cache miss, and there'll never be branch history for it-- because neither have touched it yet.

this is probably a silly question because the content, though it might always be in RAM, will be branched to an order-of-magnitude less than it'll be used (once it's been loaded to cache)...but still, there should be an observable temporal-boundary to the context stored in cache and branch predictor in a procedural language, that would be manifest as an abstraction-boundary in a more parallelized environment

I don't really understand what you're trying to get at, but the concurrency abstractions/safety in Rust is static, there's little-to-no dynamic cost over the raw C/C++ APIs. And, in fact, the checks mean that one can sometimes be more aggressive about what designs can be used, without risking weird runtime corruption.