Filling a HashMap (or set) by String

I have a Simple structure with a HashSet with a lifetime:
Please let me know how can I correct lines 3 & 4:

pub struct MyStruct<'a> {
    set: HashSet<&'a str>,
}

impl<'a>  MyStruct<'a> {
    fn fill(&mut self) {
        let b = "b";
        let c = String::from("c");
        let d = format!("{}", "d");
        
        self.set.insert("a"); // 1- works
        self.set.insert(b);   // 2- works
        //self.set.insert(&c);  // 3- Not works
        //self.set.insert(&d);  // 4- Not works
    }
}

fn main() {
    let mut foo = MyStruct{set:HashSet::new()};
    {
        let e = String::from("e");
        let f = format!("{}", "df");
        
        foo.set.insert(&e);  // 5- works (compare with 3)
        foo.set.insert(&f);  // 6- works (compare with 4)
    }
    
    let mut bar = MyStruct{set:HashSet::new()};
    bar.fill();   
}

Check playground for full code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=e8f24eebd8707454b3337a79715ae413

Hello,
Add println!("{:?}", foo); to line 29 and 5, 6 will stop working. Take ownership of the objects instead of references otherwise the objects have to live as long as MyStruct.

1 Like

And why 1 and 2 works?
Is there any way to declare lifetime an object when I create it?

I assume using &'a str is a good practice for using as key in Hash or Set. Right?

It works because 1, 2 have static lifetime. You can do: let b: &'static str = "b";.
I would say it depends of the context. For this case, it wouldn't work.
Something similar in Attempting to implement a Tree using Rust.

1 Like

What do you prefer to use as key: &'a str or String?

Use String instead of &'str, it will work.

The string literals worked only because they're a special case where a string view is into a "leaked" memory, so its scope is the whole program.

You must remove <'a> from the struct and change temporary string view &str to an owned string String (both store the string by reference, but one is temporary and limited to a scope, the other is permanent and can be used after }).

I fully got your point. My question is for key (which supposed to be immutable) string literal fits more. right?

String literal is only usable if the key is literally hardcoded in your codebase.

2 Likes

Box<str> has identical memory representation, in case you want that extra perf from fixed length strings.

String is just as immutable as &'static str unless you declare it mut. For most HashMaps, I would use String for keys, to let the map control ownership.

No. You do not declare lifetimes. You can only annotate lifetimes to express relationships between them. You cannot change an object's lifetime with annotations.