Rustで変数の型の名前を取得・確認
Rustで変数の型の名前を文字列で取得し確認するにはstd::any::type_name
を利用する。
なお、Rustは静的型付き言語であり、例えばVSCode + rust-analyzerではソースコード上の変数にマウスを合わせるとその型が確認できる。std::any::type_name
のドキュメントにあるように、コード内で型の名前を取得するのはあくまでも診断・デバッグのため。
This is intended for diagnostic use. The exact contents and format of the string returned are not specified, other than being a best-effort description of the type. type_name in std::any - Rust
型の名前を文字列スライスで取得: std::any::type_name
std::any::type_name
は型の名前を文字列スライスで返す。
ターボフィッシュ::<>
で型を指定する。ここでは便宜上assert_eq!
を使っているが、結果を出力したい場合はprintln!
などを使えばよい。以降も同様。
assert_eq!(std::any::type_name::<i32>(), "i32");
assert_eq!(std::any::type_name::<bool>(), "bool");
ドキュメントにあるように、返される文字列はユニークであるとは限らず、コンパイラのバージョンによって出力が変わる可能性もある。例えばrustc 1.67.0
時点ではライフタイム注釈は無視される。
assert_eq!(std::any::type_name::<&str>(), "&str");
assert_eq!(std::any::type_name::<&'static str>(), "&str");
以降の例もすべてrustc 1.67.0
のもの。
プリミティブ型以外はモジュールを含む名前が返される。std
ではなくalloc
やcore
が使われる。
assert_eq!(std::any::type_name::<String>(), "alloc::string::String");
assert_eq!(std::any::type_name::<Vec<i32>>(), "alloc::vec::Vec<i32>");
assert_eq!(
std::any::type_name::<Option<i32>>(),
"core::option::Option<i32>"
);
入れ子になっている場合。
assert_eq!(
std::any::type_name::<Vec<String>>(),
"alloc::vec::Vec<alloc::string::String>"
);
assert_eq!(
std::any::type_name::<Option<String>>(),
"core::option::Option<alloc::string::String>"
);
自分で定義した構造体の場合。例のtype_of
はファイル名(type_of.rs
)。Cargo.toml
の[package]
や[[bin]]
でname
を指定している場合はそれが使われる。
struct MyStruct(i32);
assert_eq!(std::any::type_name::<MyStruct>(), "type_of::main::MyStruct");
type
で型エイリアスを定義した場合、元の型の名前が返される。
- 関連記事: Rustのtypeで型エイリアスを定義
type MyAlias = u8;
assert_eq!(std::any::type_name::<MyAlias>(), "u8");
変数の型の名前を文字列スライスで取得
std::any::type_name_of_val
は変数の型の名前を文字列スライスで返す。rustc 1.67.0
時点はNightly版のみ。
std::any::type_name_of_val
の実装を参考に関数を定義する。
fn type_of<T>(_: &T) -> &'static str {
std::any::type_name::<T>()
}
以下のように使える。
let i = 100;
assert_eq!(type_of(&i), "i32");
let u = 100_u8;
assert_eq!(type_of(&u), "u8");
let b = true;
assert_eq!(type_of(&b), "bool");
let s = "abc";
assert_eq!(type_of(&s), "&str");
let t = (100, 100);
assert_eq!(type_of(&t), "(i32, i32)");
let v = vec![String::from("abc")];
assert_eq!(type_of(&v), "alloc::vec::Vec<alloc::string::String>");
参照の場合。
let i = 100;
let ref_i = &i;
assert_eq!(type_of(&ref_i), "&i32");
let mut i = 100;
let mut_ref_i = &mut i;
assert_eq!(type_of(&mut_ref_i), "&mut i32");
配列とスライスの場合。
let a = [0, 1, 2];
assert_eq!(type_of(&a), "[i32; 3]");
let s = &a[1..];
assert_eq!(type_of(&s), "&[i32]");
上で定義した構造体やtype
による型エイリアスの場合。
let my_struct = MyStruct(100);
assert_eq!(type_of(&my_struct), "type_of::main::MyStruct");
let u: MyAlias = 100;
assert_eq!(type_of(&u), "u8");
より複雑な例。
let it = [0, 1, 2].iter().enumerate();
assert_eq!(
type_of(&it),
"core::iter::adapters::enumerate::Enumerate<core::slice::iter::Iter<i32>>"
);
let result = "100".parse::<i32>();
assert_eq!(
type_of(&result),
"core::result::Result<i32, core::num::error::ParseIntError>"
);