Why there are no errors in this code

fn main(){

loop {
  println!("rust is fun, but i wanna run");
}; // is this loop going to be statement?

}

I try some experiment. loop is an expression so the end of the loop brackets is not use semicolon ";". I put semicolon on it :sweat_smile:. Yay the code run smoothly, no error was found. But when i create this code:

fn main() {

    let y: i32 = harga_martabak(1500);
      
    println!("Harga martabak adalah: {y}"); 
  }
    
  fn harga_martabak( x: i32) -> i32 {
     x + 9000; //put the semicolon here
  } 

My code is error because it is turn to statement and cant return the value. So why loop with/without ";" is not error?

https://doc.rust-lang.org/book/ch03-03-how-functions-work.html?highlight=semicolon#statements-and-expressions

https://doc.rust-lang.org/book/ch03-03-how-functions-work.html?highlight=semicolon#functions-with-return-values

First, you have written an infinite loop. This is important because infinite loops have a special result type: !. I tend to read this as "diverges". This is the type used for expressions which do not produce a result. For example:

let x: i32 = panic!("whoopsie!");

This works not because panic! returns an i32, but because panic! diverges. Once the panic happens, nothing after that matters. As a result, expressions of type ! can be coerced into any other type just fine.

That's why you can remove the semicolon after loop: it results in ! (because the loop never ends and thus never resolves to a value), which can be implicitly coerced to () which is the type that main expects the final expression to be.

With the semicolon is also valid because it's an infinite loop. It doesn't matter what happens after that.

The other reason code like this is valid is that every block without an explicit result expression automatically returns ().

3 Likes

It's correct both syntactically and semantically:

  • syntactically, because it's a block, so there's no need for a semicolon to disambiguate the end of the expression/statement;
  • and semantically, because an infinite loop has the "never" (! or "bottom") type, which coerces to any type whatsoever, including unit (()).
1 Like

Thanks got it :grin:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.