Reputation: 475
Excuse my novice Rust-ing. I wrote a function to clean a file, and verified that the logic of the function appears to be fine. I then wanted to rename this function from main to a helper function. I'm aware that I could keep some of IO stuff in the main function, but for the sake of fun, let's say I want to keep all the code below in the helper function.
The code beneath will compile if we change the return type to Result<(), std::io::Error>
, and modify the last line to give Ok(())
. Hovewer, this code doesn't. The compiler suggests I modify &str
to &'static str
, though this change doesn't appear to help things, as the compiler then says that "E0277, main
can only return types that implement termination"
And at this point I start imploding under an insufficient understanding of how to avoid dangling references.
fn main() -> Result<Vec<&str>, std::io::Error> {
let file = File::open("22names.txt")?;
let mut buf_reader = BufReader::new(file);
let mut contents = String::new();
buf_reader.read_to_string(&mut contents)?;
contents.retain(|c| c != '"');
let v: Vec<&str> = contents.split(',').collect();
println!("first 10 indices of v are: {:?}", &v[..10]);
Ok(v)
}
Edit: If I modify the above, renaming main to arbitrary function f
, and call f
from a new main function and assign the result to a variable, let v = f()
I get the following error, which results from the fact that contents
is going out of scope. How do I keep contents
in scope, or rather, the vector v
which points to it?
error[E0515]: cannot return value referencing local variable contents
, where contents
is referenced by v
, the thing I want to return.
Upvotes: 0
Views: 250
Reputation: 143
The main function is the entry point to your program. As this function is the first thing that gets executed no other function has called it. Your program exits after the main function has returned. The return value of the main function is used to determine the exit status of your program. Because of that no other function can use the return value of main
. I suggest renaming your function.
The other error happens because you return slices of a String. Content
contains the data you read from the file, while v
only contains references to this data. After content
goes out of scope, the memory is freed. This would lead to v
containing invalid pointers. The compiler will not allow that.
You could return String
instead of &str
. String
owns the underlying data. For that you should change the function signature to fn helper() -> Result<Vec<String>, std::io::Error>
. You than would need to transform your Vec<&str>
to Vec<String>
. You can to that using String::from
like that:
let v: Vec<String> = contents.split(',').map(String::from).collect();
Upvotes: 3