Hacker Read top | best | new | newcomments | leaders | about | bookmarklet login

> Using unsafe is like providing a "proof" that the code you write won't cause safe Rust code to exhibit undefined behavior.

My take is that Rust is proposed based on the value proposition of its Safe Rust feature, but in the Linux kernel that feature has limited use.

Therefore, if Safe Rust is out of the table then what's the point of writing/rewriting parts of the Linux kernel in Rust? What's the value proposition?



sort by: page size:

There's a real sense in which, if this were true, we might not need Rust. If we could mechanically translate the Linux kernel to safe Rust, we could prove the Linux kernel safe. If we could prove the Linux kernel safe, that would be a strong argument against a need to translate it to Rust.

Note that this point is independent of the question of whether rewriting the Linux kernel in Rust is actually good/feasible idea. I also think that Rust has other advantages over C that aren't just safety, so it's not a complete comparison--safety is just the biggest one.


> it's just that using unsafe reduces the benefits you get from Rust's model.

No, you still get the benefits where it matters.

The "unsafe" is basically marking a boundary where you're doing things outside of what the compiler can verify. If you're poking at hardware registers, that's expected and normal.

Putting "unsafe" in a program at the hardware boundary doesn't reduce the benefits of Rust elsewhere in the program.


> the existence of unsafe Rust means that Rust as a whole isn't safe by construction

That's true, and it's a good reason to be very clear about when the Safe Rust subset is all that's been used. Unfortunately it's rare to hear written in Safe Rust, but that's how we ought to refer to code written purely in the safe subset. It should be a point of pride. (Corollary: making needlessly excessive use of Rust's unsafe features, should be a point of shame.)

> We also need to be careful about what we mean by "safe". Rust's definition of safety isn't exotic

Rust does a fine job of defining safety as they use it:

> If all you do is write Safe Rust, you will never have to worry about type-safety or memory-safety. You will never endure a dangling pointer, a use-after-free, or any other kind of Undefined Behavior. [0]

This total absence of undefined behaviour definition sounds about right to me. I think Safe Rust also guarantees against reading indeterminate data from an uninitialized variable, but by the total absence of undefined behaviour criterion, that's not strictly relevant to whether it's safe.

> it doesn't cover the gamut of all possible safety concerns.

Sure, but that's not really what safe language means.

> But to prove whether your unsafe code is, in fact, safe to use -- you're back to formal verification again, or (more typically) code reviews.

At the risk of sounding pedantic, code reviews do not prove anything about unsafe code, they only lower the odds of a defect making it through your process.

> You can (often) avoid the use of unsafe Rust altogether, but then you're using a subset of the language -- roughly like the case with MISRA C.

I'd flip that round though, as you generally shouldn't be using Rust's unsafe features. I'd rather say that in the rare case that you really need it, Rust offers additional unsafe features beyond the Safe Rust language.

Safe Rust is intended to have excellent ergonomics, very much unlike MISRA C. If Rust is doing its job, its unsafe features should seem like inline assembly in C. C programmers don't generally feel constrained by an absence of assembly code in their codebases, as that kind of code just isn't necessary very often.

(Also, MISRA C isn't a truly safe language, for what that's worth. C is not so easily tamed.)

[0] https://doc.rust-lang.org/nomicon/meet-safe-and-unsafe.html


> Lots of unsafe code is safe.

This seems like a weird statement to make to me when defending Rust simultaneously. The whole selling point of Rust is that it's supposed to let you write provably safe code. When "unsafe" is used, what you're writing can no longer be proven as safe by the compiler. Maybe you've convinced yourself it's actually safe via some other argument, but people have been convincing themselves that their code is memory safe for decades and they're often wrong. More insidiously, relying on anything in Rust that uses "unsafe" makes it seem like the compiler is proving your own code is safe, but that is no longer true.

