以下代码似乎微不足道(Playground):
let a: u16 = 5;
let b: u32 = 10;
let c = a as u32 < b;
然而编译器(截至2017-05-30)因语法错误而失败:
error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `;`
--> src/main.rs:6:25
|
6 | let c = a as u32 < b;
|
编译器出了什么问题?
答案 0 :(得分:12)
注意:最新的Rust编译器现在提供了更有用的错误消息(#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)`
这是一个已知的编译器问题(#22644)。简单地说,由于类型(u32
)后跟<
,编译器尝试将<
解析为类型参数列表的开头。因此,编译器期待类似u32 < b >
的东西,这在语法上是有效的,即使它没有意义。但是,一个完全有效的Rust的例子是foo as Rc < fmt::Debug >
,如果语法太急于使<
小于运算符,那么这个就会失败。
当然,技术上有很多方法:C ++和C#从一开始就具有相同的歧义,它们碰巧有一些机制消除了这些情况的歧义(例如预测任意数量的令牌),虽然也使解析器更复杂。在Rust中包含这些机制可能会导致语法中的更改(或者可能只是rustc语法包)。
由于目前没有积极的讨论来解决这个问题,一个相当简单和长期的解决方案是将括号括起来围绕括号:
let c = (a as u32) < b;