1

I am very new to rust, (still working my way through the book) and am re-writing a DNA searching algorithm I wrote in node.js in rust. Each error I've gotten so far I've been able to get through except this one. I am trying to write a function that takes a DNA sequence and a 3-letter flag, and returns all indexes where that flag is found in the input sequence.

fn get_termination_flag_indices (input_sequence: String, flag: String) -> Vec<(usize, &'static str)> {
let flag_indices: Vec<_> = input_sequence.match_indices(&flag).into_iter().collect();

println!("{:?}", flag_indices);
flag_indices
}

I haven't been able to make sense of the error I'm receiving:

returns a value referencing data owned by the current function

I understand from a very high level what it's telling me, but I don't know how to fix it. Honestly I'm just not far enough along to really grasp what's going on here. Any help explaining what's going on under the hood would be extremely helpful.

Herohtar
  • 5,347
  • 4
  • 31
  • 41
  • Have you read the [Understanding Ownership](https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html) chapter? – Chayim Friedman May 10 '22 at 22:08
  • 1
    Please provide a [mre] and the full error message, including the compiler explanations and suggestions. In particular you say that your function returns the indexes where the flag is found, which should be `Vec`, but you appear to also be returning string slices in addition to the indexes. – Jmb May 11 '22 at 06:38
  • As a rule of thumb, when using Rust without a good understanding of lifetimes, it's best to avoid references in return values and structs. Where necessary, cloning is easy. (And in this case, `Vec` should indeed be enough, as all the returned `&str`s should be equal.) – Caesar May 12 '22 at 09:06

1 Answers1

2

Here is how I would solve it (you could make flag a &str to make it even better but it is not required to solve the error):

fn get_termination_flag_indices (input_sequence: &str, flag: String) -> Vec<(usize, &str)> {
    let flag_indices: Vec<_> = input_sequence.match_indices(&flag).into_iter().collect();
    
    println!("{:?}", flag_indices);

    flag_indices
}

Here is what I think caused the error:

Unfortunately, I don't know enough to say for certain but here goes:

When calling match_indices, a reference of input_sequence is created under the hood (match_indices takes a reference to self). Let's give it a lifetime of 'a

Later, the &str that flag_indices collects, has that same lifetime 'a. The problem is that as soon as the function returns with flag_indices, the reference that was created inside the function (with lifetime 'a) is dropped as well. So the flag_indices now contains references that were dropped.

Dacite
  • 76
  • 4
  • 1
    You explanation is quite right, here's some details: `input_sequences` is [auto-(de)referenced](https://stackoverflow.com/a/53344847/401059) into `&'a str` when calling [`match_indices`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.match_indices). This returns a `MatchIndices<'a, …>`, which implements [`Iterator – Caesar May 12 '22 at 08:58
  • That was it. I believe I need to dig deeper into lifetimes in relation to ownership. Thanks! – SeaBrackets May 12 '22 at 13:16