Rust error E0308: mismatched types
What Rust's E0308 mismatched types error means, how to read expected vs found, and fixes for the most common causes.
E0308 means an expression has a different type from the one the compiler needed at that spot. It's the most common Rust error, and the message always has the same shape: expected X, found Y.
- expected comes from something you wrote earlier: a type annotation, a function signature, the first branch of an
if. - found is the type of the expression underlined with
^^^.
So the fix is either to change the expression to produce the expected type, or to change what you declared.
Cause 1: a semicolon after the return value
fn total(a: i32, b: i32) -> i32 {
a + b;
}
fn main() {
println!("{}", total(1, 2));
}
error[E0308]: mismatched types
--> src/main.rs:1:29
|
1 | fn total(a: i32, b: i32) -> i32 {
| ----- ^^^ expected `i32`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
2 | a + b;
| - help: remove this semicolon to return this value
"found ()" almost always means a stray semicolon or a missing else. Delete the ;.
Cause 2: mixing number types
Rust never converts numbers implicitly, so i32 + i64, or an i32 passed where a usize is expected, is an error. Convert one side: i64::from(a) + b, or index as usize. (Mixed arithmetic also reports E0277, "cannot add i64 to i32".)
Cause 3: &str vs String
let name: String = "Ferris"; says expected String, found &str. Use "Ferris".to_string() or String::from("Ferris"). The reverse (a String passed to a &str parameter) is fixed by borrowing: greet(&name).
Cause 4: Option or Result used as a plain value
fn main() {
let scores = vec![10, 20, 30];
let first: i32 = scores.first();
println!("{first}");
}
error[E0308]: mismatched types
first() returns Option<&i32> because the vector might be empty. Handle the None case: scores.first().copied().unwrap_or(0), or if let Some(&first) = scores.first() { ... }.
Cause 5: branches of different types
fn main() {
let lives = 3;
let label = if lives > 0 { "alive" } else { 0 };
println!("{label}");
}
error[E0308]: `if` and `else` have incompatible types
Every arm of an if or match used as a value must have the same type. The same goes for match arms.
Cause 6: a reference where a value is expected (or the reverse)
Expected i32, found &i32 happens when iterating with for x in &v and passing x to a function taking i32. Dereference with *x, or iterate with .iter().copied(). Expected &str, found String: add &.
How to fix it fast
- Read the
expectedandfoundtypes, and find where the expected type came from (rustc points at it with---- expected due to this). - Check the
help:lines; rustc often suggests the exact conversion (.to_string(),.into(), removing a;). - If you're unsure of a type, annotate a variable with a wrong type on purpose, like
let x: () = value;. The error tells you the real type.
Example
fn total(a: i32, b: i32) -> i32 {
a + b
}
fn describe(lives: i32) -> String {
let label = if lives > 0 { "alive" } else { "out" };
format!("{label} with {lives} lives")
}
fn main() {
let small: i32 = 7;
let big: i64 = 5_000_000_000;
println!("{}", total(1, 2));
println!("{}", i64::from(small) + big);
let name: String = "Ferris".to_string();
println!("{}", describe(3));
println!("{name} {}", describe(0));
let scores = vec![10, 20, 30];
let first: i32 = scores.first().copied().unwrap_or(0);
let none: Vec<i32> = Vec::new();
println!("{first} {}", none.first().copied().unwrap_or(0));
let mut sum = 0;
for s in &scores {
sum += *s;
}
println!("sum {sum}");
}
Output:
3
5000000007
alive with 3 lives
Ferris out with 0 lives
10 0
sum 60