La macro todo!

En ocasiones, se necesita escribir código para ayudar a imaginar el proyecto que se está desarrollando. Por ejemplo, se puede imaginar un proyecto para hacer algo con libros. Esto es lo que se puede ir pensando mientras se va escribiendo:

struct Libro {} // Primero necesitaré una estructura para los libros.
               // Nada aquí aún - se añadirá más tarde

enum TipoLibro { // Un Libro puede ser de TapaDura o de TapaBlanda: necesito un enumerado
    TapaDura,
    TapaBlanda,
}

fn get_libro(libro: &Libro) -> Option<String> {} // ⚠️ get_libro debería recibir un &Libro y devolver un Option<String>

fn delete_libro(libro: Libro) -> Result<(), String> {} // delete_libro debería recibir un Libro y devolver un Result...
                        // TODO: bloque impl con el cntenido de estas funciones...
fn check_tipo_libro(tipo_libro: &TipoLibro) { // Me aseguro de que este match funciona
    match tipo_libro {
        TipoLibro::TapaDura => println!("Es TapaDura"),
        TipoLibro::TapaBlanda => println!("Es TapaBlanda"),
    }
}

fn main() {
    let tipo_libro = TipoLibro::TapaDura;
    check_tipo_libro(&tipo_libro); // Vamos a probarlo
}

Rust no puede compilar el código anterior debido a get_libro y delete_libro. Dice:

error[E0308]: mismatched types
 --> src/main.rs:9:32
  |
9 | fn get_libro(libro: &Libro) -> Option<String> {} // ⚠️ get_libro debería recibir un &Libro y devolver un Option<String>
  |    ---------                   ^^^^^^^^^^^^^^ expected enum `Option`, found `()`
  |    |
  |    implicitly returns `()` as its body has no tail or `return` expression
  |
  = note:   expected enum `Option<String>`
          found unit type `()`

error[E0308]: mismatched types
  --> src/main.rs:11:34
   |
11 | fn delete_libro(libro: Libro) -> Result<(), String> {} // delete_libro debería recibir un Libro y devolver un Result...
   |    ------------                  ^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `()`
   |    |
   |    implicitly returns `()` as its body has no tail or `return` expression
   |
   = note:   expected enum `Result<(), String>`
           found unit type `()`

En este momento no es posible completar el código de get_libro, ni de delete_libro. Para esto se puede usar todo!(). Si se añade a la función, se evitan los fallos que encuentra Rust.

struct Libro {}

fn get_libro(libro: &Libro) -> Option<String> {
    todo!() // todo! significa "Lo añadiré después. Por favor, dalo por bueno mientras tanto."
}

fn delete_libro(libro: Libro) -> Result<(), String> {
    todo!()
}

fn main() {}

Ahora el código compila y se puede ver el resultado de check_tipo_libro: Es TapaDura.

Es necesario tener cuidado, ya que aunque compile no se pueden usar las funciones que contienen todo. Si se llamaa una de estas funciones, el programa entrará en pánico.

Adicionalmente, las funciones que contienen todo! siguen necesitando tipos de entrada y salida existentes. Si se escribe un tipo inexistente, el programa no compilará. Por ejemplo:

struct Libro {}

fn get_libro(libro: &Libro) -> WorldsBestType { // ⚠️
    todo!()
}

fn main() {}

Dirá al compilar:

error[E0412]: cannot find type `WorldsBestType` in this scope
 --> src/main.rs:3:32
  |
3 | fn get_libro(libro: &Libro) -> WorldsBestType { // ⚠️
  |                                ^^^^^^^^^^^^^^ not found in this scope

La macro todo! funciona de forma igual a unimplemented!(). Simplemente unimplemented!() es demasiado largo de escribir, por lo que se creó todo!() que es más corto.