D言語の更新まとめ 2022年5月版（dmd 2.100.0）

# はじめに

D言語の公式コンパイラである dmd が更新され、最新バージョンである `2.100.0` が 2022/05/10 にリリースされました。

今回は前回からほぼ2ヶ月でのリリースですが、最近間隔がまちまちだったこと踏まえると正常サイクルに戻ったとも言えそうです。

さて、非常に区切りの良いバージョン番号ですが、これに合わせて結構な数の非推奨機能が削除される運びとなっており、このあたり漏らさず整理していきたいと思います。
もちろん他にも今回も新機能や改善がありますのでご紹介します。

より細かい内容は下記リンクからChangeLogをご覧ください。

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

また、前回である3月版のリリースまとめは以下になります。

- D言語の更新まとめ 2022年3月版（dmd 2.099.0）
    - https://qiita.com/lempiji/items/89469239595ee1237115

# 変更点目次

## コンパイラ変更点

- DIP1038(`mustuse`) が実装されました。
- `invariant` 契約のバージョン識別子が追加されました。
- 静的配列の `.tupleof` プロパティを追加しました。
- `inout` 属性が `return` 属性を意味しないようになりました。
- C++ヘッダ生成が改善されました。
- クラス宣言、構造体宣言、`enum` 宣言の型制約としての `scope` は非推奨となりました。
- `switch case` のフォールスルーで一部のケースが非推奨となり警告を発生させるようになりました。
- 部分代入の `alias this` の使用に関する非推奨期間が終了しました。
- D1スタイルの演算子の非推奨期間が終了しました。
- 非アノテーションの `asm` ブロックの非推奨期間が終了しました。
- `delete` キーワードの非推奨期間が終了しました。
- インターフェイス宣言の型制約としての `scope` の非推奨期間が終了しました。
- 型としての `this` と `super` の使用が削除されました。

### 改善点

* Bugzilla 3632: floatをビット単位で比較するように変更します。
* Bugzilla 11463: DDocのHTMLで通常のエスケープされたASCII文字を表示できるようにします。
* Bugzilla 14277: コンパイル時の配列のキャストエラーを改善します。
* Bugzilla 20853: 静的配列の `.ptr` は安全なコードで使用できませんが、許可されるべきです。
* Bugzilla 21673: [SIMD][Win64] `_mm_move_ss` のコード生成が間違っています。
* Bugzilla 22027: `inout` 属性 は `return` 属性を意味しないはずです。
* Bugzilla 22541: DIP1000: `ref-return-scope` パラメータの曖昧さを解決します
* Bugzilla 22770: C++ ヘッダージェネレータは、末尾の改行を生成します。
* Bugzilla 22790: `ref-return-scope` は `return-scope` がこの順序で現れない限り、常に `ref-return`, `scope` となります。
* Bugzilla 22820: `opIndex` を持つ構造体でスライスのポインタを取得する場合のエラーメッセージは改善できる場合があります。
* Bugzilla 22821: dub パッケージがインクリメンタルコンパイルを使用しません。
* Bugzilla 22861: コンパイラをPGO（Profile guided optimization）と共にビルドします
* Bugzilla 22880: ImportC: `__restrict__` `__signed__` `__asm__` をサポートしました。
* Bugzilla 22922: `-betterC` で空の配列リテラルをサポートします。
* Bugzilla 22945: [条件付きコンパイル] `invariant` のバージョンフラグをサポートしました。
* Bugzilla 22967: [dip1000] 拡張されたreturnセマンティクスでreturn refが推論されるようにします。
* Bugzilla 23021: [dip1000] pure nothrow から return scope を推論するようにします。

## ランタイム変更点

### 改善点

* Bugzilla 18816: [betterC] 標準ストリームをリンクできるようにする。
* Bugzilla 19933: MSVC: -betterC で `stdin` `stdout` `stderr` が未定義となる問題を解消する。
* Bugzilla 22766: `copyEmplace` がコピーコンストラクタと `@disable this()` を持つ場合も動作を可能にする。
* Bugzilla 22964: 配列のキャストメッセージが不格好な表現になっているため改善する。


## ライブラリ変更点

