[habr] На пальцах: ассоциированные типы в Rust и в чём их отличие от аргументов типов


#1

#2

Вроде бы и верно всё написано, но как-то поставлено с ног на голову.
По-моему автор путает причину и следствие:

TL;DR Первые контролирует вызываемый код, вторые — вызывающий.

Это как раз следствие того как работает система вывода типов в Rust.

Суть отличия, в моем понимании, в том что типаж с ассоциированным типом может быть реализован только один раз для каждого типа. Т.е. это такая вариация обобщенного параметра с намеренными ограничениями - конкретный тип определяется при реализации, но реализация может быть только одна. Конечно, об этом упоминается в статье, но подается как следствие того что типажи с ассоциированными типами контрилуруются вызываемым кодом.

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

struct Foo(&'static str);

#[derive(PartialEq, Debug)]
struct Bar(&'static str, i32);

trait Add<RHS, OUT>{
    fn add(self, rhs: RHS) -> OUT;
}

impl Add<i32, Bar> for Foo {
    fn add(self, rhs: i32) -> Bar {
        Bar(self.0, rhs)
    }
}

fn main() {
    let x = Foo("test");
    let y = x.add(42);
    assert_eq!(y, Bar("test", 42));
}

Тип переменной у выводится компилятором без проблем.