Несоответствие типа параметра типа и связанного типа вывода std :: ops :: BitXor

Я изучаю Rust. Я считаю, что "чрезмерно инженерные" игрушечные примеры полезны на ранних этапах, что и привело меня к этой ситуации.

Начиная с этой простой функции:

extern crate data_encoding;

use std::ops::BitXor;
use data_encoding::hex;
use std::iter::FromIterator;


fn fixed_xor_basic(l: &[u8], r: &[u8]) -> Vec<u8> {
    l.iter().zip(r.iter()).map(|(x, y)| *x ^ *y).collect()
}

#[test]
fn test_fixed_xor_basic() {
    let input_1 = hex::decode(b"1C0111001F010100061A024B53535009181C").unwrap();
    let input_2 = hex::decode(b"686974207468652062756C6C277320657965").unwrap();

    let expected_output = hex::decode(b"746865206B696420646F6E277420706C6179").unwrap();

    assert_eq!(fixed_xor_basic(&input_1, &input_2), expected_output);
}

Я перешел к простому варианту избавления от распределения:

fn fixed_xor_basic_inplace(l: &mut [u8], r: &[u8]) {
    for (left, right) in l.iter_mut().zip(r.iter()) {
        *left = *left ^ *right;
    }
}

И еще один, который принимает любой тип, который можно использовать XOR:

fn fixed_xor_generic<T>(l: &[T], r: &[T]) -> Vec<T>
    where T: BitXor + Copy,
          Vec<T>: FromIterator<<T as BitXor>::Output> {
    l.iter().zip(r.iter()).map(|(x, y)| *x ^ *y).collect()
}

Этот второй вариант изначально не компилировался, но сообщение об ошибке подсказало мне, что нужно добавить ограничение Vec<T>: FromIterator<<T as BitXor>::Output>. По-видимому, это ограничение дало компилятору некоторый намек на то, что BitXor::Output на самом деле то же самое, что и T, но я не понимаю, что именно это подсказка.

Теперь ... объединение этих двух вещей поставило меня в тупик:

fn fixed_xor_generic_inplace<T>(l: &mut [T], r: &[T])
    where T: BitXor + Copy {
    for (left, right) in l.iter_mut().zip(r.iter()) {
        *left = *left ^ *right;
    }
}

Выдает ошибку:

error[E0308]: mismatched types
  --> src/xor_lib.rs:27:17
   |
27 |         *left = *left ^ *right;
   |                 ^^^^^^^^^^^^^^ expected type parameter, found associated type
   |
   = note: expected type `T`
   = note:    found type `<T as std::ops::BitXor>::Output`

error: aborting due to previous error

Я сильно подозреваю, что эти две ситуации похожи и что мне нужно предоставить дополнительный бит контекста, чтобы помочь компилятору понять, что T на самом деле <T as std::ops::BitXor>::Output под другим именем.

Я на правильном пути? Если да, то что это будет за подсказка?

(также следующая задача - заставить функцию принимать типы IntoIterator, а не срезы - если это вообще может повлиять на решение).


person jdeastwood    schedule 28.02.2017    source источник


Ответы (1)


Вам просто нужно сообщить компилятору, что связанный тип Output совпадает с T.

fn fixed_xor_generic_inplace<T>(l: &mut [T], r: &[T])
    where T: BitXor<Output = T> + Copy {
    for (left, right) in l.iter_mut().zip(r.iter()) {
        *left = *left ^ *right;
    }
}
person Peter Hall    schedule 28.02.2017
comment
Что ж, это было легко! Это также упрощает первый общий пример, Vec<T>: FromIterator<<T as BitXor>::Output> больше не нужен. Спасибо! - person jdeastwood; 28.02.2017