【问题标题】:a collection of type `str` cannot be built from `std::iter::Iterator<Item=char>`不能从 `std::iter::Iterator<Item=char>` 构建类型为 `str` 的集合
【发布时间】:2020-01-04 11:16:03
【问题描述】:

以下代码编译失败

fn main() {
    let n = 10;
    let mut s = String::new();
    let v = vec!['a'; n];
    s += &v.into_iter().collect();
}

出现错误:

error[E0277]: a collection of type `str` cannot be built from an iterator over elements of type `char`
 --> src/main.rs:5:25
  |
5 |     s += &v.into_iter().collect();
  |                         ^^^^^^^ a collection of type `str` cannot be built from `std::iter::Iterator<Item=char>`
  |
  = help: the trait `std::iter::FromIterator<char>` is not implemented for `str`

但是这个修改似乎有效:

fn main() {
    let n = 10;
    let mut s = String::new();
    let v = vec!['a'; n];
    let t: String = v.into_iter().collect();
    s += &t;
}

我试图了解原因。任何提示/解释都会有所帮助。谢谢。

【问题讨论】:

标签: rust


【解决方案1】:

首先,什么是有效的:

fn main() {
    let n = 10;
    let mut s = String::new();
    let v = vec!['a'; n];
    s += &v.into_iter().collect::<String>();
}

其次,让我们探讨一下为什么会这样。您可以在 String 上执行 add-assign +=,因为它实现了 AddAssign trait

impl<'_> AddAssign<&'_ str> for String

但前提是右侧是&amp;str。因此,在您的第一个示例中,rustc 尝试将char 的向量收集到str 中。不行,因为Iterator::collect的签名:

fn collect<B>(self) -> B
where
    B: FromIterator<Self::Item>,

规定迭代器只能收集到实现FromIterator 的容器中。在所有做implement it的类型中,你可以看到str不是其中之一,但String是。这就是您看到的错误消息。

另一方面,在您的第二个示例和此答案中的代码中,rustc 被明确告知要收集到String。由于Stringstr 作为目标类型实现了Deref trait

impl Deref for String {
    type target = str;
}

&amp;String 可以强制转换为 &amp;str。编译器现在很高兴。


所以现在您应该能够理解为什么以下看起来很有趣的代码也可以工作:

fn main() {
    use std::borrow::Cow;

    let n = 10;
    let mut s = String::new();
    let v = vec!['a'; n];
    s += &v.into_iter().collect::<Cow<'_, str>>();
}

【讨论】:

  • 这是Deref trait 允许从&amp;String&amp;str 的强制转换。另一方面,AsRef 只是一种转换特征(如 From/Into),在语言本身中没有特殊行为。
  • 根据 OP 的先验知识,可能有必要提及 why &amp;str 作为collect 的目标没有意义,即为什么它没有' t 并且无法实现FromIterator。 (例如,因为collect 必须返回一个容器,而&amp;str 不是一个,但String 是。)
猜你喜欢
  • 1970-01-01
  • 2022-10-13
  • 1970-01-01
  • 2020-04-20
  • 1970-01-01
  • 1970-01-01
  • 2020-05-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多