Betrachten Sie den folgenden Rostcode:
fn f() -> i32 {
loop {
println!("Infinite loop!");
}
println!("Unreachable");
}
Dies wird kompiliert (mit einer Warnung) und ausgeführt, obwohl der Rückgabetyp falsch ist. Es scheint, dass der Compiler mit dem Rückgabetyp ()
in der letzten Zeile einverstanden ist, da er feststellt, dass dieser Code nicht erreichbar ist.
Wenn wir jedoch das letzte Semikolon entfernen:
fn f() -> i32 {
loop {
println!("Infinite loop!");
}
println!("Unreachable")
}
Dann wird der Code nicht mehr kompiliert und gibt einen Tippfehler aus:
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)
Warum ist das? Ist der Rückgabetyp ()
in diesen beiden Codeausschnitten nicht der gleiche ?
Hinweis: Ich möchte verstehen, warum sich der Rust-Compiler in diesen beiden Beispielen unterschiedlich verhält, dh wie der Rust-Compiler implementiert ist. Ich wollte keine philosophische Frage stellen, wie es sich aus Sicht des Sprachdesigns "verhalten" sollte (ich verstehe, dass eine solche Frage wahrscheinlich nicht zum Thema gehört).
!
aufgrund der Endlosschleife, die Sinn macht , als Rückgabetyp. Im zweiten Fall gibt es einen Rückgabeausdruck, sodass der Typinferenzlöser diesen verwendet, um auf den Typ zu schließen, was ebenfalls sinnvoll ist. Ich denke nicht, dass dies in der Sprachreferenz angegeben ist, und ich denke auch nicht, dass es in irgendeiner Weise wichtig ist - lassen Sie einfach die nicht erreichbare Aussage weg und es wird Ihnen gut gehen.Antworten:
Der Rückgabetyp im ersten Codeblock ist tatsächlich
!
(nie genannt), da Sie eine Schleife haben, die niemals beendet wird (also gibt Rost eine Warnung aus, dass sie nicht erreichbar ist). Der vollständige Typ wäre:fn f() -> !
Ich vermute, es
!
ist mehr wie der "untere" Typ in Rust als alles andere. Im zweiten Fall tritt Ihre Funktion wahrscheinlich in einem früheren Stadium während der Typprüfung aufgrund der Nichtübereinstimmung zwischen i32 und () auf, bevor der Compiler wie im ersten Beispiel zur Analyse der Nichterreichbarkeit gelangt.Bearbeiten: Wie vorgeschlagen, ist hier der relevante Teil des Rostbuchs https://doc.rust-lang.org/book/ch19-04-advanced-types.html#the-never-type-that-never-returns
quelle
!
kann in jeden anderen Typen umgewandelt werden. “println!
)(Umwandlung von Svens erstem Kommentar in eine Antwort)
Der Rust-Compiler muss einen Typ für den Funktionskörper ableiten. Im ersten Fall gibt es keinen Rückgabeausdruck, und anscheinend schließt der Compiler daraus! als Rückgabetyp wegen der Endlosschleife, was Sinn macht. Im zweiten Fall gibt es einen Rückgabeausdruck, sodass der Typinferenzlöser diesen verwendet, um auf den Typ zu schließen, was ebenfalls sinnvoll ist.
Ich denke nicht, dass dies in der Sprachreferenz angegeben ist, und ich denke auch nicht, dass es in irgendeiner Weise wichtig ist - lassen Sie einfach die nicht erreichbare Aussage weg und es wird Ihnen gut gehen.
quelle