Rust 1.39.0でabsがconst fnになる

# Rust 1.39.0でabsが`const fn`対応する
RustのリポジトリのRELEASES.mdを見ていて気づいたのですが、どうやら`abs`が`const fn`になるようです。

つまりこれが通る

```rust
fn main() {
    const A: i32 = 42_i32.abs();
    const B: i32 = (-42_i32).abs();
    assert_eq!(A, B);
}
```
[実行結果](https://play.rust-lang.org/?version=beta&mode=debug&edition=2018&gist=aa9ce0b0cfd7b64b55cb010bb31ae6db)

[過去の自分の記事](https://qiita.com/block/items/8a4aadd1f25c1ac9ad21)で制限が多すぎて`abs`すら素直に書けないと言っていたので標準入するのは嬉しいです。

## 実装を見てみる
[libcore/num/mod.rs#L1962-L1981](https://github.com/rust-lang/rust/blob/6576f4be5af31a5e61dfc0cf50b7130e6c6dfb35/src/libcore/num/mod.rs#L1962-L1981)が整数の`abs`の実装っぽいので見てみましょう。

```rust
pub const fn abs(self) -> Self {
    // Note that the #[inline] above means that the overflow
    // semantics of the subtraction depend on the crate we're being
    // inlined into.

    // sign is -1 (all ones) for negative numbers, 0 otherwise.
    let sign = self >> ($BITS - 1);
    // For positive self, sign == 0 so the expression is simply
    // (self ^ 0) - 0 == self == abs(self).
    //
    // For negative self, self ^ sign == self ^ all_ones.
    // But all_ones ^ self == all_ones - self == -1 - self.
    // So for negative numbers, (self ^ sign) - sign is
    // (-1 - self) - -1 == -self == abs(self).
    //
    // The subtraction overflows when self is min_value(), because
    // (-1 - min_value()) - -1 is max_value() - -1 which overflows.
    // This is exactly when we want self.abs() to overflow.
    (self ^ sign) - sign
}
```

ビット演算してそうだけどわからん。
`$BITS`ってなんだ。

もう少し範囲を広げて見てみると、どうやら`abs`の実装は`int_impl`というマクロの定義で囲まれており、`$BITS`というのは整数型のビット数のようです。

```rust
// `Int` + `SignedInt` implemented for signed integers
macro_rules! int_impl {
    ($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr, $Min:expr, $Max:expr, $Feature:expr,
     $EndFeature:expr, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr,
     $reversed:expr, $le_bytes:expr, $be_bytes:expr,
     $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => {
```
[int_implの先頭](https://github.com/rust-lang/rust/blob/6576f4be5af31a5e61dfc0cf50b7130e6c6dfb35/src/libcore/num/mod.rs#L237-L244)

```rust
#[lang = "i32"]
impl i32 {
    int_impl! { i32, i32, u32, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301",
        "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
        "[0x12, 0x34, 0x56, 0x78]", "", "" }
}
```
[int_implの使用箇所(i32)](https://github.com/rust-lang/rust/blob/6576f4be5af31a5e61dfc0cf50b7130e6c6dfb35/src/libcore/num/mod.rs#L2242-L2247)

### absの実装 (i32型の場合)
`$BITS`は整数型のビット数ということがわかったのでi32型の場合の`abs`の実装は下記のようになります。
(コメントは消してます)

```rust
pub const fn abs(self) -> Self {
    let sign = self >> (32 - 1);
    (self ^ sign) - sign
}
```

順番に確認していきましょう。

---
最初の行では自身の値を31ビット右シフトして、先頭のビットだけを`sign`に代入しています。

```rust
let sign = self >> (32 - 1);
```
Rustの符号あり数値は「2の補数」という体系が使用されています。
そのため`sign`の値は`self`が負の数であれば`-1`、それ以外なら`0`になります。
(最初に貼ったコードのコメントに`sign is -1 (all ones) for negative numbers, 0 otherwise.`とありますね)

---
次の行では`self`と`sign`のXORから`sign`を引いています。

```rust
(self ^ sign) - sign
```

##### `self >= 0`のとき
`self`が`0`以上の場合`sign`は`0`なので

```rust
(self ^ 0) - 0
```
となります。
`self ^ 0`の値は`self`のまま。そこから`0`を引いても`self`の値は変わらないので`self`がそのまま返ります。

##### `self < 0`(負の数)のとき
`self`が負の数のときは`sign`は`-1`なので

```rust
(self ^ -1) - (-1)
```
`-1`を「2の補数」で表すと`11111111111111111111111111111111`なので`self ^ -1`は`self`のビットがすべて反転します。
そこから`sign`(`-1`)を引いているので、これは`1`を足しています。
すべてのビットを反転させた後に`1`を足すという処理は「2の補数」では符号を反転させる処理なので、`self`の符号が反転した値が返ります。

## 所感
標準の`abs`が`const fn`になった。
その実装はビット演算。

初めてlibcoreのコードを読みました。

いつかC++の`constexpr`のように`const fn`も制限緩和されて楽に書けるようになるといいですね。

→だいぶ楽に書けるようになりました
[Rustのconst fnの制限がさらに緩和された(Rust 1.46.0)](https://qiita.com/block/items/de9ecbb4d102eaa35ac8)