rust

How can I use structs containing String in a union?


One task of my university homework is to sort data in a structure with variant fields (a union). We usually use C, but I decided to try Rust and faced a problem.

One of the structs inside the union must include a string. As far as I understand this string is the problem.

My structure:

pub struct Show {
    type_name: ShowType,
    type_data: ShowTypeData,
}
enum ShowType {
    Childish,
    Adultish,
}
union ShowTypeData {
    childish: ChildishShow,
    adultish: AdultishShow,
}
struct ChildishShow {
    age_target: i8,
}
struct AdultishShow {
    subtype: String,
}

Errors:

error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
  --> src/lib.rs:10:5
   |
10 |     childish: ChildishShow,
   |     ^^^^^^^^^^^^^^^^^^^^^^
   |
   = 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<...>`
   |
10 |     childish: std::mem::ManuallyDrop<ChildishShow>,
   |               +++++++++++++++++++++++            +

I don't understand what "Copy" and "Drop" mean exactly.


Solution

  • Do not copy unions from C to Rust verbatim.

    Write instead:

    pub struct Show
    {
        theatre: String,
        name: String,
        director: String,
        price_min: i64,
        price_max: i64,
        show_type: ShowType,
    }
    enum ShowType
    {
        Childish(ChildishShow),
        Adultish(AdultishShow),
        Musical(MusicalShow),
    }
    

    Unions are a low-level, intrinsically unsafe construct in Rust, and quite limited about what you can put in. Use an enum instead when possible. No unions, no problems.