#rust
Вопрос:
В моем проекте есть структура A
, которая логически связана со структурой B
из другого ящика. Оба имеют внутреннюю необязательную подструктуру ( C
/ D
).
Допустим, для этого примера у них есть такое определение структуры:
struct D {
name: Option<String>
}
struct B {
spec: Option<D>
}
struct C {
name: Option<String>
}
struct A {
spec: Option<C>
}
Теперь я хочу внедрить Into
-черту в A
B
:
impl Into<D> for C {
fn into(self) -> D {
D {
name: self.name
}
}
}
impl Into<B> for A {
fn into(self) -> B {
B {
spec: self.spec.into()
}
}
}
Но ржавчина этого не позволяет:
error[E0277]: the trait bound `std::option::Option<D>: From<std::option::Option<C>>` is not satisfied
--> srcmodelk8s.rs:615:29
|
615 | spec: self.spec.into()
| ^^^^ the trait `From<std::option::Option<C>>` is not implemented for `std::option::Option<D>`
|
= help: the following implementations were found:
<std::option::Option<amp;'a T> as From<amp;'a std::option::Option<T>>>
<std::option::Option<amp;'a mut T> as From<amp;'a mut std::option::Option<T>>>
<std::option::Option<amp;'a tracing_core::span::Id> as From<amp;'a tracing::span::EnteredSpan>>
<std::option::Option<amp;'a tracing_core::span::Id> as From<amp;'a tracing::span::Span>>
and 10 others
= note: required because of the requirements on the impl of `Into<std::option::Option<D>>` for `std::option::Option<C>`
Хотя я предоставляю пользовательскую реализацию для Into
on C, она проверяет только From
. Который я не могу предоставить, так как D-это еще один ящик.
Я должен написать это:
spec: if let Some(v) = self.spec { Some(v.into()) } else { None }
Теперь вопрос:
Есть ли лучший способ, которого мне не хватает?
Если нет: почему это так хлопотно с into()
вариантами?
Комментарии:
1.
A
C
Определены ли и в вашем ящике, в то времяB
как иD
определены в другом ящике?2. @Sven: Да, A amp; C-это мой собственный код, B amp; D-это то, что мне нужно для библиотеки, которую я использую
Ответ №1:
Проблема в том, что вы вызываете Into::into
Option<C>
тип, а не тип Option
, который удерживает ( C
).
Вы можете использовать Option::map
метод, который работает с внутренним типом Option
:
impl Into<B> for A {
fn into(self) -> B {
B {
spec: self.spec.map(Into::into)
}
}
}
В стандартной библиотеке нет общего impl<T, U: Into<T>> Into<Option<T>> for Option<U>
(или From
эквивалентного), поэтому вы не можете использовать Into
свойство для Option<T>
превращения Option<U>
непосредственно в Option
и должны полагаться Option::map
или каким-либо другим способом (например, ваш последний фрагмент) извлекать внутренний тип вместо этого.