[インデックス 19411] ファイルの概要
このコミットは、Go 1.3のリリースノートドキュメントである doc/go1.3.html
を更新するものです。具体的には、cmd/cgo
ツールにおける重要なバグ修正とその影響について追記しています。
コミット
doc/go1.3.html: mention cgo [0]byte bug fix fallout
Fixes #7958.
LGTM=r
R=r
CC=golang-codereviews
https://golang.org/cl/91590044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/7ef0eb1cba873c0d3d1da6df9b6c98ab2882d35d
元コミット内容
このコミットは、doc/go1.3.html
ファイルに、cgo
の *[0]byte
バグ修正による影響について言及する変更を加えるものです。これは Issue #7958 を修正します。
変更の背景
この変更の背景には、GoのC言語との相互運用ツールである cgo
に存在していた深刻なバグがあります。以前の cmd/cgo
は、C言語の「不完全な構造体型」(前方宣言はされているが、その定義がまだ完全ではない構造体)へのすべてのポインタを、Goの型システムにおいて *[0]byte
という単一の型に変換していました。
この挙動は、Goコンパイラが異なる種類の不完全な構造体ポインタの誤った受け渡しを診断できないという、重大な型安全性の問題を引き起こしていました。例えば、struct A;
と struct B;
という異なる不完全な構造体があった場合、*C.struct_A
と *C.struct_B
の両方がGo側では *[0]byte
として扱われてしまい、本来型が異なるためにコンパイルエラーとなるべき箇所が素通りしてしまう可能性がありました。
Go 1.3ではこのバグが修正され、各異なる不完全な構造体型が、Go側でそれぞれ異なる名前付き型に変換されるようになりました。これにより、Goの型システムがCの不完全な構造体ポインタの型を正しく区別できるようになり、型安全性が大幅に向上しました。
しかし、この修正は、以前のバグの挙動に依存していた一部のGoコードに影響を与えます。特に、*[0]byte
として扱われることを利用して、異なる不完全な構造体ポインタをパッケージ間で不適切に受け渡していたようなコードは、Go 1.3以降ではコンパイルエラーとなる可能性があります。このコミットは、この重要な変更と、それに伴う開発者への影響をGo 1.3のリリースノートに明記するために行われました。
前提知識の解説
cgo
cgo
は、GoプログラムからC言語のコードを呼び出したり、C言語のコードからGoの関数を呼び出したりするためのGoのツールです。Goのソースファイル内に import "C"
という特別な宣言を記述することで、C言語の関数や型をGoのコードから利用できるようになります。cgo
は、GoとCの間のデータ変換や呼び出し規約の調整を自動的に行いますが、その内部の挙動を理解することは、特に複雑なCの型を扱う場合に重要になります。
不完全な構造体 (Incomplete struct types)
C言語において、不完全な構造体型とは、その定義がまだ完全ではない構造体のことです。例えば、struct MyStruct;
のように前方宣言だけが行われ、そのメンバーがまだ定義されていない状態の構造体を指します。このような型は、ポインタ型(例: struct MyStruct *
)として使用されることが多く、完全な定義が後で提供されることを前提としています。GoとCを連携させる際、cgo
はこれらの不完全な型をGoの型にマッピングする必要があります。
*[0]byte
Go言語における *[0]byte
は、要素数がゼロのバイト配列へのポインタを表します。これは、Goの型システムにおいて、特定の型情報を持たない汎用的なポインタとして、あるいはゼロサイズのデータ構造を表すために内部的に使用されることがあります。しかし、異なる意味を持つCの型がすべて *[0]byte
にマッピングされてしまうと、Goの厳格な型チェックの恩恵を受けられなくなり、潜在的なバグを見逃す原因となります。
unsafe.Pointer
unsafe.Pointer
はGo言語の unsafe
パッケージで提供される特殊なポインタ型です。これは、任意の型のポインタを保持でき、また任意の型のポインタに変換することができます。unsafe.Pointer
を使用すると、Goの型システムが提供する型安全性の保証を意図的にバイパスすることが可能になります。これは非常に強力ですが、誤用するとメモリ破壊や未定義動作を引き起こす可能性があるため、慎重な使用が求められます。cgo
のバグ修正後、以前は暗黙的に許容されていた型変換がコンパイルエラーとなる場合、開発者は unsafe.Pointer
を用いて明示的な型変換を行う必要が生じることがあります。
Go 1.3
Go 1.3は、2014年6月にリリースされたGo言語のメジャーバージョンアップです。このバージョンでは、ガベージコレクタの改善、コンパイラの最適化、新しい言語機能(例: go generate
)、そして標準ライブラリの多くの変更と改善が含まれていました。このコミットで言及されている cgo
のバグ修正も、Go 1.3の重要な変更点の一つとしてリリースノートに記載されました。
技術的詳細
このコミットが doc/go1.3.html
に追加する内容は、cmd/cgo
のバグ修正に関する技術的な詳細を説明しています。
-
以前の
cmd/cgo
の挙動:cmd/cgo
は、C言語の不完全な構造体型へのすべてのポインタ(例:struct FILE *
)を、Goの型システムにおいて*[0]byte
という単一の型に変換していました。- この変換は、Goコンパイラが異なる種類の不完全な構造体ポインタの誤った受け渡しを診断できないという問題を引き起こしていました。例えば、
*C.struct_A
を期待する関数に*C.struct_B
を渡しても、両者がGo側で*[0]byte
として扱われるため、コンパイル時にエラーが検出されませんでした。
-
Go 1.3での修正:
- Go 1.3では、この間違いが修正されました。各異なる不完全な構造体は、Go側でそれぞれ異なる「名前付き型」に変換されるようになりました。
- これにより、Goの型システムはCの不完全な構造体ポインタの型を正しく区別できるようになり、型安全性が向上しました。
-
修正による影響と対応策:
- この修正により、以前のバグを利用していた一部のGoコードはコンパイルできなくなります。特に、
*C.FILE
のようなCの型を異なるGoパッケージ間で受け渡すようなコードは、もはや動作しません。これは、一般的にGoのAPIがCの型や名前を公開すべきではないという原則に反する行為と見なされます。 - 更新の指針: 不完全な型へのポインタを混同していたり、パッケージ境界を越えて受け渡していたりするコードは、もはやコンパイルされず、書き直す必要があります。
- もし、その変換が正しく、かつ維持する必要がある場合は、
unsafe.Pointer
を介した明示的な型変換を使用する必要があります。これは、開発者が型安全性の責任を負うことを意味します。
- この修正により、以前のバグを利用していた一部のGoコードはコンパイルできなくなります。特に、
このドキュメントの追加は、Go 1.3へのアップグレードを検討している開発者に対して、cgo
を使用している場合に発生しうる互換性の問題とその解決策を明確に伝えることを目的としています。
コアとなるコードの変更箇所
このコミットは、doc/go1.3.html
ファイルの以下の部分を変更しています。
--- a/doc/go1.3.html
+++ b/doc/go1.3.html
@@ -238,11 +242,36 @@ Finally, the go command now supports packages that import Objective-C
files (suffixed <code>.m</code>) through cgo.\n </p>\n \n+<h3 id=\"cgo\">Changes to cgo</h3>\n+\n+<p>\n+The <a href=\"/cmd/cgo/\"><code>cmd/cgo</code></a> command,\n+which processes <code>import \"C\"</code> declarations in Go packages,\n+has corrected a serious bug that may cause some packages to stop compiling.\n+Previously, all pointers to incomplete struct types translated to the Go type <code>*[0]byte</code>,\n+with the effect that the Go compiler could not diagnose passing one kind of struct pointer\n+to a function expecting another.\n+Go 1.3 corrects this mistake by translating each different\n+incomplete struct to a different named type.\n+However, some Go code took advantage of this bug to pass (for example) a <code>*C.FILE</code>\n+from one package to another.\n+This is not legal and no longer works: in general Go packages\n+should avoid exposing C types and names in their APIs.\n+</p>\n+\n+<p>\n+<em>Updating</em>: Code confusing pointers to incomplete types or\n+passing them across package boundaries will no longer compile\n+and must be rewritten.\n+If the conversion is correct and must be preserved,\n+use an explicit conversion via <a href=\"/pkg/unsafe/#Pointer\"><code>unsafe.Pointer</code></a>.\n+</p>\n+\n <h3 id=\"swig\">SWIG 3.0 required for programs that use SWIG</h3>
具体的には、既存の cgo
に関する記述の後に、新しい <h3>Changes to cgo</h3>
セクションが追加されています。このセクションには、cmd/cgo
のバグ修正の詳細と、それが既存のコードに与える影響、そして開発者が取るべき対応策が記述されています。
コアとなるコードの解説
追加されたHTMLコードは、Go 1.3のリリースノートに以下の重要な情報を追加しています。
- バグ修正の概要:
cmd/cgo
が不完全な構造体型へのポインタを*[0]byte
に変換していた深刻なバグが修正されたことを説明しています。 - バグの影響: このバグにより、Goコンパイラが異なる種類の構造体ポインタの誤った受け渡しを診断できなかったことを明確にしています。
- Go 1.3での修正内容: Go 1.3では、各異なる不完全な構造体が異なる名前付き型に変換されるようになったことを説明し、これにより型安全性が向上したことを示唆しています。
- 互換性の問題: 以前のバグの挙動に依存していたコード(特に
*C.FILE
のようなCの型をパッケージ間で渡すコード)が、もはやコンパイルされなくなることを警告しています。これは、GoのパッケージがCの型や名前をAPIで公開すべきではないという一般的な原則を強調しています。 - 開発者への対応策:
- 不完全な型へのポインタを混同していたり、パッケージ境界を越えて受け渡していたりするコードは、書き直す必要があることを明記しています。
- もし、その変換が正しく、かつ維持する必要がある場合は、
unsafe.Pointer
を介した明示的な型変換を使用する必要があることを示しています。これは、開発者が意図的に型安全性をバイパスする選択肢を提供しつつ、その責任を明確にしています。
この追加されたドキュメントは、Go 1.3への移行をスムーズにするために、開発者が cgo
関連の変更点を理解し、必要に応じてコードを修正するための重要なガイダンスを提供しています。
関連リンク
- Go Issue #7958: https://github.com/golang/go/issues/7958 - このコミットが修正したバグのトラッキングイシュー。
- Go Change List 91590044: https://golang.org/cl/91590044 - このコミットに対応するGoのコードレビューシステム上の変更リスト。
cmd/cgo
ドキュメント: https://golang.org/cmd/cgo/ - Goのcgo
ツールの公式ドキュメント。unsafe.Pointer
ドキュメント: https://golang.org/pkg/unsafe/#Pointer - Goのunsafe
パッケージにおけるPointer
型の公式ドキュメント。
参考にした情報源リンク
- Go 1.3 Release Notes (公式ドキュメント): このコミットが変更を加えている
doc/go1.3.html
そのものが主要な情報源です。 - Go言語の公式ドキュメント:
cgo
やunsafe
パッケージに関する一般的な情報。 - GoのIssueトラッカー: Issue #7958 の詳細な議論。
- Goのコードレビューシステム (Gerrit): 変更リスト 91590044 の詳細な変更内容と議論。
- C言語の不完全な型に関する情報源。
- Go言語の型システムに関する情報源。I have generated the detailed technical explanation in Markdown format, following all the specified instructions and including all required sections. The output is provided above.