Skip to content

Rust Error E0614: Type Cannot Be Dereferenced

E0614 means: you wrote * in front of something that isn’t a reference, so there’s nothing to follow. The * operator means “go to the value this reference points to”. A plain u32, i32 or struct isn’t pointing anywhere: it is the value. This usually happens in closures and loops, where it’s easy to lose track of whether you have &u32 or u32. rustc tells you the real type in the headline, and the fix is almost always to delete one *. (This page is part of Rust compiler errors explained.)

error[E0614]: type `u32` cannot be dereferenced
--> src/main.rs:3:64
|
3 | let doubled: Vec<u32> = visits.iter().copied().map(|count| *count * 2).collect(); // ❌ `count` is already a `u32`
| ^^^^^^ can't be dereferenced

This is the program that produces it:

fn main() {
let visits: Vec<u32> = vec![12, 0, 7, 30];
let doubled: Vec<u32> = visits.iter().copied().map(|count| *count * 2).collect(); // ❌ `count` is already a `u32`
println!("{:?}", doubled);
}

The ^^^^^^ points at *count on line 3, labelled “can’t be dereferenced”. The headline tells you what count really is: a u32, not a &u32.

Follow the types along the chain:

  1. visits.iter() gives you references to the items: &u32, &u32, …
  2. .copied() turns each &u32 into a plain u32 copy. The references are gone.
  3. So in .map(|count| ...), count is a u32, and *count asks Rust to follow a pointer that doesn’t exist.

When the headline says type `{integer}` cannot be dereferenced, it’s the same thing. {integer} is how rustc writes “some integer type I haven’t settled yet”, usually a number like 72 that you never gave a type.

It’s like asking someone “what’s at this address?” and handing them the parcel instead of a slip of paper with an address on it. They already have the thing; there’s no address to go to.

In Rust, a reference (&T) and the value itself (T) are different types. * only works on things that point somewhere: references &T and &mut T, smart pointers like Box<T> and Rc<T>, and any type that implements the Deref trait. A u32 or a plain struct has none of that, so * on it has no meaning.

Rust could quietly ignore the extra *, but it doesn’t. An extra * usually means you’re wrong about which type you have, and that confusion tends to cause other bugs: comparing the wrong things, or moving a value you meant to borrow. So rustc stops and tells you the real type. See Borrowing and Smart Pointers.

The opposite mistake has its own error. If you forget a * on a reference, like count > 10 where count is a &u32, you get E0308 mismatched types.

Choose this almost every time, especially after .copied(), .cloned(), .into_iter() on a Vec, or anything else that hands you values. The value is already there, so just use it:

fn main() {
let visits: Vec<u32> = vec![12, 0, 7, 30];
let doubled: Vec<u32> = visits.iter().copied().map(|count| count * 2).collect();
println!("{:?}", doubled);
// `filter` lends each item to the closure, so here `count` IS a `&u32`
// and the `*` is right.
let busy: Vec<u32> = visits.iter().copied().filter(|count| *count > 10).collect();
println!("{:?}", busy);
}

Output:

[24, 0, 14, 60]
[12, 30]
▶ Try it Yourself

That second part trips up a lot of people: in the same chain, map gets the item itself and filter gets a reference to the item. When in doubt, look at the method in the docs. filter takes FnMut(&Self::Item) -> bool, with a &. See Iterators and Closures.

Fix 2: In a for loop, choose values or references

Section titled “Fix 2: In a for loop, choose values or references”

Choose this when the * is inside a for loop. for score in scores takes the Vec apart and gives you each value, so *score fails:

error[E0614]: type `{integer}` cannot be dereferenced
--> src/main.rs:5:18
|
5 | total += *score; // ❌ `score` is a number, not a reference
| ^^^^^^ can't be dereferenced

The broken program:

fn main() {
let scores = vec![72, 95, 88];
let mut total = 0;
for score in scores {
total += *score; // ❌ `score` is a number, not a reference
}
println!("total: {}", total);
}

Either drop the *, or loop over &scores. Then each score is a &i32, the * is correct, and you can still use the Vec after the loop:

fn main() {
let scores = vec![72, 95, 88];
let mut total = 0;
for score in &scores {
total += *score; // `score` is a `&i32` now
}
println!("total: {}", total);
// `scores` wasn't moved into the loop, so it's still here.
println!("{} scores, average {}", scores.len(), total / scores.len() as i32);
}

Output:

total: 255
3 scores, average 85
▶ Try it Yourself

