Assignment in Conditionals

The omission of an = in an == condition turns it into an assignment that evaluates to true:

  1. int result = getResponseCode();
  2. if (result = 200) { // BUG!
  3. // Success
  4. }
  5. else {
  6. //... Process error
  7. }

So here, result was assigned the value 200 rather than compared to the value 200. Compilers should
issue a warning for these cases, but an error would be better.

Developers might also try to reverse the left and right hand side to mitigate the issue:

  1. if (200 = result) { // Compiler error
  2. // Success
  3. }
  4. else {
  5. // ... Process error
  6. }

Now the compiler will complain because the value of result is being assigned to a constant which makes no sense. This may work if a variable is compared to a constant but arguably it makes the code less readable and wouldn’t help if the left and right hand sides were both assignable so their order didn’t matter.

The goto fail example that we saw in section “Missing braces in conditionals” also demonstrates a real world dangers combining assignment and comparison into a single line:

  1. if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0)
  2. goto fail;

This line is not broken for other reasons, but it’s easy to see how might be, especially if this pattern were repeated all over the place. The programmer might have saved a few lines of code to combine everything in this way but at a greater risk. In this case, the risk might be inadvertantly turning the = into an ==, i.e. comparing err to the function call and then comparing that to 0.

  1. if ((err == SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0)
  2. goto fail;

How Rust helps

This code just won’t compile:

  1. let mut result = 0;
  2. if result = 200 { // Compile Error
  3. //...
  4. }

The only form of assignment inside a conditional is the specialised and explicit if let and while let forms which are explained elsewhere.