rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
98.36k stars 12.72k forks source link

Confusing precedence for shifts #104122

Open Pratyush opened 2 years ago

Pratyush commented 2 years ago

I tried this code:

1 << 13 - 10

I expected to get (1 << 13) - 10, but instead got 1 << (13 - 10). I would have expected the precedence rules here to align with those for multiplication/division.

Meta

rustc --version --verbose:

rustc 1.65.0 (897e37553 2022-11-02)
binary: rustc
commit-hash: 897e37553bba8b42751c67658967889d11ecd120
commit-date: 2022-11-02
host: aarch64-apple-darwin
release: 1.65.0
LLVM version: 15.0.0
memoryruins commented 2 years ago

Multiplication and division also have stronger precedence than shifts https://doc.rust-lang.org/nightly/reference/expressions.html#expression-precedence. cargo clippy can help catch these cases https://rust-lang.github.io/rust-clippy/master/index.html#precedence.

Lokathor commented 2 years ago

Unfortunately, the precedence for shifts cannot be changed at this point. It's about 6 years too late for that.

Pratyush commented 2 years ago

Perhaps it would be worthwhile to lift the clippy lint to rustc to catch this? Also, is this something that can be cargo fix-ed at edition boundaries?

Lokathor commented 2 years ago

This is extremely unlikely to change at an edition because it would be hard to spot the difference, and I just don't think that the language team would go for such a proposal.

lifting the clippy lint into rustc is probably possible

jruderman commented 2 years ago

@rustbot label +T-lang -C-bug

tbu- commented 2 years ago

This is extremely unlikely to change at an edition because it would be hard to spot the difference, and I just don't think that the language team would go for such a proposal.

lifting the clippy lint into rustc is probably possible

What would work is making the unparenthesised expression an error. I.e. not allowing an expression like 1 << 13 - 10, and requiring it to be (1 << 13) - 10 or 1 << (13 - 10). I think there's precedence in some programming language for this, and it completely sidesteps the issue of there being different precedence rules between languages.

I checked, the expression 1 << 13 - 10 evaluates to 8 in all of Python, Rust and C, so that's probably not so bad. For 2 | 1 == 3, Rust and Python agree on a precedence, but C has the opposite one. This is bad, especially because people probably try to port C code to Rust.

Lokathor commented 2 years ago

Making old code into an error in any current edition of rust would not work. Making that an error in a future edition of rust is possible.

In the case of 2 | 1 == 3, while C has automatic conversion from bools to ints, Rust doesn't. One precedence ordering makes an expression that type checks, and the other doesn't. But yeah, I'd probably suggest that people use some parens in there. In that case, and in some other cases of "ambiguous looking" expressions the compiler won't even fire the normal warning against unnecessary parens.