I have read some answers to similar questions and still couldn't find an answer that fits my situation. I understand the problem here (I practically return dangling references) but because I use an external enum (polars_core::datatypes::any_value::AnyValue) I don't know how to handle this problem. here is a simplified version of my code:
fn foo<'a>(value1: &'a str, value2: &'a str) -> HashMap<String, AnyValue<'a>> {
let mut result = HashMap::new();
result.insert("key1".to_string(), AnyValue::String(value1));
result.insert("key2".to_string(), AnyValue::String(value2));
result
}
fn bar() -> HashMap<String, AnyValue<'static>> {
let v1 = get_value();
let v2 = get_value();
foo(&v1, &v2)
}
fn get_value() -> String {
"value".to_string()
}
The get_value()
function is an external code so I can't change it.
the error I get:
error[E0515]: cannot return value referencing local variable `v2`
--> src\main.rs:517:5
|
517 | foo(&v1, &v2)
| ^^^^^^^^^---^
| | |
| | `v2` is borrowed here
| returns a value referencing data owned by the current function
error[E0515]: cannot return value referencing local variable `v1`
--> src\main.rs:517:5
|
517 | foo(&v1, &v2)
| ^^^^---^^^^^^
| | |
| | `v1` is borrowed here
| returns a value referencing data owned by the current function
Bonus question:
can anyone simplify 'static
for me?
Thanks a lot!
Your types, as they are, are not compatible. With the return type
fn bar() -> HashMap<String, AnyValue<'static>> {
what you are saying is that the HashMap only depends on values with the 'static
lifetime. However with your function
fn foo<'a>(value1: &'a str, value2: &'a str) -> HashMap<String, AnyValue<'a>> {
you are very much returning a non-'static
datastructure since the lifetime depends on the input string lifetime.
fn bar() -> HashMap<String, AnyValue<'static>> {
let v1 = get_value();
let v2 = get_value();
foo(&v1, &v2)
}
will for example allocate two String
s on-stack, and you're passing references to those strings to foo
. When bar
eventually returns, those String
s will be freed, and nothing may reference them. Your code as it stands would be passing the caller of bar
addresses that have already been freed.
Since your goal is to return a structure with a 'static
lifetime, you need to create that off the bat, without any arbitrary 'a
stuff getting in the way.
Looking over the polars
docs, there appears to be an AnyValue::StringOwned
variant, which would be a good fit for what you want. Given that, I'd instead make this function:
fn foo<'a>(value1: &'a str, value2: &'a str) -> HashMap<String, AnyValue<'static>> {
let mut result = HashMap::new();
result.insert("key1".to_string(), AnyValue::StringOwned(value1.into()));
result.insert("key2".to_string(), AnyValue::StringOwned(value2.into()));
result
}
If you want to avoid additional allocations, you could also adjust the argument types to be String
s instead of &str
and then pass that to StringOwned
.