D言語の更新まとめ 2019年11月版（dmd 2.089.0）

# はじめに
D言語の公式コンパイラである dmd が更新され、最新バージョンである `2.089.0` が 2019/11/02 にリリースされました。

今回もほぼ予定通りのスケジュールで、言語的な強化は控えめながらツール周りでいくつか目立った強化が行われました。
また不具合修正の一環で多数の改善が入っているので、これもいくつか拾っておきたいと思います。

より細かい内容は下記リンクからChangeLogや公式ブログの原文をご覧ください。

- ChangeLog : https://dlang.org/changelog/2.089.0.html

また、前回9月ののリリースまとめは以下になります。

- D言語の更新まとめ 2019年9月版（dmd 2.088.0）
    - https://qiita.com/lempiji/items/04b2cb5ce6da7d2f46d4

# 変更点目次

## コンパイラ変更点
- `foreach` ループで許可されていた変数のshadowingが廃止されました。
- is式が `const` 、`inout` 、 `shared` の組み合わせに正確に一致するようになりました。
- `template mixin` 中の `extern(C)` 宣言がグローバルスコープで使われたとき、Cのマングルでシンボルを生成します。
- Digital Marsのツールチェインにおけるデフォルトのリンカが `optlink.exe` になります。
- Issue 6952のため、新しく `-Xcc` コンパイラフラグが追加されました。

### 改善点
* Bugzilla 809: lazyな引数はdelegateに変換できるべきです。
* Bugzilla 1547: デフォルト引数の値は暗黙的なopCallを使うべきです。
* Bugzilla 3004: 不正なpragmaのハンドリングを改善
* Bugzilla 18272: `-gf`のchangelogとドキュメントがない (参照された型について不可解なデバッグ情報が出力される)
* Bugzilla 18617: 式がdeprecatedであるか確かめるために `__traits(deprecated, expr)`が必要です。

## ランタイム変更点
- `core.atomic` に `atomicFetchAdd` と `atomicFetchSub` を追加します。
- `wstatus` を `pure` と `@safe` にします。
    - 訳注）Posixの `wait(2)` を `pure/@safe` にする、という意味のようです

### 改善点
* Bugzilla 8831: `core.atomic` に 異なる戻り値の`compare-and-swap` 関数を追加します。
* Bugzilla 13826: `volatileLoad` と `volatileStore` を `core.volatile` へ移動します。
* Bugzilla 15007: `core.atomic` を C++11 に合わせる
* Bugzilla 20105: `core.atomic` の `cas` 関数が不完全
* Bugzilla 20106: `core.atomic` の `atomicFence` が `MemoryOrder` の指定を受け付けない
* Bugzilla 20107: `core.atomic` の Memory order にキーが不足している

訳注）いくつかをまとめて `atomicFetchAdd` あたりに還元されており、トピックとしては `core.volatile` の追加が大きいです

## ライブラリ変更点
- `std.traits.Unconst` を追加

### 改善点
* Bugzilla 20147: `std.bigint.BigInt` と浮動小数点型の間で比較(==, >, >=, <=, <)が有効になりました。
* Bugzilla 20159: `std.math.scalbn` がCTFE可能となりました。
* Bugzilla 20192: `std.math.isSubnormal` がCTFE可能となりました。
* Bugzilla 20196: `std.math.isNormal` がCTFE可能となりました。
* Bugzilla 20199: `std.math.frexp` がCTFE可能となりました。
* Bugzilla 20200: `std.math.isPowerOf2` が浮動小数点数に対してCTFE可能になりました。
* Bugzilla 20201: `std.math.scalbn` が `pure` になりました。
* Bugzilla 20202: `std.math.signbit` がCTFE可能となりました。
* Bugzilla 20203: `std.math.copysign` がCTFE可能となりました。
* Bugzilla 20242: `BitArray` のコンストラクタは入力値を変更しないべきです。

