Does it assure to execute condition expression while empty if clause

I am a bit confused about a question, maybe it is very basic. code as following,

fn condition()-> bool {
  println!("do condition");
  false
}
fn main() {
  if condition() {
  }
  println!("finished");
}

when the clause of if statement is empty, does the compiler optimize the whoe statement so that the expression in the judgement condition is not executed?
I did a test, and it did execute the condition expression.

But I want to know whether this case is guaranteed by the rules of the compiler?

Any help will be appreciated, thanks.

Optimizing away if condition() {} would change the observable behavior of the program because "do condition" wouldn't be printed, so the compiler won't do it. If you replaced the println! with some purely computational work (no side effects), then that could be optimized away.

2 Likes

Thanks for reply.
As you said, does it mean the compiler will definitely not optimize away the condition expression as long as the expression has any effect on the outside? Is it guaranteed by some explicit rules of the compiler?

Not clear the rules for a compiler to do the optimization, you should not rely on it either, instead you can use const fn and const variable to force the compiler do the optimization at compile time:

const fn condition()-> bool {
    println!("do condition");
    false
}
fn main() {
    const CON: bool = condition();
    if CON {
    }
    println!("finished");
}

In this way, if you write something in condition(), which the compiler will not infer a result at compile time, it will report an error, so you can fix it.

notice the line const CON: bool = condition(); is necessary, otherwise the compiler will treat condition as a normal function, and the optimization will gone.

Thanks for reply.
I donot want to compiler to optimize away the condition expression. Instead I worry that the compiler will optimize away that expression which should be executed whether the clause if is empty.
If the compiler has some explicit rules for this case, I can write these code with confidence

fn do_something()-> Result<(), Box<dyn std::error::Error>> {...}
if let Err(e) = do_something() {
   //show some error when debug mode, and do nothing when release version
}

If the expression does something observable and is reachable, compiler is not allowed to optimize it away, wherever it is. Your last code is equivalent to this:

{
    let res = do_something();
    if let Err(e) = res {
       //show some error when debug mode, and do nothing when release version
    }
}

In this case, do_something is not connected to the if, so it should be obvious that it will be executed.

1 Like

If the code has side effects (and reachable, of-cause), it is definitely not optimized out, this is for sure.

1 Like

As usual with extremely broad topics you should look that info not in Rust books, but on Wikipedia, instead. Specifically here.

In practice, since safe Rust doesn't have UB you should only worry about these issues when you need unsafe.

2 Likes

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.