Description
Background
As we all know, Rust doesn't require parentheses around the condition of an if
, but does require braces around the bodies of if
and else
.
This is good because it avoids the ambiguity and potential for mistakes around nested if
s and else
s that exists in other C-family languages.
The problematic example is this:
if (foo())
if (bar())
baz();
else quux(); // which `if` does this belong to?
In current Rust, that example must look like this:
if foo() {
if bar() {
baz();
}
} else { // aha! it belongs to the first one
quux();
}
Or like this:
if foo() {
if bar() {
baz();
} else { // or in this case, the second one
quux();
}
}
In either case, the meaning is now explicit and unambiguous.
The idea
But as far as I can tell, only the first pair of braces are in fact required to accomplish this.
If we only put braces on the if
:
if foo() {
if bar() {
baz();
}
} else quux();
if foo() {
if bar() {
baz();
} else quux();
}
It's still just as explicit.
Advantages
The potential benefits of relaxing this would be:
-
We could avoid a proliferation of braces and indentation when the
else
block consists entirely of another construct delimited by braces, such as amatch
. For example, this:if foo() { do_this() } else { match bar() { A => do_that(), B => do_the_other() } }
Could instead be this:
if foo() { do_this() } else match bar() { A => do_that(), B => do_the_other() }
-
As a special case of the above, we currently allow writing
if
...else if
...else
chains "naturally", as opposed to requiringelse { if {
... by simply giving special treatment toif else
. This would now "fall out" of the general rule, and would no longer require special casing.
Drawbacks
-
It's a bit less symmetric.
-
There'd still be the hazard that you could accidentally write:
if foo() { ... } else bar(); baz();
and imagine that the
baz()
is in theelse
, when it's actually not (a lagoto fail
).A slightly more sophisticated rule that avoids this hazard would be that you may omit the braces around the body of an
else
if the body is a single expression which itself requires braces. So you could writeelse match { ... }
,else for { ... }
,else loop { ... }
,else if { ... }
, and so on, but notelse bar()
orelse quux()
.
Evaluation
In my estimation, in terms of theoretical elegance getting to remove the if else
special case would roughly cancel out with breaking the if ... { ... } else { ... }
symmetry, leaving the practical benefit of fewer braces and less rightward drift, which is a net win.