如何在Rust中打印variables的types?

我有这个代码片段:

let mut my_number=32.90; 

我需要知道my_number的types。 使用typetype_of不起作用; 有什么其他方法可以打印数字的types?

如果你只想找出一个variables的types,并且愿意在编译时做这个variables,那么你可能会导致一个错误,让编译器把它捡起来。

例如, 将variables设置为不起作用的types ( let () = x;也可以):

 error[E0308]: mismatched types --> <anon>:2:29 | 2 | let mut my_number: () = 32.90; | ^^^^^ expected (), found floating-point variable | = note: expected type `()` = note: found type `{float}` error: aborting due to previous error 

或者在大多数情况下, 调用无效的方法或获取无效的字段 :

 error: no method named `what_is_this` found for type `{float}` in the current scope --> <anon>:3:15 | 3 | my_number.what_is_this(); | ^^^^^^^^^^^^ error: aborting due to previous error 
 error: attempted access of field `what_is_this` on type `{float}`, but no field with that name was found --> <anon>:3:5 | 3 | my_number.what_is_this | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error 

这些揭示了在这种情况下实际上没有完全解决的types。 它在第一个例子中被称为“浮点variables”,在所有三个例子中被称为“ {float} ”; 这是一个部分解决的types,可能会结束f32f64 ,这取决于你如何使用它。 “ {float} ”不是一个合法的types名称,它是一个占位符,意思是“我不完全确定这是什么”,但它一个浮点数。 在浮点variables的情况下,如果不约束它,它将默认为f64 。 (一个不合格的整数字面量将默认为i32 。)


¹编译器可能仍然存在一些问题,以至于无法在f32f64之间做出决定。 我不确定。 它曾经是32.90.eq(&32.90)那样简单,但是现在把它当作f64并且愉快地f64 ,所以我不知道。

有一个不稳定的函数std::intrinsics::type_name可以得到一个types的名字,但是你必须使用每晚构build的Rust(这个不太可能在稳定的Rust中工作)。 这是一个例子:

 #![feature(core_intrinsics)] fn print_type_of<T>(_: &T) { println!("{}", unsafe { std::intrinsics::type_name::<T>() }); } fn main() { print_type_of(&32.90); // prints "f64" print_type_of(&vec![1, 2, 4]); // prints "std::vec::Vec<i32>" print_type_of(&"foo"); // prints "&str" } 

UPD以下不起作用了。 检查Shubham的更正答案 。

检查出std::intrinsics::get_tydesc<T>() 。 现在它处于“实验”状态,但是如果你只是在types系统中进行黑客攻击,那也没关系。

看看下面的例子:

 fn print_type_of<T>(_: &T) -> () { let type_name = unsafe { (*std::intrinsics::get_tydesc::<T>()).name }; println!("{}", type_name); } fn main() -> () { let mut my_number = 32.90; print_type_of(&my_number); // prints "f64" print_type_of(&(vec!(1, 2, 4))); // prints "collections::vec::Vec<int>" } 

这是内部用来实现着名的{:?}格式化程序的东西。

如果事先知道所有的types,你可以使用traits来添加一个type_of方法:

 trait TypeInfo { fn type_of(&self) -> &'static str; } impl TypeInfo for i32 { fn type_of(&self) -> &'static str { "i32" } } impl TypeInfo for i64 { fn type_of(&self) -> &'static str { "i64" } } //... 

没有内疚或没什么,所以虽然更有限这是唯一的解决scheme,让你一个string,是稳定的。 然而,这是非常费力的,不考虑types参数,所以我们可以…

 trait TypeInfo { fn type_name() -> String; fn type_of(&self) -> String; } macro_rules! impl_type_info { ($($name:ident$(<$($T:ident),+>)*),*) => { $(impl_type_info_single!($name$(<$($T),*>)*);)* }; } macro_rules! mut_if { ($name:ident = $value:expr, $($any:expr)+) => (let mut $name = $value;); ($name:ident = $value:expr,) => (let $name = $value;); } macro_rules! impl_type_info_single { ($name:ident$(<$($T:ident),+>)*) => { impl$(<$($T: TypeInfo),*>)* TypeInfo for $name$(<$($T),*>)* { fn type_name() -> String { mut_if!(res = String::from(stringify!($name)), $($($T)*)*); $( res.push('<'); $( res.push_str(&$T::type_name()); res.push(','); )* res.pop(); res.push('>'); )* res } fn type_of(&self) -> String { $name$(::<$($T),*>)*::type_name() } } } } 

让我们使用它:

 impl_type_info!(i32, i64, f32, f64, str, String, Vec<T>, Result<T,S>); fn main() { println!("{}", 1.type_of()); println!("{}", 1.0.type_of()); println!("{}", "abc".type_of()); println!("{}", String::from("abc").type_of()); println!("{}", vec![1,2,3].type_of()); println!("{}", Result::<String,i64>::type_name()) } 

输出:

 i32 f64 str String Vec<i32> Result<String,i64> 

铁锈游乐场

我放了一个小箱子,根据vbo的回答做到这一点。 它给你一个macros来返回或打印出types。

把它放在你的Cargo.toml文件中:

 [dependencies] t_bang = "0.1.2" 

那么你可以这样使用它:

 #[macro_use] extern crate t_bang; use t_bang::*; fn main() { let x = 5; let x_type = t!(x); println!("{:?}", x_type); // prints out: "i32" pt!(x); // prints out: "i32" pt!(5); // prints out: "i32" } 

您也可以使用在println!("{:?}", var)中使用variables的简单方法。 如果Debugtypes没有实现,你可以在编译器的错误信息中看到types:

 mod some { pub struct SomeType; } fn main() { let unknown_var = some::SomeType; println!("{:?}", unknown_var); } 

( 围栏 )

这是肮脏的,但它的作品。