Considere el siguiente código Rust:
fn f() -> i32 {
loop {
println!("Infinite loop!");
}
println!("Unreachable");
}
Esto compila (con una advertencia) y se ejecuta, a pesar de que el tipo de retorno es incorrecto. Parece que el compilador está bien con el tipo de retorno de ()
en la última línea porque detecta que este código es inalcanzable.
Sin embargo, si eliminamos el último punto y coma:
fn f() -> i32 {
loop {
println!("Infinite loop!");
}
println!("Unreachable")
}
Entonces el código ya no se compila, dando un error de tipo:
error[E0308]: mismatched types
--> src/main.rs:14:5
|
14 | println!("Unreachable")
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `()`
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
¿Por qué es esto? ¿No es el mismo tipo de retorno ()
, en ambos fragmentos de código?
Nota: Estoy interesado en comprender por qué el compilador Rust se comporta de manera diferente en estos dos ejemplos, es decir, cómo se implementa el compilador Rust. No quise hacer una pregunta filosófica sobre cómo "debería" comportarse, desde la perspectiva del diseño del lenguaje (entiendo que tal pregunta probablemente estaría fuera de tema).
!
como el tipo de retorno debido al bucle infinito, lo cual tiene sentido. En el segundo caso, hay una expresión de retorno, por lo que el solucionador de inferencia de tipos la usa para inferir el tipo, lo que también tiene sentido. No creo que esto esté especificado en la referencia del lenguaje, ni creo que importe de ninguna manera, solo omita la declaración inalcanzable y estará bien.Respuestas:
El tipo de retorno en el primer bloque de código es en realidad
!
(llamado nunca) porque tiene un bucle que nunca sale (por lo que el óxido le da una advertencia que dice que es inalcanzable). El tipo completo sería:fn f() -> !
Sospecho que
!
se parece más al tipo 'inferior' en Rust que a cualquier otra cosa. En el segundo caso, es probable que su función se equivoque en una etapa anterior durante la verificación de tipo debido a la falta de coincidencia entre i32 y () antes de que el compilador llegue al análisis de 'inalcanzabilidad', como lo hace en el primer ejemplo.editar: como se sugiere, aquí está la parte relevante del libro de óxido https://doc.rust-lang.org/book/ch19-04-advanced-types.html#the-never-type-that-never-returns
fuente
!
se pueden coaccionar a cualquier otro tipo " .println!
)(Convertir el primer comentario de Sven en una respuesta)
El compilador Rust necesita inferir un tipo para el cuerpo de la función. En el primer caso, no hay expresión de retorno, ¡y aparentemente el compilador infiere! como el tipo de retorno debido al bucle infinito, lo que tiene sentido. En el segundo caso, hay una expresión de retorno, por lo que el solucionador de inferencia de tipos la usa para inferir el tipo, lo que también tiene sentido.
No creo que esto esté especificado en la referencia del lenguaje, ni creo que importe de ninguna manera, solo omita la declaración inalcanzable y estará bien.
fuente