, более принципиальный решатель для типов проблем, которые создает сложная система типов.

фрагмент действителен в Rust 1.26.1:

use std::ops::AddAssign;

trait Trait
where
    for<'a> Self: AddAssign<Self> + AddAssign<&'a Self> + Sized,
{
}

trait Trait2 {
    type Associated: Trait;

    fn method(u32) -> Self::Associated;
}

fn func<T2: Trait2>() {
    let mut t = T2::method(1);
    let t2 = T2::method(2);
    t += &t2;
}

Заметить, чтоTrait реализует обаAddAssign<Self> а такжеAddAssign<&'a Trait> (в том порядке, который важен позже). Поэтому вfunc мы знаем, что обаt += t2 а такжеt += &t2 должно быть в силе. Как виднона площадке, t += &t2 действителен, нос помощьюt += t2 не:

error[E0308]: mismatched types
  --> src/main.rs:19:10
   |
19 |     t += t2;
   |          ^^
   |          |
   |          expected reference, found associated type
   |          help: consider borrowing here: `&t2`
   |
   = note: expected type `&<T2 as Trait2>::Associated`
              found type `<T2 as Trait2>::Associated`

Я читаю эту ошибку, так как компилятор не признает, чтоAddAssign<Self> реализован дляT::Associated, что явно неправильно, так как он реализуетTrait, который требуетAddAssign<Self>.

Если мы изменим порядокAddAssign ограничиваетTrait тогда верно обратное:t += t2 действует покаt += &t2 не.

Быстрое решение проблемы - сделатьfunc общий по обоим признакам:

fn func<T: Trait, T2: Trait2<Associated = T>>() {
    let mut t = T2::method(1);
    let t2 = T2::method(2);
    t += t2;
}

Это не должно быть необходимым; компилятор может распознать один изAddAssignс, почему не другой? Кажется, последняя граница - это та, которую нужно признать.

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

Мое текущее подозрение - ошибка компилятора, когда средство проверки типов не учитывает обобщенные элементы в границах признаков, когда это связанный тип. Легко представить, что такой конкретный случай упускается из виду.

Что здесь происходит?

Ответы на вопрос(1)

Ваш ответ на вопрос