idoay
idoay

Reputation: 21

Mismatched types error: expected `char`, found reference

the code snippet is:

use std::collections::HashSet;
  
fn main() {
    let dna = String::from("ACCCX");
    let dict: HashSet<char> = vec!['A', 'C', 'G', 'T'].into_iter().collect();
    println!("{}", dna.chars().all(|&x| dict.contains(x)));

}

the error shown in compilation is:

error[E0308]: mismatched types
 --> src/main.rs:6:37
  |
6 |     println!("{}", dna.chars().all(|&x| dict.contains(x)));
  |                                     ^--
  |                                     ||
  |                                     |expected due to this
  |                                     expected `char`, found reference
  |                                     help: did you mean `x`: `&char`
  |
  = note:   expected type `char`
          found reference `&_`

Not sure why &x cannot be inferred as &char and the links I referred to are:

  1. https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.all
  2. https://doc.rust-lang.org/std/collections/struct.HashSet.html#method.contains

Thanks!

Upvotes: 2

Views: 3694

Answers (2)

HJVT
HJVT

Reputation: 2192

The error message is a bit confusing, essentially it is backwards.

dna.chars().all(|&x| dict.contains(x)));

String::chars returns a char, not &char, and HashSet::contains expects a reference to the type it contains, so &char. However, closure |&x| dict.contains(x) expects a reference to some type.
It is a little confusing, but &argument_name in function parameters essentially performs pattern matching on incoming parameter, dereferencing it. It is the same as writing |(a, b)| for a closure that takes a two element tuple and immediately destructures it into two variables.
So really the message should be Expected reference &_, found char.

Upvotes: 3

cadolphs
cadolphs

Reputation: 9617

Actually I just went to the Rust playground and did what I suggested: First I removed the & from your |&x|. Then the compiler complained that the contains(x) wasn't a reference, so I added a & there:

use std::collections::HashSet;
  
fn main() {
    let dna = String::from("ACCCX");
    let dict: HashSet<char> = vec!['A', 'C', 'G', 'T'].into_iter().collect();
    println!("{}", dna.chars().all(|x| dict.contains(&x)));

}

That compiles and prints "false" because X isn't in the hash set.

Upvotes: 1

Related Questions