How do I resolve a struct 'Copy' trait issue?

In the code below, for Struct ID lint tells me:

the trait `Copy` may not be implemented for this typerustc(E0204)
board.rs(45, 5): this field does not implement `Copy`
board.rs(42, 10): Error originated from macro here

The enum X has no problem since the #derive attribute provides the Copy trait for it, but please show me how to implement a trait for the sprite_image_instance member type.

use sprite::*;

#[derive(Copy, Clone, Eq, Hash, Debug, PartialEq)]
pub enum X {
    A,
    B,
}

#[derive(Copy, Clone, Eq, Hash, Debug, PartialEq)]
pub struct SpriteID {
    pub sprite_piecetype: X,
    pub sprite_image_instance: Sprite<gfx_texture::Texture<gfx_device_gl::Resources>>,
    // pub sprite_image_instance: &'a mut Sprite<gfx_texture::Texture<gfx_device_gl::Resources>>,
}

You can’t do that for a third-party library type. If that was some other type where author merely not though to add Copy implementation you could either

  1. convince author to add it;
  2. or if you are absolutely sure that type is actually copyable and will never become not copyable in the future you can use a unsafe workaround: since Copy is only valid for types which can be copied with memcpy you can just replace sprite_image_instance with an instance of struct SpriteBytes([u8; std::mem::size_of::<Sprite<…>>]) (with proper #[repr(align(N))] attribute) and do some unsafe magics to cast that to Sprite for use.

But based on what I see in Texture definition the structure will include at least one Arc (first field of Sampler which Texture has inside) and you definitely can’t just copy that with memcpy.

Why do you want copy there in first place? It is generally bad idea to implement Copy for large structs as that will allow compiler to copy large amounts of data without making user aware that it does that.

1 Like

@ ZyX-I

Each Sprite instance has a.set_position() method, so I just wanted to put all Sprite instances in a HashMap with Points as Keys so I could access them to move them from their current positions; which is the HashMap key Point.

Each Point is the top-left coordinate of a rectangle, so I wanted to associate the sprite instances with a rectangle location.

Can you suggest a better alternative than HashMap to associate rectangle coords with a sprite image using Rust such that the 'Copy' trait is not required?

You can't derive Copy for your SpriteID because it owns an instance of your sprite. Based on your use case, you shouldn't need to be copying the sprite around anyway, and should be passing them around by reference.

A hashmap doesn't require you to implement Copy, so can you show us the code that told you to implement Copy for SpriteID? I have a feeling you tried to move the sprite out of your hashmap and the compiler said you are trying to move when you aren't allowed to, and one of the suggestions it gives is to copy the object instead. How you would normally fix this is to replace let sprite = sprites[some_point] with let sprite = &sprites[some_point].

1 Like

@Michael-F-Bryan
Now I'm just getting confused! :slight_smile:

I'm definitely not trying to move the sprite out of the HashMap.

@ZyX-I feels I shouldn't be using a struct for the sprite in the first place, so now I'd like suggestions for what other pattern/technique would be better....

(do this with many sprites)
I create a sprite and set its position:

let mut br_sprite: Sprite<Texture<Resources>> = Sprite::from_texture(br_tex.clone());
br_sprite.set_position(10 as f64, 10 as f64);

I store the position in a point struct:

let square_position_id_point = Point {
        top_left_x: 10,
        top_left_y: 10,

Now, I want to use some Rust technique to associate br_sprite with square_position_id_point.

I thought HashMap was the way to go since I could remove and insert associations easily, and look up a sprite based on the Point key, but now I have a 'copy' problem and a 'moving huge data' problem. I just want a way to do this without these problems. Clearly HashMap is not the way to go.

Any suggestions?

HashMap is the way to go, you just need to use correct syntax. map[key] is a syntax to copy out the value from the map. If you want to take a reference of the value, instead of to copy it out, use &map[key] instead.

https://doc.rust-lang.org/stable/std/ops/trait.Index.html

@Hyeonu
Thanks for you input, but I think everyone is getting confused about the issue here. I'm not copying out any value from a map.

If you look at my first entry in this thread you'll see that the error I get is pre-compile time, from lint in VSCode.

The error is telling me I need to implement a copy trait for one of my struct member fields. One of the fields is fine with the #derive attribute applying a Copy trait, the other field does not accept the Copy trait from the #derive attribute.

@ZyX-I above was more in line with what is going on.

So far, from all the input I've received (and THANK YOU ALL!), along with my own attempts at wrestling with the issue, it appears:

1- the struct X.sprite_instance field won't accept a convoluted sprite instance type since it requires a Copy trait that can't be satisfied without super contortions (see @ZyX-I) .

2- the HashMap does not require a copy of anything, so that is not the issue

3- one may probably be able to place the reference of the sprite instance in the HashMap as a value (not a key) instead of using a struct containing a reference of the sprite instance (couldn't get this to work either)

I just was hoping I could place the sprite instance and it's color type in a struct so I could access two values that way, but apparently this is not possible in Rust.

It certainly is possible; what isn’t possible is to #[derive(Copy)] for that struct. As you’ve already noted, Copy isn’t required for what you want to do— why not just omit it from your structure definition? This should compile just fine:

use sprite::*;

#[derive(Copy, Clone, Eq, Hash, Debug, PartialEq)]
pub enum X {
    A,
    B,
}

#[derive(Clone, Eq, Hash, Debug, PartialEq)]
pub struct SpriteID {
    pub sprite_piecetype: X,
    pub sprite_image_instance: Sprite<gfx_texture::Texture<gfx_device_gl::Resources>>,
    // pub sprite_image_instance: &'a mut Sprite<gfx_texture::Texture<gfx_device_gl::Resources>>,
}

Observation: It appears most of the time the solutions to issues presented in this forum have a simple solution.

Let me take this opportunity to recognize this forum as most likely the best place in the world to get Rust help!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.