Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I fix a missing lifetime specifier?

Tags:

rust

lifetime

I have a very simple method. The first argument takes in vector components ("A", 5, 0) and I will compare this to every element of another vector to see if they have the same ( _ , 5 , _) and then print out the found element's string.

Comparing ("A", 5, 0 ) and ("Q", 5, 2) should print out Q.

fn is_same_space(x: &str, y1: i32, p: i32, vector: &Vec<(&str, i32, i32)>) -> (&str) {
    let mut foundString = "";

    for i in 0..vector.len() {

        if y1 == vector[i].1 {
            foundString = vector[i].0;
        }

    }
    foundString    
}

However, I get this error

error[E0106]: missing lifetime specifier
 --> src/main.rs:1:80
  |
1 | fn is_same_space(x: &str, y1: i32, p: i32, vector: &Vec<(&str, i32, i32)>) -> (&str) {
  |                                                                                ^ expected lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or one of `vector`'s 2 elided lifetimes
like image 309
boss revs Avatar asked Apr 10 '17 18:04

boss revs


1 Answers

By specifying a lifetime:

fn is_same_space<'a>(x: &'a str, y1: i32, p: i32, vector: &'a Vec<(&'a str, i32, i32)>) -> (&'a str)

This is only one of many possible interpretations of what you might have meant for the function to do, and as such it's a very conservative choice - it uses a unified lifetime of all the referenced parameters.

Perhaps you wanted to return a string that lives as long as x or as long as vector or as long as the strings inside vector; all of those are potentially valid.


I strongly recommend that you go back and re-read The Rust Programming Language. It's free, and aimed at beginners to Rust, and it covers all the things that make Rust unique and are new to programmers. Many people have spent a lot of time on this book and it answers many beginner questions such as this one.

Specifically, you should read the chapters on:

  • ownership
  • references and borrowing
  • lifetimes

There's even a second edition in the works, with chapters like:

  • Understanding Ownership
  • Generic Types, Traits, and Lifetimes

For fun, I'd rewrite your code using iterators:

fn is_same_space<'a>(y1: i32, vector: &[(&'a str, i32, i32)]) -> &'a str {
    vector.iter()
        .rev() // start from the end
        .filter(|item| item.1 == y1) // element that matches
        .map(|item| item.0) // first element of the tuple
        .next() // take the first (from the end)
        .unwrap_or("") // Use a default value
}
  • Removed the unneeded parameters.
  • Using an iterator avoids the overhead of bounds checks, and more clearly exposes your intent.
  • Why is it discouraged to accept a reference to a String (&String) or Vec (&Vec) as a function argument?
  • Rust does not use camelCase variable names.
  • I assume that you do want to return the string from inside vector.
  • Remove the redundant parens on the return type
like image 97
Shepmaster Avatar answered Oct 01 '22 03:10

Shepmaster