Go 1.18 で追加される `any` は `interface{}` のエイリアス

先日、次の Issue を教えてもらって「any って type parameters 専用じゃなかったの？」と驚いたので調べてみました。

https://github.com/golang/go/issues/49884

結論から書くと Go 1.18 で追加される `any` は `interface{}` のエイリアスとして事前定義された識別子なのでどこでも使えます。
最新の仕様 [^1] にも次のように記載されています。

> For convenience, the predeclared type any is an alias for the empty interface.

[^1]: https://tip.golang.org/ref/spec#Interface_types

## 型制約のための any (2021 年 1 月 12 日～)

https://go.dev/blog/generics-proposal

https://github.com/golang/go/issues/43651

Go でジェネリクスをサポートするための仕様変更は 2021 年 1 月 12 日に提案されました。
(実際にはそれ以前に Go2 としての提案やデザインドラフトが公開されています)

この時点での `any` はすべての型を受け付ける型制約 (type constraint) です。

> The new predeclared name any is a type constraint that permits any type.

`interface{}` は結果的にすべての型を表しているだけなので、より明確な意味を持つ識別子として `any` が定義されたようです。
同時に型制約において `interface{}` と `any` は交換可能 (どちらを使っても同じ) であるとされています。

また、 proposal ドキュメント [^2] では事前定義された識別子としての `any` を型制約以外では使えないものとして定義しています。

> It will not be valid to use any as anything other than a type constraint.

この proposal はジェネリクスサポートに焦点を絞っているため `any` を他の場所でも使えるようにするかどうかについては別に議論する必要があるというのがその理由です。

[^2]: https://github.com/golang/proposal/blob/135750a71111d228b1b5c552b20eacb227a663be/design/43651-type-parameters.md#the-any-constraint

## 型制約以外でも使えるように (2021 年 9 月 23 日～)

https://github.com/golang/go/issues/33232

`any` を型制約以外の場所でも使えるようにする変更は Go2 としての提案時点で行われていました。
賛成意見も反対意見もあったようですがジェネリクスとともに導入されることが 2021 年 9 月 23 日に決まりました。 [^3]
導入の理由については次のコメントで説明されています。

https://github.com/golang/go/issues/33232#issuecomment-915333205

[^3]: https://github.com/golang/go/issues/33232#issuecomment-925303192

## 関連する修正

https://github.com/golang/go/commit/1e5774889212bdaff5d061b2a45cd0093a291b44

`any` を型制約以外の場所でも使えるようにする修正です。

https://github.com/golang/go/commit/f6647f2e3bc0b803a67c97a7d5d8733cefbd5d5b

Go 仕様に `any` についての説明が追加されました。

https://github.com/golang/go/commit/3d7cb23e3d5e7880d582f1b0300064bd1138f3ee

https://github.com/golang/go/commit/1d004fa2015d128acf6302fc74b95f6a36c35680

ジェネリクスが有効な場合は runtime のコンパイル時に事前定義された識別子として `any` を出力する修正です。

https://github.com/golang/go/commit/b31dda8a2ad833ea5ec3c807119372b27cc0e782

事前定義された識別子である `any` を `interface{}` のエイリアスとして処理するための修正です。

https://github.com/golang/go/commit/098599003ba78225152d22984f82f78892221dad

`builtin` の godoc [^4] に `any` と `comparable` を追加する修正です。
ドキュメントには `any` について次のように記載されています。

> any is an alias for interface{} and is equivalent to interface{} in all ways.

なお `comparable` は `any` と異なり型制約でしか使用できません。

> comparable is an interface that is implemented by all comparable types (booleans, numbers, strings, pointers, channels, interfaces, arrays of comparable types, structs whose fields are all comparable types). The comparable interface may only be used as a type parameter constraint, not as the type of a variable.

[^4]: https://pkg.go.dev/builtin@master

## 既存コードへの影響はないのか？

あくまでも事前定義された識別子であり、予約語ではないため既存コードへの影響はないようです。
例えば `type any = interface{}` という定義を自分で行っていたり、 `any` という変数を使用していてもそれは事前定義された `any` をシャドウイングするだけとのことです。 [^5] [^6]

[^5]: https://github.com/golang/go/issues/33232#issuecomment-925202264
[^6]: https://github.com/golang/go/issues/33232#issuecomment-925205036

とはいえ Linter に怒られて CI が失敗するとかはあるかもしれません。

## any の使い方

(2021 年 12 月 18 日追記)

`any` はどのように使えばいいのか、どういった場合に使うべきかについては [syumai さんによる 12 日目の記事](https://zenn.dev/syumai/articles/c6q5un1j0msim0aj0ca0) で解説されていますので、そちらをご覧ください。

https://zenn.dev/syumai/articles/c6q5un1j0msim0aj0ca0