Почему компилятор ожидает двойную ссылку вместо ссылки при обработке среза как итератора?

Я хочу создать структуру, которая принимает как Vec<String>, так и &[&str] (среди других типов):

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

При передаче Vec<String> он работает как положено:

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

Но при прохождении &[&str]:

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

... Я получаю следующую ошибку:

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`

Почему в этом случае T рассматривается как &&'a str?

Решение состоит в том, чтобы вместо этого использовать следующую нотацию, но я действительно хочу знать, почему запись T как &'a str не работает.

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

Как вы думаете, почему &[T] реализует Iterator<Item = T>? (подсказка: это не так).

Shepmaster 08.04.2022 21:11

На ваш вопрос могут ответить ответы В чем разница между iter и into_iter?; Разница между iter() и into_iter() в общем заимствованном Vec?. Если нет, пожалуйста, редактировать свой вопрос, чтобы объяснить различия. В противном случае мы можем пометить этот вопрос как уже отвеченный.

Shepmaster 08.04.2022 21:12

Посмотрите на реализацияIntoIterator для &'a [T]. Что такое T в вашем коде?

BallpointBen 08.04.2022 21:15
Как создавать пользовательские общие типы в Python (50/100 дней Python)
Как создавать пользовательские общие типы в Python (50/100 дней Python)
Помимо встроенных типов, модуль типизации в Python предоставляет возможность определения общих типов, что позволяет вам определять типы, которые могут...
1
3
35
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

IntoIterator for &[T] дает ссылки: &T, поэтому, поскольку ваш тип фрагмента — &str, итератор Item — это &&str.

Кроме того, ваш код можно упростить, не принимая во внимание второй общий параметр. Вы можете использовать I::Item для ограничения типа итератора:

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]>;

Другие вопросы по теме