Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 1537] ファイルの概要

このコミットは、test/bugs/bug132.go ファイルに詳細なコメントを追加するものです。このファイルは、Go言語の初期段階における、構造体内のフィールドやメソッドの命名に関するバグ、または設計上の議論をテストするために作成されたものです。追加されたコメントは、この問題に関する主要な開発者間のメールスレッドを要約したものであり、将来の参照のために議論の背景と様々な視点を記録することを目的としています。

コミット

このコミットは、Go言語の型システムにおける特定の振る舞い、特に構造体内の重複する識別子(フィールドやメソッド)の扱いに関する議論の経緯を文書化するために、既存のテストファイルにコメントを追加しました。これはコードの機能的な変更ではなく、設計上の決定やバグの解決に至るまでの思考プロセスを保存するためのものです。

GitHub上でのコミットページへのリンク

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

元コミット内容

- added comment with various viewpoints so we have whole story
once we close this

R=r
OCL=23239
CL=23239

変更の背景

このコミットの背景には、Go言語の初期開発段階における、構造体のフィールドとメソッドの命名規則、特に重複する識別子の扱いに関する設計上の議論があります。bug132.go は、obj.x のようなアクセスが曖昧になる可能性のあるケースをテストするために存在していました。このコミットは、その曖昧さや、コンパイラ(当時の6g)とGo言語仕様(spec)の間でどのように振る舞いが一致すべきか、あるいは異なるべきかについての主要な開発者(Russ Cox, Rob Pike, Robert Griesemer, Ken Thompson)間のメールスレッドを要約し、その議論の経緯をコード内に永続的に記録することを目的としています。これにより、将来的にこの問題が再浮上した際に、過去の議論の文脈を容易に理解できるようになります。

前提知識の解説

このコミットを理解するためには、Go言語の基本的な型システムと、初期の言語設計に関する知識が必要です。

  1. Go言語の構造体(Structs): 構造体は、異なる型のフィールドをまとめることができる複合データ型です。
  2. メソッド(Methods): Goでは、型に紐付けられた関数をメソッドと呼びます。レシーバ引数(func (p *T) x()p *T の部分)を持つことで、特定の型の値に対して操作を行うことができます。
  3. 識別子の解決(Identifier Resolution): プログラム内で名前(識別子)が使われたときに、それがどの変数、関数、型などを指すのかを決定するプロセスです。Goでは、スコープのルールに基づいて識別子が解決されます。
  4. Go言語仕様(Go Spec): Go言語の公式な定義であり、言語の構文、セマンティクス、標準ライブラリの振る舞いを記述しています。コンパイラは、この仕様に準拠して実装されるべきです。
  5. 6gコンパイラ: Go言語の初期のコンパイラの一つで、gcツールチェーンの一部でした。当時のGo開発では、仕様とコンパイラの実装が並行して進化しており、時には不一致が生じることもありました。
  6. スコープ(Scope): プログラム内で識別子が有効である領域を指します。Goでは、ブロック、パッケージ、ファイル、ユニバース(組み込み識別子)など、様々なスコープが存在します。構造体のフィールドやメソッドも、その構造体のスコープ内で識別子として扱われます。

この議論の核心は、「構造体のフィールドやメソッドのスコープ内で、同じ名前の識別子が複数存在することを許容するかどうか」という点にあります。特に、メソッドのオーバーロード(同じ名前で引数の異なるメソッドを定義すること)がGoでは許されていないこととの整合性も論点となっています。

技術的詳細

メールスレッドで議論されている技術的なポイントは以下の通りです。

  • Russ Coxの視点: xを参照しない限りエラーではないと主張。構造体内に複数の「pad」要素を命名できるという利点を挙げています。これは、フィールドが実際に使用されるまで、その曖名さをエラーとしないという考え方です。
  • Rob Pikeの視点: 「このプログラムが仕様に合致しているか、合致していないならどちらが間違っているのか」という根本的な問いを投げかけています。これは、言語仕様が最終的な権威であるべきだという原則に基づいています。
  • Russ Coxの再度の視点: 6gコンパイラが仕様と異なる振る舞いをしていることを認め、6gを仕様に合わせることに同意しています。これは、コンパイラの実装が仕様に準拠することの重要性を示しています。
  • Robert Griesemerの視点: 仕様がより明確であるべきだと指摘。6gが異なるシグネチャを持つ同じ名前のメソッド(例: func (p *T) x()func (p *T) x(a, b, c int))を受け入れることを問題視しています。Goの仕様では、スコープ内で識別子は一度しか宣言できないとされており、構造体のフィールドやセレクタのスコープ内で複数のxが存在することは、このルールに反すると解釈できると主張しています。プログラマの視点からは、宣言時点でエラーとすることがより自然であると考えています。
  • Ken Thompsonの視点: 宣言時か使用時かに関わらず、エラーが発生するタイミングは「小さな点」であり、自身はこれをエラーとは考えていなかったと述べています。これは、実用性と実装の簡潔さを重視する視点を示唆しています。
  • Robert Griesemerの最終的な視点: 整合性を重視し、メソッドの再宣言がエラーとなることとの不一致を指摘しています。仕様がこの点に関して「二つの異なることを言っている」か、少なくともより正確であるべきだと主張しています。特に、セレクタに関するセクション(比較的新しいセクション)がこのような宣言を許容する可能性がある一方で、メソッドの再宣言はエラーとなるという矛盾を指摘しています。

