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

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

このコミットは、Go言語のテストスイートにおけるエラーメッセージのマッチングロジックを更新するものです。具体的には、gccgoコンパイラが出力するエラーメッセージとの互換性を確保するために、test/fixedbugs/issue4510.dir/f1.goテストファイル内の期待されるエラーパターンを修正しています。これにより、異なるGoコンパイラ(gcとgccgo)間でエラーメッセージの表現が異なる場合でも、テストが正しくパスするようになります。

コミット

コミットハッシュ: 5ddc6bd84d44639f7775abf2ba9606b684dc8f53 Author: Ian Lance Taylor iant@golang.org Date: Thu Dec 12 17:18:37 2013 -0800

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

https://github.com/golang/go/commit/5ddc6bd84d44639f7775abf2ba9606b684dc8f53

元コミット内容

test: match gccgo error messages

fixedbugs/issue4510.dir/f2.go:7: error: 'fmt' defined as both imported name and global name
f1.go:7: note: 'fmt' imported here

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/41530044

変更の背景

Go言語には、公式コンパイラであるgc(Go Compiler)と、GCC(GNU Compiler Collection)をバックエンドとするgccgoという、主に2つの主要なコンパイラ実装が存在します。これら2つのコンパイラは、Go言語の仕様に準拠してコードをコンパイルしますが、エラーメッセージの出力形式や文言には細かな違いが生じることがあります。

このコミットの背景にあるのは、issue4510に関連するテストケースにおいて、gcgccgoの間でエラーメッセージの表現が異なっていた問題です。具体的には、fmtという名前がインポートされた名前とグローバルな名前の両方として定義されている場合に発生するエラーについて、gccgo'fmt' defined as both imported name and global nameというメッセージを出力し、gcfmt redeclaredというメッセージを出力していました。

Goのテストスイートでは、特定の行に特定のERRORコメントを記述することで、その行で期待されるエラーメッセージを正規表現でマッチングさせることができます。しかし、コンパイラによってエラーメッセージが異なる場合、一方のコンパイラではテストがパスしても、もう一方では失敗するという問題が発生します。

このコミットは、gccgoのエラーメッセージにも対応できるように、テストファイル内のERRORコメントを修正し、両方のコンパイラでテストが正しく動作するようにすることを目的としています。これにより、Go言語のテストスイートの堅牢性とコンパイラ間の互換性テストの信頼性が向上します。

前提知識の解説

Go言語のパッケージとインポート

Go言語では、コードは「パッケージ」という単位で整理されます。パッケージは、関連する機能や型、変数をまとめたもので、他のパッケージから利用することができます。他のパッケージの機能を利用するには、importキーワードを使ってそのパッケージをインポートする必要があります。

例: import "fmt" は、標準ライブラリのfmtパッケージをインポートしています。fmtパッケージは、フォーマットされたI/O(入出力)機能を提供し、fmt.Printfなどの関数が含まれます。

名前空間と名前の衝突

プログラミング言語において、「名前空間」は、識別子(変数名、関数名、型名など)が定義されるスコープを指します。異なる名前空間では同じ名前の識別子を定義できますが、同じ名前空間内で同じ名前の識別子を複数定義しようとすると、「名前の衝突(name collision)」が発生し、コンパイルエラーとなります。

このコミットで扱われている問題は、fmtという名前が、インポートされたパッケージ名としても、また別のグローバルな識別子としても定義されようとしたために発生する名前の衝突です。Go言語の仕様では、このような名前の衝突は許可されていません。

Goコンパイラ (gcとgccgo)

  • gc (Go Compiler): Go言語の公式かつ主要なコンパイラです。Go言語のソースコードを直接機械語にコンパイルします。Go言語の開発チームによってメンテナンスされており、Go言語の最新の機能や最適化が最も早く反映されます。
  • gccgo: GCC(GNU Compiler Collection)のフロントエンドとしてGo言語をサポートするコンパイラです。Go言語のソースコードをGCCの中間表現に変換し、その後GCCのバックエンドが機械語にコンパイルします。gccgoは、GCCがサポートする多様なアーキテクチャや最適化を利用できるという利点がありますが、gcと比較してGo言語の最新機能への対応が遅れることや、エラーメッセージの形式が異なることがあります。

GoテストにおけるERRORコメント

