Привязка признака не выполняется при использовании связанного типа

#rust #traits #generic-programming #type-safety

#Ржавчина #Трейты #generic-программирование #безопасность типов

Вопрос:

Я пытаюсь разработать приложение для отслеживания дорог и разработал следующую структуру признаков (доступно на игровой площадке):

 pub trait Source: Sized {
    type Path: Path<Source = Self>;
}

pub trait Destination<S: Source>{ }

pub trait Path {
    type Source: Source;
    type Destination: Destination<Self::Source>;
}
  

Дело в том, что он не может скомпилироваться с ошибкой

    Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `<<Self as Source>::Path as Path>::Destination: Destination<Self>` is not satisfied
 --> src/lib.rs:2:16
  |
2 |     type Path: Path<Source = Self>;
  |                ^^^^^^^^^^^^^^^^^^^ the trait `Destination<Self>` is not implemented for `<<Self as Source>::Path as Path>::Destination`
...
7 | pub trait Path {
  |           ---- required by a bound in this
8 |     type Source: Source;
9 |     type Destination: Destination<Self::Source>;
  |                       ------------------------- required by this bound in `Path`
  |
help: consider further restricting the associated type
  |
1 | pub trait Source: Sized where <<Self as Source>::Path as Path>::Destination: Destination<Self> {
  |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error
  

Это неясно. Я указал привязку связанного типа, type Path: Path<Source = Self>; которая подразумевает привязку к связанному типу, указанному в сообщении об ошибке.

Но это должно запрещать реализацию с неправильными типами, а не объявлять ее такой, какая она есть. Есть ли способ это исправить?

Ответ №1:

Я нашел способ исправить это, указав еще один связанный тип, но причина исходной ошибки неясна. Вот рабочий пример:

 pub trait Source: Sized {
    type Path: Path<Source=Self, Destination=Self::Destination>;
    type Destination: Destination<Self>; // Added associated type
}

pub trait Destination<S: Source>{ }

pub trait Path {
    type Source: Source;
    type Destination: Destination<Self::Source>;
}