Earlier quoted context omitted.
This is indeed a very powerful property. However, I have a question: is it a regular practice to ensure that code marked unsafe is actually safe for whichever parameters it receives? Or could the safety of some unsafe code depend on the way its safe wrapper is called?
If you have an unsafe function---that is, a function that is unsafe to call---then it is common practice to document the precise preconditions that the caller must uphold in order to ensure safety. This may indeed include passing a correct parameter. For example, the preconditions of the slice method `get_unchecked` require the caller to verify that the index provided is in bounds, otherwise the behavior is UB. If yo…
Blue Team Rust: What Is “Memory Safety”, Really?
101–105 of 105 posts
Re: Blue Team Rust: What Is “Memory Safety”, Really?
#102Earlier quoted context omitted.
In Rust, the way to force removal of bounds checks is to use iterators rather than a for loop.
I don't think that forces their removal either. It just happens to help the compiler enough that it can remove them automatically most of the time. As far as I know the only way to guarantee that bounds checks are not used in a block of code is to use `unsafe`.
// This is unidiomatic. Don't do this.
for i in 0..100 {
// Oops! Array indexing. Here's a nasty bounds check!
array[i] * 2
}
// Very unidiomatic. Never do this! Not even as an
// optimization. You should properly use safe abstractions
// in stead.
for i in 1..100 {
// Oh, NOOOO! This isn't supposed to be C!
unsafe { array.get_unchecked(i) * 2 }
}
// This is still unidiomatic unless you want to use
// it to explicitly show your code has side-effects.
// However, we're completely rid of the bounds check and
// yet it's perfectly safe perfectly safe.
// The only way this could be unsafe is if rustbelt's
// formal proofs, reviews, audits
// and (probably) MLOC of thoroughly tested and
// possibly fuzzed code using this in practice
// have all somehow missed an unsoundness bug
// in one of the more used safe abstractions in the
// core library for years.
for a in array {
// Look, Ma! No indexing, therefore no bounds check!
// Internally `get_unchecked` is (conceptually) used
// but it's perfectly safe!
a * 2
}
// This is idiomatic Rust. Again, there's no bounds check
// to start with, since the save abstraction knows
// exactly how many elements are in the array and
// that the borrow checker will ensure nobody can
// possibly invalidate its indexing.
// Ditto what was said above that the safe abstraction
// is pretty much guaranteed to be sound.
a.iter().map(|a| a * 2).collect()Re: Blue Team Rust: What Is “Memory Safety”, Really?
#103Earlier quoted context omitted.
I don't think that forces their removal either. It just happens to help the compiler enough that it can remove them automatically most of the time. As far as I know the only way to guarantee that bounds checks are not used in a block of code is to use `unsafe`.
Iterators do indeed not force the removal of bounds check, but that's simply because they don't exist to remove in the first place. That's because iterators actually do use `unsafe` internally. They are a safe abstraction. // This is unidiomatic. Don't do this. for i in 0..100 { // Oops! Array indexing. Here's a nasty bounds check! array[i] * 2 } // Very unidiomatic. Never do this! Not even as an // optimization. You…
Re: Blue Team Rust: What Is “Memory Safety”, Really?
#104Earlier quoted context omitted.
I don't think that forces their removal either. It just happens to help the compiler enough that it can remove them automatically most of the time. As far as I know the only way to guarantee that bounds checks are not used in a block of code is to use `unsafe`.
Iterators do indeed not force the removal of bounds check, but that's simply because they don't exist to remove in the first place. That's because iterators actually do use `unsafe` internally. They are a safe abstraction. // This is unidiomatic. Don't do this. for i in 0..100 { // Oops! Array indexing. Here's a nasty bounds check! array[i] * 2 } // Very unidiomatic. Never do this! Not even as an // optimization. You…
Re: Blue Team Rust: What Is “Memory Safety”, Really?
#105Earlier quoted context omitted.
> Safe rust prevents all those memory bugs, instead causing a panic. Rust is even stronger than that, in the vast majority of cases, panics are not related to memory bugs as those are caught at compile time in Rust (panics are usually the quick and dirty way to deal with invalid files names and such things, as Rust refuses to accept those silently).
> panics are usually the quick and dirty way to deal with invalid files names and such things, as Rust refuses to accept those silently And if you were writing quick and dirty C those would likely be memory bugs instead.
In Rust the program explicitly expects there to be an invalid file name or such thing and explicitly panics. This is both safer and more deterministic than C. Additionally, it's easy to grep for things like `panic!`, `unwrap`, `expect`, `unimplemented!`, `todo!`, etc. in your own code or your dependencies' code (assuming you have access to the source). Panicking code also tends to stand out like a sore tooth during code review.
Finally, Rust's approach slightly decreases the odds that someone will be sloppy in the first place. Since you have to explicitly acknowledge the issue and handle it (even if simply by saying `.unwrap()`), there's a chance you'll decide to just handle it properly even though you wouldn't have bothered in C. This is especially the case if you could've handled it properly by shortening `unwrap()` to `?`.