- `std.functional` に `bind` 関数が追加されました。
- `std.typecons` の `Nullable` は1要素を持つレンジとして振舞えるようになりました。
- Zlib のバージョンが `1.2.12` に更新されました。

### 改善点

* Bugzilla 22736: `std.typecons.Tuple` および `tuple` に破壊的束縛(destrucuring bind)を追加します。（訳注：変更点にある `bind` 関数との連携のことです）
* Bugzilla 22798: `std.getopt.defaultGetoptPrinter` は `@safe` であるべきです。

## DUB 変更点

- 動的ライブラリのビルドでは、静的ライブラリではなく動的ライブラリと指定しないとビルドされなくなりました。
- 環境変数に `$DUB_BUILD_PATH` が追加されました。
- コマンド環境変数の置換動作が変更されました。
- Posix環境で、DUBが `/usr` にインストールされている場合、`/etc/dub/settings.json` を使用するようになりました。
- `injectSourceFiles` コマンドで依存関係からソースファイルを注入する機能が追加されました。

## ツール変更点

- rdmd は `RDMD_DMD` 環境変数を使ったコンパイラの指定が可能になりました。


# 注目トピック

## 言語・コンパイラ変更点

### 追加 : DIP1038(`mustuse`) が実装されました。

更新(2022/05/22): 関数属性として使えると記載していましたが誤りだったため修正しました。

今回の目玉機能です。

言語機能として `@mustuse` という属性が追加されました。
何をするものかというと、構造体(`struct`)か共用体(`union`)に付与すると、その型を戻り値とする関数の戻り値が無視できなくなる（エラーを発生させる）というものです。

たとえば、何か処理をした結果エラー値を返すような関数の場合、エラー値を見て処理分岐することを期待しますので、無視しないでちゃんと使ってほしいという意味で `mustuse` をつけることになります。

```d:mustuseの利用法
import core.attribute: mustuse;

// 無視できない型を定義
@mustuse struct ProcessResult {
    int status;
    string message;
}

// 結果を無視してほしくない関数を定義
ProcessResult processHoge(string msg) {
    return ProcessResult(0, null);
}

// 戻り値を見ないためエラーとなる例
processHoge("test");

// 戻り値を見るため正常な例
auto result = processHoge("test");
if (result.status != 0) {
    // エラー処理など
}
```

ちなみにこちらの `@mustuse` ですが、既存コードをできるだけ壊さないようにということで `core.attribute` モジュールに定義されています。

使うには `import core.attribute` が必要なので、なんか使えないなと思ったら `import` を書いてみてください。

#### 訂正ポイント : 関数属性として付けられない

今回追加されている `@mustuse` ですが、他の言語でも類似機能が提供されています。たとえばC++17の `[[nodiscard]]` という属性であったり、Rustの `#[must_use]` というアトリビュートなどです。

