如何传递具有特征的 Arc 作为参考?

How to pass a Arc with a trait as a reference?

如何传递对 Arc<A> 的引用,以便以下代码能够成功编译?

use std::sync::Arc;

trait A {
    fn send(&self);
}

struct B;
impl A for B {
    fn send(&self) {
        println!("SENT");
    }
}

fn ss(a: &Arc<A>) {
    let aa = a.clone();
    aa.send();
}

fn main() {
    let a = Arc::new(B);
    ss(&a);
}

(playground)

如果我省略引用,它可以编译,但 Clippy 警告我在这种情况下是没有意义的。

code without reference 上的 Clippy 错误:

  Compiling playground v0.0.1 (file:///playground)
warning: this argument is passed by value, but not consumed in the function body
  --> src/main.rs:13:10
   |
13 | fn ss(a: Arc<A>) {
   |          ^^^^^^ help: consider taking a reference instead: `&Arc<A>`
   |
   = note: #[warn(needless_pass_by_value)] on by default
   = help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/v0.0.186/index.html#needless_pass_by_value

您可以改为传递对 Arc 内容的引用。

fn ss(a: &A) {
    a.send();
}

fn main() {
    let a = Arc::new(B);
    ss(&*a);
}

嗯,最简单的解决方法是忽略 Clippy。 Clippy 中的许多 lints 并不是特别在基本编译器中,因为它们可能是错误的或不适用的。除此之外,Arc 已经是一种参考,采用 &Arc<_>(或 &Rc<_>)几乎没有多大意义。

其次,如 red75prime 所述,您可以更改函数以取而代之 &A

最后,如果你真的想安抚Clippy,你可以按照它说的去做:

fn main() {
    let a = Arc::new(B);
    { let a: Arc<A> = a.clone(); ss(&a); }
}

您必须这样做的原因是您只能强制 "outermost" 间接层。 letArc<B> 强制转换为 Arc<A>,然后创建指向它的指针。

如果有某种原因 ss 需要 它的参数是 Arc (例如克隆它),只需忽略 Clippy 或禁用该 lint。如果没有理由 ss 需要 它的参数是 Arc (你只需要它里面的东西),将 ss 改为 &A 代替。

最后一个主要是为了完整性。