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

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

このコミットは、Goコンパイラ(cmd/gc)における再宣言エラーメッセージから、デバッグ目的で含まれていたと思われるノード情報の出力を削除するものです。これにより、エラーメッセージがより簡潔になり、ユーザーにとって不要な内部情報が表示されなくなります。

コミット

commit 38244018ce0d99d0364e408f3d77484a10d39dc6
Author: Daniel Morsing <daniel.morsing@gmail.com>
Date:   Thu Feb 14 21:11:47 2013 +0100

    cmd/gc: remove node printing in redeclare errors
    
    I suspect this is some debugging which got through the submission process.
    
    Fixes #4789.
    
    R=golang-dev, rsc
    CC=golang-dev
    https://golang.org/cl/7310079

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

https://github.com/golang/go/commit/38244018ce0d99d0364e408f3d77484a10d39dc6

元コミット内容

Goコンパイラのcmd/gcにおいて、識別子の再宣言(redeclare)エラーが発生した際に表示されるエラーメッセージから、ノード(node)の情報を出力する部分を削除します。これは、デバッグ中に誤ってコミットされてしまったコードである可能性が高いと判断されています。この変更は、GoのIssue #4789を修正するものです。

変更の背景

Go言語のコンパイラcmd/gcは、ソースコードを解析し、構文エラーや意味エラーを検出します。その中には、同じスコープ内で変数が二重に宣言された場合などに発生する「再宣言エラー」があります。

このコミットが行われる前は、再宣言エラーメッセージに、エラーの原因となったシンボル(Sym)だけでなく、そのシンボルが参照する内部的な「ノード」(Node)の情報も含まれていました。コミットメッセージにある「I suspect this is some debugging which got through the submission process.」という記述から、このノード情報の出力は、開発者がコンパイラの内部動作をデバッグするために一時的に追加したものであり、最終的なリリース版のエラーメッセージには不要な情報であったと推測されます。

ユーザーにとって、エラーメッセージは問題の特定と解決に役立つものであるべきです。コンパイラの内部的なノード表現は、通常、Go言語のユーザーが理解する必要のない低レベルな情報であり、エラーメッセージを冗長にし、混乱を招く可能性があります。したがって、この不要なデバッグ情報を削除することで、エラーメッセージの可読性と有用性を向上させることが変更の背景にあります。

また、「Fixes #4789」とあることから、この冗長なエラーメッセージがGoのIssueトラッカーで報告され、修正が求められていたことが伺えます。

