Fix lỗi Rust error[E0308]: mismatched types — Kiểu Không Khớp Tại Thời Điểm Biên Dịch

beginner🦀 Rust2026-03-18| Rust 1.60+ trên Linux, macOS, Windows — bất kỳ nền tảng nào chạy rustc

Error Message

error[E0308]: mismatched types --> src/main.rs:5:18 | 5 | let x: i32 = "hello"; | --- ^^^^^^^ expected `i32`, found `&str`
#rust#hệ-thống-kiểu#kiểu-không-khớp#trình-biên-dịch#kiểu-dữ-liệu

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 &str khi cần String (hoặc ngược lại)
  • Trộn lẫn các kiểu số nguyên như i32 vs u32 vs usize
  • Dùng giá trị Option<T> khi cần T trự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ưới i32 — kiểu được khai báo
  • ^^^^^^^ dưới "hello" — giá trị gây ra lỗi
  • expected 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

Related Error Notes