不能从`std :: iter :: Iterator <Item = char>`构建类型为`str`的​​集合。

时间:2020-01-04 11:16:03

标签: rust

以下代码无法编译

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

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

1 个答案:

答案 0 :(得分:4)

首先,有效的方法:

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

其次,让我们探讨一下为什么可行。您可以在+=上添加String,因为它实现了AddAssign trait

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

,但仅当右侧是&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;
}

&String可以强制为&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>>();
}