2017-05-29 35 views
7

下面的代碼似乎是微不足道的,毫不含糊(Playground):爲什麼編譯器不能解析「a作爲u32 <b」或類似的?

let a: u16 = 5; 
let b: u32 = 10; 

let c = a as u32 < b; 

但是編譯器(截至2017年5月30日)失敗,語法錯誤:

error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `;` 
--> src/main.rs:6:25 
    | 
6 |  let c = a as u32 < b; 
    |   

什麼是錯的與編譯器?

回答

12

注:最新防鏽編譯器現在提供了更多有用的錯誤消息(#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; 
相關問題