Erring code in question:
#[derive(Debug, Clone, Copy)]
struct OfflineWord {
word: u64,
flag: u64,
}
#[derive(Debug, Clone, Copy)]
struct OnlineWord<'file, F: AsRef<Path>> {
file: &'file F,
byte_offset: u64,
}
union FileWord<'file, F: AsRef<Path>> {
online: OnlineWord<'file, F>,
offline: OfflineWord,
}
Note that word in OfflineWord is in reality a Newtype but I have replaced it here since the newtype only represents processing and this way the snippet is MRE.
The file field is intended to stored a shared reference to a valid system path so it can be reused to open a file for all instances of OnlineWord. In other words, all words share a single origin file.
Whole error message:
error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
--> src/rspeer_freq.rs:20:5
|
20 | online: OnlineWord<'file, F>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
help: wrap the field type in `ManuallyDrop<...>`
|
20 | online: std::mem::ManuallyDrop<OnlineWord<'file, F>>,
| +++++++++++++++++++++++ +
For more information about this error, try `rustc --explain E0740`.
As seen the structs implement Copy by derive and each field does so too (including &T) but compiler is still complaining about them not having Copy (or ManuallyDrop).
rustc --explain E0740 Gives a slightly different explanation, saying that no fields in a union may have destructors. Though I have no powers over that aside from not implementing them, Copy should automatically deal with that by just forgetting the memory AFAIK.
The generic type F in OnlineWord does not have a requirement for Copy but that should not be a problem since 1. derive(Copy) is not complaining 2. &T, as mentioned, has blanket Copy impl. Including Copy as a requirement removes the error but in my understanding it should not be there in the first place.
What am I doing wrong/Misunderstanding here, or is this a bug/limitation within the compiler?
A better way of doing this is encouraged but not required for answering this post.
derive(Trait) on a generic type works by bounding all generic parameters on Trait, therefore your #[derive(Copy)] is only applicable when F: Copy, even though it is not needed. There is a desire for a "smarter" derive called "perfect derive", but nothing is implemented yet (also, it cannot currently work in all cases due to some type system quirks).
You can manually implement Copy and Clone.