documentation of the Clone trait表示"如果所有字段都是Clone,则此特性可用于#[derive]."我正在处理这样一种情况,即所有字段areClone都不起作用,但派生Clone不起作用.

请考虑以下简化的示例(Playground link):

use std::fmt;
use std::rc::Rc;

trait Printer: Clone {
    fn print(&self) -> ();
}

#[derive(Clone)]
struct ClosurePrinter<T: fmt::Display> {
    get_value: Rc<dyn Fn() ->T>,
}

impl<T: fmt::Display> ClosurePrinter<T> {
    pub fn new(get_value: Rc<dyn Fn() -> T>) -> ClosurePrinter<T> {
        ClosurePrinter { get_value }
    }
}

impl<T: fmt::Display> Printer for ClosurePrinter<T> {
    fn print(&self) -> () {
        println!("{}", (self.get_value)())
    }
}

struct ClosurePrinter只有一个字段get_value: Rc<dyn Fn() -> T>.Rc等于Clone,所以我假设get_value等于Clone.然而,编译器坚持认为T也必须是Clone:

error[E0277]: the trait bound `T: Clone` is not satisfied
  --> src/lib.rs:19:23
   |
19 | impl<T: fmt::Display> Printer for ClosurePrinter<T> {
   |                       ^^^^^^^ the trait `Clone` is not implemented for `T`
   |
note: required because of the requirements on the impl of `Clone` for `ClosurePrinter<T>`
  --> src/lib.rs:8:10
   |
8  | #[derive(Clone)]
   |          ^^^^^
note: required by a bound in `Printer`
  --> src/lib.rs:4:16
   |
4  | trait Printer: Clone {
   |                ^^^^^ required by this bound in `Printer`
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider further restricting this bound
   |
19 | impl<T: fmt::Display + std::clone::Clone> Printer for ClosurePrinter<T> {
   |                      +++++++++++++++++++

为什么编译器坚持T必须是Clone

推荐答案

文档中的第二句话应该解释这一点

对于泛型 struct ,#[derive]通过在泛型参数上添加边界Clone来有条件地实现Clone.

这就是派生宏的工作方式.此外,这是它could工作的唯一方式,因为过程性宏的执行发生在编译器能够推理这些特征界限是否必要之前.幸运的是,您可以通过手动实现Clone个特征来解决这个问题.

use std::fmt;
use std::rc::Rc;

struct ClosurePrinter<T: fmt::Display> {
    get_value: Rc<dyn Fn() ->T>,
}

impl<T: fmt::Display> Clone for ClosurePrinter<T> {
    fn clone(&self) -> Self {
         let get_value = Rc::clone(&self.get_value);
         Self { get_value }
    }
}

Rust相关问答推荐

如何最好地并行化修改同一Rust向量的多个切片的代码?

如何使用 list 在Rust for Windows中编译?

如何为rust trait边界指定多种可能性

如何使用盒装枚举进行模式匹配?

为什么基于高山Linux的Docker镜像不能在绝对路径下找到要执行的命令?

如何防止Cargo 单据和Cargo 出口发布( crate )项目

正在将带有盒的异步特征迁移到新的异步_fn_in_特征功能

Rust移动/复制涉及实际复制时进行检测

是否可以使用Serde/Rust全局处理无效的JSON值?

当我编译 Rust 代码时,我是否缺少 AVX512 的目标功能?

实现 Deref 的 struct 可以返回对外部数据的引用吗?

Rust 中的静态引用

如何在 Rust 中编写一个通用方法,它可以接受任何可以转换为另一个值的值?

.to_owned()、.clone() 和取消引用 (*) 之间有区别吗?

如何将 C++ 程序链接到 Rust 程序,然后将该 Rust 程序链接回 C++ 程序? (cpp -> rust -> cpp)

如何在 Emacs Elisp 中获得类似格式化的 LSP?

了解 Rust 闭包:为什么它们持续持有可变引用?

仅在运行测试时生成调试输出

有没有办法在 Rust 中对 BigInt 进行正确的位移?

当引用不再被borrow 时,Rust 不会得到它