No, that's sort of the problem, isn't it? Safety actually does depend on the whole shebang, or rather, the correctness of all the code that supplies inputs to the "unsafe" block. I think safety has to be thought about at level of the unit of code that can enforce its own invariants, rather than the specific syntax that does the dirty work.
Safety depends on any module containing unsafe code upholding the invariants that are required. But once you've done that, it's safe.
The question is, how much code is in this state, vs being purely safe? My experience and that of others shows that it's generally a smaller amount than many people not experienced with Rust assume.
Basically, I find the "there's always unsafe code somewhere at the bottom and therefore it's the same as 100% unsafe" to be overly reductive.
> Basically, I find the "there's always unsafe code somewhere at the bottom and therefore it's the same as 100% unsafe" to be overly reductive.
I totally agree; it's not the same. However, I think there is disagreement about whether saying only "there's always unsafe code somewhere at the bottom" is better or worse than saying "it's 100% unsafe".
I tend to write some sketchy unsafe code, and the only thing I can say with a straight face is "please don't use this if you care about safety", i.e. treat it as if "it's 100% unsafe". I'm slightly weirded out that Rust has a keyword that amounts to "I understand UB really well; tell others to trust me on it transitively".
I'll be less weirded out when the UB story gets shaken out more, or if cargo gets an "audit-unsafe" option that shows you all unsafe blocks you transitively depend on (does that exist yet?). Still like Rust, but letting randoms write unsafe code is scary.
> However, I think there is disagreement about whether saying only "there's always unsafe code somewhere at the bottom" is better or worse than saying "it's 100% unsafe".
Are you saying that Rust doesn't have a better memory safety story than C++? In practice, that hasn't been our experience.
I would say that Rust has a different memory safety story from say C#, which distinguishes between "is safe" and "contains unsafe code outside the CLR itself". I find that very-binary distinction more helpful than Rust's memory safety story.
I don't use C++ anymore, but I am not clear on how Rust has better memory safety guarantees than C++. I do like its story more, for sure, and I could see how they might turn in to guarantees (but I could also believe that someone could identify a similarly safe fragment of modern C++, and don't want to start that).
Edit: will rust-lang.org take a PR changing "guaranteed memory safety" to "memory safety story"? ;)
> Edit: will rust-lang.org take a PR changing "guaranteed memory safety" to "memory safety story"? ;)
I hope not. The value proposition of Rust is that if you stick to writing code without unsafe, then you have a guarantee that you will not fall victim to memory unsafety unless there is a bug in the language or in some unsafe block in a dependency you're using.
Personally, I find your quibbling in this thread pretty strange. Rust very clearly provides more memory safety guarantees than C++. For starters, you could not take the guarantee I just stated above and apply it to C++ because there is no such thing as "C++ without unsafe blocks."
I really don't have a position on C++; I don't use it, and don't really want to make supportive or limiting statements.
I have used other memory safe languages, and I find their guarantees qualitatively different from Rust. I would say of them "you will not fall victim to memory unsafety unless there is a bug in the language or in the standard library" with no mention of other dependencies. The standard library is then fairly thoroughly audited.
By comparison, you have e.g. the `memmap` crate, which I like and use, written by serious people known to you, where `unsafe` is used in construction of the memory map. It is then on the user to ensure that there are no concurrent writes to the backing file for the lifetime of the map, at the risk of (as I understand it) UB. Would you describe such a program as "safe"? Or at least, can you understand why I might not? If a concurrent modification happens, is the bug to be found in the `unsafe { MmapMut::map_mut(&file)? }` block, or perhaps farther away where you safely open and modify the file before dropping the map?
I'm sorry if this comes off as quibbling; I do actually care about getting these things right, as I want to rely on them and do more interesting things (e.g. de-abomonate mapped memory).
HN wants me to stop posting, so this will be the last one. You two know how to find me elsewhere.
What I should have written is: "you will not fall victim to memory unsafety unless there is a bug in the language or in the standard library, or you explicitly opt out of safety". Using `unsafe` in C# is opting out of its safety guarantees (and requires the `/unsafe` flag); I'm pretty sure none of the C# team would say "guaranteed memory safety" of unsafe C#. I expect the same is true of Java, and have no clue about Python.
To the extent that we are talking about unsafe C#, I think you are right; it's mostly the same as Rust. But, no one would claim that unsafe C# has "guaranteed memory safety" where the guarantee is "as long as your code and all the code you bring in don't have memory safety bugs". At least, I hope not.
My original point was just meant to be that there is the risk of harm when you try and quantify a language as "more safe" because there are fewer regions where unsafe operations are permitted. People might read "guaranteed memory safety" and misunderstand what it means, as evidenced by me not actually knowing what it means.
There is some tooling but not a ton. Check out the Miri link elsewhere in the thred; eventually I expect us to have amazing tools here. It’s gonna take some time though.