Search code examples
genericsrusthashmapgeneric-programming

The `Copy` trait may not be implemented for this type


I would like to make a fancy universal dictionary for faster prototyping, where the keys are Strings and the values are types wrapped in an AnyType container.

Please be advised that simply adding the normal derive statement above the struct isn't really sufficient, which is why it's not included among the original contents.

My implementation looks like this:

use std::collections::HashMap;
use std::boxed::Box;
use std::rc::Rc;
use std::cell::RefCell;
use std::clone::Clone;

struct AnyType<AT> {
    ___value: Rc<RefCell<Box<AT>>>
}
impl<AT> AnyType<AT> {
    pub fn new(value: AT) -> AnyType<AT> {
        AnyType { 
            ___value: Rc::new(RefCell::from(Box::new(value)))
        }
    }
}

impl<AT> Copy for AnyType<AT> {}
impl<AT> Clone for AnyType<AT> {
    fn clone(&self) -> Self {
        *self
    }
}

struct Dict<AT> {
    ___self: HashMap<String, AnyType<AT>>
}

impl<AT> Dict<AT> {
    pub fn new(keys: Option<Vec<String>>, values: Option<Vec<AnyType<AT>>>) 
        -> Result<Dict<AT>, &'static str>
    {
        // ...

Error:

error[E0204]: the trait `Copy` may not be implemented for this type
  --> src/lib.rs:18:10
   |
8  |     ___value: Rc<RefCell<Box<AT>>>
   |     ------------------------------ this field does not implement `Copy`
...
18 | impl<AT> Copy for AnyType<AT> {}
   |          ^^^^

Playground


Solution

  • You are implementing Copy for AnyType but not for AT. Hence the compiler knows that the full type AnyType cannot be copied in all instances. This is due to the fact that you are not specifying that AT must implement Copy as well. You will have to specify a trait bound AT: Copy to tell Rust that AT can also be copied.

    A short example:

    #[derive(Clone)]
    struct A<T> {
        _v: T
    }
    
    impl<T> Copy for A<T> {}
    
    // Overloaded functions in Rust!
    fn main() {
        let a = A::<i32>{_v: 1};
    }
    

    will also lead to error[E0204]: the trait `Copy` may not be implemented for this type.

    However, by adding the trait bound Copy to all type parameters, the rust compiler will now accept the code since A can be copied because T can be copied.

    #[derive(Clone)]
    struct A<T: Copy> {
        _v: T
    }
    
    impl<T> Copy for A<T> where T: Copy {}
    
    // Overloaded functions in Rust!
    fn main() {
        let a = A::<i32>{_v: 1};
    }