Я хотел бы реализовать Borrow
для UserFriendlyDataStructure
, чтобы обеспечить доступ к полю internal_data
внутри функции, которая должна быть независимой от поставщика данных. Тип поля internal_data
определяется типом, связанным с признаком TraitA
. Обратите внимание, что черта Sealed
гарантирует, что ни одна из этих черт здесь не может быть реализована другими клетями; это функциональность, которую я строго предоставляю. Кроме того, тип TraitA::Data
ограничен пустой чертой DataTrait
для предотвращения использования UserFriendlyDataStructure
в качестве этого типа.
Следующий пример объясняет лучше всего:
use std::borrow::Borrow;
use std::marker::PhantomData;
mod private {
pub trait Sealed {}
}
pub trait DataTrait: private::Sealed {}
pub trait TraitA: private::Sealed {
type Data: DataTrait;
}
pub struct UserFriendlyDataStructure<A: TraitA> {
internal_data: A::Data,
_a: PhantomData<A>,
}
impl<A: TraitA> Borrow<A::Data> for UserFriendlyDataStructure<A> {
fn borrow(&self) -> &A::Data {
&self.internal_data
}
}
pub fn important_function<A: TraitA, T: Borrow<A::Data>>(data: &T) {
let _internal_data = data.borrow();
// Do lots of work.
}
#[cfg(test)]
mod tests {
use super::*;
pub struct TestData(u32);
impl super::private::Sealed for TestData {}
impl DataTrait for TestData {}
pub struct TestProvider;
impl super::private::Sealed for TestProvider {}
impl TraitA for TestProvider {
type Data = TestData;
}
#[test]
fn basic_test() {
let ufds: UserFriendlyDataStructure<TestProvider> = UserFriendlyDataStructure {
internal_data: TestData(100),
_a: PhantomData::default(),
};
important_function::<TestProvider, _>(&ufds);
}
}
К сожалению, компилятор жалуется:
error[E0119]: conflicting implementations of trait `std::borrow::Borrow<UserFriendlyDataStructure<_>>` for type `UserFriendlyDataStructure<_>`:
--> src/lib.rs:19:1
|
19 | impl<A: TraitA> Borrow<A::Data> for UserFriendlyDataStructure<A> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `core`:
- impl<T> std::borrow::Borrow<T> for T
where T: ?Sized;
Есть ли способ достичь того, что я пытаюсь сделать?