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