gpt4 book ai didi

rust - 为什么编译器声称来自更高级别特征绑定(bind)的关联类型没有实现 `Display` ,即使它应该实现?

转载 作者:bug小助手 更新时间:2023-10-28 10:48:22 25 4
gpt4 key购买 nike

我正在构建一个实现字符串连接的库;也就是说,打印由分隔符分隔的容器的所有元素。我的基本设计如下所示:

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)
})
}
}
}
}

此 trait 实现编译时没有任何提示。注意 &'a C: IntoIterator 上的界限。许多容器实现 IntoIterator 来引用它们自己,以允许迭代对所包含项目的引用(例如,Vec 实现它 here )。

但是,当我实际尝试使用我的 Join 结构时,我得到一个不满意的 trait bound:

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 类型是什么,而是基于我对 the docs 的阅读。 ,它似乎是 &T,在这种情况下表示 &&str

为什么编译器不认为&&str 实现了Display?我已经尝试过许多其他类型,例如 usizeString,但它们都不起作用;他们都失败了同样的错误。我知道这些引用类型不直接实现Display,但是应该通过deref coercion自动获取实现,对吧?

最佳答案

好像是 a compiler limitation .您现在可以通过根据表示“显示与生命周期”的私有(private)助手特征来编写 impl 绑定(bind)来解决它。这使编译器可以看到 for<'a> private::Display<'a>暗示 fmt::Display .

use std::fmt;

pub struct Join<Container, Sep> {
container: Container,
sep: Sep,
}

mod private {
use std::fmt;
pub trait Display<'a>: fmt::Display {}
impl<'a, T> Display<'a> for T where T: fmt::Display {}
}

impl<Container, Sep> fmt::Display for Join<Container, Sep>
where
for<'a> &'a Container: IntoIterator,
for<'a> <&'a Container as IntoIterator>::Item: private::Display<'a>,
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)
})
}
}
}
}

fn main() {
println!(
"{}",
Join {
container: vec!["Hello", "World"],
sep: ", ",
}
);
}

关于rust - 为什么编译器声称来自更高级别特征绑定(bind)的关联类型没有实现 `Display` ,即使它应该实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53364798/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com