Cannot return value referencing temporary value!?

I have a fn that wants to return Vec<&'static str>, but the api used is a String, so I used as_str() to convert it to &str, but the following problem occurred:

error[E0515]: cannot return value referencing temporary value
  --> src/schema_util.rs:48:5
   |
30 |         list.push(iter.name().as_str());
   |                   ----------- temporary value created here
...
48 |     list
   |     ^^^^ returns a value referencing data owned by the current function

Function code:

pub fn column_schema(session: &Session, condition: &'static str, table_name: &str) -> Vec<&'static str> {
    let mut list = Vec::new();
    let schema_meta = session.get_schema_meta();
    let mut keyspace_meta = schema_meta.get_keyspace_by_name("nebula_device_data");
    let table_meta = keyspace_meta.table_by_name(table_name).unwrap();
    let column_iter = table_meta.columns_iter();

    for iter in column_iter {
        list.push(iter.name().as_str());
    }

    let mut check_bool = false;
    let mut condition_vec = Vec::new();

    for specified_condition in list.iter() {

        if specified_condition == &condition {
            check_bool = true;
            warn!("{:?}", check_bool);
            condition_vec.push(condition);
        }
    }

    if check_bool {
        return condition_vec
    }
    list
}
  • I don't want to use Vec, because the function calling it needs to use clone. If I can, I try to avoid the occurrence of clone.

  • The function of this program is to insert the column name and column value of the query into the HashMap.

Call the code of column_schema
I don't want to use the part of clone,remove the error message from clone

error[E0507]: cannot move out of borrowed content
   --> src/main.rs:227:28
    |
227 |                 map.insert(column[index],json_value);
    |                            ^^^^^^^^^^^^^ cannot move out of borrowed content

This is my previous project, using the same method.The value returned is`Vec<&'static str>
So I think it is the Vec type, maybe the most fundamental problem.
But for now, this is one of the problems that affect my project.

Sorry my bad, I was asking whether it would be a problem if column_schema() return Vec< String > instead of Vec< &str > ..
Note that iter.name() is going to create a new String any way.

The most fundamental problem is trying to return a &'static str when you don’t have such a thing :slight_smile:. You can Box::leak(string.into_boxed_str()) a String but, well, you’ve (memory) leaked it. You can try to “remember” in later code that these &'static str are actually leaked, and drop them manually. But, this is errorprone and will lead to nasty bugs in all likelihood.

Is it a hard constraint to return a static string? As @prataprc suggested, can you return what you actually have - Vec<String>?

Not hard constraint.It only affects the function that calls the column_schema.
Because I am worried about the use of clone(), it will reduce the performance of the program (when sending multiple requests at the same time)...

To answer the original question,

  1. A reference must not live longer than the value it references. Otherwise you get a dangling pointer.

  2. Returned value should be alive when the function call is end. That's why we returned it anyway :slight_smile:

  3. function's stack frame should be cleared before the function returns, to reclaim the stack memory.

  4. Variables lives inside the stack frame.

  5. Consequently, return value should live longer than function's variables, so it can't reference them.

  6. But the question is temporaries right? In Rust temporaries are stored as hidden variable and be cleared as so.

1 Like

Worry about correctness first, and performance later. The strings have to live somewhere.

If the allocations are indeed seen to affect performance, there's a variety of tricks you can employ depending on your use case. E.g. if you call the function repeatedly, you can provide a &mut Vec<String> so that allocations can be reused between calls. Or if you sometimes have preexisting strings and sometimes have to construct new strings, you can use Cow<str>. Etc.

5 Likes

I’m not familiar with cassandra_cpp, but what options does it provide? Is there a way to load a schema and then get column names as references? If not, you’re not going to have much choice.

You can convert the Strings into Rc<str> so that cloning them is cheap. You can also load the schema once per query, not once per page (what it looks like it’s doing now).

But ultimately you’re going to be limited by what the underlying cassandra lib/driver allows.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.