es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

La duración de vida de la referencia Rust debe ser mayor a la función.

Tengo un pequeño analizador sintáctico ficticio que utiliza el mismo &str durante el análisis sintáctico:

struct Parser<'a>{
    r: &'a str,
    pos: usize
}

impl<'a, 'b: 'a> Parser<'a>{
    fn new(s: &'b str)->Parser<'a>{
        Parser{r: s, pos:0}
    }
    fn next(&'a self)->Parser<'a>{
        Parser{r: self.r, pos: self.pos + 1}
    }
    fn nnext(&'a self)->Parser<'a>{
        Parser{r: self.r, pos: self.pos + 2}
    }
    fn nnnext(&'a self)->Parser<'a>{
        return self.next().nnext()
    }
}

Lo utilizaría así:

fn parse(s: &str){
    let parser = Parser::new(s);
    parser.nnnext();
}

Obtengo el siguiente error:

25 |         return self.next().nnext()
   |                -----------^^^^^^^^
   |                |
   |                devuelve un valor que hace referencia a datos de propiedad de la función actual
   |                valor temporal creado aquí

La referencia está garantizada de durar más que todos los métodos de Parser. ¿Cómo debo anotar las duraciones de vida para expresar esto? Especialmente, ¿por qué no se compila nnnext? Debería quedar claro que la referencia sobrevive a la llamada a self.next().nnext().

Muchas gracias por cualquier ayuda.
Hendrik

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para expresar que la referencia 'a sobrevive a todos los métodos del analizador, es necesario agregar un parámetro de tiempo de vida al bloque impl y especificar que el tiempo de vida de r está atado al parámetro de tiempo de vida 'a. Así es como puedes hacerlo:

    struct Parser<'a>{
        r: &'a str,
        pos: usize
    }
    
    impl<'a> Parser<'a> {
        fn new(s: &'a str) -> Parser<'a> {
            Parser {r: s, pos: 0}
        }
        fn next(&self) -> Parser<'a> {
            Parser {r: self.r, pos: self.pos + 1}
        }
        fn nnext(&self) -> Parser<'a> {
            Parser {r: self.r, pos: self.pos + 2}
        }
        fn nnnext(&self) -> Parser<'a> {
            self.next().nnext()
        }
    }
    

    Cabe destacar que todos los métodos ahora tienen el parámetro de tiempo de vida 'a agregado a la estructura del analizador y a los tipos de retorno. La función parse también necesita ser actualizada para usar el mismo parámetro de tiempo de vida que la estructura Parser:

    fn parse<'a>(s: &'a str) {
        let parser = Parser::new(s);
        parser.nnnext();
    }
    

    Ahora, al llamar a nnnext, los tiempos de vida de referencia están debidamente anotados y el código debería compilar sin errores.

Comments are closed.