この議論は、Go言語の設計における「シンプルさ」と「厳密さ」のバランス、そして言語仕様とコンパイラ実装の間の整合性をどのように保つかという、初期の重要な課題を浮き彫りにしています。最終的に、このコミットは、この複雑な議論の経緯をコードベース内に保存し、将来の参照を容易にすることを目的としています。

コアとなるコードの変更箇所

変更は test/bugs/bug132.go ファイルに集中しており、具体的にはファイルの末尾に63行のコメントブロックが追加されています。

--- a/test/bugs/bug132.go
+++ b/test/bugs/bug132.go
@@ -15,3 +15,66 @@ Accessing obj.x for obj of type T will lead to an error so this cannot
 be used in a program, but I would argue that this should be a compile-
 tume error at the declaration point.
 */
+\n+/* Condensed e-mail thread:\n+\n+---------- Russ Cox	
+I don't think this is an error as long as you don't refer to x. I like the fact that you could name
+multiple elements in the struct "pad".
+\n+\n+---------- Rob 'Commander' Pike to Russ, me, go-dev, reviewlog2
+the real question is whether this program matches the spec and if not, which is in error.
+\n+\n+---------- Russ Cox to Rob, me, go-dev, reviewlog2
+true enough.  the spec disagrees with 6g.
+when we discussed the disambiguation
+rules for anonymous structs i thought we'd
+mentioned this issue too and decided the
+opposite, but i'm happy to make 6g agree
+with the spec.
+\n+\n+---------- Robert Griesemer to Russ, Rob, go-dev, reviewlog2
+I think the spec could perhaps be more definitive. Note that 6g also accepts:
+\n+type T struct {
+\tx int
+}\n+\n+func (p *T) x() {
+}\n+\n+func (p *T) x() {
+}\n+\n+The spec says that the scope of methods and fields is selectors of the form obj.selector. In a scope an identifier can be declared only once. I'd conclude that in the scope of fields and selectors of T, there are multiple x. But it's somewhat indirect. From a programmer's point of view making this an error seems less surprising, at least to me.
+\n+\n+---------- Ken Thompson to me, Russ, Rob, go-dev, reviewlog2
+obviously i dont think this is an error, or
+i would have made it an error. it seems like
+a small point if the error comes up at
+declaration or use.
+\n+\n+---------- Robert Griesemer to Ken, Russ, Rob, go-dev, reviewlog2
+I don't really care too much, but I think it should be consistent. The following code:
+\n+type T struct {
+\tx int;
+}\n+\n+func (p *T) x() {
+}\n+\n+func (p *T) x(a, b, c int) {
+}\n+\n+does result in an error (method redeclared). I don't quite see why this should behave any different then if both x() had the same parameter list.
+\n+PS: I agree that the spec is saying two different things here - or at least should be more precise; the section on selectors (which arguably is the newer section), would allow such a declaration. I suspect that the case below leads to an early error possibly due to some interaction with code that checks for forward declaration of functions/methods (this not having looked at 6g).
+\n+I am happy to go either way. It's a small item and we can close it once we all agree.
+*/

コアとなるコードの解説

このコミットにおける「コアとなるコードの変更」は、追加されたコメントブロックそのものです。このコメントは、Go言語の設計における重要な議論の記録として機能します。

コメントは、以下の主要な開発者間のメールスレッドを要約しています。

  • Russ Cox: 重複するフィールド名が参照されない限りエラーではないという立場。
  • Rob Pike: 言語仕様との整合性を問う。
  • Russ Cox (再): 6gコンパイラと仕様の不一致を認め、仕様に合わせる意向を示す。
  • Robert Griesemer: 仕様の明確化を求め、重複する識別子(特にメソッド)の扱いにおける6gの不整合を指摘。宣言時にエラーとすべきだと主張。
  • Ken Thompson: エラーのタイミングは重要ではないという立場。
  • Robert Griesemer (最終): メソッドの再宣言がエラーとなることとの不整合を強調し、仕様の曖昧さを指摘。

このコメントは、bug132.goがテストしようとしている問題(構造体内の重複する識別子の扱い)に対する、Go開発チーム内の様々な視点と議論のプロセスを詳細に説明しています。これにより、このテストケースが存在する理由と、関連する設計上の決定がどのように行われたかについての貴重な文脈が提供されます。これは、単なるコードの変更ではなく、プロジェクトの歴史と設計思想を文書化する重要な役割を果たしています。

関連リンク

  • Go言語の公式ウェブサイト: https://go.dev/
  • Go言語仕様: https://go.dev/ref/spec (特に「Declarations and scope」および「Selectors」のセクションが関連します)

参考にした情報源リンク

  • GitHubコミットページ: https://github.com/golang/go/commit/e1e158a90c76ff76334356a42fe4140d862edbf1
  • Go言語の初期のバグトラッカーやメーリングリストのアーカイブ(このコミットの議論の元となったメールスレッドは、当時のGo開発コミュニティのメーリングリストで交わされたものと推測されますが、具体的なリンクはコミットメッセージからは特定できませんでした。)
  • Go言語の歴史に関するドキュメントや記事(Go言語の設計思想や初期の課題について理解を深めるために参照しました。)