From 98682c7a8792e7e79e487fea5024d25cee5aa310 Mon Sep 17 00:00:00 2001
From: nsfisis contained unnecessary whitespaces inside it
---
.../rust-where-are-primitive-types-from/index.html | 36 ++++++++--------------
1 file changed, 12 insertions(+), 24 deletions(-)
(limited to 'public/posts/2021-10-02/rust-where-are-primitive-types-from')
diff --git a/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html b/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html
index 8bcb923..5b1f86a 100644
--- a/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html
+++ b/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html
@@ -55,8 +55,7 @@
Rust において、プリミティブ型の名前は予約語でない。したがって、次のコードは合法である。
- #![allow(non_camel_case_types)]
+ #![allow(non_camel_case_types)]
#![allow(dead_code)]
struct bool;
@@ -75,8 +74,7 @@ struct u128;
struct usize;
struct f32;
struct f64;
-struct str;
-
+struct str;
では、普段単にboolと書いたとき、このboolは一体どこから来ているのか。rustc のソースを追ってみた。
@@ -111,34 +109,29 @@ struct str;
rustcはセルフホストされている (=rustc自身が Rust で書かれている) ので、boolやcharなどで適当に検索をかけてもノイズが多すぎて話にならない。 しかし、お誂え向きなことにi128/u128というコンパイラ自身が使うことがなさそうな型が存在するのでこれを使ってgit grepしてみる。
- $ git grep "\bi128\b" | wc # i128
+ $ git grep "\bi128\b" | wc # i128
165 1069 15790
$ git grep "\bu128\b" | wc # u128
293 2127 26667
$ git grep "\bbool\b" | wc # cf. bool の結果
-3563 23577 294659
-
+3563 23577 294659
165 程度であれば探すことができそうだ。今回は、クレート名を見ておおよその当たりをつけた。
-
- $ git grep "\bi128\b"
+ $ git grep "\bi128\b"
...
rustc_resolve/src/lib.rs: table.insert(sym::i128, Int(IntTy::I128));
-...
-
+...
rustc_resolveというのはいかにも名前解決を担いそうなクレート名である。該当箇所を見てみる。
- /// Interns the names of the primitive types.
+ /// Interns the names of the primitive types.
///
/// All other types are defined somewhere and possibly imported, but the primitive ones need
/// special handling, since they have no place of origin.
@@ -169,8 +162,7 @@ table.insert(sym::u64, Uint(UintTy::U64));
table.insert(sym::u128, Uint(UintTy::U128));
Self { primitive_types: table }
}
-}
-
+}
これは初めに列挙したプリミティブ型の一覧と一致している。doc comment にも、 @@ -186,8 +178,7 @@ Self { primitive_types: table } とある。次はこの struct の使用箇所を追う。追うと言っても使われている箇所は次の一箇所しかない。なお説明に不要な箇所は大きく削っている。
-
- /// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
+ /// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
/// (略)
fn resolve_ident_in_lexical_scope(
&mut self,
@@ -207,8 +198,7 @@ return Some(LexicalScopeBinding::Item(binding));
}
None
-}
-
+}
関数名や doc comment が示している通り、この関数は識別子 (identifier, ident) を現在のレキシカルスコープ内で解決 (resolve) する。if ns == TypeNSのブロック内では、primitive_type_table(上記のPrimitiveTypeTable::new()で作られた変数) に含まれている識別子 (bool、i32など) かどうか判定し、そうであればそれに紐づけられたプリミティブ型を返している。
@@ -226,15 +216,13 @@ None
動作がわかったところで、例として次のコードを考える。
- #![allow(non_camel_case_types)]
+ #![allow(non_camel_case_types)]
struct bool;
fn main() {
let _: bool = bool;
-}
-
+}
ここでmain()のboolはstruct boolとして解決される。なぜなら、プリミティブ型の判定をする前にboolという名前の別の型が見つかるからだ。
--
cgit v1.2.3-70-g09d2