With that said, I don't really disagree with what I think your main point is. But seeing unsafe code in Rust is similar to seeing unsafePerformIO in Haskell libraries. Both of these are much more common than the languages' respective evangelists would have you believe, and at some point it actually does start to call into question whether the languages are successful at their basic design goals. (Spoiler: I believe that they are successful more than they are not, and even in the face of the proliferation of "unsafe" code in both languages, they're still worth using.)


> For non-rusties: unsafe means turning off Rust's advanced safety features, reducing its safety level to that of C or C++.

Actually, it's a bit more subtle: unsafe allows using some things which are not protected by "Rust's advanced safety features", like dereferencing raw pointers, and using these things can "reduce its safety level to that of C or C++" (for that module). However, if these things are not used, the safety is not reduced; you can take a block of Rust code which has no "unsafe", put it in an "unsafe" block, and it will be identically safe as before.


I take the exact opposite view: The goal of Rust is to give you tools to manager you unsafe code. Writing Rust code that avoids `unsafe` is counteracting its raison d'etre.

> As far as I understand the libraries of Rust itself can't have everything written in "safe" code.

Extremely low-level code or code that uses FFI indeed uses unsafe, this in unavoidable, but most Rust code doesn't need unsafe at all.


This entire conversation is assuming that `unsafe` in Rust is designed to be syntactic salt to discourage unsafe code, but this is false. The `unsafe` keyword exists to make it easier to understand, review, and audit where memory-safety invariants might ultimately be violated in a zillion-line program, so that instead of needing to carefully consider a zillion lines you only need to consider a tiny fraction of those. It's not there to make programmers' lives harder, it's intended to make programmers' lives easier.

>Using unsafe is like providing a "proof" that the code you write won't cause safe Rust code to exhibit undefined behavior

It is more like providing an "axiom" as the compiler won't be able to check it and instead has to assume that it true.

I wonder if there is scope to extend the language in the future to actually add machine checked proofs.

Normally full machine checking doesn't scale to large projects, but if one had to restrict to writing proofs only for the small subset of unsafe code and let the simpler type/lifetime system handle the rest of the code it might be manageable.


From the link:

"The intention is to make these as safe as possible so that modules written in Rust require the smallest amount of `unsafe` code possible."

When writing a kernel, some unsafe somewhere is always required, on some level.


> People arguing that "you can not ever write safe C" might also come to the conclusion that one "unsafe" somewhere in your Rust code potentially means that the whole code base is immediately at the same level of implicit memory safety as C.

No, the forced use of "unsafe" in Rust for some kinds of safety mechanisms to be disabled makes the code to audit easier to locate and reason about.

IF the code in the "unsafe" block does not actually isolate the "unsafe"-ness THEN conclusions can be drawn about the rest of the code.

Contrast that to C where the code introducing unsafeness, UB and unsoundness could be basically anywhere instead of a convenient "rg/grep unsafe" away.


> A large Rust project uses unsafe only because its authors don't care enough.

This is not true at all. There are plenty of reasons to occasionally use unsafe code, even if your bar for "is it really worth it" is quite high. One reason, if you're writing a crypto library, is that certain kinds of timing attacks are pretty much impossible to prevent without inline assembly.


The point of `unsafe` in Rust is that you can generally limit `unsafe` code to a few short functions and encapsulate them in a safe interface. This means less code to review and maintaining strong guarantees in the rest of the safe Rust code.

unsafe is a part of rust, and this is an important step for OS writers as sometimes it's just more convenient to put in some inline ASM

I never understood that logic.

You can write perfectly safe code in C where virtually everything is unsafe in the sense of the unsafe keyword.

To my understanding, the idea of unsafe is that you now leave the guard rails that Rust provides and have to think for yourself.


> Unsafe Rust is at best equivalent to C/C++ and at worst it's a false sense of security.

This is a bit of a misconception for people who've not worked with unsafe Rust. It's not like the language and most of its features disappear. It just allows a few extra features that are unsafe, like working with pointers... Which, granted, is a lot of interaction with hardware. But you can kinda "cordon" this to a small subset of the codebase dedicated to this low level hardware IO


> you'd need unsafe in Rust

Unsafe is part of the rust language. Theres nothing wrong with using it if you know what you’re doing. The value of unsafe is that it boxes your unsafe code - so you can direct extra care to those functions when writing, reviewing and auditing. (As opposed to C where memory corruption could happen anywhere, so you need to be careful everywhere.)

I could imagine a separate language on the programming languages shootout which is “safe rust”. It’d be interesting how the best unsafe and the best safe programs compare in speed and size.


I'm not talking about 'uses of unsafe', I'm talking about code that is unsafe. Much of that code is not even written in Rust, so there's no 'unsafe' to use.

I'm not a pro but here are my two cents.

The benefit, and really the point of unsafe, is to encapsulate the unsafe stuff behind safe APIs and to use Rust's other features, like the borrow checker for example, to enforce correct usage of such API.

Ex.: I was using nanovg (vector graphics library in C) to build a GUI app some day. I was using Rust and a bare-bones FFI library that provided a 1:1 mapping to the C API. On top of this unsafe C-API, I built a wrapper library in safe Rust that doesn't allow me to use nanovg incorrectly. And not in the use-after-free sense of incorrect (that too), but instead in the "you can't call this function between these other two, that's undefined / will produce unexpected graphical results".

So the power of unsafe is to encapsulate "unsafe" behaviour and to enrich it with compile-time information, to build guarantees around it.

next

Legal | privacy