Rust в ядро ​​конфликта реализации

У меня есть результат, например перечисление:

enum Choice<A, B> {
    A(A),
    B(B),
} 

Я хотел, чтобы этот тип реализовался Into, если оба дженерика — T.
Попытка 1:

impl<T> Into<T> for Choice<T, T> {
    fn into(self) -> T {
        let (Choice::A(x) | Choice::B(x)) = self;
        x
    }
}

Получает меня:

conflicting implementation in crate `core`:
            - impl<T, U> Into<U> for T
              where U: From<T>;

Попытка 2:

impl<T> From<Choice<T, T>> for T {
    fn from(x: Choice<T, T>) -> Self {
        let (Choice::A(x) | Choice::B(x)) = x;
        x
    }
}

Получает меня:

implementing a foreign trait is only possible if at least one of the types  
for which it is implemented is local, and no uncovered type parameters  
appear before that first local type

Обновлено: я понимаю обе эти ошибки, я просто пытаюсь выяснить, есть ли другой способ реализовать Into.

Примечание: вас может заинтересовать Либо.

cdhowie 28.06.2024 00:04

Возможный дубликат stackoverflow.com/questions/37347311/…

fdan 28.06.2024 05:10
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
1
2
79
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Для первой попытки, как упоминалось в примечании, реализация Into для T, определенная в ядре Rust, содержит все типы, такие как ваш типаж Choice, поэтому возникает конфликт реализации, когда вы хотите снова реализовать его для своего типажа.

conflicting implementation in crate `core`:
            - impl<T, U> Into<U> for T
              where U: From<T>;

Я думаю, что для второй попытки примечание об ошибке было объяснено достаточно.

Если вы не хотите использовать Либо по какой-то причине. вы можете использовать следующую реализацию. которые удаляют черту Into.

impl<T> Choice<T, T> {
    fn into(self) -> T {
        let (Choice::A(x) | Choice::B(x)) = self;
        x
    }
}

Вы прямо не сказали, но нет ли другого обходного пути для реализации моего выбора типа Into<T>?

jk_games 28.06.2024 13:36

Причина, по которой вторая попытка не сработала, заключается в том, что какой-то другой ящик может написать что-то вроде следующего, что может конфликтовать с вашим имплементом.

struct Foo;

impl<T: Debug> From<T> for Foo { .... }

Rust пришлось сделать тай-брейк и разрешить только одну из двух конфликтующих реализаций трейта. И, к сожалению, он решил запретить ваше.

Ответ принят как подходящий

Обновлено: я понимаю обе эти ошибки, я просто пытаюсь выяснить, есть ли другой способ реализовать Into.

Нет, ты не можешь. Это может измениться в будущем. Единственный рабочий сценарий — использовать типы, о которых компилятор знает, что From<Choice<..>> не реализован. Это будет работать:

impl Into<i32> for Choice<i32, i32> {
    fn into(self) -> i32 { todo!() }
}

Здесь i32 не реализуется From<Choice<..>>. Использование любого другого типа, который реализует From (или может реализовать, как общие типы), приводит к конфликту с общей реализацией std::core.

Следующая неуниверсальная реализация для Into не компилируется по той же причине:

struct Other;

impl<T> From<Choice<T, T>> for Other {
    fn from(_value: Choice<T, T>) -> Self { todo!() }
}

impl Into<Other> for Choice<Other, Other> {
    fn into(self) -> Other { todo!() }
}

Другие вопросы по теме