Rustの競技プログラミング用万能int型

## MSRV (Minimum Supported Rust Version)

1.42.0

## 動機

Rustの組み込み整数型は1.42.0の時点で{8-bit, 16-bit, 32-bit, 64-bit, 128-bit, pointer-sized} × {signed, unsigned}の12種類があります。

組み込み整数型は一般的なプログラミング言語のように、`+`, `-`, `*`, `/`, `%`の演算子で四則演算を行なうことができます。

```rust
let x = 1i32;
let y = 1i32;
let _: i32 = x + y;
```

しかしRustでは異なる2つの整数型で四則演算を行なうことができません。

```rust
let x = 1i32;
let y = 1i64;
let _ = x + y;
```

```
error[E0308]: mismatched types
 --> src/main.rs:4:17
  |
4 |     let _ = x + y;
  |                 ^ expected `i32`, found `i64`

error[E0277]: cannot add `i64` to `i32`
 --> src/main.rs:4:15
  |
4 |     let _ = x + y;
  |               ^ no implementation for `i32 + i64`
  |
  = help: the trait `std::ops::Add<i64>` is not implemented for `i32`

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
```

エラーメッセージを読んでみましょう。

```
  = help: the trait `std::ops::Add<i64>` is not implemented for `i32`
```

<code>[std::ops::Add\<\_\>](https://doc.rust-lang.org/stable/std/ops/trait.Add.html)</code>という[トレイト](https://doc.rust-lang.org/book/ch10-02-traits.html)があり、`i32`は`Add<i64>`を実装していないようです。

Rustでは`Add`のメソッドである<code>[Add::add](https://doc.rust-lang.org/stable/std/ops/trait.Add.html#tymethod.add)</code>が`operator+`や`__add__`の役割を果たします。

```rust
use std::ops::Add;

let _: Foo = Foo + Foo;

struct Foo;

// 型引数のデフォルトが指定されているため、`Add<Self>`と同様
impl Add for Foo {
    type Output = Self;

    fn add(self, _: Self) -> Self {
        Self
    }
}
```

`Add`は型引数`Rhs`を取ります。 よって2種類以上の右辺の型に対して`+`を定義することができます。

```rust
use std::ops::Add;

let _: Foo = Foo + Foo;
let _: Foo = Foo + Bar;

struct Foo;
struct Bar;

impl Add<Foo> for Foo {
    type Output = Self;

    fn add(self, _: Foo) -> Self {
        Self
    }
}

impl Add<Bar> for Foo {
    type Output = Self;

    fn add(self, _: Bar) -> Self {
        Self
    }
}
```

`i32`も`Add<i32>`のほかに`Add<&'_ i32>`が実装されています。

```rust
#![allow(clippy::op_ref)]

// イテレータ等でよく`&i32`が発生する

let _: i32 = 1i32 + 1i32; // `<i32 as Add<i32>::add`
let _: i32 = 1i32 + &1i32; // `<i32 as Add<&'_ i32>::add`
let _: i32 = &1i32 + 1i32; // `<&'_ i32 as Add<i32>::add`
let _: i32 = &1i32 + &1i32; // `<&'_ i32 as Add<&'_ i32>::add`
```

しかし`Add<i64>`は実装されていません。 これは意図的なデザインによるものです。

> Rust provides no implicit type conversion (coercion) between primitive types. But, explicit type conversion (casting) can be performed using the `as` keyword.

[5.1. Casting - Rust by Example](https://doc.rust-lang.org/rust-by-example/types/cast.html)

スライスについても、添字には[usize及びusizeの範囲](https://doc.rust-lang.org/stable/std/slice/trait.SliceIndex.html)しか許されていません。 `isize`でも駄目です。

```rust
let val: i64 = x + y - z;
counts[val] += 1;
```

See also:
- [\[Pre-RFC\] Implicit number type widening](https://internals.rust-lang.org/t/pre-rfc-implicit-number-type-widening/10432)
- [rustc: Require that vector indices are uints · rust-lang/rust@46abacf](https://github.com/rust-lang/rust/commit/46abacfdfebf3978b5bf39673d0b751636dd2257)

```
error[E0277]: the type `[{integer}]` cannot be indexed by `i64`
 --> src/main.rs:8:5
  |
8 |     counts[val] += 1;
  |     ^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
  |
  = help: the trait `std::slice::SliceIndex<[{integer}]>` is not implemented for `i64`
  = note: required because of the requirements on the impl of `std::ops::Index<i64>` for `std::vec::Vec<{integer}>`

error: aborting due to previous error
```

`usize`でない整数型は`as usize`等で明示的に`usize`に変換しなければなりません。  競技プログラミングでのRustの提出でよく見る`as usize`は主にこのためです。

```rust
let val: i64 = x + y - z;
counts[val as usize] += 1;
```

ただRustの`usize`や`u64`には<code>[saturating\_sub](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.saturating_sub)</code>や<code>[wrapping\_add](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.wrapping_add)</code>等があります。 これらを使えば非負整数型のままでもある程度の操作はどうにかできます。

```rust
let (a, b) = (1usize, 2usize);
assert_eq!(a.saturating_sub(b), 0);

let mut i = 10usize;
for &d in &[!0, 1] {
    i = i.wrapping_add(d);
}
assert_eq!(i, 10);
```

ただやっぱり符号付き整数型の方が圧倒的に使いやすいため、多くの人が`as i64`と`as usize`を連打しています。 C++等で競技プログラミングをやっていたRustの入門者だと一層煩わしく感じるのではないでしょうか?

ところで`as`が一々必要になるのが型システム等の都合でないならば、「`i64`のように振舞い、かつすべての組み込み整数型との比較と四則演算ができる`i64`のラッパー型」が作れるのではないでしょうか?

```rust
struct Int(i64);
```

やってみたところ、それっぽいものができました。

この記事ではこのような型`Int`を作っていきます。

```rust
// `str`から直にパース
let mut x = "1".parse::<Int>().unwrap();

// 整数型すべてと四則演算可能。
x += 1usize;
x = 1usize + x;

// 整数型すべてと比較可能
assert_eq!(x, 3usize);
assert_eq!(3usize, x);

// `.sum()`, `.product()`にも対応
let _: Int = vec![1, 2, 3].into_iter().sum();
let _: Int = vec![1, 2, 3].into_iter().product();
let _: usize = vec![x, x, x].into_iter().sum();
let _: usize = vec![x, x, x].into_iter().product();

// そのままprint可能
assert_eq!(x.to_string(), "3");

// `[_]`, `Vec<_>`, `VecDeque<_>`の添字にも使える
let xs = vec![Int(1), Int(2), Int(3), Int(4)];
assert_eq!(xs[x], 4);

// 整数型と相互に変換可能 (`as`は無理)
let _: i64 = x.into();
let _: i64 = x.to_i64();
let _: usize = x.into();
let _: usize = x.to_usize();
let _: Int = 0usize.into();
```

## 実装

まず最初に`std`のderive macroで実装できるトレイトは実装してしまいましょう。

```rust
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
struct Int(i64);
```

これでこの`Int`は<code>[Copy](https://doc.rust-lang.org/stable/std/marker/trait.Copy.html)</code>になり、また`==`, `<`, `<=`で比較できるようになります。

次にとりあえず`Int`同士で四則演算できるようにしましょう。 `Add`, `Sub`, `Mul`, `Div`, `Rem`を実装します。

```rust
#[rustfmt::skip] impl Add for Int { type Output = Self; fn add(self, rhs: Self) -> Self { Int(self.0 + rhs.0) } }
#[rustfmt::skip] impl Sub for Int { type Output = Self; fn sub(self, rhs: Self) -> Self { Int(self.0 - rhs.0) } }
#[rustfmt::skip] impl Mul for Int { type Output = Self; fn mul(self, rhs: Self) -> Self { Int(self.0 * rhs.0) } }
#[rustfmt::skip] impl Div for Int { type Output = Self; fn div(self, rhs: Self) -> Self { Int(self.0 / rhs.0) } }
#[rustfmt::skip] impl Rem for Int { type Output = Self; fn rem(self, rhs: Self) -> Self { Int(self.0 % rhs.0) } }
```

```rust
let _: Int = Int(1) + Int(2);
```

しかし本物の組み込み整数型は先程触れたように、`i64 + &i64`のようなことが可能です。 `Add<&'_ Int> for Int`や`Add<Int> for &'_ Int`も実装しましょう。 ただ`impl`の数が4倍になります。 20個書くのもまあ、キツくはないでしょうが見た目があまりよろしくなくなってきます。 [マクロ](https://doc.rust-lang.org/book/ch19-06-macros.html)を使いましょう。

```rust
macro_rules! impl_bin_ops {
    ($(<$lhs:ty> ~ <$rhs:ty>;)*) => {
        $(
            impl Add<$rhs> for $lhs { type Output = Int; fn add(self, rhs: $rhs) -> Int { Int(self.0 + rhs.0) } }
            impl Sub<$rhs> for $lhs { type Output = Int; fn sub(self, rhs: $rhs) -> Int { Int(self.0 - rhs.0) } }
            impl Mul<$rhs> for $lhs { type Output = Int; fn mul(self, rhs: $rhs) -> Int { Int(self.0 * rhs.0) } }
            impl Div<$rhs> for $lhs { type Output = Int; fn div(self, rhs: $rhs) -> Int { Int(self.0 / rhs.0) } }
            impl Rem<$rhs> for $lhs { type Output = Int; fn rem(self, rhs: $rhs) -> Int { Int(self.0 % rhs.0) } }
        )*
    };
}

// この辺のシンタックスは気分と好みで
impl_bin_ops! {
    <Int>     ~ <Int>;
    <Int>     ~ <&'_ Int>;
    <&'_ Int> ~ <Int>;
    <&'_ Int> ~ <&'_ Int>;
}
```

<code>[AddAssign\<\_\>](https://doc.rust-lang.org/stable/std/ops/trait.AddAssign.html)</code> (`+=`)などの複合代入演算子も実装してしまいましょう。

```rust
macro_rules! impl_bin_assign_ops {
    ($(<Int> ~= <$rhs:ty>;)*) => {
        $(
            impl AddAssign<$rhs> for Int { fn add_assign(&mut self, rhs: $rhs) { self.0 += rhs.0; } }
            impl SubAssign<$rhs> for Int { fn sub_assign(&mut self, rhs: $rhs) { self.0 -= rhs.0; } }
            impl MulAssign<$rhs> for Int { fn mul_assign(&mut self, rhs: $rhs) { self.0 *= rhs.0; } }
            impl DivAssign<$rhs> for Int { fn div_assign(&mut self, rhs: $rhs) { self.0 /= rhs.0; } }
            impl RemAssign<$rhs> for Int { fn rem_assign(&mut self, rhs: $rhs) { self.0 %= rhs.0; } }
        )*
    };
}

impl_bin_assign_ops! {
    <Int> ~= <Int>;
    <Int> ~= <&'_ Int>;
}
```

あとは<code>std::iter::\{[Sum](https://doc.rust-lang.org/stable/std/iter/trait.Sum.html), [Product](https://doc.rust-lang.org/stable/std/iter/trait.Product.html)\}</code>を実装することで`Int`のイテレータから`.sum()`, `.product()`ができるようになります。

```rust
#[rustfmt::skip] impl Sum for Int { fn sum<I: Iterator<Item = Self>>(iter: I) -> Self { iter.fold(Int(0), Add::add) } }
#[rustfmt::skip] impl<'a> Sum<&'a Self> for Int { fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self { iter.fold(Int(0), Add::add) } }
#[rustfmt::skip] impl Product for Int { fn product<I: Iterator<Item = Self>>(iter: I) -> Self { iter.fold(Int(1), Mul::mul) } }
#[rustfmt::skip] impl<'a> Product<&'a Self> for Int { fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self { iter.fold(Int(1), Mul::mul) } }
```

<code>[Neg](https://doc.rust-lang.org/stable/std/ops/trait.Neg.html)</code>も付けちゃいましょう。

```rust
#[rustfmt::skip] impl Neg for Int { type Output = Int; fn neg(self) -> Int { Int(-self.0) } }
#[rustfmt::skip] impl Neg for &'_ Int { type Output = Int; fn neg(self) -> Int { Int(-self.0) } }
```

これで`Int`同士であれば比較、四則演算できるようになりました。

```rust
#![allow(clippy::op_ref)]

let _: bool = Int(1) == Int(1);
let _: bool = Int(1) < Int(2);
let _: bool = Int(2) > Int(1);

let _: Int = Int(1) + Int(2);
let _: Int = Int(1) + &Int(2);
let _: Int = &Int(1) + Int(2);
let _: Int = &Int(1) + &Int(2);
let _: Int = -Int(1);
let _: Int = -&Int(1);

let mut x = Int(1);
x += Int(1);
x += &Int(1);

let _: Int = [Int(1), Int(2), Int(3)].iter().sum();
let _: Int = [Int(1), Int(2), Int(3)].iter().product();
```

そして今回の目的、本来の`i64`が行なわない機能である「すべての組み込み整数型との比較、四則演算」を実装していきましょう。 組み込み整数型は12種類ありますがこのようにすれば問題ありません。

```rust
macro_rules! impl_for_primitive_integers {
    ($($ty:ty),*) => {
        $(
            //
        )*
    };
}

impl_for_primitive_integers!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize);
```

比較はこのように組み込み整数型の方を`as`で雑に`i64`にキャストしてしまえば良いでしょう。

```rust
macro_rules! impl_for_primitive_integers {
    ($($ty:ty),*) => {
        $(
            impl PartialEq<$ty> for Int { fn eq(&self, other: &$ty) -> bool { self.0 == (*other as i64) } }
            impl PartialEq<Int> for $ty { fn eq(&self, other: &Int) -> bool { (*self as i64) == other.0 } }

            impl PartialOrd<$ty> for Int { fn partial_cmp(&self, other: &$ty) -> Option<cmp::Ordering> { Some(self.0.cmp(&(*other as i64))) } }
            impl PartialOrd<Int> for $ty { fn partial_cmp(&self, other: &Int) -> Option<cmp::Ordering> { Some((*self as i64).cmp(&other.0)) } }
        )*
    };
}

impl_for_primitive_integers!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize);
```

そして四則演算の方ですが`Int`同士のとは違い単純に`self.0 ~ rhs.0`とはできません。 関数をクロージャの形でマクロに渡して適切に型を変換しましょう。 ただし直接`(|_| ..)(self) + (|_| ..)(rhs)`のようにしようとすると型注釈が必要となってしまいます。 このような関数を噛ませましょう。

```rust
fn apply<T, O>(f: fn(T) -> O, x: T) -> O {
    f(x)
}
```

```rust
#[rustfmt::skip] impl AsRef<i64> for Int { fn as_ref(&self) -> &i64 { &self.0 }}
#[rustfmt::skip] impl AsMut<i64> for Int { fn as_mut(&mut self) -> &mut i64 { &mut self.0 }}

macro_rules! impl_for_primitive_integers {
    ($($ty:ty),*) => {
        $(
            impl PartialEq<$ty> for Int { fn eq(&self, other: &$ty) -> bool { self.0 == (*other as i64) } }
            impl PartialEq<Int> for $ty { fn eq(&self, other: &Int) -> bool { (*self as i64) == other.0 } }

            impl PartialOrd<$ty> for Int { fn partial_cmp(&self, other: &$ty) -> Option<cmp::Ordering> { Some(self.0.cmp(&(*other as i64))) } }
            impl PartialOrd<Int> for $ty { fn partial_cmp(&self, other: &Int) -> Option<cmp::Ordering> { Some((*self as i64).cmp(&other.0)) } }

            impl_bin_ops_for_primitive_integers! {
                <Int>     ~ <$ty>     { { |Int(l)| l  } ~ { |r| r as i64  } }
                <Int>     ~ <&'_ $ty> { { |Int(l)| l  } ~ { |&r| r as i64 } }
                <&'_ Int> ~ <$ty>     { { |&Int(l)| l } ~ { |r| r as i64  } }
                <&'_ Int> ~ <&'_$ty>  { { |&Int(l)| l } ~ { |&r| r as i64 } }

                <$ty>     ~ <Int>     { { |l| l as i64  } ~ { |Int(r)| r  } }
                <$ty>     ~ <&'_ Int> { { |l| l as i64  } ~ { |&Int(r)| r } }
                <&'_ $ty> ~ <Int>     { { |&l| l as i64 } ~ { |Int(r)| r  } }
                <&'_ $ty> ~ <&'_ Int> { { |&l| l as i64 } ~ { |&Int(r)| r } }
            }

            impl_assign_ops_for_primitive_integers! {
                <Int> ~= <$ty>     { *{ AsMut::<i64>::as_mut } ~= { |r| r as i64  } }
                <Int> ~= <&'_ $ty> { *{ AsMut::<i64>::as_mut } ~= { |&r| r as i64 } }

                <$ty> ~= <Int>     { *{ convert::identity } ~= { |Int(r)| r as $ty  } }
                <$ty> ~= <&'_ Int> { *{ convert::identity } ~= { |&Int(r)| r as $ty } }
            }

            impl Sum<$ty> for Int { fn sum<I: Iterator<Item = $ty>>(iter: I) -> Self { Self(iter.map(|x| x as i64).sum()) } }
            impl<'a> Sum<&'a $ty> for Int { fn sum<I: Iterator<Item = &'a $ty>>(iter: I) -> Self { Self(iter.map(|&x| x as i64).sum()) } }

            impl Sum<Int> for $ty { fn sum<I: Iterator<Item = Int>>(iter: I) -> Self { iter.map(|Int(x)| x as $ty).sum() } }
            impl<'a> Sum<&'a Int> for $ty { fn sum<I: Iterator<Item = &'a Int>>(iter: I) -> Self { iter.map(|&Int(x)| x as $ty).sum() } }

            impl Product<$ty> for Int { fn product<I: Iterator<Item = $ty>>(iter: I) -> Self { Self(iter.map(|x| x as i64).product()) } }
            impl<'a> Product<&'a $ty> for Int { fn product<I: Iterator<Item = &'a $ty>>(iter: I) -> Self { Self(iter.map(|&x| x as i64).product()) } }

            impl Product<Int> for $ty { fn product<I: Iterator<Item = Int>>(iter: I) -> Self { iter.map(|Int(x)| x as $ty).product() } }
            impl<'a> Product<&'a Int> for $ty { fn product<I: Iterator<Item = &'a Int>>(iter: I) -> Self { iter.map(|&Int(x)| x as $ty).product() } }
        )*
    };
}

macro_rules! impl_bin_ops_for_primitive_integers {
    ($(<$lhs_ty:ty> ~ <$rhs_ty:ty> { { $lhs_val:expr } ~ { $rhs_val:expr } })*) => {
        $(
            impl Add<$rhs_ty> for $lhs_ty { type Output = Int; fn add(self, rhs: $rhs_ty) -> Int { Int(apply($lhs_val, self) + apply($rhs_val, rhs)) } }
            impl Sub<$rhs_ty> for $lhs_ty { type Output = Int; fn sub(self, rhs: $rhs_ty) -> Int { Int(apply($lhs_val, self) - apply($rhs_val, rhs)) } }
            impl Mul<$rhs_ty> for $lhs_ty { type Output = Int; fn mul(self, rhs: $rhs_ty) -> Int { Int(apply($lhs_val, self) * apply($rhs_val, rhs)) } }
            impl Div<$rhs_ty> for $lhs_ty { type Output = Int; fn div(self, rhs: $rhs_ty) -> Int { Int(apply($lhs_val, self) / apply($rhs_val, rhs)) } }
            impl Rem<$rhs_ty> for $lhs_ty { type Output = Int; fn rem(self, rhs: $rhs_ty) -> Int { Int(apply($lhs_val, self) % apply($rhs_val, rhs)) } }
        )*
    };
}

macro_rules! impl_assign_ops_for_primitive_integers {
    ($(<$lhs_ty:ty> ~= <$rhs_ty:ty> { *{ $lhs_val:expr } ~= { $rhs_val:expr } })*) => {
        $(
            impl AddAssign<$rhs_ty> for $lhs_ty { fn add_assign(&mut self, rhs: $rhs_ty) { *$lhs_val(self) += $rhs_val(rhs) } }
            impl SubAssign<$rhs_ty> for $lhs_ty { fn sub_assign(&mut self, rhs: $rhs_ty) { *$lhs_val(self) -= $rhs_val(rhs) } }
            impl MulAssign<$rhs_ty> for $lhs_ty { fn mul_assign(&mut self, rhs: $rhs_ty) { *$lhs_val(self) *= $rhs_val(rhs) } }
            impl DivAssign<$rhs_ty> for $lhs_ty { fn div_assign(&mut self, rhs: $rhs_ty) { *$lhs_val(self) /= $rhs_val(rhs) } }
            impl RemAssign<$rhs_ty> for $lhs_ty { fn rem_assign(&mut self, rhs: $rhs_ty) { *$lhs_val(self) %= $rhs_val(rhs) } }
        )*
    };
}

impl_for_primitive_integers!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize);

fn apply<T, O>(f: fn(T) -> O, x: T) -> O {
    f(x)
}
```

次は`usize`のように`[T]`や`Vec<T>`の添字として使えるようにします。 Rust1.41以前では不可能でしたが`re_rebalance_coherence`という名でfeature-gateされていた機能がRust1.42で安定化されてorphan ruleが緩くなったことにより、`usize`に対しては可能になりました。

`re_rebalance_coherence`は

```rust
impl<A, B, ..> ForeignTrait<LocalType> for ForeignType<A, B, ..> {
    // ...
}
```

の形式の`impl`を可能にするものです。(型引数無しなら前から可能だった)

これを利用して`[_]`, `Vec<_>`, `VecDeque<_>`に対し、<code>std::ops::\{[Index](https://doc.rust-lang.org/stable/std/ops/trait.Index.html), [IndexMut](https://doc.rust-lang.org/stable/std/ops/trait.IndexMut.html)\}</code>を実装しましょう。 比較と四則演算のと同様に`[index.0 as usize]`とすれば良いです。

```rust
macro_rules! impl_index {
    ($(impl <$tyarg:ident> {Index<Int>, IndexMut<Int>} for $ty:ty { type Output = $output:ty; })*) => {
        $(
            impl<$tyarg> Index<Int> for $ty { type Output = $output; fn index(&self, index: Int) -> &$output { &self[index.0 as usize] } }
            impl<$tyarg> IndexMut<Int> for $ty { fn index_mut(&mut self, index: Int) -> &mut $output { &mut self[index.0 as usize] } }
        )*
    };
}

impl_index! {
    impl<T> {Index<Int>, IndexMut<Int>} for [T] { type Output = T; }
    impl<T> {Index<Int>, IndexMut<Int>} for Vec<T> { type Output = T; }
    impl<T> {Index<Int>, IndexMut<Int>} for VecDeque<T> { type Output = T; }
}
```

あと`str`から直接パースするのに<code>std::str::[FromStr](https://doc.rust-lang.org/stable/std/str/trait.FromStr.html)</code>を、`println!`や`dbg!`のために<code>std::fmt::\{[Display](https://doc.rust-lang.org/stable/std/fmt/trait.Display.html), [Debug](https://doc.rust-lang.org/stable/std/fmt/trait.Debug.html)\}</code>を忘れずに。

```rust
#[rustfmt::skip] impl FromStr for Int { type Err = ParseIntError; fn from_str(s: &str) -> Result<Self, ParseIntError> { s.parse().map(Self) } }
#[rustfmt::skip] impl fmt::Display for Int { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) } }
#[rustfmt::skip] impl fmt::Debug for Int { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self.0, f) } }
```

最後に<code>[From](https://doc.rust-lang.org/stable/std/convert/trait.From.html)</code>で相互に`from`か`into`で変換できるようにしましょう。

```rust
macro_rules! impl_for_primitive_integers {
    ($($ty:ty),*) => {
        $(
            impl From<$ty> for Int { fn from(from: $ty) -> Self { Self(from as _) } }
            impl From<Int> for $ty { fn from(from: Int) -> Self { from.0 as _ } }

            // ...
        )*
    };
}
```

あとRust1.28ですべての組み込み整数型に`From<bool>`が実装されました。 たまに使えます。

```diff
-f() + if p() { 1 } else { 0 }
+f() + i64::from(p())
```

せっかくなので`Int`にも同じように実装しましょう。

```rust
#[rustfmt::skip] impl From<bool> for Int { fn from(from: bool) -> Self { Self(from as _) } }
```

## 最後に

考え自体は前からあったのですが、今回作ってみた感想としては...それほど使いやすいか...? ただ一応今回のマクロを駆使した実装はmodint(ℤ/pℤを表わすnewtype)等の実装にも応用できると思います。

コードはCC0-1.0でGistに置きました。 パッケージとしてリポジトリに置くことは今のところ考えていません。 このコードはRust 1.42でコンパイル可能です。 もしも使ってみたいならどうぞ。 私は使いません。

[longlong.rs - Gist](https://gist.github.com/qryxip/b8f4259f6dcf77fe89e55c5e424bdf67)