## DUB変更点
- LDCにおけるクロスコンパイルのサポートを改善しました。
- `Lint` コマンドを追加しました。
- セマンティックバージョニングにおける "^" の指定を追加しました

# 注目トピック
## 言語・コンパイラ変更点
### 強化: is式の推論改善

is式の推論が少し賢くなりました。
Change Logの抜粋ですが、以前は通らなかった以下の判定が通るようになります。

```d:
static assert(is(shared(const int) U == shared U) && is(U == const int));
static assert(is(shared(inout int) U == inout U) && is(U == shared int));
```

ランタイムにも `Unconst` の追加という強化があるので、このあたりの推論と何かつながりがあるのかもしれません。
いずれにしてもメタプログラミングが捗りそうです。

### 強化: `template mixin` 中の `extern(C)` 宣言の変更

Change Logの例から一部抜粋ですが、要するに「WebAssemblyのエントリポイントをよろしく生成するテンプレートを書きたい」という要望に応えるための強化のようです。

```d:エントリポイントをテンプレート化する例
// library code
mixin template WasmEntryPoint() {
    extern(C) export void _start() {
        // boilerplate code
    }
}

// application code
mixin WasmEntryPoint;

static assert(_start.mangleof == "_start");
```

こういった取り組みも行われているということで、今後WebAssembly関連のライブラリ強化も期待できそうですね！

### 改善: `lazy`な引数が `delegate` に変換可能になります。

`lazy` というのは関数引数の修飾子で、その引数の評価が使われるときまで遅延される、というものです。

たとえばフラグに応じて処理をするか切り替えるとき、「使わないかもしれない値を先に計算して用意しておく」というのはできれば避けたいですよね。

`lazy` を使うと以下のように書くことで遅延評価になります。

```d:
// lazy引数で遅延評価
void times(int n, lazy string message) {
    while (n--)
        writeln(message);
}

// 繰り返し回数は実行時ゼロになることを想定
int n = 0;
int days = 10;
string s = "days";
string m = "later";

// formatの部分はlazyになっているので1度も評価されない
n.times(format!"%d %s %s"(10, s, m));
```

これを `lazy` なしに実現しようと考えた場合、 `string` ではなく `string delegate()` として、以下のようになるでしょうか。

```d:
void times(int n, string delegate() message) {
    while (n--)
        writeln(message());
}
```

これは `lazy` に対して内部的に行われていることとほぼ同じなのですが、表現の分かりやすさから `lazy` キーワードが導入されています。
逆に中身を知ってしまうと、「元々 `delegate` と変わらないのだから変換できても良いだろう」ということで改善された格好になります。

実際に変換するには以下のようになります。

```d:
void test(lazy string t)
{
    string delegate() dg = &t; // アドレスを取るイメージで変換できる
    string s = dg();
}
```

ちなみにこれをキャストで変換しようとするとエラーになるので注意してください。

互換性などの問題があるのかもしれませんがちょっと思いつかず、実際に問題になるようなケースをご存知の方がいれば教えてください。

## ランタイム変更点
### 強化： `core.atomic` に `atomicFetchAdd` と `atomicFetchSub` を追加
今回追加されたのはC++に元々ある `std::atomic::fetchAdd` 等にあたる関数です。

機能としては、既存の `atomicOp` をそれぞれ `+` または `-` 演算子で実行してアトミックに置き換え、元の値を返す、というものになります。
（既存の `atomicOp` は値を置き換えてその値を返すため、変更前の値は取得できません）

サンプルは以下のようになります。

```d:
import core.atomic;

shared x = 10;
auto y = atomicFetchAdd(x, 10);

assert(x == 20);
assert(y == 10);
```

こちら、前回9月のリリースで `cas` のオーバーロードや `atomicExchange` の追加がありましたが、今回もその流れで強化があったようです。

こういった関数の追加で使い勝手が良くなって、非同期のプログラムが気楽に書けるようになるのはありがたいですね！