A quick rule: for x in v gives values, for x in &v gives & references, for x in &mut v gives &mut references. Only the last two need a *. See for loops and Vectors.

Fix 3: Match the reference with &x, or use *x, but not both

Section titled “Fix 3: Match the reference with &x, or use *x, but not both”

Choose this when your closure or loop already has a & in the pattern, like |&p|. A & in a pattern unpacks the reference for you, so p is a plain number and *p is one step too many:

error[E0614]: type `{integer}` cannot be dereferenced
--> src/main.rs:3:53
|
3 | let with_fee: Vec<i32> = prices.iter().map(|&p| *p + 1).collect(); // ❌ `&p` already removed the `&`
| ^^ can't be dereferenced

The broken program:

fn main() {
let prices = [3, 5, 8];
let with_fee: Vec<i32> = prices.iter().map(|&p| *p + 1).collect(); // ❌ `&p` already removed the `&`
println!("{:?}", with_fee);
}

Pick one way of getting rid of the reference. Both lines below do the same thing:

fn main() {
let prices = [3, 5, 8];
let with_fee: Vec<i32> = prices.iter().map(|&p| p + 1).collect(); // pattern removes the `&`
let same: Vec<i32> = prices.iter().map(|p| *p + 1).collect(); // `*` removes the `&`
println!("{:?} {:?}", with_fee, same);
// `filter` on `.iter()` gets `&&i32`: two `&`s, so the pattern is `&&p`.
let pricey = prices.iter().filter(|&&p| p > 4).count();
println!("{} pricey items", pricey);
}

Output:

[4, 6, 9] [4, 6, 9]
2 pricey items
▶ Try it Yourself

The same goes for loops: for &(name, qty) in &orders unpacks each reference, so use name and qty without a *. See Pattern Matching.

Fix 4: Check the type, and use the field or Deref for wrappers

Section titled “Fix 4: Check the type, and use the field or Deref for wrappers”

Choose this when the headline names your own type, like type `Meters` cannot be dereferenced. A struct isn’t a reference either, even when it wraps just one value:

error[E0614]: type `Meters` cannot be dereferenced
--> src/main.rs:5:18
|
5 | let longer = *run + 1.0; // ❌ `run` is a `Meters`, not a reference
| ^^^^ can't be dereferenced

The broken program:

struct Meters(f64);
fn main() {
let run = Meters(2.5);
let longer = *run + 1.0; // ❌ `run` is a `Meters`, not a reference
println!("{} m", longer);
}

To get the number inside a tuple struct, use its field, .0:

struct Meters(f64);
fn main() {
let run = Meters(2.5);
let longer = run.0 + 1.0;
println!("{} m", longer);
}

Output:

3.5 m
▶ Try it Yourself

If your type really is a smart-pointer-like wrapper and you want * to work, implement std::ops::Deref for it. Do that only for wrapper types; for a “newtype” like Meters, .0 or a method is clearer. Not sure what type a variable has? Hover over it in your editor (rust-analyzer shows the type), or trust the headline: it always names the real type. See Structs and Smart Pointers.

* on a struct field. *config.retries, where config is a struct (or a reference to one) and retries is a u32, gives type `u32` cannot be dereferenced. The . already follows the reference for you. Fix: config.retries.

Looping over a HashMap by value. for (word, count) in counts { total += *count; } gives type `u32` cannot be dereferenced, because looping over counts itself gives owned keys and values. Fix: drop the *, or loop over &counts if you need the map afterwards. See HashMaps.

After .copied().max() or .cloned().find(...). These give Option<u32>, not Option<&u32>, so in if let Some(best) = ... { *best } the * is one too many. Fix: use best directly. Without .copied(), .iter().max() gives Option<&u32> and *best is right.

  • E0308: mismatched types; the opposite mistake, a missing * where a reference meets a plain value.
  • E0369: binary operation cannot be applied to a type, another error you can get when references and values mix.
  • E0507: cannot move out of a reference; here * does work, but it would move a value that isn’t Copy.
  • E0610: {integer} is a primitive type and has no fields, the “it’s just a number” cousin of this error.
  • E0599: no method found, when the value isn’t the type you thought it was.
  • All compiler errors: the full list of error pages.

Quick check

1. In visits.iter().copied().map(|count| *count + 1), why does *count give E0614?

2. for score in &scores { total += *score; } where scores is a Vec<i32>. Does it compile?

3. prices.iter().map(|&p| *p * 2) gives E0614. What's a correct version?

Score: 0 / 3