0

Given

  • A vector of String values is set
  • Iteration clones the String values

Requirements

  • Create a vector of &str values from the given String clones

Details

I've tried to convert these in a single loop or map statement but ran into lifetime issues that I'm confused about. I've written a map statement that works and one that doesn't but want to gain intuition into what exactly is going on and what the best practice is.

Source Code

#[derive(Debug)]
struct Container<'a> {
    items: Vec<&'a str>,
}

fn main() {
    let numbers = vec![
        String::from("one"),
        String::from("two"),
        String::from("three"),
    ];

    // --- using two closures with map --- WORKS ---
    let strings: Vec<String> = numbers
        .iter()
        .map(|number| {
            let item = String::from(number);
            item.clone()
        })
        .collect();
    let items: Vec<&str> = strings.iter().map(|string| string.as_str()).collect();
    println!("{:?}", Container { items });

    // --- using single closures with map --- DOESN'T WORK ---
    let string_items: Vec<&str> = numbers
        .iter()
        .map(|number| {
            let item = String::from(number);
            let string = item.clone();
            string.as_str()
        })
        .collect();
    println!(
        "{:?}",
        Container {
            items: string_items
        }
    );
}
error[E0515]: cannot return value referencing local variable `string`
  --> src/main.rs:30:13
   |
30 |             string.as_str()
   |             ------^^^^^^^^^
   |             |
   |             returns a value referencing data owned by the current function
   |             `string` is borrowed here

Question Why does one closure fail while two closures work? What is best practice?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
webish
  • 701
  • 2
  • 9
  • 17
  • In the failing example, you clone the `String`, take a reference to it, then *drop the `String`* when the closure ends. That's exactly the kind of memory unsafety that Rust was designed to prevent. – Shepmaster Nov 18 '20 at 03:30
  • ah I see, and pardon the poor formed question... kudos on the cleanup. so... because I'm setting the String clones to a new vector and as_str() returns a &str, two closures keeps the clones in memory thus preserving the &str references in the second vector? – webish Nov 18 '20 at 04:07
  • Yep. It’s not really a matter of the number of closures, it’s that the `String`s are owned by something before you take a reference to them. – Shepmaster Nov 18 '20 at 04:11

0 Answers0