【发布时间】:2018-10-30 00:51:46
【问题描述】:
我想为 UserFriendlyDataStructure 实现 Borrow 以提供对函数中的 internal_data 字段的访问,该函数应该与数据提供者无关。 internal_data 字段的类型由关联到 trait TraitA 的类型决定。请注意,Sealed 特征确保此处的这些特征都不能被其他 crate 实现;这是我严格提供的功能。此外,TraitA::Data 类型受空 trait 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;
有没有办法实现我想要做的事情?
【问题讨论】:
-
看起来确实是同一个问题。我不太高兴它需要使用专业化来解决,因为这还不稳定。我看到的替代方法是为所有实现
TraitA的类型手动编写实现(这不是很灵活),或者使用AsRef而不是Borrow(在我的情况下由于其他原因不是最佳的) . -
是否有任何合理的特征限制可以应用于
Data?如果您可以限制它使其不能是UserFriendlyDataStructure,则该错误应该得到解决。 -
Data确实允许任意类型。由于我控制了哪些类型实现了TypeA(这是一个永远不应该有外部实现的内部特征),我可以创建一个绑定到Data的人工特征(例如一个空特征)。如果可行,我会尝试并写一个答案。 -
不幸的是,添加绑定到
Data的特征(通过TraitA)不起作用。我可以通过尝试以这种方式解决问题来更新原始问题或添加答案。我该怎么办?
标签: rust