Error : returns a value referencing data owned by the current function

Hello,
I'm trying to code a function that will return the list of the domains from a filename or the filename itself if the file doesn't exists...
But I have the following error :

returns a value referencing data owned by the current function
content is borrowed here

here is my code :

fn get_domains(domain_or_file: &str) -> Vec<&str> {

    if Path::new(domain_or_file).exists()  {
        let path = Path::new(domain_or_file);
        let display = path.display();

        // Open the path in read-only mode, returns `io::Result<File>`
        let mut file = match File::open(&path) {
            // The `description` method of `io::Error` returns a string that
            // describes the error
            Err(why) => panic!("couldn't open {}: {}", display,
                               why.description()),
            Ok(file) => file,
        };

        // Read the file contents into a     string, returns `io::Result<usize>`
        let mut s = String::new();
        let content : String = match file.read_to_string(&mut s) {
            Err(why) => panic!("couldn't read {}: {}", display,
                               why.description()),
            Ok(_) => s
        };

        content.lines().collect()
    }else {
        vec![domain_or_file]
    }

}

I tried to use clone() but it doesnt work either, I learn rust like 6 months ago and completly forgot how to pass this error

You can return Vec<String> instead and use to_string to convert &str to String

Thank you for your help, but I have another issue now ...
On the line :

content.lines().collect()

I got the following error :

a collection of type std::vec::Vec<std::string::String> cannot be built from std::iter::Iterator<Item=&str>

You have to turn the &strs into Strings, which you can do with map(String::from) (or by mapping |x| x.to_string(), or From::from, etc.):

content.lines().map(String::from).collect()

Thanks !

1 Like

You mentioned how you forgot how to fix this type of error. I’m relatively new to Rust also (just over a year). I also don’t have the chance to work on it regularly. To develop a more long lasting intuition, I wonder if the following is useful.

Identify where new memory is being allocated.

  1. By definition of reading in new information from a file in the body of the function using a variable that is declared in the body of the function, you are creating new memory within the body of the function.

  2. The only way to maintain referential integrity when this function is called is to hand-over (move) ownership to the caller. Thus, the return type is a type with ownership (if you will), in this case Vec<String> (say bye bye to having that memory reference anything that has not transferred ownership i.e., anything with & such as references and slices)

  3. Both branches of the if statement must have the same type which means we need to call a function &str -> Vec<String> for the else, and Vec<&str> -> Vec<String> for the if. The first cannot be accomplished creating a new Vec and clone of a slice.

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