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);
}
I would like to call the .clone()
method of Clone
but from the trait Clone2
but for some reason it doesn't compile. There are some caveats:
- I don't want to do simply
x.clone()
because I won't necessarily haveClone2
in scope (nor event Clone). - I don't want to use
Clone::clone(&x)
because I need to ensure that the type actually implementsClone2
.
Here is a playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=2657776369da56fded5b62f5bad16d4d
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
Right now the only way I found that works is this:
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);
}
This is okayish but I really wish to do that without defining a new function.
In the end I think the best solution I found is to copy (no pun intended) what they did with
core::mem::copy()
for the traitCopy
.https://doc.rust-lang.org/std/mem/fn.copy.html
Since I'm using a trait, I have put the function inside the trait as "provided method":
Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=7ed949c36bc6cc98471835e38f8b2f61