[インデックス 1155] ファイルの概要
このコミットは、Go言語の初期段階におけるimport
文の構文解析に関するバグを修正するものです。具体的には、import
ブロック内でパッケージにエイリアスを付けてインポートする際に、本来セミコロン(または改行)が必要な箇所でそれが省略されていてもコンパイラがエラーを報告せず、不正な構文を許容してしまっていた問題に対処しています。この修正は、新しいテストケースtest/bugs/bug125.go
の追加と、そのテストの期待される出力(test/golden.out
)の更新によって行われています。
コミット
import syntax incorrect
R=r
OCL=19457
CL=19457
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/6c5fc055c804c4b2327e23f1a03f5ffec5ddbf91
元コミット内容
commit 6c5fc055c804c4b2327e23f1a03f5ffec5ddbf91
Author: Robert Griesemer <gri@golang.org>
Date: Tue Nov 18 09:39:34 2008 -0800
import syntax incorrect
R=r
OCL=19457
CL=19457
---
test/bugs/bug125.go | 15 +++++++++++++++
test/golden.out | 7 +++++--
2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/test/bugs/bug125.go b/test/bugs/bug125.go
new file mode 100644
index 0000000000..e2be1645bc
--- /dev/null
+++ b/test/bugs/bug125.go
@@ -0,0 +1,15 @@
+// errchk $G $D/$F.go
+
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ OS "os" // should require semicolon here; this is no different from other decls
+ IO "io"
+)
+
+func main() {
+}
diff --git a/test/golden.out b/test/golden.out
index 3e113a375b..efad87433d 100644
--- a/test/golden.out
+++ b/test/golden.out
@@ -125,7 +125,7 @@ BUG: errchk: command succeeded unexpectedly: 6g bugs/bug104.go
=========== bugs/bug105.go
bugs/bug105.go:8: P: undefined
-bugs/bug105.go:8: illegal types for operand: RETURN
+bugs/bug105.go:9: illegal types for operand: RETURN
int
BUG: should compile
@@ -139,7 +139,7 @@ BUG: bug115 should compile
=========== bugs/bug117.go
bugs/bug117.go:9: undefined DOT get on PS
-bugs/bug117.go:9: illegal types for operand: RETURN
+bugs/bug117.go:10: illegal types for operand: RETURN
int
BUG: should compile
@@ -169,6 +169,9 @@ BUG: errchk: command succeeded unexpectedly: 6g bugs/bug123.go
=========== bugs/bug124.go
BUG: errchk: command succeeded unexpectedly: 6g bugs/bug124.go
+=========== bugs/bug125.go
+BUG: errchk: command succeeded unexpectedly: 6g bugs/bug125.go
+
=========== fixedbugs/bug016.go
fixedbugs/bug016.go:7: overflow converting constant to uint
変更の背景
Go言語の初期開発段階において、コンパイラの構文解析器がimport
文の特定の形式、特にパッケージにエイリアスを付けてインポートする際に、Go言語の文法規則を厳密に適用していませんでした。具体的には、以下のようなimport
ブロック内で、各インポート宣言の間にセミコロン(;
)がない場合でも、コンパイラがエラーを報告せずに受け入れてしまっていました。
import (
OS "os"
IO "io"
)
Go言語の文法では、複数の宣言が同じ行に記述される場合や、特定の文脈ではセミコロンによる区切りが必要です。通常、Goでは改行がセミコロンとして扱われるため、明示的にセミコロンを記述することは稀ですが、このケースではコンパイラが期待通りに構文エラーを検出できていませんでした。このバグにより、不正な構文のコードがコンパイルされてしまう可能性があり、言語の厳密性と一貫性を保つ上で修正が必要とされました。
前提知識の解説
Go言語のimport
文
Go言語では、外部パッケージの機能を利用するためにimport
文を使用します。import
文にはいくつかの形式があります。
- 単一インポート:
import "fmt"
- 複数インポート(グループ化):
import ( "fmt" "net/http" )
- エイリアス付きインポート: パッケージ名を変更してインポートする場合。
この場合、import myfmt "fmt"
fmt.Println
はmyfmt.Println
として呼び出されます。 - ブランクインポート: パッケージの
init
関数を実行するだけで、そのパッケージの識別子を直接使用しない場合。import _ "image/png"
- ドットインポート: パッケージの識別子を修飾なしで直接使用する場合(非推奨)。
この場合、import . "fmt"
fmt.Println
はPrintln
として呼び出せます。
Go言語におけるセミコロンの扱い
Go言語の文法では、C言語やJavaのような言語とは異なり、ほとんどの文の終わりに明示的にセミコロンを記述する必要はありません。これは、Goのコンパイラが改行を自動的にセミコロンとして解釈する「自動セミコロン挿入(Automatic Semicolon Insertion: ASI)」ルールを持っているためです。
しかし、ASIルールには例外があります。例えば、複数の文を同じ行に記述する場合や、for
ループの初期化、条件、後処理の各セクションなど、特定の文脈では明示的なセミコロンが必要です。また、import
ブロック内でのエイリアス付きインポートのように、複数の宣言が連続する場合に、コンパイラが正しく区切りを認識できないケースも存在しました。
このコミットが修正しようとしているのは、まさにこのASIルールが正しく適用されていなかった、あるいは構文解析器が特定のimport
文の構造を誤って解釈していたケースです。
技術的詳細
このコミットは、Goコンパイラの構文解析器(パーサー)がimport
ブロック内のエイリアス付きインポート宣言を処理する際のロジックの不備を修正しています。
Go言語の文法仕様では、import
ブロック内の各インポートパスは、改行またはセミコロンによって区切られる必要があります。例えば、以下の形式は有効です。
import (
OS "os" // 改行で区切られる
IO "io"
)
しかし、このコミット以前のコンパイラは、エイリアス付きインポートが連続する場合に、たとえ改行があっても、そのエイリアス部分の解析が不完全であったため、本来エラーとすべき構文を誤って受け入れてしまっていました。
test/bugs/bug125.go
のコメント// should require semicolon here; this is no different from other decls
が示唆するように、この問題はimport
宣言が他の一般的な宣言(変数宣言など)と同様に扱われるべきであるにもかかわらず、エイリアス付きインポートの特定のケースでその一貫性が保たれていなかったことに起因します。
このコミットは、コンパイラがimport ( ... )
ブロック内でエイリアス付きインポートを解析する際に、各インポート宣言の区切りをより厳密にチェックするように変更を加えたと考えられます。これにより、OS "os"
の後に続くIO "io"
が、前の宣言と正しく区切られていない場合に、コンパイラが構文エラーを報告するようになります。
test/golden.out
の変更は、この修正が正しく機能していることを確認するためのものです。test/bugs/bug125.go
は、このバグを再現するためのテストケースであり、このテストがコンパイル時にエラーを発生させることを期待しています。コミット前の状態では、このテストは「予期せず成功」していましたが、修正後は期待通りにエラーを発生させるようになります。
コアとなるコードの変更箇所
このコミットで変更されたコアとなるコードは、Go言語のコンパイラそのものではなく、そのコンパイラの動作を検証するためのテストファイルです。
-
test/bugs/bug125.go
(新規追加): このファイルは、import
文の構文解析バグを再現するための新しいテストケースです。package main import ( OS "os" // should require semicolon here; this is no different from other decls IO "io" ) func main() { }
このコードは、
import
ブロック内でOS "os"
とIO "io"
という2つのエイリアス付きインポート宣言が連続しています。コメントにあるように、この形式は本来セミコロン(または改行による適切な区切り)が必要であり、それがなければ構文エラーとなるべきです。 -
test/golden.out
(変更): このファイルは、Goコンパイラのテストスイートにおける期待されるエラー出力やテスト結果を記録する「ゴールデンファイル」です。 このコミットでは、test/golden.out
にbugs/bug125.go
に関する新しいエントリが追加されています。=========== bugs/bug125.go BUG: errchk: command succeeded unexpectedly: 6g bugs/bug125.go
この行は、
6g bugs/bug125.go
(当時のGoコンパイラコマンド)を実行した際に、errchk
ツールが「予期せず成功した」ことを示しています。これは、bug125.go
が本来エラーを出すべきなのに、コミット前のコンパイラがエラーを出さずにコンパイルを成功させてしまっていた、というバグの状態を記録しています。このgolden.out
の更新は、コンパイラの修正が適用された後、このテストが期待通りにエラーを出すようになったことを検証するために使用されます。
コアとなるコードの解説
test/bugs/bug125.go
は、Goコンパイラの構文解析器がimport
文のエイリアス付き宣言を正しく処理しているかを検証するためのものです。
このテストファイルは、// errchk $G $D/$F.go
という特別なコメントで始まっています。これは、Goのテストフレームワークがこのファイルをコンパイルし、その結果がエラーになることを期待していることを示します。もしエラーにならなければ、それはバグ(BUG: errchk: command succeeded unexpectedly
)として報告されます。
問題の核心は、import
ブロック内の以下の部分です。
import (
OS "os" // should require semicolon here; this is no different from other decls
IO "io"
)
Go言語の文法では、import
ブロック内の各インポート宣言は、改行またはセミコロンによって区切られる必要があります。エイリアス付きインポートOS "os"
の後に改行がありますが、当時のコンパイラはこの特定のケースで、エイリアスと次のインポートパスの間の区切りを正しく認識できていなかったと考えられます。
このコミットが行われる前は、このbug125.go
はコンパイルが成功してしまっていました。しかし、Go言語の設計思想からすると、これは不正な構文であり、コンパイラはエラーを報告すべきでした。
このコミットの修正(コンパイラ内部の構文解析ロジックの変更)により、bug125.go
は期待通りにコンパイルエラーを発生させるようになりました。test/golden.out
の更新は、この新しい振る舞い(エラーの発生)が正しいものであることをテストスイートに伝える役割を果たしています。
つまり、このコミットは、Go言語の文法規則に対するコンパイラの厳密性を向上させ、より堅牢な言語処理系を構築するための一歩であったと言えます。
関連リンク
- Go言語の公式ドキュメント: https://go.dev/doc/
- Go言語の仕様: https://go.dev/ref/spec (特に "Declarations and scope" や "Import declarations" のセクション)
参考にした情報源リンク
- コミット情報:
/home/orange/Project/comemo/commit_data/1155.txt
- GitHub上のコミットページ: https://github.com/golang/go/commit/6c5fc055c804c4b2327e23f1a03f5ffec5ddbf91
- Go言語の自動セミコロン挿入に関する一般的な情報 (Go言語の仕様や関連ブログ記事)