Hãy xem xét mã Rust sau đây:
fn f() -> i32 {
loop {
println!("Infinite loop!");
}
println!("Unreachable");
}
Điều này biên dịch (với một cảnh báo) và chạy, mặc dù thực tế là loại trả lại là sai. Có vẻ như trình biên dịch vẫn ổn với kiểu trả về của ()
dòng cuối cùng vì nó phát hiện ra rằng mã này không thể truy cập được.
Tuy nhiên, nếu chúng ta xóa dấu chấm phẩy cuối cùng:
fn f() -> i32 {
loop {
println!("Infinite loop!");
}
println!("Unreachable")
}
Sau đó, mã không còn biên dịch, đưa ra một lỗi loại:
error[E0308]: mismatched types
--> src/main.rs:14:5
|
14 | println!("Unreachable")
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `()`
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
Tại sao lại thế này? Không phải kiểu trả về giống nhau ()
, trong cả hai đoạn mã này?
Lưu ý: Tôi muốn tìm hiểu lý do tại sao trình biên dịch Rust hoạt động khác nhau trên hai ví dụ này, tức là cách trình biên dịch Rust được triển khai. Tôi không có ý hỏi một câu hỏi triết học về cách nó "nên" hành xử, từ quan điểm của thiết kế ngôn ngữ (tôi hiểu rằng một câu hỏi như vậy có thể sẽ lạc đề).
!
là kiểu trả về vì vòng lặp vô hạn, điều này có ý nghĩa. Trong trường hợp thứ hai, có một biểu thức trả về, do đó, bộ giải suy luận kiểu sử dụng nó để suy ra kiểu, điều này cũng có ý nghĩa. Tôi không nghĩ rằng điều này được chỉ định trong tài liệu tham khảo ngôn ngữ, tôi cũng không nghĩ nó quan trọng theo bất kỳ cách nào - chỉ cần bỏ qua tuyên bố không thể truy cập và bạn sẽ ổn.