Я создаю библиотеку, которая реализует объединения строк; то есть печать всех элементов контейнера, разделенных разделителем. Мой базовый дизайн выглядит так:
use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Join<Container, Sep> {
container: Container,
sep: Sep,
}
impl<Container, Sep> fmt::Display for Join<Container, Sep>
where
for<'a> &'a Container: IntoIterator,
for<'a> <&'a Container as IntoIterator>::Item: fmt::Display,
Sep: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut iter = self.container.into_iter();
match iter.next() {
None => Ok(()),
Some(first) => {
first.fmt(f)?;
iter.try_for_each(move |element| {
self.sep.fmt(f)?;
element.fmt(f)
})
}
}
}
}
Эта реализация черты компилируется без жалоб. Обратите внимание на ограничение на &'a C: IntoIterator
. Многие контейнеры реализуют IntoIterator
для ссылки на себя, чтобы разрешить итерации по ссылкам на содержащиеся элементы (например, Vec
реализует его здесь ).
Однако, когда я на самом деле пытаюсь использовать мою Join
структуру, я получаю неудовлетворенную черту:
fn main() {
let data = vec!["Hello", "World"];
let join = Join {
container: data,
sep: ", ",
};
println!("{}", join);
}
Этот код выдает ошибку компиляции:
error[E0277]: `<&'a std::vec::Vec<&str> as std::iter::IntoIterator>::Item` doesn't implement `std::fmt::Display`
--> src/main.rs:38:20
|
38 | println!("{}", join);
| ^^^^ `<&'a std::vec::Vec<&str> as std::iter::IntoIterator>::Item` cannot be formatted with the default formatter
|
= help: the trait `for<'a> std::fmt::Display` is not implemented for `<&'a std::vec::Vec<&str> as std::iter::IntoIterator>::Item`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
= note: required because of the requirements on the impl of `std::fmt::Display` for `Join<std::vec::Vec<&str>, &str>`
= note: required by `std::fmt::Display::fmt`
Ключевая строка выглядит так:
the trait `for<'a> std::fmt::Display` is not implemented for `<&'a std::vec::Vec<&str> as std::iter::IntoIterator>::Item`
К сожалению, на самом деле компилятор не сообщает мне, что такое тип Item
, но, исходя из моего чтения документов , он выглядит как &T
, что в данном случае означает &&str
.
Почему компилятор не думает, что &&str
реализует Display
? Я пробовал это со многими другими типами, такими как usize
и String
, и ни один из них не работает; все они терпят неудачу с одной и той же ошибкой. Я знаю, что эти ссылочные типы не напрямую реализуют Display
, но реализация должна быть автоматически подхвачена путем принудительного приведения, верно?