在使用关联类型的情况下,如何为通用容器实现Borrow



我想为UserFriendlyDataStructure实现Borrow,以提供对函数中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;

有没有办法实现我想要做的事情?

可以通过引入一个冗余的第二类型参数来诱使编译器接受代码,该参数被约束为与A::Data:相同

impl<A, D> Borrow<D> for UserFriendlyDataStructure<A>
where
A: TraitA<Data = D>,
D: DataTrait,
{
fn borrow(&self) -> &A::Data {
&self.internal_data
}
}

我不知道为什么这是有效的,简单地约束A::Data: DataTrait是无效的。我认为编译器应该接受这两个版本。

(操场上的完整代码(

编辑:我们在上面的代码中需要冗余类型D这一事实似乎是当前编译器实现的一个缺点,一旦实验类型推理引擎chalk集成到编译器中,这一问题有望得到解决。

相关内容

  • 没有找到相关文章

最新更新