DMD 2.079 変更点まとめ

# はじめに
2018年3月1日、D言語の公式コンパイラであるdmd 2.079がリリースされました！

今回change logがかなり大規模で、自分でもよくわからない項目が多かったので内容まとめてみました。
なお、すべての機能をちゃんと試したわけではないので、間違っていたらコメントもらえると助かります。

# ざっくりまとめ
- 公式ChangeLog
    - https://dlang.org/changelog/2.079.0.html
    - いろいろと例が増えた印象です。かなり詳細に記載されていて勉強になりました
- 新機能
    - ラムダ式の同一性比較ができる`__traits(isSame, lambda1, lambda2)`の追加
    - 任意の関数に対する`@disable`の追加。それをテストできる`__traits(isDisabled, func)`の追加
    - `-i`フラグによる追加のインポート指定機能（include importモード、というらしい）
    - ランタイムを独自実装に切り替えられる機能の追加
        - 新プラットフォームサポートや組み込み用途の人に朗報
- 試験的な機能（experimental）
    - 標準ライブラリをすべてimportする`std.experimental.all`の追加
    - @nogc中の例外サポート（[DIP1008](https://github.com/dlang/DIPs/blob/master/DIPs/DIP1008.md)）
- 以下のdeprecated期間が終了
    - コンマ演算子
    - OSX向けの`-dylib`フラグ（今後は`-shared`を使う）
- 以下が新たにdeprecatedになった
    - delete演算子
        - 今後はGC任せか、手動でやりたいなら`core.memory.__delete`
    - 16進文字列リテラル（`x"304A314B"`みたいなの）
        - 今後は`std.conv`の`hexString!"304A314B"`という感じ
    - 選択インポートでprivate宣言まで参照できていた動作
- その他たくさんの修正や改善
    - GCの初期化が最初に使われるときまで遅延される（NoGCなアプリが速くなる）
    - Windowsの64bitビルドでVisual C++とWindows SDKに依存しなくなった（うれしい）
    - etc.

# コンパイラ変更点一覧
- 引数のミスマッチ時のエラーメッセージを改善
- コンマ演算子のdeprecated期間が終了
- 関数のデフォルト引数が可変長テンプレート引数の後は許されなくなった
- delete演算子がdeprecatedになった
- OSXの`-dylib`フラグがdeprecated期間終了。今後は`-shared`を使う。
- `-dip1008`フラグで実験的に\@nogc例外のスローするようになる
- 関数に対する@disable属性のマークをコンパイラで適切に検知できるようになった
- Issue 17630の修正：選択インポートでプライベートなシンボルがインポートできていた
- Issue 17899の修正：コンパイル時にデリゲートを初期化できるようにする
- Issue 18053の修正：long/ulongがint64_t/uint64_tとしてマングルするように変更
- Issue 18219の修正：構造体の中でprivate importされた型が変数宣言に使える
- Issue 18361の修正：Ddocの実行可能テキストにおける自動キーワードハイライト機能をopt-outにする
- Win32とOSXをターゲットにした場合のABIを変更
- 16進文字列リテラルがdeprecatedになった
- 追加のインポートを指定するための`-i`フラグを追加
- JSONにフィールドを追加する`-Xi=<name>`フラグを追加
- `__traits(isSame, ...)`でラムダ式が同じか比較できるようになった
- Windowsの64bitビルドでVisual C++とWindows SDKに依存しなくなった
- D言語を、ランタイムなし/最小構成/独自ランタイム、で切り替えて使える仕組みを追加
- macOSのデプロイターゲットを10.9に引き上げ
- 選択インポートでプライベートメンバーまでimportしていた動作がdeprecatedになった
- `@safe`属性の中で配列の.ptrが使用できなくなった

# ランタイム変更点一覧
- `core.memory.__delete`を追加
- GCの初期化処理を最初に使うときまで遅延するよう変更

# 標準ライブラリ変更点一覧
- `std.format`にテンプレート引数でフォーマット文字列を渡すと処理が最適化されるようになった
- `std.conv.hexString`がimmutableな文字列を返すように変更
- クラスやインターフェースCに対する`Nullable!C.nullify`が.destroyを呼ばなくなる
- `std.algorithm.searching.substitute`を追加
- `std.bigint`にdivModを追加
- `std.bigint`にgetDigitを追加
- `std.exception.enforce`で同名テンプレート(eponymous template)の仕組みを使って独自の関数が作れるようになった
- 全モジュールをimportする`std.experimental.all`を追加
- `std.experimental.allocator.IAllocator`を`std.experimental.allocator.RCIAllocator`に置き換え
- `std.experimental.allocator.ISharedAllocator`を`std.experimental.allocator.RCISharedAllocator`に置き換え
- `readText`がBOMをチェックするようになった
- `std.parallelism.TaskPool`にfoldを追加
- `std.range`にnullSinkを追加
- `std.range.slice` (いわゆる固定サイズを持った窓関数)を追加
- `std.string.strip`で取り除く文字を指定できるようになった
- `isSomeString`と`isNarrowString`がenumに対してfalseを返すようになった
- `toString`でOutputRangeを指定できるようになった

# 変更点紹介
全部翻訳するのは大変そうなので、個人的に注目っぽいところだけまとめます。
ChangeLogにサンプルコードや該当Issueへのリンクもあるので、気になったものは確認してみてください。

## コンパイラ変更点
### 新機能：`-i`による追加インポートの指定
ChangeLog: https://dlang.org/changelog/2.079.0.html#includeimports

公式の解説でもimportという言葉が多用されるので、ソースに勝手にimport文挿入できるのかと思ったら全然違いました。

ざっくりいうと、`dmd main.d hoge/a.d hoge/b.d ...`と書いていたものが、`dmd main.d -i=hoge`でよくなる、という機能です。
もっというと`dmd main.d -i=.`で良いです。（ファイル指定なしにはできないので、main.dの指定は必要）

rdmdとかdubを使っている人はあまり使うことがないと思いますが、Makefileでやっている人はちょっと記述がスッキリするかもしれません。

またinclusiveパターンとexclusiveパターンというものがあり、追加だけじゃなくて除外もできます。
exclusiveの記法は頭にハイフンをつけて、`dmd main.d -i=hoge -i=-hoge.testing` みたいになります。


### 新機能：ランタイムを独自実装に差し替える機能
ChangeLog: https://dlang.org/changelog/2.079.0.html#minimal_runtime

object.dとかをソースの1つとして用意しておくことで、ランタイムを独自の物に差し替えたりできる機能のようです。

たとえば、新しいプラットフォームのサポートで空のランタイムを使い、少しずつ機能を実装すると動くようになっていく、といった使い方が想定されています。

ほかにも組み込み用途での利用促進にもつなげていきたい、とか、他言語との親和性が上げられる、とか色々書いてありました。今後に期待しましょう！


ChangeLogにいくつか例がありますが、mainの呼び出しに至る部分も全部書けるので、生成されるバイナリがかなり細かくコントロールできるようになる、というのが注目っぽいです。

バイナリサイズの比較なども具体例があるので、組み込み関係の方は一度詳細確認されてみてはいかがでしょうか！

参考までにChangeLogから引っ張ってくると以下のような内容です。

```d:object.d
module object;

extern(C) void __d_sys_exit(long arg1)
{
    asm
    {
        mov RAX, 60;
        mov RDI, arg1;
        syscall;
    }
}

extern void main();
private extern(C) void _start()
{
    main();
    __d_sys_exit(0);
}
```
```d:math.d
module main;

void main() { }
```
```bash
dmd -c -lib main.d object.d -of=main.o
ld main.o -o main
size main
   text    data     bss     dec     hex filename
     56       0       0      56      38 main
```

56ばいと…？

### 試験中：`-dip1008`フラグによる@nogc中の例外サポート
ChangeLog: https://dlang.org/changelog/2.079.0.html#dip1008

DIP1008として提案され、事前審査中の機能が試験的に実装されたものです。（正式にはPost-Preliminary Reviewという段階）
今後正式レビューで採用か否決が判断され、否決されると入らない機能なので今はまだ参考程度に眺めておくのが良いと思います。


内容をざっくり言うと「nogc中でも例外が使いたい。throw new Exception("...")したい。」というものです。（正直書いてる最中もまったく意味が分からない）
DIP1008の詳細はこちら:  https://github.com/dlang/DIPs/blob/master/DIPs/DIP1008.md


こういった提案は事前審査の前にDraftという下書き提案フェーズがあるのですが、そこは通っているので何かわからないけど大義があるんだと思います。

で、本来メモリが確保されない前提の領域でメモリ確保するっていう話なので、色々な課題が残っています。
興味がある方は使ってフィードバックしてみると良いかもしれません。

※当然nogcなのでGCが動かないからThrowableにオプショナルで参照カウントを付けようとかいろいろ。Rustで言うライフタイムに近い提案であるDIP1000とも関連しています。先は長そう。


### 修正：import関連
ChangeLog:

- https://dlang.org/changelog/2.079.0.html#fix18219
- https://dlang.org/changelog/2.079.0.html#private

インポート関連は実際のプルリクエストを見ると、あれこれまとめて修正されているようです。

特に選択インポートの部分でdeprecatedになった動作があるので、今後注意が必要です。
※一度deprecatedになると何回かあとのリリースで機能が削除されるので、あまり長い間置いておくと突然エラーになります。早めに対処しましょう。

なお、どれも今まで[アクセス保護属性の仕様](https://dlang.org/spec/attribute.html#visibility_attributes)に反してシンボルが使えていた状況だった、という問題のようです。

個人的に悩まされた思い出もありますが、対処は人それぞれになると思われます。
まずはdmdを更新して1回ビルドしてみよう！って感じですね。


## 標準ライブラリ変更点
### `std.experimental.all`の追加
ChangeLog: https://dlang.org/changelog/2.079.0.html#std-experimental-all

すべての標準ライブラリをまとめてimportできる`std.experimental.all`というモジュールの追加です。

つまり、


```d:これが
import std.algorithm;
import std.math;
import std.stdio;
import std.range;

void main()
{
    10.iota.map!log.sum.writeln;
}
```

```d:こうじゃ
import std.experimental.all;

void main()
{
    10.iota.map!log.sum.writeln;
}
```

ということです。

元々`std.experimental.sctipting`モジュールとして提案されていたこともあり、D言語をスクリプトのように気軽に使えるようにしようぜって意図があるようです。
今後はWandboxでとりあえずこれ書いとけ、みたいな使い方になるかもしれません。

ちなみにフォーラムで提案されたときは「将来的に`import std;`にしよう」などと言われていました。既存のpackage.dファイルの仕組みを考えるとそうだよね、って感じです。
（しかし何か既視感と嫌悪感があるような…）


# まとめ
前回のdmd2.078リリースが2018/01/01でした。
その後3度のマイナーリリースをしながら、（それなりに準備はあったでしょうが）丸2ヶ月でこれだけのアップデートをやったということです。開発陣すごい。

内容としては、便利に使える機能がいろいろ増えたのと、deprecated周りが多く大変健全になった印象ですね。
試験中の機能も追加されていますし、まだまだこれからだ！