[インデックス 1821] ファイルの概要
このコミットは、Go言語の公式仕様書である doc/go_spec.html
ファイルに対する変更です。このファイルは、Go言語の設計とセマンティクスを定義する中心的なドキュメントであり、言語の挙動に関するあらゆる側面が記述されています。この特定の変更は、Go言語の型システム、特にシフト演算における型の扱いに関する記述の明確化を目的としています。
コミット
- コミットハッシュ:
e20834092f1887149391c9eda84547f4b04ad2e0
- 作者: Rob Pike (
r@golang.org
) - コミット日時: 2009年3月12日 木曜日 18:40:07 -0700
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/e20834092f1887149391c9eda84547f4b04ad2e0
元コミット内容
weasel words about types in shift expressions suggested by rsc
R=rsc
OCL=26220
CL=26220
変更の背景
このコミットは、Go言語の初期開発段階において、言語仕様の記述をより正確かつ曖昧さなくするために行われました。コミットメッセージにある「weasel words」という表現は、特定の記述が不明瞭であったり、誤解を招く可能性があったりしたため、より厳密な表現に修正されたことを示唆しています。「rsc」とは、Go言語の主要な設計者の一人であるRuss Cox氏を指しており、彼からの提案に基づいてこの修正が行われたことがわかります。
具体的には、Go言語における二項演算、特にシフト演算(<<
, >>
)におけるオペランドの型変換ルールに関する記述が対象となりました。Go言語では、型付けされていない定数(「理想数」と呼ばれる)が、型付けされた変数との演算においてどのように型変換されるかというルールが存在します。このコミットは、そのルールがシフト演算には適用されないことを明確にするために、仕様書に例外を追加しました。
前提知識の解説
Go言語の型システムと「理想数」(Untyped Constants)
Go言語は静的型付け言語であり、すべての変数には型があります。しかし、数値リテラル(例: 10
, 3.14
, 1e6
)や一部の定数は、初期段階では特定の型を持たない「型付けされていない定数(untyped constants)」として扱われます。これらはGo言語の仕様では「理想数(ideal numbers)」とも呼ばれます。
理想数は、その値が表現できる限り、任意の精度と範囲を持つことができます。例えば、10
という定数は、int
, int8
, int64
, float32
, float64
など、様々な数値型に適合できます。理想数が型付けされた変数と組み合わされて演算される場合、その理想数は自動的に変数の型に変換されます。この柔軟性により、Go言語では数値リテラルをより自然に扱うことができます。
例:
var i int = 10 // 10 は int 型に変換される
var f float64 = 3.14 // 3.14 は float64 型に変換される
Go言語のシフト演算
Go言語におけるシフト演算子には、左シフト(<<
)と右シフト(>>
)があります。これらの演算子は、数値のビットを左右に移動させるために使用されます。
x << y
:x
のビットをy
ビットだけ左にシフトします。これはx * 2^y
と同等です。x >> y
:x
のビットをy
ビットだけ右にシフトします。これはx / 2^y
と同等です(整数除算)。
シフト演算のオペランドには特定の制約があります。左オペランド(x
)は整数型である必要があり、右オペランド(y
)は符号なし整数型であるか、型付けされていない定数である必要があります。また、右オペランドはシフト量を表すため、非負の値でなければなりません。
二項演算における型変換の一般ルール
Go言語の二項演算(加算、減算、乗算、除算など)では、両方のオペランドが同じ型である必要があります。もし片方のオペランドが型付けされた数値型で、もう片方が理想数である場合、理想数は型付けされたオペランドの型に変換されます。これが、Go言語が型付けされていない定数を柔軟に扱える理由です。
例:
var a int = 5
var b = 10 // b は理想数
var c = a + b // b (10) は int 型に変換され、c も int 型になる
技術的詳細
このコミットは、Go言語仕様の「二項演算におけるオペランドの型」に関するセクションに修正を加えています。修正前の記述は、二項演算において片方のオペランドが数値型で、もう片方が理想数である場合、理想数が型付けされたオペランドの型に変換されるという一般的なルールを述べていました。
しかし、このルールはシフト演算にはそのまま適用できないという重要な例外が存在します。シフト演算の右オペランド(シフト量)は、その値がシフトされる左オペランドの型に影響を与えることはありません。シフト量は常に符号なし整数として扱われるか、または型付けされていない定数として扱われ、その値が左オペランドの型に「変換される」という概念は適用されません。例えば、1 << 3.0
のようなコードは、3.0
が int
に変換されるのではなく、コンパイルエラーになります。シフト量は整数でなければならないためです。
このコミットは、この重要な例外を明示するために、既存のルールに「Except in shift expressions,」(シフト式を除いて、)という句を追加しました。これにより、Go言語の仕様がより正確になり、シフト演算における型変換の挙動に関する曖昧さが解消されました。
この変更は、Go言語の設計思想、特に「明示的であること」と「曖昧さを排除すること」を反映しています。言語の初期段階でこのような細かな仕様の調整が行われたことは、Go言語が堅牢で予測可能な挙動を持つように、細部にわたって注意深く設計されていたことを示しています。
コアとなるコードの変更箇所
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -2426,7 +2426,7 @@ unary_op = "+" | "-" | "!" | "^" | "*" | "&" | "<-" ."
The operand types in binary operations must be equal, with the following exceptions:
</p>
<ul>
- <li>If one operand has numeric type and the other operand is
+ <li>Except in shift expressios, if one operand has numeric type and the other operand is
an ideal number, the ideal number is converted to match the type of
the other operand (§Expressions).</li>
コアとなるコードの解説
変更された行は、Go言語仕様の二項演算における型変換の例外ルールを記述している部分です。
-
変更前:
<li>If one operand has numeric type and the other operand is
(もし片方のオペランドが数値型で、もう片方のオペランドが)この記述は、二項演算全般にわたる一般的なルールを示唆していました。
-
変更後:
<li>Except in shift expressios, if one operand has numeric type and the other operand is
(シフト式を除いて、もし片方のオペランドが数値型で、もう片方のオペランドが)追加された「
Except in shift expressios,
」という句がこのコミットの核心です。これは、直後に続く「理想数が型付けされたオペランドの型に変換される」というルールが、シフト演算には適用されないことを明確に宣言しています。
この修正により、Go言語の仕様は、シフト演算の右オペランド(シフト量)が、他の二項演算における理想数のように左オペランドの型に自動的に変換されるわけではないことを明示しました。シフト量は常に整数値として扱われ、その型は左オペランドの型とは独立しています。これにより、開発者はシフト演算の挙動をより正確に理解し、予期せぬ型変換によるバグを避けることができます。
関連リンク
- Go言語の公式ドキュメント: https://go.dev/doc/
- Go言語仕様: https://go.dev/ref/spec (現在の仕様)
- Go言語の初期の設計に関する議論やブログ記事(当時の情報源を見つけるのは困難な場合がありますが、Goの公式ブログやGo開発者の個人ブログが参考になることがあります)
参考にした情報源リンク
- Go言語の公式仕様書 (現在のバージョン): https://go.dev/ref/spec
- Go言語の型付けされていない定数に関する情報: https://go.dev/blog/constants
- Go言語のシフト演算に関する情報: https://go.dev/ref/spec#Shift_operators
- Go言語の初期のコミット履歴 (GitHub): https://github.com/golang/go/commits/master
- Russ Cox氏のGoに関するブログ記事や発表 (Go言語の設計に関する洞察を得るため)
- Rob Pike氏のGoに関するブログ記事や発表 (Go言語の設計に関する洞察を得るため)
- Go言語の初期のメーリングリストやフォーラムの議論 (当時の設計決定の背景を理解するため)