Почему я могу создать итератор в штучной упаковке из Vec, а не из массива?

Приведенный ниже код компилируется, но если аргументы, переданные функции f, изменяются с Vec на массив строк, этого не происходит. Я пытаюсь понять почему. Я предполагаю, что это как-то связано с правилами владения, но я мог бы использовать некоторые пояснения. Спасибо.

fn f(args: Box<dyn Iterator<Item=String>>) {
    for arg in args {
        println!("{}", arg)
    }
}


fn main() {
    let args = vec!["one_arg".to_string()]; // If changed to array, I get error below
    f(Box::new(args.into_iter()));
}

Если vec!["One_arg".to_string()]; заменяется на: ["one_arg".to_string()];, приведенная ниже ошибка является результатом.

error[E0271]: type mismatch resolving `<std::slice::Iter<'_, std::string::String> as std::iter::Iterator>::Item == std::string::String`
  --> src/main.rs:10:7
   |
10 |     f(Box::new(args.into_iter()));
   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::string::String`, found reference
   |
   = note: expected struct `std::string::String`
           found reference `&std::string::String`
   = note: required for the cast to the object type `dyn std::iter::Iterator<Item = std::string::String>`

1 ответ

Решение

Причина в том, что Vec::into_iter возвращает итератор по своим элементам, а slice::into_iterвозвращает итератор по ссылкам на свои элементы. Так,args.into_iter() является Iterator<Item=&String> вместо того Iterator<Item=String> когда argsэто кусок. Кстати, неBox а dyn Iterator а вместо этого просто используйте общий:

fn f<I: Iterator<Item=String>>(args: I) {
    for arg in args {
        println!("{}", arg)
    }
}


fn main() {
    let args = vec!["one_arg".to_string()];
    f(args.into_iter());
}
Другие вопросы по тегам