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

There is a problem here - it's verbose and prone to silent-ish breakage if the surrounding context changes e.g. due to refactors (well, probably not with this tiny example, but I hope you know what I mean). Thankfully, there is also a solution to this problem: https://github.com/rust-lang/rust/issues/90091

split_array will eventually allow something like the following, which avoids any explicit indexing and will fail to compile if the sizes don't match up:

    struct IVec2(i32, i32);

    impl IVec2 {
        fn parse(b: [u8; 8]) -> Self {
            let (first, second) = b.split_array();
            IVec2(i32::from_le_bytes(first),
                  i32::from_le_bytes(second))
        }
    }


> [...] well, probably not with this tiny example, but I hope you know what I mean [...]

Well, here's the thing. These small pieces of code DO show up in actual, real codebases! I've gotten feedback during code reviews along the lines of, "What if the surrounding context is refactored, this tiny, simple piece code could break" and to be perfectly honest, when I get it, I come down to your desk and we have a discussion about whether that kind of feedback is appropriate, and the purpose of code reviews.

(It also always seems like the issue I'm looking at is "fixed in nightly", but some of those features in nightly take a long time to get accepted, and the ergonomics of split_array() seem a bit dubious to me. Are you going to chain three split_array() for four fields? Obviously, for simple serialization and deserialization there are a ton of different options to automate this code away, but it's nice to be able to write simple code like this when appropriate, and the ergonomics of simple tasks matter.)


That's helpful for that one example, but it doesn't solve the general case. I can think of a hundred different examples that aren't handled by the type system or stdlib.

  fn high_word(n: u32) -> u16 {
      (n >> 16).try_into().unwrap()
  }
Unless someone manages to solve the halting problem, we'll always need unwrap() or equivalent.


It's also the case that this call to `unwrap()` will be removed by dead code elimination.

See: https://play.rust-lang.org/?version=nightly&mode=release&edi...

Where if you look at the asm for playground::high_word then you'll see it's a bare shrl.

I'd quite like an analogue to unwrap() that's checked at compile time -- an out for the type checker, but an error if it's not dead code eliminated. This helps us to trust and rely on the compiler, and is the converse of `unsafe_unwrap`, which tells the compiler to trust us.


In this example you could do: (n >> 16) as u16

There is also this thing called "Infallible". Which will eventually be merged with "!". To express to the compiler and the programmer that something can never fail.

https://doc.rust-lang.org/std/convert/enum.Infallible.html


Maybe the function unwrap should be renamed to ISolemnlySwearThisCanNeverFail.


We'd need an even more unholy name for `unsafe { foo.unwrap_unchecked() }`!


That’s a feature!

I’d be thrilled if C++ required wrapping declaration and use of global variables with ‘unsafe_and_evil { … }’


I do appreciate that Rust tends to have the mentality that they will, after careful consideration, add something like split_array to solve X ugly problem.

But it leads to just a TON of features and approaches to learn.




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

Search: