# Pre-RFC: x++ and x-- operator for clarity

**URL:** <https://internals.rust-lang.org/t/pre-rfc-x-and-x-operator-for-clarity/21007>\
**Category:** language design\
**Created:** [June 10, 2024, 10:10pm UTC](https://internals.rust-lang.org/t/pre-rfc-x-and-x-operator-for-clarity/21007 "2024-06-10T22:10:34Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![jrmoserbaltimore](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jrmoserbaltimore/32/12259_2.png) [@jrmoserbaltimore](https://internals.rust-lang.org/u/jrmoserbaltimore)\
**Post date:** [June 10, 2024, 10:10pm UTC](https://internals.rust-lang.org/t/pre-rfc-x-and-x-operator-for-clarity/21007/1 "2024-06-10T22:10:34Z")

</div>

# Summary

Add an `n++` operator, but not a `++n` operator, to Rust.

# Motivation

Rust already has `n+=1`, which is the `++n` operator. This is increment first, then return the incremented value.

Increment and then return the un-incremented value is a more verbose affair requiring the allocation of a temporary variable.

In Rust, allocating something like an index from a free list can be done as such:

```rust
    fn allocate(&mut self) -> u16 {
        if let Some(id) = self.free_list.pop() {
            id
        } else {
            let id = self.counter;
            self.counter += 1;
            id
        }
    }

```

This could be more concise:

```rust
    fn allocate(&mut self) -> u16 {
        if let Some(id) = self.free_list.pop() {
            id
        } else {
            self.counter++
        }
    }

```

# Explanation

Because Rust provides `n+=1` already, we don't need `++n`. Besides redundancy, `++n` and `n++` look similar; if the goal is code readability by removing unnecessary verbosity, then implementing only `n++` gives two clearly-different statements, avoiding the need to remember the semantic difference for whether the `++` is before or after the variable.

In other words, `++n` is unnecessary and so implementing only `n++` gives the unary `++` operator exactly one meaning, instead of two possible meanings. This meaning is also slightly more immediately recognizable than three lines of syntax with two different variables interspersed.

Do note `foo = a + (n+=1)` is not legal and there's no particular reason `foo = a + n++` should be legal either. Such syntax can be problematic, especially in weird uses like `foo = a + n++ + b*(n++) - (n++)/(n++)`. It's probably best to just treat `n++` as an assignment (i.e. `++` is an assignment operator like `+=`).

There are other syntaxes that could express the same, such as `n=+1` and `n=-1`, but `-1` has its own meaning and typographical errors are much more likely than with `++` and `--`. Another possibility is to allow syntax like `n++2` which would add 2 to `n`, essentially making `++` equivalent to `+=` but returning the pre-assignment value; whether to allow the unary `n++` to imply `n++1` is a judgment call in that case.

---

<div class="post-metadata">

**Author:** ![elidupree](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/elidupree/32/4304_2.png) [@elidupree](https://internals.rust-lang.org/u/elidupree)\
**Post date:** [June 10, 2024, 11:08pm UTC](https://internals.rust-lang.org/t/pre-rfc-x-and-x-operator-for-clarity/21007/2 "2024-06-10T23:08:04Z")

</div>

This is a frequently-requested feature that Rust purposefully doesn't include. From [the FAQ](https://prev.rust-lang.org/en-US/faq.html#why-doesnt-rust-have-increment-and-decrement-operators):

> ## Why doesn't Rust have increment and decrement operators?
> 
> Preincrement and postincrement (and the decrement equivalents), while convenient, are also fairly complex. They require knowledge of evaluation order, and often lead to subtle bugs and undefined behavior in C and C++. x = x + 1 or x += 1 is only slightly longer, but unambiguous.

I do want to point out one thing:

> [@jrmoserbaltimore](#):
>
> Do note `foo = a + (n+=1)` is not legal and there's no particular reason `foo = a + n++` should be legal either. Such syntax can be problematic, especially in weird uses like `foo = a + n++ + b*(n++) - (n++)/(n++)`. It's probably best to just treat `n++` as an assignment (i.e. `++` is an assignment operator like `+=`).

The reason `a + (n+=1)` isn't legal is that the return type of an assignment is `()`. Therefore, treating `n++` as an assignment would prevent the very thing you want to use it for.

I do miss post-increment sometimes. Although perhaps the practical thing would be to use "defer" for this; in current Rust, with the `scopeguard` crate, we could implement your function as:

```rust
    fn allocate(&mut self) -> u16 {
        self.free_list.pop().unwrap_or_else(|| {
            defer!{ self.counter += 1; }
            self.counter
        })
    }

```

---

<div class="post-metadata">

**Author:** ![quinedot](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/quinedot/32/7294_2.png) [@quinedot](https://internals.rust-lang.org/u/quinedot)\
**Post date:** [June 10, 2024, 11:37pm UTC](https://internals.rust-lang.org/t/pre-rfc-x-and-x-operator-for-clarity/21007/3 "2024-06-10T23:37:14Z")

</div>

[A `post_add` method could fill the role.](https://internals.rust-lang.org/t/post-increment-method-on-numeric-types/19959)

---

<div class="post-metadata">

**Author:** ![jrmoserbaltimore](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jrmoserbaltimore/32/12259_2.png) [@jrmoserbaltimore](https://internals.rust-lang.org/u/jrmoserbaltimore)\
**Post date:** [June 10, 2024, 11:49pm UTC](https://internals.rust-lang.org/t/pre-rfc-x-and-x-operator-for-clarity/21007/4 "2024-06-10T23:49:09Z")

</div>

> The reason `a + (n+=1)` isn't legal is that the return type of an assignment is `()`. Therefore, treating `n++` as an assignment would prevent the very thing you want to use it for.

I think you may have not actually read the post. From the part you quoted:

> Do note `foo = a + (n+=1)` is not legal and **there's no particular reason `foo = a + n++` should be legal either**. Such syntax can be problematic

The feature I described doesn't require any knowledge of evaluation order because what I described has the same exact rules and can occur only in the same exact places as `n+=1`.

---

<div class="post-metadata">

**Author:** ![elidupree](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/elidupree/32/4304_2.png) [@elidupree](https://internals.rust-lang.org/u/elidupree)\
**Post date:** [June 10, 2024, 11:57pm UTC](https://internals.rust-lang.org/t/pre-rfc-x-and-x-operator-for-clarity/21007/5 "2024-06-10T23:57:29Z")

</div>

> [@jrmoserbaltimore](#):
>
> what I described has the same exact rules and can occur only in the same exact places as `n+=1`.

In Rust, the _only_ restriction on where `n+=1` can appear is that it must be somewhere you can put an expression of type `()`. For example, this is perfectly legal (though bad) Rust:

```rust
    let mut n = 0;
    let a = ();
    let foo = a == (n+=1);

```

So if you say that `self.counter++` returns `u16` but can't be used somewhere a `u16` can be used, that would be an additional restriction that is not part of present Rust.

---

<div class="post-metadata">

**Author:** ![jrmoserbaltimore](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jrmoserbaltimore/32/12259_2.png) [@jrmoserbaltimore](https://internals.rust-lang.org/u/jrmoserbaltimore)\
**Post date:** [June 11, 2024, 12:29am UTC](https://internals.rust-lang.org/t/pre-rfc-x-and-x-operator-for-clarity/21007/6 "2024-06-11T00:29:02Z")

</div>

Oh, that makes sense. Somehow I thought I'd seen code that used `n+=1` as a return value for a function returning `u16`. That's my fault. `

---

<div class="post-metadata">

**Author:** ![197g](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/197g/32/7276_2.png) [@197g](https://internals.rust-lang.org/u/197g)\
**Post date:** [June 11, 2024, 8:29am UTC](https://internals.rust-lang.org/t/pre-rfc-x-and-x-operator-for-clarity/21007/7 "2024-06-11T08:29:04Z")

</div>

On unstable it's almost simpler to use an atomic here:

```rust
        self.free_list.pop().unwrap_or_else(|| {
            AtomicUsize::from_mut(&mut self.counter)
                fetch_add(1, Ordering::Relaxed)
        })

```

Bad code in another way, but I find it remarkable and slightly amusing precedent for an operation that 'returns the old value' of its operand.

---

<div class="post-metadata">

**Author:** ![tczajka](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tczajka/32/8923_2.png) [@tczajka](https://internals.rust-lang.org/u/tczajka)\
**Post date:** [June 11, 2024, 8:32am UTC](https://internals.rust-lang.org/t/pre-rfc-x-and-x-operator-for-clarity/21007/8 "2024-06-11T08:32:26Z")

</div>

Even when coding in C++ I would implement the `allocate` function without the post-increment because the evaluation order of that is just too confusing.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [September 9, 2024, 8:33am UTC](https://internals.rust-lang.org/t/pre-rfc-x-and-x-operator-for-clarity/21007/9 "2024-09-09T08:33:05Z")

</div>

Closed on September 9, 2024, 8:33am UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
