3

My questions is two parts (since I couldn't get the first part, I moved to the second part, which still left me with questions)

Part #1: How do you insert heterogeneous struct types into a HashMap? At first I thought to do it via an enum

E.g.,

enum SomeEnum {
    TypeA,
    TypeB,
    TypeC,
}

struct TypeA{}
struct TypeB{}
struct TypeC{}

let hm = HashMap::new();
hm.insert("foo".to_string(), SomeEnum::TypeA);
hm.insert("bar".to_string(), SomeEnum::TypeB);
hm.insert("zoo".to_string(), SomeEnum::TypeC);

But I get a "Expected type: TypeA, found type TypeB" error

Part #2: So then I went to the docs and read up on Using Trait Objects that Allow for Values of Different Types, and simplified the problem down to just trying to put heterogeneous types into a Vec. So I followed the tutorial exactly, but I'm still getting the same type of error (in the case of the docs, the error is now "Expected type SelectBox, found type Button".

I know static typing is huge part of Rust, but can anyone tell me/show me/refer me to any info related to putting different struct types in either a Vec or HashMap.

semore_1267
  • 1,327
  • 2
  • 14
  • 29

1 Answers1

5

Rust won't do any mapping of types to enum variants for you - you need to explicitly include the data in the enum itself:

use std::collections::HashMap;

enum SomeEnum {
    A(TypeA),
    B(TypeB),
    C(TypeC),
}

struct TypeA {}
struct TypeB {}
struct TypeC {}

fn main() {
    let mut hm = HashMap::new();
    hm.insert("foo".to_string(), SomeEnum::A(TypeA {}));
    hm.insert("bar".to_string(), SomeEnum::B(TypeB {}));
    hm.insert("zoo".to_string(), SomeEnum::C(TypeC {}));
}

That said, if the only context in which you'll need to use those struct types is when you're using that enum, you can combine them like so:

use std::collections::HashMap;

enum SomeEnum {
    A {},
    B {},
    C {},
}

fn main() {
    let mut hm = HashMap::new();
    hm.insert("foo".to_string(), SomeEnum::A {});
    hm.insert("bar".to_string(), SomeEnum::B {});
    hm.insert("zoo".to_string(), SomeEnum::C {});
}
Joe Clay
  • 33,401
  • 4
  • 85
  • 85
  • "Rust won't do any mapping of struct names to enum variants for you - you need to explicitly include the data in the enum itself:" no ? – Stargateur Aug 20 '18 at 18:44
  • @Stargateur: Elaborate? To me, the question sounded like they were trying to insert three different types into a hash map, which would require them to either use trait objects or wrap their three types in a single enum (the latter being what I showed in my answer). Maybe "Rust won't do any mapping of *types* to enum variants for you" would be a better way to phrase what I was saying, though. – Joe Clay Aug 20 '18 at 19:16
  • Well, https://play.rust-lang.org/?gist=e8974a51ee3d664bebc734345e0484cc&version=stable&mode=debug&edition=2015 work fine... someenum is the common type – Stargateur Aug 20 '18 at 19:24
  • @Stargateur: None of the structs are being used, though (see the compiler warnings). There's no actual relationship defined between the enum variant `SomeEnum::TypeA` and the struct `TypeA`, they just have the same name. – Joe Clay Aug 20 '18 at 19:33
  • Oh sorry, I was completely off – Stargateur Aug 20 '18 at 20:06
  • @Stargateur: No problem, just wanted to make sure I wasn't missing something :) – Joe Clay Aug 20 '18 at 20:23