このあたり既存実装との比較はD言語の改善提案である [DIP1038](https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1038.md#prior-work) にまとめられていますが、D言語版の大きな違いとして「他の言語では関数単位で付けられるが、D言語の場合は型にしか適用できない」という点が挙げられます。

つまり現状以下のようなコードは書けません。

```d:
int processHoge() @mustuse {
    return;
}
```

`@mustuse` が関数属性につけられない理由を挙げると、主なところは以下3つです。

- 仕様が複雑になる（式の評価や警告など細かい規定が増える）
- 複雑な式の呼び出しがあったとき、その複雑度に応じてコンパイル速度への影響が考えられる
- 上記のため実装が複雑になると保守性の問題が考えられる

つまるところ何か理屈的に問題があって実装できないのではなく、将来的に付けられるようにする提案は十分考えられ、現時点では実装してないだけということです。（ハードルはそれなりに高そうですが）

ちなみに何が複雑か考えるには、たとえば `@mustuse` な戻り値を持つ `dontIgnoreMe` という関数があったとして、以下の呼び出しを考えてみると雰囲気がつかめます。

```d:
a ? b : dontIgnoreMe(); // 分岐は全パターン網羅しなければいけないのでNGになるべき

(writeln("side effect"), dontIgnoreMe()); // 副作用や例外が起きるケース、noreturn型も考慮すべき

(() => dontIgnoreMe())(); // ラムダ式自体が mustuse を戻り値に伝搬していると推論する必要がある
```

この中でも一番面倒そうなのは最後の戻り値伝搬でしょうか。
`mustuse`な関数を `return dontIgnoreMe();` としていたら呼び出し元の関数にも `mustuse` を付けるべきで、そうなっていなければ警告を出し、更に上位の呼び出しは無視しないように広く直すことになります。
逆に内部の `mustuse` をもし外したら、上位の `mustuse` が不適切な指示として残ってしまうので外して回ることになりますが、意図したものか機械的な区別は困難です。いずれにしても大幅改修は想定されるでしょう。

今回の実装のように型に付けるだけならそういったつけ忘れ/外し忘れのようなものもなく、任意の階層でチェックできるのでコンパイル速度への影響も少なそうです。

とはいえ戻り値が `int` の関数で戻り値無視するなというC言語の関数がありそうなのは十分考えられ、そちらを踏まえると関数に付けられるような強化は今後期待したいところです。
仕様をシンプルに保ちつつ、何か上手い実装が見つかることを期待したいと思います。

### 追加 : `invariant` 契約のバージョン識別子が追加されました。

新しい組み込みバージョン識別子です。
デバッグモードやリリースモードがありますが、それらの組み合わせで契約プログラミングの不変条件(`invariant`)が使える場合に使える識別子です。

```d
version (D_Invariants) {
    // 不変条件が使えるときだけ実行される
}
```

公式のサンプルを見ると、元々は `invariant` の中でカウントアップする等の副作用を起こして呼び出したかテストするような事を想定し、不変条件が動くときだけチェックするテストを書きたい、というのが要望のようです。

```d
bool hit;

class Foo
{
    this() {}
    invariant { hit = true; }
}

void main()
{
    auto obj = new Foo();

    version(D_Invariants) assert(hit); // 不変条件が実行されるときだけ hit が書き換わったことをテストする
}
```

こういった不変条件の呼び出しそのものがチェックできる、というのはテスト駆動で開発する場合にも有用だと思います。
ぜひぜひテストを書いて安心安全な開発を実現していきましょう。


### 追加 : 静的配列の `.tupleof` プロパティを追加しました。

静的配列を要素数に応じたタプルとして扱う `.tupleof` というプロパティが追加されました。

```d
void foo(int, int, int) { /* ... */ }

int[3] ia = [1, 2, 3];
foo(ia.tupleof); // `foo(1, 2, 3);` と同じ
```

また公式サンプルでちょっと面白い使い方が紹介されており、要素型の違う静的配列があたかも代入できるかのように扱える、というのがあります。

```d
float[3] fa;
//fa = ia; // 直接代入は int[] と float[] で要素型が不一致のため当然エラー
fa.tupleof = ia.tupleof; // tupleof では要素を1つ1つ代入するため、 int -> float で型変換できることからOK
assert(fa == [1F, 2F, 3F]);
```

### 変更 : `inout` 属性が `return` 属性を意味しないようになりました。

`inout` 属性というのは、大まかに言うと引数（クラスや構造体のメソッドなら `this` を含む）と戻り値が同じ不変性であることを示すものです。

入力が `const` なら戻り値も `const`、あるいは `immutable`、そうでないなら非 `const` という状況で「コードは同じなのに別に書かなければいけない」という場合にオーバーロードを削減するなど記述を簡便化する効果があります。

ここで今回の変更ですが、今までは「すべての `inout` 関数がその引数(`this` を含む)を返す」という前提でした。

ここから更に `return` という属性につながりますが、「関数に `inout` 修飾されていれば、 `this` などの一部を返す `return` セマンティクスを満たすはず」として内部的に `return` 属性を追加したうえでコンパイラは推論していました。

しかし、`const` と `immutable` は推移的ですが、元来 `return` セマンティクスは推移的ではなく別途計算する必要があるものです。
たとえば1段階メンバーを辿ると推移的な属性は `inout` で流用できても `return` ではないということが起こり得ます。これを今回排除する目的で推論を厳密にするため `inout` と `return` が分離されました。

```d
@safe:

struct Node
{
    Node* next;
    int x;

    // 以前は inout が return を兼ねていたので、inout 関数なら自身の一部をポインタで返すことが許されました
    // この場合、コンパイラは内部的に return 属性を付けたとして推論し、警告は出ません
    @safe inout(int)* getScopePointer() inout
    {
        return &this.x;
    }

    // 一方、 inout は const や immutable と違って推移的ではありません
    // このため1度メンバーを辿ると inout は正しく伝搬しますが、return 性は誤って推論される場合があります
    @safe inout(int)* getNonScopePointer() inout
    {
        return &this.next.x;
    }

    // 今後自身の一部を返す関数として正しく推論させるには、関数を return で修飾します
    // 修飾しないと警告が出ます
    @safe inout(int)* getScopePointerFixed() inout return
    {
        return &this.x;
    }
}
```

後述の非推奨の項でも触れますが、これは自己参照を返す場合に `return` で修飾しなさいというよくある警告を発生させます。
以下のような警告を見たら「関数に `return` が足りないかもよ」と言われているので付けるなどの対策をしてみてください。

__警告の例__

```
onlineapp.d(11): Deprecation: returning `&this.x` escapes a reference to parameter `this`
onlineapp.d(9):        perhaps annotate the function with `return`
```


## ライブラリ変更点

### 強化 : `std.typecons` の `Nullable` は1要素を持つレンジとして振舞えるようになりました。

今回の目玉強化の1つです。
D言語の特徴的な設計パターンである「レンジ」と、要素が空かもしれない事を表す `Nullable` 型が意味的につながりを持つようになりました。

結論から言ってしまうと、 `Nullable` が要素を持てば「1要素のレンジ」、空なら要素を持たない「0要素のレンジ」として扱えるようになった、というものです。

これて `Nullable!int[]` のような要素があるかわからない配列から要素があるものだけ取り出すような処理が標準ライブラリの範囲で簡単に書けるようになります。

```d
int[] filterNotNull(Nullable!int[] values)
{
    import std.algorithm: joiner;
    import std.array: array;

    return values.joiner().array();
}
```

何をやっているかというと、`joiner` というのがいわゆる `flatten` や `flatMap` と呼ばれる二重のレンジをフラット化する処理なので、「要素がないなら空のレンジ」という今回追加された特性から値を持たない要素を無視して連結、それを `array` 関数で配列として取り直すと要素があるものだけ取り出す、という処理になります。

これがないと `values.filter!(a=>!a.isNull).map!(a=>a.get)` と何段階か加工が必要で結構手間のかかるコードになるのでこれは結構劇的です。 

他にもいろいろ便利な用途が考えられると思うので、ぜひぜひ使ってみて便利な使い方を見つけてください。

### 追加 : `std.functional` に `bind` 関数が追加されました。

ワンライナー教徒やメタプログラミング勢には嬉しいタイプの新機能です。

`Tuple` 型で定義されたオブジェクトを受け取り、引数に展開、マッピングしてくれる関数を新しく作る `bind` というテンプレート関数が追加されました。
少し言い換えると、「『複数の引数を `Tuple` にまとめた引数』を受け取る関数を作る」という関数です。

公式サンプルがややトリッキーですが、以下のようになります。

```d
import std.stdio;
import std.range;
import std.algorithm;
import std.functional;

void printWithLineNumbers(File f)
{
    f.byLine
        .enumerate
        .each!(bind!((num, line) {
            writefln("%8d %s", num, line);
        }));
}
```

`f.byLine.enumerate` という部分まで読むと戻り値が `Tuple!(size_t, string)` という型になっており、要するに2要素のタプルです。

`each!(...)` で上記のタプルを受け取って使うわけですが、普通に書くと `t[0]` や `t[1]` という形で個々にアクセスしなければいけません。
これをパラメーターに対応するようバラしてくれるのが `bind` 関数です。

これをちょっと変えると以下のようにも書けます。

```d
// 呼び出したい関数は普通に引数を書く
void test(int n, string s, int[] arr) { }

// 引数を Tuple で持っている
Tuple!(int, string, int[]) params = tuple(0, "one", [2]);

// 引数を params[0] などと書くのが面倒なので bind!test とした関数にするとそのまま呼べる
bind!test(params);

// ちなみにこれは `.expand` というプロパティを使っても同じようにできる
test(params.expand);
```

というわけで `.expand` が便利です！

一方 `bind` は、主にワンライナーしたいときに対応付けの関数を自動で作ってくれるのがメリットです。
今まで書いていたコードをよりシンプルにできるかもしれない関数ですので、ぜひ便利に使ってみてください。

## DUB変更点

### 追加 : 環境変数に `$DUB_BUILD_PATH` が追加されました。

ビルドツールの `dub` で使える環境変数が追加されました。
名前は `$DUB_BUILD_PATH` で、ビルドキャッシュなどが置かれる `.dub` 以下、実行ファイルが生成される場所の絶対パスが取得できます。

たとえばWindows環境では以下のようなパスになります。

```
C:\dev\D\dub_test\.dub\build\application-debug-windows-x86_64-dmd_v2.100.0-dirty-724EADC5EA9914B6BE83CF27BAED6453
```

こちら元々シンボルファイルなどが生成された場合、それをどこかのパスにコピーしたいという要件から追加となりました。そのため「`postBuildCommands` セクションでしか利用できない」という点に注意が必要です。

ちなみに実際エクスポートされたシンボルを使うのは以下のようになります。（公式サンプル抜粋、書き換えです）

__dub.jsonの場合__

```json
{
    "postBuildCommands-windows": [
        "copy /y $DUB_BUILD_PATH\\$DUB_TARGET_NAME.lib $PACKAGE_DIR\\lib"
        "copy /y $DUB_BUILD_PATH\\$DUB_TARGET_NAME.exp $PACKAGE_DIR\\lib"
    ],
}
```

__dub.sdlの場合__

```
postBuildCommands "copy /y $DUB_BUILD_PATH\\$DUB_TARGET_NAME.lib $PACKAGE_DIR\\lib" platform="windows"
postBuildCommands "copy /y $DUB_BUILD_PATH\\$DUB_TARGET_NAME.exp $PACKAGE_DIR\\lib" platform="windows"
```


### 追加 : `injectSourceFiles` コマンドで依存関係からソースファイルを注入する機能が追加されました。

（内容確認中です）

### 強化 : Posix環境で、DUBが `/usr` にインストールされている場合、`/etc/dub/settings.json` を使用するようになりました。

（内容確認中です）

### 変更 : 動的ライブラリのビルドでは、静的ライブラリではなく動的ライブラリと指定しないとビルドされなくなりました。

（内容確認中です。見出しは翻訳しましたが若干怪しいかもしれません）

### 変更 : コマンド環境変数の置換動作が変更されました。

（内容確認中です）


## ツール変更点

### 追加 : rdmd は `RDMD_DMD` 環境変数を使ったコンパイラの指定が可能になりました。

`rdmd` はD言語をスクリプト風に扱えるコンパイラ付属のツールです。

`rdmd script.d` といった感じでファイルを指定するとコンパイルと実行をまとめてやってくれるのですが、これが中々[便利](https://qiita.com/lempiji/items/0730a6441f4f23a57119)です。

そんな `rdmd` ですが、`dmd` と付く割にコンパイラを指定する機能を持っており、 `rdmd --compiler=ldc2 script.d` といった引数指定をするスタイルが可能でした。
これを `RDMD_DMD` という環境変数で設定できるようにし、設定しておけば引数指定が不要になった、という強化です。

私も日々のちょっとしたタスクを `rdmd` でやるようになると少し実行を速くしたいなと思うことがあり、同じような経験のある方であれば `RDMD_DMD` を `ldc2` と設定しておくのは一案として良いかもしれません。


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

今回は節目ということで、ここに合わせて多くの非推奨機能がエラーとなる予定でした。

追加の非推奨が2件、エラーとなるものが6件です。
とはいえ今回も長年非推奨だったものがエラーになるケースがほとんどなので影響を受けることはほぼないと思います。

今後の予定などは以下のページにまとまっていますので、こちらも参考としてみてください。

https://dlang.org/deprecate.html

というわけで個々の対応方法についてまとめていきます。

__非推奨__

- `inout` 属性が `return` 属性を意味しないようになりました。
- クラス宣言、構造体宣言、`enum` 宣言の型制約としての `scope` は非推奨となりました。
- `switch case` のフォールスルーで一部のケースが非推奨となり警告を発生させるようになりました。

__削除/エラー__

- 部分代入の `alias this` の使用に関する非推奨期間が終了しました。
- D1スタイルの演算子の非推奨期間が終了しました。
- 非アノテーションの `asm` ブロックの非推奨期間が終了しました。
- `delete` キーワードの非推奨期間が終了しました。
- インターフェイス宣言の型制約としての `scope` の非推奨期間が終了しました。
- 型としての `this` と `super` の使用が削除されました。

### 非推奨 : `inout` 属性が `return` 属性を意味しないようになりました。

リリースノートでは単に変更扱いでトピックとしても触れていますが、この変更によって一部警告が発生するようになりますのでこちらで補足します。

今回の変更により警告が発生するのは下記のコードです。

__警告の例__

```d
@safe:

struct Node
{
    Node* next;
    int x;

    // inout な関数で、自身の一部をポインタとして返しているが return はない
    @safe inout(int)* getScopePointer() inout
    {
        return &this.x;
    }
}
```

__警告の例__

```
onlineapp.d(11): Deprecation: returning `&this.x` escapes a reference to parameter `this`
onlineapp.d(9):        perhaps annotate the function with `return`
```

エラー内容としては、「関数が自身の一部を参照として返しているので、関数を `return` で修飾せよ」ということです。

`inout` が内部的に `return` でもあるとして扱われていたところ、厳密に意味が分けられたので別途修飾が必要になります。
ただ推論の面でも幾分効率化されること、安全面では警告が出たり属性が付いていたりするほうが読み手としては分かりやすかったりしますので、これも安全性が重視された結果ではないかなと思います。

ただ `inout` 属性使う機会は割と少ないような気もしますので、そこまで多くの方が注意すべき内容でもないかもしれません。 
警告に対処が表示されますのでその通り行っておけば良いかと思います。


### 非推奨 : クラス宣言、構造体宣言、`enum` 宣言の型制約としての `scope` は非推奨となりました。

元々2019年7月1日の dmd 2.087.0 で、クラスに対する `scope` 宣言機能が非推奨となっていました。

https://qiita.com/lempiji/items/602c46b379f3c2af3d25#%E3%82%AF%E3%83%A9%E3%82%B9%E5%AE%A3%E8%A8%80%E3%81%AB%E5%AF%BE%E3%81%99%E3%82%8Bscope%E4%BF%AE%E9%A3%BE%E3%81%8C%E9%9D%9E%E6%8E%A8%E5%A5%A8%E3%81%A8%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%97%E3%81%9F

今回これに合わせて `struct` と `enum` に対する `scope` 宣言が同じように非推奨となりました。

宣言に付けられないだけで、利用時に `scope` な変数（スコープ外に持ち出すコピーができない）として使う事は可能です。
今後エラーを見かけたら以下のような記述に書き換えてください。

```
// ここに scope は付けられない
class Test { }

void test()
{
    // 変数宣言で付ける
    scope obj = new Test;

    // スコープを抜けるときにデストラクタが実行される
}
```

### 非推奨 : `switch case` のフォールスルーで一部のケースが非推奨となり警告を発生させるようになりました。

前回 2.099.0 ですべてエラーとなるはずだった `switch case` のフォールスルーに一部対応漏れがあり、今回非推奨とされるパターンが追加されました。
今回は対応漏れと言えど一気にエラーにするのではなく、非推奨にするところから改めて段階的に進めていくため幾分安全に配慮したやり方と言えます。

非推奨の内容としては、以下のように `case` の値が複数あるような場合とのことです。

```d
void main()
{
    int i = 0;
    switch (10)
    {
        case 10, 11:
            i = 4;
            // 誤ってフォールスルーが許容されてしまうパターン
        default:
            i = 8;
    }
    assert(i == 4); // フォールスルーによって i は 8 になるため失敗
}
```

なお、この場合は以下のようなエラー文が表示されます。

```
onlineapp.d(9): Deprecation: switch case fallthrough - use 'goto default;' if intended
```

発生行はフォールスルーによって辿り着いてしまう次の `case` 文で、`use 'goto default;'` と書くべき内容が指示されています。
対応としては、メッセージの行番号に指定された内容を差し込むだけなので幾分簡単な対応となっています。

ちなみに次の `case` に何か値が指定される場合は `use 'goto case;'` と言われるのでその通りにすれば大丈夫です。

### エラー : 部分代入の `alias this` の使用に関する非推奨期間が終了しました。

2019年5月4日の dmd 2.086.0 から非推奨で警告が出ていたものが今回エラーになりました。

「`alias this` による部分代入」とはなんぞやという話ですが、公式サンプルによると以下のような内容です。

```d:
struct Allowed
{
    int onemember;
    alias onemember this;
}

struct Rejected
{
    int aliased;
    long other;
    alias aliased this;
}

void fun(Allowed a, Rejected r)
{
    a = 0; // struct がメンバーを1つしか持たないためOK
    r = 0; // alias this による部分代入でありエラー。 `r.aliased` を使う必要があります
}
```

一方は `int` のみの構造体、もう一方は `int` と `long` を持つ構造体です。ここに `int` を代入して大丈夫？という話で、危険そうなパターンが報告されたことから非推奨となりました。

実際に発生すると以下のようなメッセージが表示されます。

```
onlineapp.d(19): Error: cannot use `alias this` to partially initialize variable `r` of type `Rejected`. Use `r.aliased`
```

エラーメッセージにもある通り、対処はメンバーを明示すればOKです。

また、どうしても代入側を直したくないという場合は `opAssign` を定義する手もあります。
上記の `Rejected` 型を直してコンパイルを通す場合以下のようになります。

```d:
struct Rejected
{
    int aliased;
    long other;
    alias aliased this;

    // 代入が通るように代入用の演算子オーバーロードを実装する
    ref typeof(this) opAssign(int n) return
    {
        this.aliased = n;
        return this;
    }
}
```

### エラー : D1スタイルの演算子の非推奨期間が終了しました。

2019年9月1日の dmd 2.088.0 から非推奨で警告が出ていたものが今回エラーになりました。

非推奨時点の記事は以下にありますが、内容は過去のバージョンである `dmd 1.xxx` というD1の演算子オーバーロードを利用しているとエラーになるというものです。

https://qiita.com/lempiji/items/04b2cb5ce6da7d2f46d4#d1%E5%BD%A2%E5%BC%8F%E3%81%AE%E6%BC%94%E7%AE%97%E5%AD%90%E3%82%AA%E3%83%BC%E3%83%90%E3%83%BC%E3%83%AD%E3%83%BC%E3%83%89%E3%81%AE%E5%BB%83%E6%AD%A2

元々演算子ごとに特別な名前を持った関数を定義するスタイルだったのですが、今はテンプレート引数で演算子が分かるようになりました。

詳しい書き換えはエラーメッセージにも出てきますが、改めて一覧がまとめられていますのでこちらご覧ください。
https://dlang.org/changelog/2.100.0.html#d1_style_operators


### エラー : 非アノテーションの `asm` ブロックの非推奨期間が終了しました。

2015年5月4日の dmd 2.067.0 からずっとエラーだったのですが、メッセージが正式に改められ、機能として正式に定められたため表記されました。
元々 `@nogc` などのキーワードが `asm` ブロックに使えるようになったときからずっとエラーとなる動作であり、これで新たに困る方はいないと思います。

ちなみにエラーは以下のような感じです。

```
onlineapp.d(4): Error: `asm` statement is assumed to be `@system` - mark it with `@trusted` if it is not
```

### エラー : `delete` キーワードの非推奨期間が終了しました。

2018年3月1日の dmd 2.079.0 から非推奨で警告が出ていたものが今回エラーになりました。

消すぞ消すぞと言われてなかなか消えないので気付けば [記事にもなっていた](https://qiita.com/nak2yoshi/items/99f23047377ba68c9d9) のですが、対応以外にも理由などに触れられていてこちらが非常に詳しいです。

対応ざっくり言えば、既定で読み込まれている `object` モジュールの `destroy` 関数を使うか、`core.memory` モジュールにある `__delete` 関数を使えばOKですのでエラーに遭遇したら書き換えてください。


### エラー : インターフェイス宣言の型制約としての `scope` の非推奨期間が終了しました。

2019年7月1日の dmd 2.087.0 から非推奨で警告が出ていたものが今回エラーになりました。

たとえば以下のような記述がエラーになります。

```d
scope interface Test { }
```

なおクラスや構造体の宣言と同様、利用時に `scope` をつけた変数に入れることで同じ動作をさせることができます。

```
// ここに scope は付けられない
interface TestInterface { }
class Test : TestInterface { }

void test()
{
    // 変数宣言で付ける
    scope TestInterface obj = new Test;

    // スコープを抜けるときにデストラクタが実行される
}
```

### エラー : 型としての `this` と `super` の使用が削除されました。

2019年7月1日の dmd 2.087.0 から非推奨で警告が出ていたものが今回エラーになりました。

これは元々以下のように書ける機能です。

```d
class C
{
    shared(this) x;    // Error: Using `this` as a type is obsolete. Use `typeof(this)` instead
}

class D : C
{
    shared(super) a;   // Error: Using `super` as a type is obsolete. Use `typeof(super)` instead
    super b;           // Error: Using `super` as a type is obsolete. Use `typeof(super)` instead
}
```

このようなエラーを見たら、エラーの出ている行の `this` や `super` を `typeof` で囲めばOKとなります。

__修正後__

```d
class C
{
    shared(typeof(this)) x;
}

class D : C
{
    shared(typeof(super)) a;
    typeof(super) b;
}
```

# 関連ニュース

## GCC 12.1 (Gnu Compiler Collection) のリリース

D言語はGCCにも実装があり、GDCと呼ばれる実装が動くようになっています。

そして今回 2022/05/06 のリリースでD言語のフロントエンドが 2.100.0-rc.1 相当にアップデートされました。
旧バージョンへのバックポートや次バージョンの話もありますので興味がある方はフォーラム投稿のほうを見てみてください。

__GCC公式__

https://gcc.gnu.org/gcc-12/changes.html

__フォーラム投稿__

https://forum.dlang.org/post/qgrchukzyceflenrrmct@forum.dlang.org

## LDC 1.30.0 Beta リリース

より高度な最適化を行うLLVMをバックエンドとしたD言語のコンパイラである LDC も 2.100.0 に合わせたベータ版が公開されています。
今までは大体2週間弱遅れてのリリースとなるため、普段通りなら5月中には正式版がリリースされそうです。期待して待ちたいと思います。

__v1.30.0-beta__

https://github.com/ldc-developers/ldc/releases/tag/v1.30.0-beta1

## DConf 2022

D言語の国際カンファレンスである DConf が今年も8月に行われることとなりました。

一昨年から行われていたオンライン版とは異なり、今回はなんとオフライン版の集合型カンファレンスです。
場所はイギリスのロンドンで再規制の可能性も低く、現地では各種イベントも再開しているとのことで十分な注意の元なら実施可能と判断されたと思われます。

まだトークの内容など決まっていませんが、ゲストにスクリプト向けのプログラミング言語 Lua の開発者である Roberto Ierusalimschy 氏が招かれるとのことです。
こちら元々2020年開催予定だったDConfに登壇予定だったのですが、パンデミックにより中止してオンライン開催となってしまったため今回リベンジされるようです。

ロゴも新たに公式サイトが用意されましたので、興味のある方は以下サイトからご覧ください。

__DConf 公式サイト__

https://dconf.org/2022/

ちなみに参加費は $423.30 で、近頃の円高でざっくり130円換算するとおよそ5万5千円です。
安くはないですが、その分もちろん実りあるイベントになると期待できます。

毎年キーノートなどのトークはYouTubeの公式アカウントから配信されているので今年も楽しみに待ちたいと思います。

__YouTube公式__

https://www.youtube.com/c/TheDLanguageFoundation

# まとめ

バージョン番号が `2.100.0` という節目を迎え、非常にキリが良いことから多くの非推奨がエラーとされるなど、文字通り一区切りついたリリースかと思います。

各種コンパイラとも足並みが揃えられており、裏ではC言語との連携になる ImportC の機能強化が継続的に行われているようですが、8月のDConfに向けて勢い付いていく時期になってきたかと思います。

個人的には当面 `@mustuse` あたりで遊びたいなと思ったりしていますが、他にも機能強化がありますので、今後も利便性の向上が図られることを期待しつつ次回以降のリリースを待ちたいと思います！