Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why does the compiler expect a double reference instead of a reference when treating a slice as an iterator?

I want to create a struct that accepts both a Vec<String> and a &[&str] (among other types):

pub struct Channel<I, T>
where
    I: IntoIterator<Item = T>,
    T: AsRef<str>,
{
    pub name: String,
    pub instruments: I,
}

When passing a Vec<String>, it works as expected:

pub struct Response {
    pub channels: Channel<Vec<String>, String>,
}

But when passing a &[&str]:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

pub struct Request<'a> {
    pub channels: Channel<&'a [&'a str], &'a str>,
}

… I get the following error:

error[E0271]: type mismatch resolving `<&'a [&'a str] as IntoIterator>::Item == &'a str`
  --> src/lib.rs:11:19
   |
11 |     pub channels: Channel<&'a [&'a str], &'a str>,
   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `str`, found `&str`
   |
   = note: expected reference `&'a str`
              found reference `&&'a str`
note: required by a bound in `Channel`
  --> src/lib.rs:3:21
   |
1  | pub struct Channel<I, T>
   |            ------- required by a bound in this
2  | where
3  |     I: IntoIterator<Item = T>,
   |                     ^^^^^^^^ required by this bound in `Channel`

Why is T treated as a &&'a str in that case?

The solution is to use the following notation instead, but I really want to know why writing T as &'a str, which it actually is, does not work.

pub struct Request<'a> {
    pub channels: Channel<&'a [&'a str], &'a &'a str>,
}

>Solution :

IntoIterator for &[T] yields references: &T, so since your slice type is &str, the iterator Item is &&str.

Also, your code can be simplified by not taking in the second generic parameter. You can use I::Item to constrain on the iterator type:

pub struct Channel<I>
where
    I: IntoIterator,
    I::Item: AsRef<str>,
{
    pub name: String,
    pub instruments: I,
}

let channels: Channel<Vec<String>>;
let channels: Channel<&[&str]>;
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading