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

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

このコミットは、Goコンパイラ(cmd/gc)内の不要なコードを削除し、エラーメッセージを改善するものです。具体的には、src/cmd/gc/dcl.cから未使用のnewtype関数を削除し、src/cmd/gc/go.hからその宣言を削除しています。また、dcl.c内のaddmethod関数におけるエラーメッセージがより詳細になるように修正されています。

コミット

commit f18ced3fc9bdb36029d81eb73a1848959e5a84ec
Author: Russ Cox <rsc@golang.org>
Date:   Thu Jun 7 02:15:23 2012 -0400

    cmd/gc: delete dead code
    
    R=ken2
    CC=golang-dev
    https://golang.org/cl/6307050

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

https://github.com/golang/go/commit/f18ced3fc9bdb36029d81eb73a1848959e5a84ec

元コミット内容

--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -432,21 +432,6 @@ oldname(Sym *s)
 	return n;
 }
 
-/*
- * same for types
- */
-Type*
-newtype(Sym *s)
-{
-	Type *t;
-
-	t = typ(TFORW);
-	t->sym = s;
-	t->type = T;
-	return t;
-}
-
-
 /*
  * := declarations
  */
@@ -1311,7 +1296,7 @@ addmethod(Sym *sf, Type *t, int local)
 		}
 		// Should have picked off all the reasons above,
 		// but just in case, fall back to generic error.
-\t\tyyerror("invalid receiver type %T", pa);\
+\t\tyyerror("invalid receiver type %T (%lT / %lT)", pa, pa, t);\
 		return;
 	}
 
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -942,7 +942,6 @@ Node*	methodname(Node *n, Type *t);
 Node*	methodname1(Node *n, Node *t);
 Sym*	methodsym(Sym *nsym, Type *t0, int iface);
 Node*	newname(Sym *s);
-Type*	newtype(Sym *s);
 Node*	oldname(Sym *s);
 void	popdcl(void);
 void	poptodcl(void);

変更の背景

このコミットの主な目的は、Goコンパイラ(cmd/gc)のコードベースから「デッドコード(dead code)」、すなわちもはや使用されていないコードを削除することです。デッドコードの削除は、ソフトウェアの保守性を向上させ、コンパイラのバイナリサイズを削減し、コンパイル時間を短縮する上で重要なプラクティスです。未使用の関数や変数を削除することで、コードベースがよりクリーンになり、開発者がコードの意図を理解しやすくなります。

また、addmethod関数におけるエラーメッセージの改善は、コンパイラが不正なレシーバ型を検出した際に、より詳細な情報を提供することで、開発者が問題を特定しやすくなるようにするためのものです。これは、コンパイラのエラー報告の品質向上に寄与します。

前提知識の解説

このコミットを理解するためには、以下の前提知識が役立ちます。

  • Goコンパイラ(cmd/gc)の構造: Go言語の公式コンパイラは、cmd/gcというディレクトリにそのソースコードが格納されています。これはC言語で書かれており、Goプログラムを機械語に変換する役割を担っています。コンパイラは、字句解析、構文解析、型チェック、中間コード生成、最適化、コード生成といった複数のフェーズを経て動作します。
  • コンパイラのデータ構造:
    • Sym (Symbol): コンパイラ内部で識別子(変数名、関数名など)を表すために使用されるデータ構造です。シンボルテーブルに格納され、識別子の名前、型、スコープなどの情報を含みます。
    • Type: Go言語の型システムにおける型(int, string, struct, interfaceなど)を表すデータ構造です。
    • Node: 抽象構文木(AST)のノードを表すデータ構造です。Goのソースコードは、まずASTに変換され、コンパイラの各フェーズでこのASTが操作されます。
  • dcl.c: cmd/gc内のファイルの一つで、主に宣言(declaration)と型チェックに関連する処理を扱います。変数宣言、関数宣言、型宣言などの処理が含まれます。
  • go.h: cmd/gcで使用される共通のヘッダファイルで、主要なデータ構造の定義や関数のプロトタイプ宣言が含まれています。
  • デッドコード(Dead Code): プログラムの実行フローにおいて、決して到達しない、またはその結果がプログラムの動作に影響を与えないコードのことです。デッドコードは、バグの原因となったり、コードの可読性を低下させたりするため、通常は削除されます。
  • yyerror: コンパイラがエラーを報告するために使用する関数です。C言語のprintfに似たフォーマット文字列を受け取り、エラーメッセージを出力します。
  • %T%lT フォーマット指定子: yyerrorのようなコンパイラ内部のデバッグ/エラー出力関数で使用される、Goの型情報を整形して出力するためのカスタムフォーマット指定子です。%Tは基本的な型情報を、%lTはより詳細な(例えば、ポインタの指す型や構造体のフィールド情報など)型情報を出力するために使われることがあります。

技術的詳細

このコミットは、Goコンパイラの内部実装における特定の関数とエラー報告の改善に焦点を当てています。

  1. newtype関数の削除:

    • src/cmd/gc/dcl.cからnewtype(Sym *s)関数が完全に削除されました。この関数は、コメントに「same for types」とあり、TFORW(forward declaration、前方宣言)という特殊な型を持つTypeオブジェクトを生成し、与えられたシンボルsに関連付ける役割を担っていました。
    • TFORWは、型がまだ完全に定義されていないが、その存在が参照される場合に一時的に使用されるプレースホルダーのようなものです。例えば、相互参照する型や、再帰的な型定義を扱う際に用いられることがあります。
    • この関数が「デッドコード」と判断されたということは、コンパイラの進化の過程で、このTFORW型のTypeオブジェクトを生成する特定のロジックが不要になったか、あるいは別のより汎用的なメカニズムに置き換えられたことを意味します。コンパイラの開発では、コードベースの改善や新しい機能の追加に伴い、以前の設計が不要になることがよくあります。
    • src/cmd/gc/go.hからも、この関数のプロトタイプ宣言Type* newtype(Sym *s);が削除されています。ヘッダファイルからの宣言削除は、対応する実装が削除されたことの整合性を保つために必須です。
  2. addmethod関数のエラーメッセージ改善:

    • src/cmd/gc/dcl.c内のaddmethod関数は、Goのメソッド宣言を処理する際に呼び出されます。特に、レシーバ型(メソッドが紐付けられる型)が不正である場合にエラーを報告します。
    • 変更前はyyerror("invalid receiver type %T", pa);というメッセージでした。ここでpaは不正なレシーバ型を表すNodeまたはTypeオブジェクトです。
    • 変更後はyyerror("invalid receiver type %T (%lT / %lT)", pa, pa, t);となりました。これにより、エラーメッセージにpaの型情報が%Tで表示されるだけでなく、さらに詳細な型情報が%lTフォーマットで2回(patの型)追加されるようになりました。
    • この改善により、コンパイラのエラーメッセージがより診断しやすくなり、開発者が不正なレシーバ型に関する問題をデバッグする際に役立つ情報が増えます。tは、おそらくメソッドのシグネチャの一部として期待される型、または関連する別の型情報を示していると考えられます。

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

src/cmd/gc/dcl.c

 // 削除された newtype 関数
-/*
- * same for types
- */
-Type*
-newtype(Sym *s)
-{
-	Type *t;
-
-	t = typ(TFORW);
-	t->sym = s;
-	t->type = T;
-	return t;
-}

 // addmethod 関数内のエラーメッセージ変更
@@ -1311,7 +1296,7 @@ addmethod(Sym *sf, Type *t, int local)
 		}
 		// Should have picked off all the reasons above,
 		// but just in case, fall back to generic error.
-\t\tyyerror("invalid receiver type %T", pa);\
+\t\tyyerror("invalid receiver type %T (%lT / %lT)", pa, pa, t);\
 		return;
 	}

src/cmd/gc/go.h

 // newtype 関数のプロトタイプ宣言の削除
@@ -942,7 +942,6 @@ Node*	methodname(Node *n, Type *t);
 Node*	methodname1(Node *n, Node *t);
 Sym*	methodsym(Sym *nsym, Type *t0, int iface);
 Node*	newname(Sym *s);
-Type*	newtype(Sym *s); // この行が削除された
 Node*	oldname(Sym *s);
 void	popdcl(void);
 void	poptodcl(void);

コアとなるコードの解説

newtype関数の削除

削除されたnewtype関数は、以下のような構造を持っていました。

Type*
newtype(Sym *s)
{
	Type *t; // Type構造体へのポインタを宣言

	t = typ(TFORW); // TFORW(前方宣言)型の新しいTypeオブジェクトを生成
	t->sym = s;     // 生成したTypeオブジェクトにシンボルsを関連付ける
	t->type = T;    // Typeオブジェクトの内部型をTに設定(TはTypeのエイリアスか、汎用的な型を示す定数)
	return t;       // 生成したTypeオブジェクトを返す
}

この関数は、特定の目的のためにTFORW型のプレースホルダーTypeオブジェクトを作成していました。このコードが削除されたということは、コンパイラの型システムや宣言処理において、この特定の前方宣言メカニズムがもはや必要とされなくなったことを示唆しています。これは、コンパイラの内部設計がより洗練され、より汎用的な型解決メカニズムが導入された結果である可能性が高いです。

addmethod関数のエラーメッセージ変更

addmethod関数は、Go言語のメソッド定義を処理する際に、レシーバ型が有効であるかを検証します。もしレシーバ型が不正な場合、コンパイラはエラーを報告します。

変更前は、yyerror("invalid receiver type %T", pa);という形式でエラーメッセージを出力していました。ここで%Tは、Goの型情報を表示するためのカスタムフォーマット指定子です。

変更後は、yyerror("invalid receiver type %T (%lT / %lT)", pa, pa, t);となりました。 この変更のポイントは、%lTという別のフォーマット指定子が追加されたことです。

  • 最初の%Tは、pa(不正なレシーバ型)の基本的な型情報を表示します。
  • 続く(%lT / %lT)の部分では、patという2つの引数に対して%lTフォーマット指定子を使用しています。%lTは、%Tよりも詳細な型情報を出力するためにGoコンパイラ内部で定義されていることが多いです。例えば、構造体のフィールド情報、ポインタの指す型、インターフェースのメソッドセットなど、より深いレベルの型詳細を表示するのに使われます。
  • t引数は、このコンテキストでは、おそらくメソッドのシグネチャの一部として期待される型、またはレシーバ型と関連する別の型情報を示していると考えられます。これにより、エラーメッセージは「不正なレシーバ型X(詳細Y / 関連型Z)」といった形式になり、開発者はエラーの原因をより正確に特定できるようになります。

関連リンク

  • Go言語の公式リポジトリ: https://github.com/golang/go
  • Go言語のコンパイラに関するドキュメント(公式ドキュメントやGoのブログ記事など、時期によって内容は変動します)

参考にした情報源リンク

  • Go言語のソースコード(特にsrc/cmd/gcディレクトリ)
  • Go言語のコンパイラ設計に関する一般的な知識
  • Gitのコミットログと差分表示
  • (必要に応じて)Go言語のコンパイラ開発者コミュニティの議論やメーリングリストのアーカイブ(例: golang-dev)
  • Go言語の型システムに関するドキュメント