Hacker News new | ask | show | jobs
by estebank 2164 days ago
`as` is not considered idiomatic in Rust code,. `.into()` for infallible cases and `.try_into()` for fallible cases are preferred in almost all cases (in the case of floats there's still discussion around the correct behavior of `.try_into()` for edge cases).

> So I think this is again an example of rust making a decision that hurts program correctness.

Could you expand on other examples?

2 comments

It might not be "idiomatic", but it isn't "unsafe", and so it is now providing a guaranteed behavior that... is it a bug? I certainly think saturation should always be considered a bug... like that's even worse to me than truncation as the semantics of truncation are at least interesting and related to mathematical basis of von neumann computing and sometimes extremely useful as a way to interact with memory-oriented systems, while the semantics of saturation are just subtle corruption that is almost useless to "use" for anything valuable (and are inconsistent, unless they are also doing it for integers? like if I cast a floating point to a 64-bit number and then to an 8-bit number do I get a truncated result instead of a saturated one?... I hope not, even though I reject saturation as a reasonable semantic). But if it is defined legal and guaranteed behavior, what should a tool do in this scenario? It can't say "you have a bug here" as maybe you wanted that behavior.
> But if it is defined legal and guaranteed behavior, what should a tool do in this scenario? It can't say "you have a bug here" as maybe you wanted that behavior.

Rust has a linter called Clippy which absolutely does call out things like that. It can do so because there are other mechanisms in the language which provide the same functionality without ambiguity. I believe casting with `as` is linted against by Clippy.

If this is truly a concern that you have for your code, then you can use the clippy tool to lint for any "as" conversions: https://rust-lang.github.io/rust-clippy/master/index.html#as...
"unsafe" has a very specific meaning in the context of Rust[1][2]: particularly letting you perform actions that can potentially cause undefined behavior. Defining `as` as saturating is removing UB. That being said, the reason it is considered unidiomatic is because saturating or wrapping might not be what your intention could be, so other ways of turning one type to another is needed and should be recommended (into and try_into). The compiler should help you in going in that direction[3], and even though rustc itself doesn't warn you away from using `as` casts, clippy can[4][5][6][7][8][9][10].

[1]: https://doc.rust-lang.org/nomicon/what-unsafe-does.html

[2]: https://nora.codes/post/what-is-rusts-unsafe/

[3]: https://play.rust-lang.org/?version=nightly&mode=debug&editi...

[4]: https://rust-lang.github.io/rust-clippy/master/#cast_lossles...

[5]: https://rust-lang.github.io/rust-clippy/master/#cast_possibl...

[6]: https://rust-lang.github.io/rust-clippy/master/#checked_conv...

[7]: https://rust-lang.github.io/rust-clippy/master/#char_lit_as_...

[8]: https://rust-lang.github.io/rust-clippy/master/#cast_sign_lo...

[9]: https://rust-lang.github.io/rust-clippy/master/#cast_precisi...

[10]: https://rust-lang.github.io/rust-clippy/master/#cast_possibl...

It is "removing" undefined behavior by simply defining it to be something no one would ever ever want ;P. If you are willing to just define behavior arbitrarily then I think you will find the vast majority of (but admittedly not all) undefined behaviors can be made "safe".
Nobody wants undefined behaviour. That's always worse than defining it, whatever that definition is. In any case, there are better options for selecting the behaviour you want instead of using `as`.
> `as` is not considered idiomatic in Rust code

Yes it is. It's used all the time. There's a reason as_conversions defaults to Allow in clippy.

Of course, there are lots of situations where `as` is the wrong tool for the job, but I think it's a bit of a stretch to call `as` "not idiomatic". It's perfectly idiomatic in lots of situations.

Whether or not it should be idiomatic is a separate question.

I think the parent poster is jumping the gun, but it is true that the flaws in `as` have been acknowledged for a long time and alternatives for specific use cases have been regularly introduced in order to reduce its use where possible. Giving it dedicated syntax might be one of the bigger warts of Rust 1.0: it may be the most convenient way to cast between primitive types, but it's often not the best way.

IOW, is it currently unidiomatic? No, code reviewers won't generally look sideways at it. But it's certainly getting less idiomatic over time, and that trend doesn't seem likely to stop soon.

Well or being a temporal throwback instead of gun jumping. The initial handling of integer overflow was another such decision in my view, but it was ultimately reversed.
Your claim that “as” being used is incompatible with it being unidiomatic is false.

The docs, the reference, and the RFCs all regards “as” as a mistake that should not be used, and _many_ features have been introduced over the years to reduce the cases in which “as” is the only alternative.

There are cases in which there is currently no alternative, so people “must” use “as”. This does not imply that it is idiomatic to do so.

But clippy will also scream at you if you convert a larger type to a smaller one.