Вот простой подход, который работает без функции специализации:
use std::marker::PhantomData;
trait RemoveRef {
type WithoutRef;
}
struct Ref<T> {
phantom: PhantomData<T>,
}
impl<T> RemoveRef for Ref<T> {
type WithoutRef = T;
}
impl<'a, T: RemoveRef> RemoveRef for &'a T {
type WithoutRef = T::WithoutRef;
}
fn main() {
let _: <Ref<i32> as RemoveRef>::WithoutRef = 3;
let _: <&Ref<i32> as RemoveRef>::WithoutRef = 3;
let _: <&&&&Ref<i32> as RemoveRef>::WithoutRef = 3;
}
Не уверен, однако, может ли он быть совместим с вашим фактическим сценарием использования в этой форме или он вообще полезен.
В качестве альтернативы, конечно, также можно заменить ваше общее условие выхода (impl<T> RemoveRef for T
) реализациями для конкретных типов:
impl RemoveRef for i32 {
type WithoutRef = Self;
}
Это позволяет использовать ваш исходный код теста:
let _: <i32 as RemoveRef>::WithoutRef = 3;
let _: <&i32 as RemoveRef>::WithoutRef = 3;
let _: <&&i32 as RemoveRef>::WithoutRef = 3;
Специализации AFAIK не могут помочь вам исправить проблему с перекрытием, например, проблему между for T
и for &'a T
на данном этапе.Для этого потребуются такие функции, как границы отрицательных черт.
Все элементы в default impl
неявно заданы по умолчанию.Если вы переместите ключевое слово default
к связанному типу в своем коде, вы избавитесь от переполнения оценки, но у вас появятся другие ошибки:
impl<T> RemoveRef for T {
default type WithoutRef = T;
}
error[E0308]: mismatched types
--> src/main.rs:16:45
|
16 | let _: <i32 as RemoveRef>::WithoutRef = 3;
| ^ expected associated type, found integral variable
|
= note: expected type `<i32 as RemoveRef>::WithoutRef`
found type `{integer}`
Сбой по той же причине, что и здесь.: Несоответствие между связанным типом и параметром типа, только когда impl отмечен default
Назначение T
для WithoutRef
в сочетании с default
не ограничивает WithoutRef
для типа T
.