Позвольте мне прокомментировать типы этого выражения:
for s in somethings.list.iter() {
K::abc(&s);
}
(я переименовал переменную итератора, чтобы избежать путаницы).
something
имееттип: Something
. something.list
относится к типу: Vec<Box<AwesomeTrait + Send>>
. somethings.list.iter()
относится к типу std::slice::Iter<...>
(не важно). s
имеет тип &Box<AwesomeTrait + Send>
.Важно отметить, что это ссылка на коробку, потому что вы используете iter()
вместо into_iter()
.
Для получения фактического AwesomeTrait
вынужно разыменовать s
, чтобы получить Box
, а затем снова разыменовать, чтобы добраться до внутреннего объекта: **s
.
Но **s
имеет тип AwesomeTrait
, и вам нужна ссылкак этому, поэтому вы должны получить адрес с &**s
, который имеет тип &AwesomeTrait
.
Полученный код будет:
for s in somethings.list.iter() {
K::abc(&**s);
}
Или, если вы готовыиспользовать список:
for s in somethings.list.into_iter() {
K::abc(&*s);
}
Если вы не хотите думать о том, сколько *
использовать, вы можете использовать черту AsRef
, реализованную Box
, и доверять автореференции с помощьюкомпилятор:
for s in somethings.list.iter() {
K::abc(s.as_ref());
}
Примечание: .into_iter()
также можно выделить.Как и .iter()
, если вы повторяете ссылку на Vec
:
for s in somethings.list { //consume the list
K::abc(&*s);
}
или:
for s in &somethings.list { //do not consume the list
K::abc(&**s);
}
Вы думаете, что все готово, но еще не ... этот кодвыдает эту ошибку компилятора:
error[E0277]: the trait bound `AwesomeTrait + std::marker::Send: std::marker::Sized` is not satisfied
--> src/main.rs:12:13
|
12 | K::abc(&**s);
| ^^^^^^ `AwesomeTrait + std::marker::Send` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `AwesomeTrait + std::marker::Send`
note: required by `K::abc`
--> src/main.rs:57:5
|
57 | pub fn abc<T: AwesomeTrait>(something: &T) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Почему это так?Ну, ваш K::abc
требует ссылки на тип, который реализует AwesomeTrait
и &AwesomeTrait
, безусловно, квалифицирует.Но признак - это тип без размера (DST), и для всех параметров универсального типа функции по умолчанию требуется тип Sized
.
Решение состоит в том, чтобы добавить ?Sized
без требований к K::abc
:
impl K {
pub fn abc<T: AwesomeTrait + ?Sized>(something: &T) {
something.func();
}
}
(у вас есть &
в этой функции, которая ничего не делает, я ее удалил).
Ограничение ?Sized
в том, что вы не можете объявлять переменные или параметрытипа T
, только из &T
, &mut T
, Box<T>
... но ваш текущий код ничего не запрещает, так что нет проблем.