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.)
The error message
Section titled “The error message”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 dereferencedThis 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);}What it means
Section titled “What it means”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:
visits.iter()gives you references to the items:&u32,&u32, ….copied()turns each&u32into a plainu32copy. The references are gone.- So in
.map(|count| ...),countis au32, and*countasks 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.
Why Rust does this
Section titled “Why Rust does this”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.
How to fix it
Section titled “How to fix it”Fix 1: Drop the *
Section titled “Fix 1: Drop the *”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]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 dereferencedThe 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: 2553 scores, average 85A 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 dereferencedThe 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 itemsThe 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 dereferencedThe 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 mIf 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.
Where you’ll usually see it
Section titled “Where you’ll usually see it”* 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.
Related errors
Section titled “Related errors”- 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’tCopy. - 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
Section titled “Quick check”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
Read more
Section titled “Read more”- E0614 — Rust error codes index: the official explanation, with a minimal example and the fix.
- References and Borrowing — The Rust Book: what
&and*mean, and why a reference and a value are different types. - Treating Smart Pointers Like Regular References — The Rust Book: how
*follows references, and how theDereftrait makes it work for your own types. Iterator::copied— standard library docs: the method that turns&Titems intoTitems, the most common reason a*becomes one too many.- Destructuring pointers — Rust by Example: the difference between
&valin a pattern and*valin an expression.