2017-05-29 15 views
7

Các mã sau đây dường như là không đáng kể và rõ ràng (Playground):Tại sao trình biên dịch không thể phân tích "a as u32 <b" hoặc tương tự?

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

let c = a as u32 < b; 

Tuy nhiên, trình biên dịch (tính 2017/05/30) không thành công với một lỗi cú pháp:

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

Điều gì là sai với trình biên dịch?

Trả lời

12

Lưu ý: Các trình biên dịch Rust mới nhất hiện nay cung cấp một thông báo lỗi hữu ích hơn (#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)` 

Đây là một trình biên dịch vấn đề được biết đến (#22644). Nói một cách đơn giản, vì một loại (u32) đã được theo sau bởi <, trình biên dịch đã cố gắng phân tích cú pháp < làm đầu danh sách tham số kiểu. Do đó, trình biên dịch đã mong đợi một cái gì đó như u32 <b>, mà sẽ có cú pháp hợp lệ, mặc dù nó không có ý nghĩa. Tuy nhiên, một ví dụ làm cho Rust hoàn toàn hợp lệ là foo as Rc <fmt::Debug> và nếu cú ​​pháp quá háo hức để làm cho < toán tử nhỏ hơn, điều này sẽ không thành công giống nhau. Tất nhiên, về mặt kỹ thuật có những cách xung quanh: C++ và C# có cùng sự mơ hồ ngay từ đầu, chúng chỉ xảy ra một số cơ chế phân biệt các trường hợp này (chẳng hạn như nhìn về phía trước cho một số mã thông báo tùy ý) , mặc dù cũng làm cho trình phân tích cú pháp phức tạp hơn. Việc bao gồm các cơ chế đó trong Rust có thể dẫn đến việc phá vỡ các thay đổi trong cú pháp (hoặc có thể chỉ là thùng cú pháp rustc).

Như hiện nay chưa có thảo luận tích cực để giải quyết vấn đề này, một giải pháp khá đơn giản và dài hạn là để bọc các diễn viên xung quanh ngoặc:

let c = (a as u32) < b; 
Các vấn đề liên quan