[インデックス 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
ディレクティブの使用方法)