Lỗi
Bạn chạy cargo build và trình biên dịch dừng bạn lại:
error[E0308]: mismatched types
--> src/main.rs:5:18
|
5 | let x: i32 = "hello";
| --- ^^^^^^^ expected `i32`, found `&str`
|
= note: expected type `i32`
found type `&str`
Build thất bại. Rust sẽ không biên dịch code có kiểu không khớp — không có coercion ngầm định, không có implicit casting, không có "gần đúng thôi." Biến x được khai báo là i32 nhưng được gán một string literal. Trong Rust, đó là lỗi không thể bỏ qua.
Tại Sao Lỗi Này Xảy Ra
Rust là ngôn ngữ static typing: mỗi biến có đúng một kiểu tại thời điểm biên dịch. Gán sai kiểu và trình biên dịch sẽ từ chối ngay. Không có ngoại lệ.
Điều này thực sự giúp phát hiện lỗi sớm. Coercion ngầm định trong C có thể cắt bớt giá trị 64-bit xuống 32-bit mà không cảnh báo; Rust buộc bạn xử lý nó tường minh. Đánh đổi là bạn không thể cẩu thả với các kiểu — đó chính là mục đích.
Các nguyên nhân phổ biến:
- Annotate biến với sai kiểu cho giá trị đang được gán
- Trả về sai kiểu từ một hàm
- Truyền
&strkhi cầnString(hoặc ngược lại) - Trộn lẫn các kiểu số nguyên như
i32vsu32vsusize - Dùng giá trị
Option<T>khi cầnTtrực tiếp
Cách Sửa Nhanh
Sửa 1: Điều chỉnh type annotation
Nếu giá trị đúng nhưng annotation sai, hãy sửa annotation:
// Trước (annotation sai)
let x: i32 = "hello"; // lỗi: expected i32, found &str
// Sau (annotation khớp với giá trị)
let x: &str = "hello"; // OK
// hoặc để Rust tự suy luận
let x = "hello"; // được suy luận là &str
Sửa 2: Điều chỉnh giá trị
Nếu type annotation là cố ý, hãy gán giá trị đúng:
// Bạn muốn một số nguyên, không phải chuỗi
let x: i32 = 42; // OK
Sửa 3: Chuyển đổi tường minh
Khi bạn thực sự cần thay đổi kiểu, Rust yêu cầu chuyển đổi tường minh. Chọn cái phù hợp với trường hợp của bạn:
// &str → String
let s: String = "hello".to_string();
let s: String = String::from("hello");
// String → &str
let owned = String::from("hello");
let borrowed: &str = &owned;
// i64 → i32 (cắt bớt nếu giá trị vượt quá 2_147_483_647)
let big: i64 = 100;
let small: i32 = big as i32;
// String → số nguyên
let n: i32 = "42".parse().unwrap();
// an toàn hơn — giải thích lý do thất bại:
let n: i32 = "42".parse().expect("không phải số hợp lệ");
Các Tình Huống Phổ Biến
Kiểu trả về của hàm không khớp
Dấu chấm phẩy ở cuối âm thầm thay đổi kiểu trả về thành (). Hãy xóa nó đi:
// lỗi: expected i32, found ()
fn get_value() -> i32 {
let x = 42;
// quên return x — hoặc thêm dấu chấm phẩy sau nó
}
// sửa: bỏ dấu chấm phẩy ở biểu thức cuối
fn get_value() -> i32 {
let x = 42;
x // return ngầm định — không có dấu chấm phẩy
}
Trộn lẫn các kiểu số nguyên
Vec::len() trả về usize, không phải i32. Điều này gây nhầm lẫn cho rất nhiều người mới bắt đầu:
fn print_length(v: &Vec<i32>) {
let len: i32 = v.len(); // lỗi: expected i32, found usize
}
// sửa: dùng kiểu đúng hoặc ép kiểu tường minh
fn print_length(v: &Vec<i32>) {
let len: usize = v.len(); // kiểu đúng
let len2: i32 = v.len() as i32; // ép kiểu tường minh (an toàn cho vec nhỏ)
}
Unwrap Option
Iterator::next() trả về Option<T>, không phải T trực tiếp. Hãy truyền Option hoặc cung cấp giá trị fallback:
fn first_char(s: &str) -> char {
s.chars().next() // lỗi: expected char, found Option<char>
}
// tùy chọn 1: thay đổi kiểu trả về để truyền Option
fn first_char(s: &str) -> Option<char> {
s.chars().next()
}
// tùy chọn 2: unwrap với giá trị mặc định cho chuỗi rỗng
fn first_char(s: &str) -> char {
s.chars().next().unwrap_or('\0')
}
Struct field không khớp kiểu
struct User {
age: u32,
}
// lỗi: expected u32, found i32
let user = User { age: -1i32 };
// sửa: dùng giá trị u32 hợp lệ
let user = User { age: 25u32 };
Đọc Thông Báo Lỗi
Trình biên dịch của Rust cung cấp cho bạn vị trí chính xác và cả hai kiểu liên quan. Đây là cách đọc nó:
error[E0308]: mismatched types
--> src/main.rs:5:18
|
5 | let x: i32 = "hello";
| --- ^^^^^^^ expected `i32`, found `&str`
| |
| expected due to this type annotation
src/main.rs:5:18— file, dòng 5, cột 18 (vị trí không khớp)---dướii32— kiểu được khai báo^^^^^^^dưới"hello"— giá trị gây ra lỗiexpected X, found Y— X là kiểu mà ngữ cảnh yêu cầu, Y là kiểu bạn cung cấp
Expected có nghĩa là kiểu mà ngữ cảnh yêu cầu — một annotation, chữ ký hàm, hoặc trường struct. Found là kiểu thực tế của những gì bạn viết. Sửa một phía để khớp với phía kia.
Để Type Inference Tự Làm Việc
Không chắc hàm trả về kiểu gì? Bỏ qua annotation và để Rust tự suy luận:
// Để Rust tự suy luận kiểu
let x = some_function();
// Muốn biết kiểu chính xác? Tạo một lỗi cố ý:
let _: () = some_function(); // Rust sẽ cho bạn biết kiểu thực sự
Thông báo lỗi sẽ là expected (), found SomeType — tiết lộ kiểu được suy luận thực sự. Kiểm tra kiểu nhanh chóng, miễn phí mà không cần IDE.
Kiểm Tra
Chạy cargo build. Một build thành công trông như sau:
Compiling myproject v0.1.0 (/path/to/myproject)
Finished dev [unoptimized + debuginfo] target(s) in 0.42s
Không có error[E0308] trong output nghĩa là bạn đã xong. Nếu bạn có tests, hãy chạy chúng nữa:
cargo test

