Как я могу связать несколько вызовов с `into ()`?

#rust

#Ржавчина

Вопрос:

В одном из моих проектов Rust у меня есть многоуровневая иерархия перечислений. Вот упрощенная версия (ссылка на игровую площадку):

 enum Child {
    ChildA,
    ChildB,
}

enum Parent {
    ParentA(Child),
    ParentB,
}

enum GrandParent {
    GrandParentA(Parent),
    GrandParentB,
}
  

Для удобства я реализовал конвертеры между каждым уровнем и уровнем выше него:

 impl From<Child> for Parent {
    fn from(c: Child) -> Self {
        Parent::ParentA(c)
    }
}

impl From<Parent> for GrandParent {
    fn from(p: Parent) -> Self {
        GrandParent::GrandParentA(p)
    }
}
  

Если я хочу преобразовать из a Child в a Parent , теперь я могу сделать

 let c: Child = Child::ChildA;
let p: Parent = c.into();
  

Но если я хочу преобразовать из a Child в a Grandparent , я, похоже, не могу связать несколько вызовов с into() :

 let c: Child = Child::ChildA;
let gp: GrandParent = c.into().into();

error[E0282]: type annotations needed
  --> src/main.rs:30:29
   |
30 |     let gp: GrandParent = c.into().into();
   |                           --^^^^--
   |                           | |
   |                           | cannot infer type for type parameter `T` declared on the trait `Into`
   |                           this method call resolves to `T`
   |
   = note: type must be known at this point
  

Я попытался указать тип с помощью turbofish, но это тоже не работает:

     let c = Child::ChildA;
    let gp: GrandParent = c.into::<Parent>().into();

error[E0107]: wrong number of type arguments: expected 0, found 1
  --> src/main.rs:31:36
   |
31 |     let gp: GrandParent = c.into::<Parent>().into();
   |                                    ^^^^^^ unexpected type argument
  

Каков правильный способ связать эти вызовы into() ?

Комментарии:

1. При преобразовании вы используете исходную структуру (что может быть тем, что вы хотите, но я предполагаю, что у вас есть определенные методы для каждого). Как вы относитесь к impl AsRef<Child> for Parent and impl AsRef<Parent> for Child ?

2. Для этого приложения я хочу использовать Child структуру (это преобразование всегда используется в последний раз Child , когда используется структура), но AsRef это также ценный инструмент.

Ответ №1:

 let c: Child = Child::ChildA;
let gp: GrandParent = Into::<Parent>::into(c).into();
  

Ответ №2:

Если вы просто хотите, чтобы это скомпилировалось, используйте Into::<TypeToConvertTo>::into(src) , но я бы посоветовал изучить проблему и выяснить, действительно ли связанные вызовы into() — это то, что вы хотите (подсказка: скорее всего, это не так)

Комментарии:

1. Не могли бы вы дать больше информации о том, почему я «скорее всего» не хотел бы этого делать?

2. @greg потому что тогда вы не сможете вызывать какие-либо методы для своих исходных данных. Я предполагаю, что дочерние и родительские элементы имеют разное поведение, и потенциально было бы лучше позаимствовать поведение других, а не отбрасывать одно поведение для другого. Это, очевидно, зависит от того, как структурирована остальная часть вашего кода.