[インデックス 14548] ファイルの概要
このコミットは、Go言語におけるgoステートメントおよびdeferステートメントの引数に関する特定の構文エラーを捕捉するためのテストケースを追加するものです。具体的には、これらのステートメントに渡される関数呼び出しが括弧で囲まれている場合にコンパイラがエラーを正しく報告することを確認します。これはGo言語の仕様に準拠するための重要な修正であり、コンパイラの堅牢性を高めるものです。
コミット
commit 8990dc8ca09e9255ba447b9d2d361f8e9954d3e9
Author: Ian Lance Taylor <iant@golang.org>
Date: Mon Dec 3 18:49:14 2012 -0800
test: add test for issue 4468 (go/defer expr may not be parenthesized)
R=gri
CC=golang-dev
https://golang.org/cl/6870053
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/8990dc8ca09e9255ba447b9d2d361f8e9954d3e9
元コミット内容
test: add test for issue 4468 (go/defer expr may not be parenthesized)
R=gri
CC=golang-dev
https://golang.org/cl/6870053
変更の背景
このコミットは、Go言語のIssue 4468に対応するために行われました。Issue 4468は、goステートメントやdeferステートメントに渡される関数呼び出しが、不必要に括弧で囲まれている場合に、Goコンパイラが適切なエラーメッセージを生成しないというバグを指摘していました。
Go言語の仕様では、goステートメントとdeferステートメントの後に続くのは「関数呼び出し (FunctionCall)」でなければなりません。しかし、(F())のように括弧で囲まれた式は、Goの構文解析器にとっては「式 (Expression)」として扱われ、直接的な「関数呼び出し」とは見なされません。このため、コンパイラはこのような構文を不正として検出し、適切なエラーメッセージを出すべきでした。
このコミットは、この特定の構文エラーを捕捉し、開発者に対して「must be function call」(関数呼び出しでなければならない)という明確なエラーメッセージを提示するためのテストケースを追加することで、コンパイラの挙動を改善し、よりユーザーフレンドリーなエラー報告を実現することを目的としています。
前提知識の解説
goステートメント: Go言語におけるゴルーチン(軽量スレッド)の起動に使用されます。go 関数呼び出しという形式で記述され、指定された関数を新しいゴルーチンとして並行実行します。deferステートメント: Go言語における遅延実行のメカニズムです。defer 関数呼び出しという形式で記述され、現在の関数がリターンする直前に、指定された関数呼び出しを遅延実行します。これはリソースの解放(ファイルのクローズ、ロックの解除など)によく使用されます。- Go言語の構文解析: Goコンパイラは、ソースコードを解析して抽象構文木(AST)を構築します。この過程で、コードが言語仕様に準拠しているかどうかがチェックされます。
goやdeferの後に続く要素が「関数呼び出し」であるか「式」であるかは、構文解析の段階で区別されます。 - エラーチェック(
errorcheck): Goのテストフレームワークの一部で、特定のコード行がコンパイルエラーを生成することを期待する場合に使用されるディレクティブです。テストファイルに// errorcheckと記述し、エラーを期待する行に// ERROR "エラーメッセージの一部"とコメントを付加することで、コンパイラが期待通りのエラーを出すか検証できます。
技術的詳細
Go言語の仕様では、GoStmt(goステートメント)とDeferStmt(deferステートメント)の構文は以下のように定義されています(簡略化)。
GoStmt = "go" Expression
DeferStmt = "defer" Expression
ここでいうExpressionは、さらにFunctionCall(関数呼び出し)を含む様々な種類の式を指します。しかし、goとdeferの文脈では、このExpressionは具体的にFunctionCallの形式でなければならないという制約があります。
例えば、F()はFunctionCallです。しかし、(F())は、F()というFunctionCallの結果を括弧で囲んだExpressionであり、直接的なFunctionCallとは見なされません。Goコンパイラは、goやdeferの後に続く式が、単なるExpressionではなく、特定のFunctionCallの構造を持っていることを期待します。
このコミットが追加するテストケースは、この構文上の制約を検証します。コンパイラは、go (F())やdefer (F())のようなコードに対して、"must be function call"というエラーメッセージを生成するように実装されています。これは、コンパイラが構文解析の段階で、goやdeferの引数が期待されるFunctionCallの形式ではないことを検出し、開発者にその旨を伝えるためのものです。
この修正は、コンパイラがGo言語の厳密な構文規則を適用し、開発者が意図しない、あるいは無効なコードを記述した場合に早期にフィードバックを提供できるようにするために重要です。
コアとなるコードの変更箇所
このコミットでは、test/fixedbugs/issue4468.goという新しいテストファイルが追加されています。
--- /dev/null
+++ b/test/fixedbugs/issue4468.go
@@ -0,0 +1,14 @@
+// errorcheck
+
+// Copyright 2012 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.
+
+// Issue 4468: go/defer calls may not be parenthesized.
+
+package p
+
+func F() {
+ go (F()) // ERROR "must be function call"
+ defer (F()) // ERROR "must be function call"
+}
コアとなるコードの解説
追加されたtest/fixedbugs/issue4468.goファイルは、Goコンパイラのerrorcheckテストスイートの一部です。
// errorcheck: このコメントは、このファイルがコンパイルエラーをチェックするためのテストであることを示します。package p: テスト用のパッケージを定義します。func F() {}: テスト内で呼び出されるシンプルな関数Fを定義します。この関数の具体的な実装は重要ではありません。go (F()) // ERROR "must be function call":go (F()): ここがテストの核心です。goステートメントの引数として、関数呼び出しF()を括弧で囲んだ(F())が渡されています。// ERROR "must be function call": このコメントは、この行がコンパイル時に「must be function call」というエラーメッセージを生成することを期待していることを示します。コンパイラがこのエラーを生成すれば、テストは成功します。
defer (F()) // ERROR "must be function call":defer (F()): 同様に、deferステートメントの引数として(F())が渡されています。// ERROR "must be function call": この行も同様に、「must be function call」というエラーメッセージを期待しています。
このテストファイルは、Goコンパイラがgoおよびdeferステートメントの引数として、括弧で囲まれた関数呼び出し(これは式として扱われる)を正しく拒否し、適切なエラーメッセージを出すことを保証します。これにより、Go言語の構文規則が厳密に適用され、開発者がより正確なコードを書くよう促されます。
関連リンク
- Go Issue 4468: https://github.com/golang/go/issues/4468 (このコミットの直接の背景となるIssue)
- Go Code Review CL 6870053: https://golang.org/cl/6870053 (このコミットに対応するGoのコードレビューシステム上の変更リスト)
参考にした情報源リンク
- Go言語の公式ドキュメント(
goステートメントとdeferステートメントの仕様に関する記述) - Go言語のIssueトラッカー(Issue 4468の詳細)
- Go言語のソースコード(
go/parserやgo/typesパッケージにおける構文解析と型チェックの挙動) - Go言語のテストフレームワークに関するドキュメント(
errorcheckディレクティブの使用方法)