On the code below, you can see that I'm trying to clone a: A where A derives Clone
use std::sync::Arc;
pub trait S{}
struct B{
}
impl S for B{
}
#[derive(Clone)]
struct A<T: ?Sized>{
a: Arc<Box<T>>
}
fn main() {
let a: A<dyn S> = A{
a: Arc::new(Box::new(B{}))
};
a.clone();
}
Playground
However I get this error:
Error:
Compiling playground v0.0.1 (/playground)
error[E0599]: the method `clone` exists for struct `A<dyn S>`, but its trait bounds were not satisfied
--> src/main.rs:22:7
|
3 | pub trait S{}
| ----------- doesn't satisfy `dyn S: Clone`
...
13 | struct A<T: ?Sized>{
| -------------------
| |
| method `clone` not found for this
| doesn't satisfy `A<dyn S>: Clone`
...
22 | a.clone();
| ^^^^^ method cannot be called on `A<dyn S>` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`dyn S: Clone`
which is required by `A<dyn S>: Clone`
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `clone`, perhaps you need to implement it:
candidate #1: `Clone`
Shouldn't A implement Clone for any T, since the clone on A would simply call A {a: old_a.clone()} which since it's an Arc it always implement clone?
Shouldn't it be guaranteed that A implements Clone because of #[derive(Clone)]?
This is an issue with the implementation of the derive macro for Clone. It doesn't work with structs containing generic types that don't implement clone themselves: https://github.com/rust-lang/rust/issues/41481
In that case you'll have to implement Clone manually, which is, as you say, pretty easy.
impl<T> Clone for A<T> {
fn clone(&self) -> A<T> {
A { a: self.a.clone() }
}
}
Related
The following code:
use std::marker::PhantomData;
trait MyTrait {
const FOO: usize;
}
struct MyStruct<T: MyTrait> {
v: [u32; <T as MyTrait>::FOO],
p: PhantomData<T>,
}
gives me the following compilation error:
error[E0277]: the trait bound `T: MyTrait` is not satisfied
--> src/lib.rs:8:14
|
4 | const FOO: usize;
| ----------------- required by `MyTrait::FOO`
...
7 | struct MyStruct<T: MyTrait> {
| -- help: consider further restricting this bound: `T: MyTrait +`
8 | v: [u32; <T as MyTrait>::FOO],
| ^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `T`
(Link to the playground)
How can I successfully use FOO when defining my vector?
At the moment, you can't.
Array lengths cannot use generic parameters. This is an issue that results from the way constants and generics are implemented and interact with each other in the compiler and has been worked on for a few years with slow improvements.
This code (playground):
#[derive(Clone)]
struct Foo<'a, T: 'a> {
t: &'a T,
}
fn bar<'a, T>(foo: Foo<'a, T>) {
foo.clone();
}
... does not compile:
error[E0599]: no method named `clone` found for struct `Foo<'a, T>` in the current scope
--> src/main.rs:16:9
|
3 | struct Foo<'a, T: 'a> {
| ---------------------
| |
| method `clone` not found for this
| doesn't satisfy `Foo<'_, T>: std::clone::Clone`
...
16 | foo.clone();
| ^^^^^ method not found in `Foo<'a, T>`
|
= note: the method `clone` exists but the following trait bounds were not satisfied:
`T: std::clone::Clone`
which is required by `Foo<'_, T>: std::clone::Clone`
help: consider restricting the type parameter to satisfy the trait bound
|
3 | struct Foo<'a, T: 'a> where T: std::clone::Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
Adding use std::clone::Clone; doesn't change anything, as it's already in the prelude anyway.
When I remove the #[derive(Clone)] and manually implement Clone for Foo, it compiles as expected!
impl<'a, T> Clone for Foo<'a, T> {
fn clone(&self) -> Self {
Foo {
t: self.t,
}
}
}
What is going on here?
Is there a difference between #[derive()]-impls and manual ones?
Is this a compiler bug?
Something else I didn't think of?
The answer is buried in the error message:
= note: the method `clone` exists but the following trait bounds were not satisfied:
`T: std::clone::Clone`
which is required by `Foo<'_, T>: std::clone::Clone`
When you derive Clone (and many other automatically-derived types), it adds a Clone bound on all generic types. Using rustc -Z unstable-options --pretty=expanded, we can see what it becomes:
impl <'a, T: ::std::clone::Clone + 'a> ::std::clone::Clone for Foo<'a, T> {
#[inline]
fn clone(&self) -> Foo<'a, T> {
match *self {
Foo { t: ref __self_0_0 } =>
Foo{t: ::std::clone::Clone::clone(&(*__self_0_0)),},
}
}
}
In this case, the bound is not needed because the generic type is behind a reference.
For now, you will need to implement Clone yourself. There's a Rust issue for this, but it's a comparatively rare case with a workaround.
Your example will derive Clone without any problems if you explicitly mark that T should implement Clone, like this:
#[derive(Clone)]
struct Foo<'a, T: 'a> {
t: &'a T,
}
fn bar<'a, T: Clone>(foo: Foo<'a, T>) {
foo.clone();
}
(Playground link)
It seems unusual that you can avoid specifying the bound explicitly, but Shepmaster's answer seems to suggest that the compiler inserts it implicitly, so my suggestion is functionally identical.
This code (playground):
#[derive(Clone)]
struct Foo<'a, T: 'a> {
t: &'a T,
}
fn bar<'a, T>(foo: Foo<'a, T>) {
foo.clone();
}
... does not compile:
error[E0599]: no method named `clone` found for struct `Foo<'a, T>` in the current scope
--> src/main.rs:16:9
|
3 | struct Foo<'a, T: 'a> {
| ---------------------
| |
| method `clone` not found for this
| doesn't satisfy `Foo<'_, T>: std::clone::Clone`
...
16 | foo.clone();
| ^^^^^ method not found in `Foo<'a, T>`
|
= note: the method `clone` exists but the following trait bounds were not satisfied:
`T: std::clone::Clone`
which is required by `Foo<'_, T>: std::clone::Clone`
help: consider restricting the type parameter to satisfy the trait bound
|
3 | struct Foo<'a, T: 'a> where T: std::clone::Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
Adding use std::clone::Clone; doesn't change anything, as it's already in the prelude anyway.
When I remove the #[derive(Clone)] and manually implement Clone for Foo, it compiles as expected!
impl<'a, T> Clone for Foo<'a, T> {
fn clone(&self) -> Self {
Foo {
t: self.t,
}
}
}
What is going on here?
Is there a difference between #[derive()]-impls and manual ones?
Is this a compiler bug?
Something else I didn't think of?
The answer is buried in the error message:
= note: the method `clone` exists but the following trait bounds were not satisfied:
`T: std::clone::Clone`
which is required by `Foo<'_, T>: std::clone::Clone`
When you derive Clone (and many other automatically-derived types), it adds a Clone bound on all generic types. Using rustc -Z unstable-options --pretty=expanded, we can see what it becomes:
impl <'a, T: ::std::clone::Clone + 'a> ::std::clone::Clone for Foo<'a, T> {
#[inline]
fn clone(&self) -> Foo<'a, T> {
match *self {
Foo { t: ref __self_0_0 } =>
Foo{t: ::std::clone::Clone::clone(&(*__self_0_0)),},
}
}
}
In this case, the bound is not needed because the generic type is behind a reference.
For now, you will need to implement Clone yourself. There's a Rust issue for this, but it's a comparatively rare case with a workaround.
Your example will derive Clone without any problems if you explicitly mark that T should implement Clone, like this:
#[derive(Clone)]
struct Foo<'a, T: 'a> {
t: &'a T,
}
fn bar<'a, T: Clone>(foo: Foo<'a, T>) {
foo.clone();
}
(Playground link)
It seems unusual that you can avoid specifying the bound explicitly, but Shepmaster's answer seems to suggest that the compiler inserts it implicitly, so my suggestion is functionally identical.
This code (playground):
#[derive(Clone)]
struct Foo<'a, T: 'a> {
t: &'a T,
}
fn bar<'a, T>(foo: Foo<'a, T>) {
foo.clone();
}
... does not compile:
error[E0599]: no method named `clone` found for struct `Foo<'a, T>` in the current scope
--> src/main.rs:16:9
|
3 | struct Foo<'a, T: 'a> {
| ---------------------
| |
| method `clone` not found for this
| doesn't satisfy `Foo<'_, T>: std::clone::Clone`
...
16 | foo.clone();
| ^^^^^ method not found in `Foo<'a, T>`
|
= note: the method `clone` exists but the following trait bounds were not satisfied:
`T: std::clone::Clone`
which is required by `Foo<'_, T>: std::clone::Clone`
help: consider restricting the type parameter to satisfy the trait bound
|
3 | struct Foo<'a, T: 'a> where T: std::clone::Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
Adding use std::clone::Clone; doesn't change anything, as it's already in the prelude anyway.
When I remove the #[derive(Clone)] and manually implement Clone for Foo, it compiles as expected!
impl<'a, T> Clone for Foo<'a, T> {
fn clone(&self) -> Self {
Foo {
t: self.t,
}
}
}
What is going on here?
Is there a difference between #[derive()]-impls and manual ones?
Is this a compiler bug?
Something else I didn't think of?
The answer is buried in the error message:
= note: the method `clone` exists but the following trait bounds were not satisfied:
`T: std::clone::Clone`
which is required by `Foo<'_, T>: std::clone::Clone`
When you derive Clone (and many other automatically-derived types), it adds a Clone bound on all generic types. Using rustc -Z unstable-options --pretty=expanded, we can see what it becomes:
impl <'a, T: ::std::clone::Clone + 'a> ::std::clone::Clone for Foo<'a, T> {
#[inline]
fn clone(&self) -> Foo<'a, T> {
match *self {
Foo { t: ref __self_0_0 } =>
Foo{t: ::std::clone::Clone::clone(&(*__self_0_0)),},
}
}
}
In this case, the bound is not needed because the generic type is behind a reference.
For now, you will need to implement Clone yourself. There's a Rust issue for this, but it's a comparatively rare case with a workaround.
Your example will derive Clone without any problems if you explicitly mark that T should implement Clone, like this:
#[derive(Clone)]
struct Foo<'a, T: 'a> {
t: &'a T,
}
fn bar<'a, T: Clone>(foo: Foo<'a, T>) {
foo.clone();
}
(Playground link)
It seems unusual that you can avoid specifying the bound explicitly, but Shepmaster's answer seems to suggest that the compiler inserts it implicitly, so my suggestion is functionally identical.
Suppose I want to create some type that wraps some other generic type, like so:
struct MyWrapper<T> {
pub inner: T,
}
Now I want my type to have a method if the inner type satisfies a specific bound. For example: I want to print it (in this example without using fmt traits for simplicity). To do this I have two possibilities: adding a bound to the impl or to the method itself.
Method Bound
impl<T> MyWrapper<T> {
pub fn print_inner(&self) where T: std::fmt::Display {
println!("[[ {} ]]", self.inner);
}
}
When calling this function with a MyWrapper<()> I get:
error[E0277]: `()` doesn't implement `std::fmt::Display`
--> src/main.rs:20:7
|
20 | w.print_inner();
| ^^^^^^^^^^^ `()` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string
|
= help: the trait `std::fmt::Display` is not implemented for `()`
Impl Bound
impl<T: std::fmt::Display> MyWrapper<T> {
pub fn print_inner(&self) {
println!("[[ {} ]]", self.inner);
}
}
Calling it incorrectly again, gives:
error[E0599]: no method named `print_inner` found for type `MyWrapper<()>` in the current scope
--> src/main.rs:19:7
|
1 | struct MyWrapper<T> {
| ------------------- method `print_inner` not found for this
...
19 | w.print_inner();
| ^^^^^^^^^^^
|
= note: the method `print_inner` exists but the following trait bounds were not satisfied:
`() : std::fmt::Display`
My question is: what is more idiomatic? Are there semantic differences (aside from lifetime stuff with traits, explained here)? Are there differences apart from the compiler message?
One semantic difference is that with the type bound on the method you can partially implement a trait:
trait Trait {
fn f(self) where Self: std::fmt::Display;
fn g(self);
}
struct Struct<T>(T);
impl<T> Trait for Struct<T> {
fn f(self) where Struct<T>: std::fmt::Display {
println!("{}", self);
}
fn g(self) {
println!("Hello world!");
}
}
fn main() {
let s = Struct(vec![1]);
// f is not implemented, but g is
//s.f();
s.g();
}
This may be useful if you have many optional methods with different type bounds, which would otherwise require separate traits.