Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The Cloudflare bug was unwrapping a Result::Err not an Option::None.

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.

My list of peeves would be very different from yours. I would like to prohibit move of the dodgier as casts (requiring that you write out the conversion call you actually meant explicitly and then handling any edge cases) for example.

What sort of "interacting with raw pointers" are you thinking of that's too inconvenient and ugly for your liking?





> 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.

I guess its equivalent to Go code like this:

    value, err := stuff()
    if err != nil {
        panic(err)
    }
Or in C:

    int result = stuff();
    assert(result >= 0);
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:

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:

    *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.


Err, you can't use `?` with `Option` unless I've really missed a big feature somewhere. You'd have to map it to a `Result` then unwrap, but at that point you still need to define an error type.

https://doc.rust-lang.org/std/option/enum.Option.html#impl-T...

I guess you've "really missed" this feature or more likely you are considering only the case where our function signature says we return Result and so early returning Option won't compile.

Because the modern "try v2" operator is a trait, it is implemented for Option, Result, and ControlFlow plus Poll variations.

Historically its ancestor the try! macro was provided only for Result, but that's a very long time ago now.


I guess? If it's still languishing in nightly I'm not sure I consider it usable; I'm aware some people are fine to run nightly but I keep to stable releases.

So, all of Try is unstable. This means your stable Rust isn't allowed to implement Try for your own custom types, however the syntax is stable, so since Try is implemented for all of Option, Result and ControlFlow, those all work with the ? syntax even though that implementation is marked unstable.

Let me give you another example you've probably used without realising it, when you write password.contains("foo") in Rust. Why can you write "foo" there? Rust doesn't have overloading, and yet you can pass strings, characters, and functions including lambdas - how can this work? They all implement core::str::pattern::Pattern, an unstable trait used to deliver this functionality for all string matching.

In fact mechanically what's happening here for Try is that ? always worked for Option and Result, the "try v2" feature isn't about the syntax at all, it's about the behind the scenes implementation of that syntax. But that's not important, the syntax is promised and the final implementation will almost certainly be tryv2 or something very similar.


TIL. Thanks for noting!

You have missed a big feature! They added support for that like a year ago or something.

I guess? If it's still languishing in nightly I'm not sure I consider it usable; I'm aware some people are fine to run nightly but I keep to stable releases.

No it's stable.

Years ago. In April 2021 this starts to appear as part of Try v2 implementation work.



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: