> Both Option and Result can be unwrapped and - to some extent not coincidentally - both can also be subject to the Try operator (?) which is arguably more correct here than unwrap because this can fail and perhaps the caller will have some plan to recover.
If someone wrote code like that and the program crashed, nobody would attack Go or C. In all these cases (including rust), the programmer is expressing clear, explicit intent for the program to panic if the call failed. I've seen some people say .unwrap() should be named .unwrap_or_panic() or something to make that more clear? I dunno. It seems like a nothingburger to me. A buggy program crashed. They'll do that.
> What sort of "interacting with raw pointers" are you thinking of that's too inconvenient and ugly for your liking?
I have 2 complaints. First, I wish Rust had a -> operator or something like it. This sort of thing is horrible:
(*(*(*ptr).foo).bar)
Secondly, rust's aliasing rules make writing pointer heavy code very difficult. I like to run my unsafe code through MIRI to make sure I'm not doing anything bad, and its incredibly subtle.
Here's an unsafe function which manages the internal state of a skip list:
This code is insanely fragile. There are multiple pointers to different elements floating around. The only way I got miri to calm down was to dereference the node pointer constantly. Eg:
*cursor.num_bytes -= (*node).str.len_bytes();
let next = (*node).first_next().node;
Basically everything else I tried caused obscure aliasing problems. I think if I rewrote this code today I'd probably use a Vec and safe rust instead. I can much more confident write correct C code than correct unsafe rust code. I wish it were the other way around.
As a general principle, unsafe rust should be as simple and easy to reason about as possible so we can spot security problems. But rust's syntax makes unsafe code very complex. I don't think this complexity is in any way necessary.
I see what you mean for -> although personally I haven't missed it (I spent many years writing C) I don't write much pointer twiddling in Rust so I'm the wrong person to have an opinion.
However surely the aliasing is actually a problem and so MIRI is annoyed because what you wrote might be wrong? If we hang on to (*node).first_next() but somehow node changes, we're no longer talking about the same thing, it's exactly the aliasing problem.
I'd have to (which I have not) examine in detail how your code works to offer an opinion beyond speculation, but I think my instinct is sympathy for the "Don't write aliases" approach.
> I think my instinct is sympathy for the "Don't write aliases" approach.
Yes, requiring that nothing alias it’s much more conceptually elegant. But as I said, in practice it makes programming extremely treacherous. There are no warnings when you alias. No errors. 99% of the time you’ll get a working program with no bugs every time you build. You’re just - quietly - at the whim of llvm. Maybe it won’t compile correctly on some other architecture. Maybe a minor compiler bump, or different flags, will make your program totally broken. The only way to discover there’s even a potential problem is by running the code through MIRI.
I get why it’s like this but I think it’s a mistake. I think unsafe rust should be at least as expressive and pleasant to work with as C. Having quiet foot guns here seems antithetical to rust’s philosophy of safe ergonomic programming.
I guess its equivalent to Go code like this:
Or in C: If someone wrote code like that and the program crashed, nobody would attack Go or C. In all these cases (including rust), the programmer is expressing clear, explicit intent for the program to panic if the call failed. I've seen some people say .unwrap() should be named .unwrap_or_panic() or something to make that more clear? I dunno. It seems like a nothingburger to me. A buggy program crashed. They'll do that.> What sort of "interacting with raw pointers" are you thinking of that's too inconvenient and ugly for your liking?
I have 2 complaints. First, I wish Rust had a -> operator or something like it. This sort of thing is horrible:
Secondly, rust's aliasing rules make writing pointer heavy code very difficult. I like to run my unsafe code through MIRI to make sure I'm not doing anything bad, and its incredibly subtle.Here's an unsafe function which manages the internal state of a skip list:
https://github.com/josephg/jumprope-rs/blob/3981256e4e741d8b...
This code is insanely fragile. There are multiple pointers to different elements floating around. The only way I got miri to calm down was to dereference the node pointer constantly. Eg:
Basically everything else I tried caused obscure aliasing problems. I think if I rewrote this code today I'd probably use a Vec and safe rust instead. I can much more confident write correct C code than correct unsafe rust code. I wish it were the other way around.As a general principle, unsafe rust should be as simple and easy to reason about as possible so we can spot security problems. But rust's syntax makes unsafe code very complex. I don't think this complexity is in any way necessary.