Skip to content

If-else could allow omitting braces on the else #1616

Closed
@glaebhoerl

Description

@glaebhoerl

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 ifs and elses 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 a match. 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 requiring else { if {... by simply giving special treatment to if 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 the else, when it's actually not (a la goto 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 write else match { ... }, else for { ... }, else loop { ... }, else if { ... }, and so on, but not else bar() or else 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    T-langRelevant to the language team, which will review and decide on the RFC.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions