How to convert String to &'a str or mark String as &'a str for compiler?

How to convert String to &'a str or mark String as &'a str for compiler?

use std::collections::HashSet;

fn get_str<'a>() -> &'a str {
    "str"
}

fn get_string() -> String {
    "string".to_string()
}

fn collect_hash<'a>() -> HashSet<&'a str> {
    let mut hash: HashSet<&str> = HashSet::new();

    let str = get_str();
    hash.insert(str);

    let string = get_string();
    hash.insert(&string);

    hash
}

fn main() {
    let data = collect_hash();

    dbg!(data);
}

(Playground)

Inside your collect_hash function you create a new String, which is owned data that is dropped at the end of the scope of the function. Because the string instance is dropped when collect_hash finishes, you can't return anything that contains a reference to the string, because said reference would be dangling. Strings can be leaked, but I suggest you change your interface such that the HashSet stores owned data or Cow<'a, str> or something like that.

5 Likes

Cow version

use std::collections::HashSet;
use std::borrow::Cow;

fn get_str<'a>() -> &'a str {
    "str"
}

fn get_string<'a>() -> String {
    "string".to_string()
}

fn collect_hash<'a>() -> HashSet<Cow<'a, str>> {
    let mut hash = HashSet::new();

    let str = get_str();
    hash.insert(str.into());

    let string = get_string();
    hash.insert(string.into());

    hash
}

fn main() {
    let data = collect_hash();

    dbg!(data);
}

You're entirely overlooking the ownership aspect of it.

The lifetimes track where data is borrowed from. &str isn't a string itself, it's a temporary view into a string stored elsewhere.

It doesn't make sense to have a function without arguments that returns a borrowed type. You need to have some place to borrow from. You can't lend anything created in the function, because all local variables are destroyed when the function returns.

2 Likes

To add to that, the reason why fn get_str<'a>() -> &'a str works is because it borrows from a constant value in static memory. A string literal ("something") gets the type &'static str, is baked into the program, and is available for its entire duration. The 'static lifetime can always be narrowed down to a shorter lifetime, as in your example, but not the other way around.

3 Likes

When you have a lifetime on output but not on input, it is generally a bad sign. More about it: Unbounded Lifetimes - The Rustonomicon