Несоответствие между ассоциированным типом и параметром типа, только когда impl помечен как `default` - PullRequest
0 голосов
/ 25 июня 2018

Следующий код приводит к ошибке ( Детская площадка )

#![feature(specialization)]

trait Foo {
    type Assoc;
    fn foo(&self) -> &Self::Assoc;
}

default impl<T> Foo for T {
    type Assoc = T;
    fn foo(&self) -> &Self::Assoc {
        self
    }
}

Ошибка:

error[E0308]: mismatched types
  --> src/main.rs:20:9
   |
20 |         self
   |         ^^^^ expected associated type, found type parameter
   |
   = note: expected type `&<T as Foo>::Assoc`
              found type `&T`

Это странно, поскольку <T as Foo>::Assoc T, так что должно работать.Даже более странно: когда я удаляю ключевое слово default из impl, оно работает (но, конечно, в моем реальном коде мне нужно пометить impl как default).

Та же ошибка возникает, когдапредоставление значений по умолчанию в определении черты ( Playground ):

#![feature(specialization)]
#![feature(associated_type_defaults)]

trait Foo {
    type Assoc = Self;
    fn foo(&self) -> &Self::Assoc {
        self
    }
}

Что здесь происходит?Это ошибка компилятора?Или - и именно поэтому я задаю этот вопрос - имеет ли эта ошибка смысл, поскольку в специализации есть что-то особенное, чего я еще не понял?В случае, если это ошибка, mem::transmute, безусловно, безопасно, riiiight?

1 Ответ

0 голосов
/ 25 июня 2018

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

У вас есть это:

#![feature(specialization)]

trait Foo {
    type Assoc;
    fn foo(&self) -> &Self::Assoc;
}

default impl<T> Foo for T {
    type Assoc = T;
    fn foo(&self) -> &Self::Assoc {
        self
    }
}

Но представьте, что вы добавили другую реализацию с собственным типом, но без реализации foo.foo этой реализации будет «унаследован» от другой, менее специфичной реализации:

impl<T: SomeConstraint> Foo for T {
    type Assoc = NotT;
}

Тогда возникнет проблема.Ваш foo будет возвращать T, но всякий раз, когда T равен SomeConstraint, будет несовпадение типов, поскольку он должен возвращать NotT.

RFC 2532 - связанный типпо умолчанию упоминает возможное решение в разделе Future Work .Гипотетический блок default может использоваться для указания того, что связанный тип (ы) и метод (ы) должны быть специализированы вместе.Однако нет признаков того, когда такая функция будет рассматриваться для включения.

...