Error al utilizar el operador ? en Rust

Publicado por Brisa
hace 5 meses

Hola a todos,

Estoy teniendo dificultades al utilizar el operador "?" en Rust. He estado leyendo la documentación y siguiendo algunos tutoriales, pero aún no puedo resolver este error.

Aquí está el código que tengo hasta ahora:

use std::io;
use std::fs::File;
use std::io::prelude::*;
use std::error::Error;

fn leer_archivo() -> Result<String, Box<dyn Error>> {
    let mut archivo = File::open("ejemplo.txt")?;
    let mut contenido = String::new();

    archivo.read_to_string(&mut contenido)?;

    Ok(contenido)
}

fn main() {
    match leer_archivo() {
        Ok(contenido) => println!("Contenido del archivo: {}", contenido),
        Err(e) => println!("Error al leer el archivo: {}", e),
    }
}

El error que estoy obteniendo es el siguiente:

error[E0277]: the `?` operator can only be used in a function that returns `Result` (or another type that implements `std::ops::Try`)
  --> src/main.rs:9:23
   |
9  |     let mut archivo = File::open("ejemplo.txt")?;
   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `std::result::Result<std::fs::File, std::io::Error>`
   |
   = help: the trait `std::ops::Try` is not implemented for `std::result::Result<std::fs::File, std::io::Error>`
   = note: required because of the requirements on the impl of `std::ops::Try` for `std::fs::File`
   = note: required by `std::ops::Try::from_error`
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

No entiendo muy bien qué está pasando aquí. Parece que el operador "?" solo puede ser utilizado en funciones que retornan un tipo Result, pero en mi caso, estoy utilizando ? en una función que retorna std::result::Result<std::fs::File, std::io::Error>. ¿Alguien puede explicarme qué estoy haciendo mal?

¡Gracias de antemano!

Rust operador ? manejo de errores
Respuesta de Gordon Shumway
hace 5 meses

¡Hola Brisa!

El mensaje de error que estás obteniendo es un poco confuso, pero vamos a aclararlo. La función leer_archivo está declarada correctamente para usar el operador ?, ya que retorna un Result. El error indica que dentro de la función estás utilizando el operador ? en File::open("ejemplo.txt")?, pero el compilador espera que el error retornado de esa operación se pueda convertir en el tipo de error que tu función leer_archivo retorna.

El operador ? automáticamente convierte los errores al tipo de error que tu función retorna. En tu caso, tu función retorna Result<String, Box<dyn Error>>, y el error que devuelve File::open es un std::io::Error. Entonces, lo que necesitas es una forma de convertir de std::io::Error a Box<dyn Error>.

Aquí está la corrección de tu función para que compile correctamente:

fn leer_archivo() -> Result<String, Box<dyn Error>> {
    let mut archivo = File::open("ejemplo.txt").map_err(Box::new)?;
    let mut contenido = String::new();

    archivo.read_to_string(&mut contenido).map_err(Box::new)?;

    Ok(contenido)
}

Al usar map_err(Box::new), estamos convirtiendo el std::io::Error a Box<dyn Error>, que es compatible con la firma de retorno de tu función leer_archivo.

Con estos cambios, tu código debería compilar y funcionar como esperas.

Espero que esto ayude y ¡buena suerte con tu proyecto en Rust!