## ライブラリ変更点

### `std.math` におけるCTFE強化
今回複数の関数がCTFEに対応しました。
使う頻度が少ない関数もあるようですが、それなりに数があるのでかなり目を引きます。

ちなみにざっくり機能などまとめると以下の通りで、かなりコアな部分までカバーされた印象です。


- `scalbn`
    - `scalbn(x, n)` で `x * (2 ^^ n)` を求めます。
- `isSubnormal`
    - `isSubnormal(x)` で `x` が非正規数かどうかを判定します。
- `isNormal`
    - `isNormal(x)` で `x` が通常の数（NaNやinfinity、0または非正規数でない）かどうかを判定します。
- `frexp`
    - `frexp(x, exp)` で浮動小数点を指数部と仮数部に分解します。戻り値が仮数部、 `exp` が指数部になります。
- `isPowerOf2`
    - `isPowerOf2(x)` で `x` が2のべき乗かどうかを判定します。
- `signbit`
    - `signbit(x)` で `x` の符号ビットを取得します。負数なら1、正の数なら0になります。 
- `copysign`
    - `copysign(a, b)` で、値は `a` 、符号は `b` と同じになる値を求めます。

## DUB変更点
### 強化: LDCのクロスコンパイルに対応
LDC 1.18.0でクロスコンパイルに対応したのを受けて、dubのビルドにおける `--arch` にLDCの `-mtriple` と同じ値が指定できるようになりました！

これでWindowsからLinuxバイナリを出力できたりするほか、WebAssemblyのビルドやAndroid関連のビルドをdubで行えるようになると思われます。（まだ実験不足です）

具体的に `-mtriple` に指定できる値は以下を参照してください。

- https://wiki.dlang.org/Cross-compiling_with_LDC

ちなみに主要なプラットフォームの例を挙げると以下のような感じです。

| プラットフォーム         | mtriple                              |
|:------------------------|:-------------------------------------|
| Linux x86_64 with glibc | `x86_64-linux-gnu`                   |
| macOS                   | `x86_64-apple-darwin16.7.0`          |
| Windows x64             | `x86_64-windows-msvc`                |
| Android ARMv7-A         | `armv7a-unknown-linux-androideabi`   |
| 32-bit WebAssembly      | `wasm32-unknown-unknown-webassembly` |


### 強化： `lint` コマンドの追加

シンタックスやコメントの有無をチェックできる `lint` コマンドが追加されました。

dubプロジェクトのトップで `dub lint` とすることで DScanner を使った構文チェックとスタイルチェックを行うことができます。

見つけた警告によってリターンコードが1になったりするので、CIに組み込むことで継続的なチェックが可能です。

また、解析結果をJSONで出力する `--report` というフラグもあるため、これを解析すれば何かを活かせるかもしれません。

## 非推奨または廃止される機能

今回は `foreach` における変数宣言の shadowing が廃止されるのみです。
追加で非推奨になる機能はありません！

通常の `for` ループではshadowingがエラーになるため、同じ問題で引っかかるケースは稀かと思われます。

また以前からずっと非推奨だったので、警告に気を配っていれば影響を受けることはないと思います。

```d:
int n;
foreach (i; 0 .. 100) {
    int n = i * 10;
    writeln(n);
}
```


# まとめ
修正された不具合もそれなりにありますが、求められた機能の追加を中心にツール周りが整えられた印象のリリースです。

また、「新たに非推奨になった機能等がない」というのは、「Breaking changes」という見出しが毎バージョン踊っていたころと比べて非常に印象的です。

少し前から不評な機能を消すことに終始していたのもあり、今回のリリースが1つの節目なのかと思われます。

というわけでリリースのまとめは以上です。

次は年明け元旦予定のリリースを期待して待ちつつ、今後リリースされるであろう大規模機能強化にも注目したいと思います！

（アドベントカレンダーが近いので、今年話題になったネタはある程度そちらでまとめたいと思います）