Remix.run Logo
latortuga a day ago

I seem to recall this Rust rewrite is all "unsafe" meaning it really doesn't automatically eliminate those issues.

mrothroc a day ago | parent | next [-]

Relevant passage from Jarred's post:

"At the time of writing, about 4% of Bun's Rust code sits inside an unsafe block (~13,000 unsafe keywords across ~27,000 lines / ~780,000 lines), and 78% of those blocks are a single line — a pointer that came from C++, or one call into a C library. I expect this number to go down over time as we refactor from a faithful Zig port (which had no greppable unsafe keyword) to idiomatic Rust, but we are going to continue using C & C++ libraries like JavaScriptCore so it will always have more unsafe than pure Rust projects."

dwattttt 15 hours ago | parent | next [-]

Relative "number of unsafe keywords" or "lines inside unsafe blocks" isn't a good metric.

It's unsafe to call a C library that gives you a raw pointer, that can be a single line. It's unsafe to use that pointer, that could be a second single line. Carrying that pointer around, the data structures it's in, that's all safe, and doesn't implicate lifetime checking at all, so Rust will let you do silly things with the actual lifetime.

A better metric would be absolute unsafe keywords (because each carries a need to review), or "code in a module that uses unsafe anywhere" vs total code, because module boundaries isolate unsafe.

NohatCoder 9 hours ago | parent [-]

Yeah, one needs to understand that "unsafe" does not mark which parts of the code are actually unsafe, it simply marks parts where the compiler ignores parts of its rule set. But the implications can crop up anywhere, there is no guarantee that a resulting use-after-free or similar can only happen inside the unsafe blocks.

In short, if you use an unsafe block, then potentially any part of your code is unsafe.

josephg 8 hours ago | parent | next [-]

> In short, if you use an unsafe block, then potentially any part of your code is unsafe.

The way I think about it is that the unsafe keyword is a promise that you’re going to maintain the safety invariants yourself, manually. The program is memory correct if it correctly maintains a certain set of invariants. Unsafe punts responsibility over those invariants to the programmer. If you use unsafe and mess up, the program may be in an invalid state. Yes - it might crash, anywhere. But the bug is still almost always in an unsafe block.

It’s often possible to make fully safe wrappers around unsafe code which maintains all those invariants manually. (Either statically or dynamically.). A lot of the rust standard library does this. For example, Vec, Box and slice all use unsafe code internally to create safe APIs.

DSMan195276 3 hours ago | parent [-]

> But the bug is still almost always in an unsafe block.

That's entirely dependent on how you write your Rust code. If you're derefing an invalid pointer then the bug is usually in how you calculated that pointer value, but the only part that actually requires 'unsafe' is the deref, not the bugged pointer calculation.

Now in properly written Rust code you should be marking all of that code as 'unsafe' in that case and documenting what invariants need to be maintained, but that's entirely on you to do. The only part the compiler actually enforces is that you mark the specific spots where you make use of the operations that 'unsafe' allows.

dwattttt 6 hours ago | parent | prev | next [-]

> it simply marks parts where the compiler ignores parts of its rule set

This is a common misconception, in a literal interpretation. It doesn't invalidate your point, but since people get the wrong impression: unsafe doesn't turn off any of the checks the Rust compiler does.

It allows you to perform 5 additional operations, and that's it. Using those operations wrong is what breaks the safety promises of the language. As an example, you could dereference a raw pointer and tell the Rust compiler it lives forever, when it's really a pointer to an object that's about to be freed.

randysalami 3 hours ago | parent | prev [-]

Right, so if I understand correctly, to make the code fully safe, it can be impossible? Because you have underlying dependencies which are unsafe. The best you can do is make the handling of the unsafe as safe and as restricted as possible. But I can imagine some of these are way more difficult than others, and in programming the last 10% can be the last 90% of the work. Alas in terms of perceptions, the argument works well.

Yokohiii 12 hours ago | parent | prev [-]

Why not porting JavaScriptCore?

nsonha 9 hours ago | parent | prev [-]

what is surprising about it? The way porting works has alway been first doing a faithful pass before going back to address impedance mismatches case by case. You would do that even when porting things manually, let alone in a super risky completely automated bulk migration.