调用同名函数的特征实现

nic*_*las 2 traits rust

试图抽象一些我只需要Set我编写的操作的算法

use std::collections::HashSet;

trait Set<T> {
    fn insert(self: &mut Self, item: T);
    fn contains(self: &Self, item: T) -> bool;
}

impl<T> Set<T> for HashSet<T> {
    fn insert(&mut self, item: T) {
        self.insert(item);
    }
    fn contains(&self, item: T) -> bool {
        self.contains(item)
    }
}

impl<T> Set<T> for Vec<T> {
    fn insert(&mut self, item: T) {
        self.push(item);
    }
    fn contains(&self, item: T) -> bool {
        self.contains(item)
    }
}
Run Code Online (Sandbox Code Playgroud)

我在编译时收到有关递归的警告,而我“显然”不想递归,而是在实现者上使用底层实现。

function cannot return without recursing

cannot return without recursing

note: `#[warn(unconditional_recursion)]` on by default
help: a `loop` may express intention better if this is on purposerustc(unconditional_recursion)
Run Code Online (Sandbox Code Playgroud)

我希望只有在指定的情况下才会发生递归 (self as Set<T>).insert

解决这个问题的惯用方法是什么?

rod*_*igo 5

你是对的,HashSet::insert应该优先于你的特征函数。

但问题是HashSet::insert实际上需要T实现Eq + Hash. 由于您T不受限制,HashSet::insert因此不考虑,唯一insert可用的是Set特征,并且您会得到意外的递归。

要发现这一点,您可以尝试编译:

    fn insert(&mut self, item: T) {
        HashSet::insert(self, item);
    }
Run Code Online (Sandbox Code Playgroud)

并得到错误:

error[E0277]: the trait bound `T: std::cmp::Eq` is not satisfied
Run Code Online (Sandbox Code Playgroud)

幸运的是,Rustc 的人已经考虑到了这种错误的可能性(我也遇到过),并添加了一个非常有用的警告。

如果您将其更改为:

impl<T: std::cmp::Eq + std::hash::Hash> Set<T> for HashSet<T> {
    fn insert(&mut self, item: T) {
        self.insert(item);
    }
}
Run Code Online (Sandbox Code Playgroud)

那么它的工作原理。(不过,还有其他不相关的错误。)