> I don't get how changing to if else fixes this. The compiler can still reason that the condition is always going to be true
No, the compiler can't make that assumption for an if statement. That's because the condition of an if statement is always evaluated first, so the following expression(s) are only conditionally evaluated. There's nothing the compiler can do to reason "backwards" in such a case.
then_some effectively flips the order around - the consequent of the "if" statement is evaluated first, and then the condition is evaluated. This reversal of the order makes all the difference.
For a more concrete example, consider the following snippets:
if (ptr != nullptr) {
return *ptr;
} else {
return nullptr;
}
This is (probably) safe. The condition is evaluated first, and only if the condition is true is *ptr evaluated. The buggy code, on the other hand, was more like
(ptr != nullptr).then_some(*ptr)
In this case, the argument *ptr is evaluated first,
before the condition. This is sort of equivalent to:
result = *ptr
if (ptr != nullptr) {
return result;
} else {
return nullptr;
}
And that is definitely buggy, as it unconditionally dereferences ptr.
There isn't really a compiler bug here; it's just language semantics coupled with unsafe.