[インデックス 13982] ファイルの概要
このコミットは、Go言語のテストスイートにおいて、コンパイラが生成するエラーメッセージの期待値を更新するものです。特に、Goの公式コンパイラ(gc
)とGCCベースのGoコンパイラ(gccgo
)の間でエラーメッセージの整合性を高めることを目的としています。これにより、両コンパイラが不正なコードに対して同様の、かつ期待されるエラーを報告するようにテストが調整されます。
コミット
commit 6ed800c01d0587413b9d103ea939f406e5e85efc
Author: Ian Lance Taylor <iant@golang.org>
Date: Fri Sep 28 08:30:30 2012 -0700
test: match gccgo error messages
const1.go:31:12: error: integer constant overflow
const1.go:31:12: error: integer constant overflow
const1.go:33:12: error: integer constant overflow
const1.go:33:12: error: integer constant overflow
const1.go:34:14: error: integer constant overflow
const1.go:35:17: error: integer constant overflow
const1.go:35:17: error: integer constant overflow
const1.go:35:17: error: integer constant overflow
const1.go:35:17: error: integer constant overflow
const1.go:35:17: error: integer constant overflow
const1.go:36:19: error: integer constant overflow
const1.go:37:15: error: integer constant overflow
const1.go:37:15: error: integer constant overflow
const1.go:37:24: error: integer constant overflow
const1.go:37:15: error: integer constant overflow
const1.go:37:15: error: integer constant overflow
const1.go:37:15: error: integer constant overflow
const1.go:37:24: error: integer constant overflow
const1.go:37:15: error: integer constant overflow
const1.go:38:12: error: integer constant overflow
const1.go:38:12: error: integer constant overflow
const1.go:38:12: error: integer constant overflow
const1.go:38:12: error: integer constant overflow
const1.go:41:20: error: integer constant overflow
const1.go:41:20: error: integer constant overflow
const1.go:42:20: error: integer constant overflow
const1.go:42:20: error: integer constant overflow
const1.go:44:28: error: integer constant overflow
const1.go:44:28: error: integer constant overflow
const1.go:45:14: error: integer constant overflow
const1.go:49:14: error: integer constant overflow
const1.go:50:14: error: integer constant overflow
const1.go:51:14: error: integer constant overflow
const1.go:54:23: error: integer constant overflow
const1.go:54:23: error: integer constant overflow
const1.go:54:23: error: integer constant overflow
const1.go:54:23: error: integer constant overflow
const1.go:56:14: error: integer constant overflow
const1.go:57:24: error: integer constant overflow
const1.go:57:24: error: integer constant overflow
const1.go:58:24: error: integer constant overflow
const1.go:58:24: error: integer constant overflow
const1.go:59:22: error: integer constant overflow
const1.go:59:22: error: integer constant overflow
const1.go:61:24: error: integer constant overflow
const1.go:62:20: error: division by zero
const1.go:65:19: error: floating point constant overflow
const1.go:65:19: error: floating point constant overflow
const1.go:66:28: error: floating point constant overflow
const1.go:66:28: error: floating point constant overflow
const1.go:67:19: error: floating point constant overflow
const1.go:67:19: error: floating point constant overflow
const1.go:68:19: error: division by zero
const1.go:33:14: error: integer constant overflow
const1.go:35:19: error: integer constant overflow
const1.go:42:22: error: integer constant overflow
const1.go:53:17: error: integer constant overflow
const1.go:55:14: error: integer constant overflow
const1.go:59:24: error: integer constant overflow
const1.go:69:20: error: expected integer type
const1.go:75:4: error: argument 1 has incompatible type (cannot use type int8 as type int)
const1.go:76:4: error: argument 1 has incompatible type (cannot use type int8 as type int)
const1.go:77:4: error: argument 1 has incompatible type (cannot use type uint8 as type int)
const1.go:79:4: error: argument 1 has incompatible type (cannot use type float32 as type int)
const1.go:80:4: error: argument 1 has incompatible type (cannot use type float64 as type int)
const1.go:81:4: error: floating point constant truncated to integer
const1.go:83:4: error: argument 1 has incompatible type (cannot use type float64 as type int)
const1.go:84:4: error: argument 1 has incompatible type (cannot use type string as type int)
const1.go:85:4: error: argument 1 has incompatible type (cannot use type bool as type int)
const1.go:88:7: error: const initializer cannot be nil
const2.go:14:8: error: expected ‘=’
const5.go:27:7: error: expression is not constant
const5.go:28:7: error: expression is not constant
const5.go:30:7: error: expression is not constant
const5.go:31:7: error: expression is not constant
ddd1.go:57:23: error: invalid use of ‘...’ in type conversion
ddd1.go:59:6: error: invalid use of ‘...’ in type conversion
ddd1.go:60:12: error: use of ‘[...]’ outside of array literal
ddd1.go:21:15: error: argument 1 has incompatible type
ddd1.go:22:10: error: argument 1 has incompatible type
ddd1.go:30:6: error: invalid use of ‘...’ with non-slice
ddd1.go:30:6: error: invalid use of ‘...’ with non-slice
ddd1.go:46:2: error: invalid use of %<...%> with builtin function
ddd1.go:47:2: error: invalid use of %<...%> with builtin function
ddd1.go:49:2: error: invalid use of %<...%> with builtin function
ddd1.go:50:6: error: invalid use of %<...%> with builtin function
ddd1.go:51:6: error: invalid use of %<...%> with builtin function
ddd1.go:53:6: error: invalid use of %<...%> with builtin function
ddd1.go:58:13: error: invalid use of %<...%> with builtin function
ddd1.go:20:10: error: floating point constant truncated to integer
ddd1.go:32:6: error: invalid use of ‘...’ calling non-variadic function
declbad.go:20:3: error: variables redeclared but no variable is new
declbad.go:38:3: error: variables redeclared but no variable is new
declbad.go:44:3: error: variables redeclared but no variable is new
declbad.go:51:3: error: variables redeclared but no variable is new
declbad.go:57:3: error: variables redeclared but no variable is new
declbad.go:63:3: error: variables redeclared but no variable is new
declbad.go:26:3: error: incompatible types in assignment (cannot use type float32 as type int)
declbad.go:32:3: error: incompatible types in assignment (cannot use type int as type float32)
declbad.go:44:3: error: incompatible types in assignment (different number of results)
fixedbugs/bug223.go:21:5: error: initialization expression for ‘m’ depends upon itself
fixedbugs/bug412.go:10:2: error: duplicate field name ‘x’
fixedbugs/bug413.go:11:5: error: initialization expression for ‘i’ depends upon itself
fixedbugs/bug416.go:13:1: error: method ‘X’ redeclares struct field name
fixedbugs/bug435.go:15:49: error: missing ‘)’
fixedbugs/bug435.go:15:2: error: reference to undefined name ‘bar’
fixedbugs/bug451.go:9:9: error: expected package
typeswitch3.go:39:9: error: no new variables on left side of ‘:=’
typeswitch3.go:24:2: error: impossible type switch case (type has no methods)
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6560063
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/6ed800c01d0587413b9d103ea939f406e5e85efc
元コミット内容
このコミットの元々の内容は、Go言語のテストスイートが、gccgo
コンパイラが生成するエラーメッセージと一致するように更新されたことを示しています。コミットメッセージには、const1.go
、const2.go
、const5.go
、ddd1.go
、declbad.go
、fixedbugs/bug223.go
、fixedbugs/bug412.go
、fixedbugs/bug413.go
、fixedbugs/bug416.go
、fixedbugs/bug435.go
、fixedbugs/bug451.go
、typeswitch3.go
といった複数のテストファイルで発生する具体的なエラーメッセージのリストが含まれています。これらのエラーメッセージは、gccgo
が特定の不正なGoコードに対して出力するエラーの例であり、Goの標準コンパイラ(gc
)のテストもこれらのエラーを適切に検出・報告するように調整されたことを意味します。
変更の背景
Go言語には主に2つの主要なコンパイラ実装があります。一つは公式のGoツールチェインに含まれるgc
(Go compiler)であり、もう一つはGCC(GNU Compiler Collection)の一部として開発されているgccgo
です。両コンパイラはGo言語の仕様に準拠していますが、エラーメッセージの文言や詳細度には差異が生じることがあります。
Goプロジェクトでは、異なるコンパイラ実装間での互換性と一貫性を非常に重視しています。特に、不正なコードに対するエラー報告は、開発者が問題を特定し修正するために不可欠な情報源です。もし同じ不正なコードに対してコンパイラによって全く異なるエラーメッセージが出力されると、開発者は混乱し、デバッグが困難になる可能性があります。
このコミットの背景には、gccgo
が特定のGoコードに対して出力するエラーメッセージが、gc
のテストスイートで期待されるエラーメッセージと完全に一致しないケースがあったという問題意識があります。テストスイートは、コンパイラが期待通りのエラーを報告するかどうかを検証する重要な役割を担っています。したがって、gccgo
のエラーメッセージをテストスイートに反映させることで、両コンパイラの実装がより密接に連携し、Go言語の安定性と移植性を高めることが目的とされました。
前提知識の解説
Go言語のコンパイラ (gc
と gccgo
)
gc
(Go Compiler): Go言語の公式ツールチェインに同梱されている標準のコンパイラです。Go言語の設計思想と密接に連携して開発されており、高速なコンパイルと効率的な実行バイナリの生成に特化しています。Go言語の新しい機能は通常、まずgc
に実装されます。gccgo
: GCCのフロントエンドとして実装されたGoコンパイラです。GCCの最適化バックエンドを利用できるため、特定のシナリオではgc
よりも最適化されたコードを生成する可能性があります。gccgo
はGCCのエコシステムに統合されており、他のGCCがサポートする言語との連携も可能です。
Go言語のテストにおけるエラーメッセージの検証
Go言語のテストスイートでは、コンパイラが特定のコードに対して期待されるエラーを正しく報告するかどうかを検証するために、特別なコメント構文が使用されます。
// ERROR "regexp"
: このコメントは、その行またはその周辺のコードがコンパイル時にエラーを発生させ、そのエラーメッセージが指定された正規表現(regexp
)にマッチすることを期待することを示します。例えば、// ERROR "overflow"
は、オーバーフローエラーが発生することを期待します。// GC_ERROR "regexp"
:ERROR
と同様ですが、これは特にgc
コンパイラがエラーを発生させることを期待する場合に使用されます。gccgo
のような他のコンパイラでは異なるエラーメッセージが出力されるか、あるいはエラーが発生しない可能性も考慮されます。
このコミットでは、既存のERROR
コメントの正規表現を拡張したり、GC_ERROR
に変更したりすることで、gccgo
のエラーメッセージも許容範囲に含めるように調整しています。
Go言語における一般的なコンパイル時エラー
コミットメッセージに記載されているエラーメッセージは、Go言語でよく見られるコンパイル時エラーの典型例です。
integer constant overflow
/floating point constant overflow
: 整数型や浮動小数点型の定数が、その型で表現できる最大値を超えた場合に発生します。division by zero
: 定数式でゼロ除算が行われた場合に発生します。argument 1 has incompatible type
: 関数の引数の型が、期待される型と互換性がない場合に発生します。expected integer type
: 整数型が期待される場所で、異なる型が使用された場合に発生します。expression is not constant
: 定数式が期待される場所で、定数ではない式が使用された場合に発生します。invalid use of ‘...’
: 可変長引数(variadic function)の呼び出しやスライス展開(...
演算子)の誤用に関するエラーです。variables redeclared but no variable is new
: 変数が再宣言されたが、新しい変数が導入されていない場合に発生します。Goでは、:=
演算子で変数を宣言する際、少なくとも1つの新しい変数が左辺に必要です。duplicate field name
: 構造体内でフィールド名が重複している場合に発生します。initialization loop
/depends upon itself
: 変数の初期化が循環参照になっている場合に発生します。method 'X' redeclares struct field name
: 構造体のフィールド名とメソッド名が重複している場合に発生します。missing ')'
/reference to undefined name
: 構文エラーや未定義の識別子を参照した場合に発生します。expected package
: パッケージが期待される場所で、そうではないものが指定された場合に発生します。no new variables on left side of ':='
::=
演算子で新しい変数が宣言されていない場合に発生します。
これらのエラーは、Go言語の型システム、定数評価、スコープ規則、構文解析など、コンパイラの基本的な機能に関連しています。
技術的詳細
このコミットの技術的な核心は、Goコンパイラのテストフレームワークが、異なるコンパイラ実装(特にgc
とgccgo
)からのエラーメッセージのわずかなバリエーションを許容するように適応することです。
コンパイラのエラーメッセージは、そのコンパイラの内部実装やエラー検出ロジックに強く依存します。例えば、あるコンパイラが「整数定数オーバーフロー」とだけ報告するのに対し、別のコンパイラは「整数定数オーバーフロー:値が大きすぎます」のように、より詳細な情報を含めることがあります。また、エラーの検出順序や、複数のエラーが同時に発生した場合の報告方法も異なる場合があります。
このコミットでは、主に以下の2つのアプローチでgccgo
のエラーメッセージへの対応を行っています。
-
正規表現の拡張: 既存の
// ERROR "..."
コメント内の正規表現を、|
(OR演算子)を使用して拡張しています。これにより、元のエラーメッセージとgccgo
が生成する可能性のある代替のエラーメッセージの両方を許容するようにテストが変更されます。- 例:
// ERROR "floating-point % operation"
が// ERROR "floating-point % operation|expected integer type"
に変更されることで、gccgo
が「expected integer type」というメッセージを出力した場合でもテストがパスするようになります。 - 例:
// ERROR "must be constant"
が// ERROR "must be constant|is not constant"
に変更されることで、gccgo
が「is not constant」というメッセージを出力した場合でもテストがパスするようになります。 - 例:
// ERROR "multiple-value"
が// ERROR "multiple-value|[.][.][.]"
に変更されることで、...
(可変長引数を示す)を含むエラーメッセージも許容されます。
- 例:
-
GC_ERROR
への変更: 一部のテストでは、// ERROR "..."
を// GC_ERROR "..."
に変更しています。これは、特定のエラーがgc
コンパイラに固有のものであるか、またはgccgo
では異なる振る舞いをするため、gc
のみでそのエラーを期待するようにテストのスコープを限定する意図があります。- 例:
const2.go
でのconstant multiplication overflow
やconstant shift overflow
のエラーがGC_ERROR
に変更されています。これは、これらの特定のオーバーフロー検出がgc
の内部ロジックに強く依存しており、gccgo
では異なる方法で処理される可能性があることを示唆しています。
- 例:
これらの変更は、Go言語のテストスイートがより堅牢になり、異なるコンパイラ実装間での互換性テストがより効果的に行われるようにするための重要なステップです。これにより、Go言語のコードがどのコンパイラでビルドされても、一貫したエラー報告の振る舞いが期待できるようになります。
コアとなるコードの変更箇所
このコミットでは、Go言語のテストディレクトリ(test/
)内の複数のファイルが変更されています。変更は主に、コンパイラのエラーメッセージを検証するためのコメント行に集中しています。
変更されたファイルと、その変更の概要は以下の通りです。
-
test/const1.go
:--- a/test/const1.go +++ b/test/const1.go @@ -66,7 +66,7 @@ var ( c3 float64 = float64(Big) * Big // ERROR "overflow" c4 = Big * Big // ERROR "overflow" c5 = Big / 0 // ERROR "division by zero" - c6 = 1000 % 1e3 // ERROR "floating-point % operation" + c6 = 1000 % 1e3 // ERROR "floating-point % operation|expected integer type" )
floating-point % operation
エラーに加えて、expected integer type
も許容するように正規表現が拡張されました。 -
test/const2.go
:--- a/test/const2.go +++ b/test/const2.go @@ -16,6 +16,6 @@ const ( const LargeA = 1000000000000000000 const LargeB = LargeA * LargeA * LargeA -const LargeC = LargeB * LargeB * LargeB // ERROR "constant multiplication overflow" +const LargeC = LargeB * LargeB * LargeB // GC_ERROR "constant multiplication overflow" -const AlsoLargeA = LargeA << 400 << 400 >> 400 >> 400 // ERROR "constant shift overflow" +const AlsoLargeA = LargeA << 400 << 400 >> 400 >> 400 // GC_ERROR "constant shift overflow"
ERROR
がGC_ERROR
に変更され、これらのエラーがgc
コンパイラに固有のものであることを示しています。 -
test/const5.go
:--- a/test/const5.go +++ b/test/const5.go @@ -24,10 +24,10 @@ const ( n2 = len(m[""]) n3 = len(s[10]) - n4 = len(f()) // ERROR "must be constant" - n5 = len(<-c) // ERROR "must be constant" + n4 = len(f()) // ERROR "must be constant|is not constant" + n5 = len(<-c) // ERROR "must be constant|is not constant" - n6 = cap(f()) // ERROR "must be constant" - n7 = cap(<-c) // ERROR "must be constant" + n6 = cap(f()) // ERROR "must be constant|is not constant" + n7 = cap(<-c) // ERROR "must be constant|is not constant" )
must be constant
エラーに加えて、is not constant
も許容するように正規表現が拡張されました。 -
test/ddd1.go
:--- a/test/ddd1.go +++ b/test/ddd1.go @@ -27,9 +27,9 @@ func tuple() (int, int, int) { return 1, 2, 3 } var ( _ = sum(tuple()) - _ = sum(tuple()...) // ERROR "multiple-value" + _ = sum(tuple()...) // ERROR "multiple-value|[.][.][.]" _ = sum3(tuple()) - _ = sum3(tuple()...) // ERROR "multiple-value" "not enough" + _ = sum3(tuple()...) // ERROR "multiple-value|[.][.][.]" "not enough" )
multiple-value
エラーに加えて、...
を含むエラーメッセージも許容するように正規表現が拡張されました。 -
test/declbad.go
:--- a/test/declbad.go +++ b/test/declbad.go @@ -41,8 +41,9 @@ func main() { { // multiline no new variables i := f1 - i := func() int { // ERROR "redeclared|no new|incompatible" + i := func() { // ERROR "redeclared|no new|incompatible" } + _ = i } { // single redeclaration
テストコード自体がわずかに変更され、
_ = i
が追加されましたが、エラーメッセージの正規表現自体は変更されていません。これは、テストの堅牢性を高めるための調整と考えられます。 -
test/fixedbugs/*.go
(bug223, bug412, bug413, bug416, bug435, bug451): これらのファイルでは、既存のERROR
コメントの正規表現に、|
演算子を使ってgccgo
が生成する可能性のある追加のフレーズ(例:|depends upon itself
,|duplicate field name .x.
,|redeclares struct field name
,|missing|undefined
,|expected package
)が追加されています。 -
test/typeswitch3.go
:--- a/test/typeswitch3.go +++ b/test/typeswitch3.go @@ -36,7 +36,7 @@ func main(){ } // Issue 2827. - switch _ := r.(type) { // ERROR "invalid variable name _" + switch _ := r.(type) { // ERROR "invalid variable name _|no new variables" } }
invalid variable name _
エラーに加えて、no new variables
も許容するように正規表現が拡張されました。
コアとなるコードの解説
これらの変更は、Go言語のテストスイートが、コンパイラのエラーメッセージのわずかなバリエーションに対応できるようにするためのものです。特に、gc
とgccgo
という異なるコンパイラ実装間で、同じ不正なコードに対して類似したエラーが報告されることを保証するために行われました。
-
正規表現の拡張 (
|
の使用): これは、最も一般的な変更パターンです。コンパイラAが「A」というエラーメッセージを出すのに対し、コンパイラBが「A (詳細)」や「B」というメッセージを出す場合、テストは両方のメッセージを認識できるようにする必要があります。|
演算子を使うことで、テストは複数の可能なエラーメッセージパターンを受け入れることができます。これにより、gccgo
がgc
とは異なる、しかし意味的には同等なエラーメッセージを出力した場合でも、テストが失敗することなくパスするようになります。これは、コンパイラ間のエラー報告の一貫性を高めつつ、それぞれの実装の自由度をある程度保つための実用的なアプローチです。 -
GC_ERROR
への変更: 一部のエラーがGC_ERROR
に変更されたのは、そのエラーがgc
コンパイラの特定の最適化パスや内部的な振る舞いに起因するものであり、gccgo
では異なる方法で処理されるか、あるいは全く異なるエラーとして報告される可能性があるためです。GC_ERROR
を使用することで、テストはgc
に特化したエラーを検証しつつ、gccgo
がそのエラーを報告しない場合でもテストが失敗しないようにします。これは、コンパイラ固有の振る舞いをテストするための重要な区別です。
これらの変更は、Go言語のコンパイラ開発において、異なる実装間での互換性とテストの網羅性を維持するための継続的な努力の一環です。これにより、Go言語のコードベースは、複数のコンパイラ環境でより安定して動作することが保証されます。
関連リンク
- Go言語の公式GitHubリポジトリ: https://github.com/golang/go
- Go言語のIssueトラッカー (関連するIssueがある場合): https://github.com/golang/go/issues
- Go言語のコードレビューシステム (Gerrit): https://go-review.googlesource.com/ (コミットメッセージに記載されている
https://golang.org/cl/6560063
はGerritのチェンジリストへのリンクです)
参考にした情報源リンク
- Go言語のテストに関するドキュメント (Goのソースコード内の
test
ディレクトリのREADMEや、Goの公式ドキュメント):- Goのソースコード内のテストファイルのコメント規約に関する情報
- Go言語のコンパイラ(
gc
とgccgo
)に関する情報
- GCCGoの公式ドキュメントまたは関連情報:
- Go言語の仕様書: https://go.dev/ref/spec (コンパイラが準拠すべき言語の振る舞いを定義)
- Go言語のブログや開発者向け記事 (コンパイラの内部動作やテスト戦略に関するもの)