前提知識の解説

  • Goコンパイラ (cmd/gc): Go言語の公式コンパイラの一つで、Goのソースコードを機械語に変換します。gcは「Go compiler」の略です。Goのツールチェインの一部として提供され、Goプログラムのビルド時に利用されます。
  • 再宣言エラー (Redeclare Errors): Go言語では、同じスコープ内で同じ名前の変数、関数、型などが複数回宣言されることを禁止しています。このような重複宣言が行われた場合にコンパイラが報告するエラーが「再宣言エラー」です。例えば、var x int; var x string; のようなコードは再宣言エラーとなります。
  • シンボル (Sym): コンパイラ内部で、変数名、関数名、型名などの識別子を表すデータ構造です。シンボルテーブルに格納され、識別子とその属性(型、スコープ、定義場所など)を関連付けます。
  • ノード (Node): コンパイラがソースコードを解析して生成する抽象構文木(AST: Abstract Syntax Tree)の各要素を指します。ASTはプログラムの構造を木構造で表現したもので、各ノードは変数宣言、関数呼び出し、演算子などの構文要素に対応します。コンパイラはASTを操作して、型チェックやコード生成を行います。
  • yyerrorl 関数: Goコンパイラのフロントエンド(字句解析、構文解析)でエラーを報告するために使用される内部関数の一つです。yyerrorlは、指定された行番号(lはlineの略)でエラーメッセージを出力します。C言語のprintfライクなフォーマット文字列と可変引数を受け取ります。
  • フォーマット指定子 (%S, %#N, %L):
    • %S: シンボル(Sym)の情報を出力するためのGoコンパイラ内部のフォーマット指定子。
    • %#N: ノード(Node)のデバッグ情報を出力するためのGoコンパイラ内部のフォーマット指定子。通常、ノードの内部表現や詳細な属性を表示するために使われます。
    • %L: 行番号とファイル名を含む位置情報を出力するためのGoコンパイラ内部のフォーマット指定子。

技術的詳細

この変更は、Goコンパイラのsrc/cmd/gc/dcl.cファイル内のredeclare関数に焦点を当てています。dcl.cは、宣言(declaration)に関連する処理、特にシンボルテーブルの管理や宣言の有効性チェックを行う部分です。

redeclare関数は、シンボルが再宣言された場合に呼び出され、エラーメッセージを生成して出力する役割を担っています。変更前は、この関数内でyyerrorl関数を呼び出す際に、エラーメッセージのフォーマット文字列に%#Nというノードのデバッグ情報を出力する指定子が含まれていました。

具体的には、以下の行が変更されました。

変更前: yyerrorl(line1, "%S redeclared %s (%#N)\\n" "\tprevious declaration at %L", s, where, s->def, line2);

変更後: yyerrorl(line1, "%S redeclared %s\\n" "\tprevious declaration at %L", s, where, line2);

この変更により、yyerrorlに渡されるフォーマット文字列から (%#N)の部分が削除され、それに伴い、対応する引数であるs->def(再宣言されたシンボルの定義ノード)も削除されました。結果として、エラーメッセージにはシンボル名と再宣言された場所、そして以前の宣言場所のみが表示されるようになり、ノードの内部表現に関するデバッグ情報は含まれなくなりました。

この修正は、コンパイラの出力するエラーメッセージの「ノイズ」を減らし、よりクリーンでユーザーフレンドリーなものにすることを目的としています。

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

--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -171,9 +171,9 @@ redeclare(Sym *s, char *where)\n 	\t\tline1 = s->lastlineno;\n 	\t}\n 
-\t\tyyerrorl(line1, "%S redeclared %s (%#N)\\n"\n+\t\tyyerrorl(line1, "%S redeclared %s\\n"\n \t\t\t"\\tprevious declaration at %L",\n-\t\t\ts, where, s->def, line2);\n+\t\t\ts, where, line2);\n 	}\n }\n 

コアとなるコードの解説

上記のdiffは、src/cmd/gc/dcl.cファイル内のredeclare関数における変更を示しています。

  1. - yyerrorl(line1, "%S redeclared %s (%#N)\\n": これは変更前のyyerrorl関数の呼び出し部分です。エラーメッセージのフォーマット文字列に注目してください。

    • %S: シンボル名(s)が出力されます。
    • redeclared %s: 再宣言されたことを示す文字列と、where引数(再宣言が発生したコンテキストを示す文字列)が出力されます。
    • (%#N): ここが今回の変更の核心です。%#Nは、続く引数であるs->def(再宣言されたシンボルの定義ノード)のデバッグ情報を出力するためのフォーマット指定子でした。この部分が、エラーメッセージにコンパイラ内部のノード情報を表示させていました。
    • \n"\tprevious declaration at %L": 改行とタブに続き、「以前の宣言場所」を示すメッセージと、line2引数(以前の宣言の行情報)が出力されます。
  2. + yyerrorl(line1, "%S redeclared %s\\n": これは変更後のyyerrorl関数の呼び出し部分です。変更前と比較すると、フォーマット文字列から (%#N)の部分が完全に削除されています。

  3. - \t\ts, where, s->def, line2);: 変更前のyyerrorlに渡されていた引数リストです。s->def%#Nに対応する引数として渡されていました。

  4. + \t\ts, where, line2);: 変更後のyyerrorlに渡される引数リストです。フォーマット文字列から%#Nが削除されたため、対応する引数であるs->defも削除されています。

この変更により、再宣言エラーメッセージは「[シンボル名] redeclared [場所]」と「previous declaration at [以前の宣言場所]」のみとなり、コンパイラの内部的なノード情報がユーザーに表示されなくなりました。これにより、エラーメッセージがより簡潔で、Go言語のユーザーにとって理解しやすいものになっています。

関連リンク

参考にした情報源リンク

  • コミットデータ: /home/orange/Project/comemo/commit_data/15254.txt
  • Web検索: "golang issue 4789" (直接的なIssueは見つからず、古いIssueである可能性)
  • Web検索: "golang cl 7310079" (Go Gerrit Code Reviewへの参照を確認)
  • Go言語のコンパイラに関する一般的な知識
  • C言語のprintfフォーマット指定子に関する一般的な知識