在 Rust 中的元组中匹配 BTreeSet 的类型



我有如下代码(更大库的一部分(。编译器告诉我元组没有实现特征,但我既有元组的实现,也有该元组的一个元素的实现。它适用于另一种类型的元组。

为什么元组(BTreeSet<Annotation>)在这里不匹配?

use std::collections::BTreeSet;
pub struct Axiom {}
pub struct Annotation {}
pub struct AnnotatedAxiom {
pub axiom: Axiom,
pub annotation: BTreeSet<Annotation>,
}
trait Render {
/// Render a entity to Write
fn render(&self);
}
impl<'a, T: Render> Render for &'a BTreeSet<T> {
fn render(&self) {}
}
impl<'a, A: Render> Render for (&'a A,) {
fn render(&self) {
(&self.0).render();
}
}
/// The types in `Render` are too long to type.
macro_rules! render {
($type:ty, $self:ident,
$body:tt) => {
impl Render for $type {
fn render(& $self)
$body
}
}
}
render!{
Annotation, self,
{
}
}
render!{
Axiom, self,
{
}
}
render!{
AnnotatedAxiom, self,
{
// Axiom implements Render
(&self.axiom).render();
// Annotation implements Render
(&self.annotation).render();
// A 1-element tuple of Axiom implements Render
(&self.axiom,).render();
// A 1-element tuple of Annotation does!?
(&self.annotation,).render();
}
}
fn main() {}

操场

error[E0599]: no method named `render` found for type `(&std::collections::BTreeSet<Annotation>,)` in the current scope
--> src/main.rs:62:29
|
62 |         (&self.annotation,).render();
|                             ^^^^^^
|
= note: the method `render` exists but the following trait bounds were not satisfied:
`(&std::collections::BTreeSet<Annotation>,) : Render`
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `render`, perhaps you need to implement it:
candidate #1: `Render`

实现链中存在差距:

impl<'a, T: Render> Render for &'a BTreeSet<T> {
// ....
}
impl<'a, A: Render> Render for (&'a A,) {
// ...
}

第一个impl提供了对BTreeSet的引用Render,而第二个提供了对实现Render的事物的引用元组的实现。由于BTreeSet本身没有实现Render(只有对它的引用!(,编译器将拒绝工作。

在这种情况下,从引用中抽象出来更符合人体工程学,因为Render似乎适合对另一个Render可用值的任何引用。为所有引用实现此特征&T其中T: Render

impl<'a, T> Render for &'a T
where
T: Render,
{
fn render(&self) {
(**self).render();
}
}

因此,其余的实现变得稍微简单一些:

impl<T> Render for BTreeSet<T>
where
T: Render,
{
fn render(&self) {}
}
impl<A> Render for (A,)
where
A: Render,
{
fn render(&self) {
(&self.0).render();
}
}

工作游乐场

另请参阅:

  • 我什么时候不应该实现一个特征来引用该特征的实现者?

最新更新