Go言語のテストスイートでは、特定のコンパイルエラーや実行時エラーを期待するテストケースを作成する際に、ソースコードの該当行に特別なコメントを記述する慣習があります。このコメントは通常、// ERROR "正規表現"の形式を取ります。コンパイラがこの行で指定された正規表現にマッチするエラーメッセージを出力した場合、テストは成功とみなされます。マッチしない場合はテストが失敗します。

このメカニズムは、コンパイラが特定の不正なコードに対して正しいエラーを報告するかどうかを検証するために非常に重要です。しかし、前述のように、異なるコンパイラが同じエラーに対して異なるメッセージを出力する場合、このERRORコメントを調整する必要があります。

技術的詳細

このコミットが修正しているのは、test/fixedbugs/issue4510.dir/f1.goというテストファイル内のERRORコメントです。このテストは、fmtという名前がインポートされたパッケージ名と、グローバルスコープで定義された別のエンティティ(この場合はvar _ = fmt.Printfという行でfmtが参照されているが、実際にはfmtという名前が二重に定義される状況を意図している)の両方として扱われることによる名前の衝突エラーを検出することを目的としています。

元のf1.goの該当行は以下のようになっていました。

import "fmt" // ERROR "fmt redeclared"

このERRORコメントは、gcコンパイラがfmt redeclaredというエラーメッセージを出力することを期待していました。しかし、gccgoコンパイラは、同じ状況でより詳細なエラーメッセージを出力します。

'fmt' defined as both imported name and global name

この違いにより、gccgoでテストを実行すると、期待されるエラーメッセージと実際のエラーメッセージが一致しないため、テストが失敗していました。

このコミットでは、ERRORコメントの正規表現を修正し、gcgccgoの両方のエラーメッセージにマッチするように変更しています。具体的には、正規表現にパイプ|演算子を使用して、複数のパターンをOR条件でマッチングさせています。

変更後のERRORコメントは以下の通りです。

import "fmt" // ERROR "fmt redeclared|imported"

この正規表現"fmt redeclared|imported"は、以下のいずれかの文字列にマッチします。

  • fmt redeclared (gcコンパイラのエラーメッセージ)
  • imported (gccgoコンパイラのエラーメッセージの一部、またはそのエラーメッセージ全体をカバーするより一般的なパターン)

これにより、gcfmt redeclaredを出力しても、gccgo'fmt' defined as both imported name and global nameを出力しても、テストは期待通りにパスするようになります。この修正は、Go言語のテストスイートが複数のコンパイラ実装に対して堅牢であることを保証するための、一般的なアプローチの一つです。

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

--- a/test/fixedbugs/issue4510.dir/f1.go
+++ b/test/fixedbugs/issue4510.dir/f1.go
@@ -4,6 +4,6 @@
 
 package p
 
-import "fmt" // ERROR "fmt redeclared"
+import "fmt" // ERROR "fmt redeclared|imported"
 
 var _ = fmt.Printf

コアとなるコードの解説

変更はtest/fixedbugs/issue4510.dir/f1.goファイルの1行のみです。

  • - import "fmt" // ERROR "fmt redeclared": 変更前の行です。この行はfmtパッケージをインポートしており、その直後に// ERROR "fmt redeclared"というコメントが付いています。これは、このimport文が原因でfmt redeclaredというコンパイルエラーが発生することをテストが期待していることを示しています。
  • + import "fmt" // ERROR "fmt redeclared|imported": 変更後の行です。ERRORコメント内の正規表現が"fmt redeclared"から"fmt redeclared|imported"に変更されています。

この変更の意図は、gcコンパイラが生成するエラーメッセージ(fmt redeclared)と、gccgoコンパイラが生成するエラーメッセージ('fmt' defined as both imported name and global name)の両方に対応することです。

正規表現"fmt redeclared|imported"は、以下のいずれかのパターンにマッチします。

  1. 文字列"fmt redeclared"に完全に一致する場合。
  2. 文字列"imported"を含む場合。

gccgoのエラーメッセージ'fmt' defined as both imported name and global nameは、importedという単語を含んでいるため、この新しい正規表現にマッチします。これにより、gcgccgoの両方のコンパイラでこのテストが正しくパスするようになり、コンパイラ間のエラーメッセージの差異を吸収しています。

関連リンク

参考にした情報源リンク