为什么编译器不能解析“a as u32< b”或类似的?

时间:2017-05-29 16:01:04

标签: rust syntax-error

以下代码似乎微不足道(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;
  |        

编译器出了什么问题?

1 个答案:

答案 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;