The following code appears to be trivial and unambiguous (Playground):
let a: u16 = 5;
let b: u32 = 10;
let c = a as u32 < b;
Yet the compiler (as of 2017-05-30) fails with a syntax error:
error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `;`
--> src/main.rs:6:25
|
6 | let c = a as u32 < b;
|
What is wrong with the compiler?
Note: The latest Rust compilers now provide a more useful error message (#42578):
error: `<` is interpreted as a start of generic arguments for `u32`, not a comparison
--> src/main.rs:6:22
|
6 | let c = a as u32 < b;
| -------- ^ -- interpreted as generic arguments
| | |
| | not interpreted as comparison
| help: try comparing the casted value: `(a as u32)`
This is a known compiler issue (#22644). Simply put, since a type (u32
) was followed by <
, the compiler attempted to parse <
as the beginning of a type parameter list. Hence, the compiler was expecting something like u32 < b >
, which would be syntactically valid, even though it doesn't make sense. However, an example that makes perfectly valid Rust is foo as Rc < fmt::Debug >
, and if the syntax was too eager to make <
the less-than operator, this one would fail just the same.
Of course, technically there are ways around it: C++ and C# have had the same ambiguity from the beginning, they just happen to have a combination of means to disambiguate these cases:
Any of these will either have implications in the complexity of the parser or in the complexity of the language's syntax definition. The inclusion of those mechanisms in Rust could lead to breaking changes in the syntax (or probably just the rustc syntax crate).
As there is currently no active discussion to address this issue, a fairly simple and long-term solution is to wrap the cast around parentheses:
let c = (a as u32) < b;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With