You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中如何从Clone2 Trait调用继承的Clone方法?

问题:通过Clone2 trait调用Clone方法的编译问题

我想通过自定义的Clone2 trait调用Clone trait的clone方法,但代码编译失败,同时有两个限制:

  • 不想直接使用x.clone(),因为不一定能访问到Clone2或Clone的作用域;
  • 不想使用Clone::clone(&x),因为需要确保类型确实实现了Clone2。

原代码

pub mod stuff {
    pub trait Clone2: Clone {}
    
    impl<T: Clone> Clone2 for Vec<T> {}
}

fn main() {
    let x: Vec<u32> = Default::default();
    let _ = stuff::Clone2::clone(&x);
}

编译错误信息

Compiling playground v0.0.1 (/playground)
error[E0782]: trait objects must include the `dyn` keyword
 --> src/main.rs:9:13
  |
9 |     let _ = stuff::Clone2::clone(&x);
  |             ^^^^^^^^^^^^^
  |
help: add `dyn` keyword before this trait
  |
9 |     let _ = <dyn stuff::Clone2>::clone(&x);
  |             ++++              +

error[E0038]: the trait `Clone2` cannot be made into an object
 --> src/main.rs:9:34
  |
9 |     let _ = stuff::Clone2::clone(&x);
  |                                  ^^ `Clone2` cannot be made into an object
  |
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
 --> src/main.rs:2:23
  |
2 |     pub trait Clone2: Clone {}
  |               ------  ^^^^^ ...because it requires `Self: Sized`
  |               |
  |               this trait cannot be made into an object...
  = note: required for the cast from `&Vec<u32>` to `&dyn Clone2`

error[E0277]: the size for values of type `dyn Clone2` cannot be known at compilation time
 --> src/main.rs:9:34
  |
9 |     let _ = stuff::Clone2::clone(&x);
  |             -------------------- ^^ doesn't have a size known at compile-time
  |             |
  |             required by a bound introduced by this call
  |
  = help: the trait `Sized` is not implemented for `dyn Clone2`
note: required by a bound in `clone`
 --> /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/clone.rs:160:5

error[E0038]: the trait `Clone2` cannot be made into an object
 --> src/main.rs:9:13
  |
9 |     let _ = stuff::Clone2::clone(&x);
  |             ^^^^^^^^^^^^^ `Clone2` cannot be made into an object
  |
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
 --> src/main.rs:2:23
  |
2 |     pub trait Clone2: Clone {}
  |               ------  ^^^^^ ...because it requires `Self: Sized`
  |               |
  |               this trait cannot be made into an object...

error[E0038]: the trait `Clone2` cannot be made into an object
 --> src/main.rs:9:13
  |
9 |     let _ = stuff::Clone2::clone(&x);
  |             ^^^^^^^^^^^^^^^^^^^^^^^^ `Clone2` cannot be made into an object
  |
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
 --> src/main.rs:2:23
  |
2 |     pub trait Clone2: Clone {}
  |               ------  ^^^^^ ...because it requires `Self: Sized`
  |               |
  |               this trait cannot be made into an object...

error[E0746]: return type cannot have an unboxed trait object
 --> src/main.rs:9:13
  |
9 |     let _ = stuff::Clone2::clone(&x);
  |             ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
help: box the return type, and wrap all of the returned values in `Box::new`
  |
9 |     let _ = Box<stuff::Clone2::clone>(&x);
  |             ++++                    +

Some errors have detailed explanations: E0038, E0277, E0746, E0782.
For more information about an error, try `rustc --explain E0038`.
error: could not compile `playground` (bin "playground") due to 6 previous errors

现有可行方案(定义辅助函数)

我目前找到的方法是定义一个辅助函数,但希望不用新函数就能实现:

pub mod stuff {
    pub trait Clone2: Clone {}
    
    impl<T: Clone> Clone2 for Vec<T> {}
}

fn main() {
    let x: Vec<u32> = Default::default();
    
    fn clone2_clone<T: stuff::Clone2>(x: &T) -> T {
        x.clone()
    }
    
    let _ = clone2_clone(&x);
}

无需辅助函数的解决方案

方案1:使用 turbofish 明确指定类型

直接通过 turbofish 语法指定具体的实现类型,让编译器进行静态分发,避免尝试使用动态 trait 对象:

pub mod stuff {
    pub trait Clone2: Clone {}
    
    impl<T: Clone> Clone2 for Vec<T> {}
}

fn main() {
    let x: Vec<u32> = Default::default();
    // 明确指定类型,编译器会静态解析Clone2的继承方法
    let _ = <Vec<u32> as stuff::Clone2>::clone(&x);
}

方案2:给Clone2 trait添加默认方法

在Clone2中定义自己的clone默认方法,直接调用Clone的实现,这样就能通过Clone2直接调用:

pub mod stuff {
    pub trait Clone2: Clone {
        // 定义默认方法,复用Clone的clone实现
        fn clone(&self) -> Self {
            <Self as Clone>::clone(self)
        }
    }
    
    impl<T: Clone> Clone2 for Vec<T> {}
}

fn main() {
    let x: Vec<u32> = Default::default();
    // 现在可以直接通过Clone2调用,同时确保类型实现了Clone2
    let _ = stuff::Clone2::clone(&x);
}

内容的提问来源于stack exchange,提问作者Cecile

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 17:19:50