Related
I am building a procedural macro in Rust that implements, for a given struct, the fmt::Display trait for it. Although the implementation does not change the most of the time, there are some cases the subject struct contains some fields that must be displayed in a specific way.
Inside the macro, I did iterate all input fields to determine if the field is present or not. If it does so, I need to add a specific line at the end of the Display implementation. Otherwise, the line must be ignored.
So, I was wondering, is there any way to add conditional code? Just like I show in the example below:
#[proc_macro_derive(DisplayStruct)]
pub fn display_struct(input: TokenStream) -> TokenStream {
let DeriveInput { ident, data, .. } = parse_macro_input!(input);
match data {
Data::Struct(data_struct) => {
let mut has_field = false;
data_struct.fields.iter().for_each(|field| {
if let Some(ident) = field.ident.as_ref() {
has_field |= ident.eq("my_field_name");
}
});
let code = quote! {
impl std::fmt::Display for #ident {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// ...
// this IF from here is not part of the Display implementation, but a macro conditional that tells to the macro if the contained line should be added or not.
if #has_field {
write!(f, "{}", self.my_field_name.to_string())?;
}
Ok(())
}
}
};
return code.into();
}
_ => {
let error: TokenStream = quote!(compile_error!("chonk UwU");).into();
return error;
}
}
}
So the resulting implementation if my_field_name is present should be:
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// ...
write!(f, "{}", self.my_field_name.to_string())?;
Ok(())
}
Otherwise it must look like this:
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// ...
Ok(())
}
Store this line into Option:
let line = has_field.then(|| {
quote! { write!(f, "{}", self.my_field_name.to_string())?; }
});
Then you can interpolate it into quote!:
let code = quote! {
impl std::fmt::Display for #ident {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// ...
#line
Ok(())
}
}
};
I have the following:
let mut my_number = 32.90;
How do I print the type of my_number?
Using type and type_of did not work. Is there another way I can print the number's type?
You can use the std::any::type_name function. This doesn't need a nightly compiler or an external crate, and the results are quite correct:
fn print_type_of<T>(_: &T) {
println!("{}", std::any::type_name::<T>())
}
fn main() {
let s = "Hello";
let i = 42;
print_type_of(&s); // &str
print_type_of(&i); // i32
print_type_of(&main); // playground::main
print_type_of(&print_type_of::<i32>); // playground::print_type_of<i32>
print_type_of(&{ || "Hi!" }); // playground::main::{{closure}}
}
Be warned: as said in the documentation, this information must be used for a debug purpose only:
This is intended for diagnostic use. The exact contents and format of the string are not specified, other than being a best-effort description of the type.
If you want your type representation to stay the same between compiler versions, you should use a trait, like in the phicr's answer.
If you merely wish to find out the type of a variable and are willing to do it at compile time, you can cause an error and get the compiler to pick it up.
For example, set the variable to a type which doesn't work:
let mut my_number: () = 32.90;
// let () = x; would work too
error[E0308]: mismatched types
--> src/main.rs:2:29
|
2 | let mut my_number: () = 32.90;
| ^^^^^ expected (), found floating-point number
|
= note: expected type `()`
found type `{float}`
Or call an invalid method:
let mut my_number = 32.90;
my_number.what_is_this();
error[E0599]: no method named `what_is_this` found for type `{float}` in the current scope
--> src/main.rs:3:15
|
3 | my_number.what_is_this();
| ^^^^^^^^^^^^
Or access an invalid field:
let mut my_number = 32.90;
my_number.what_is_this
error[E0610]: `{float}` is a primitive type and therefore doesn't have fields
--> src/main.rs:3:15
|
3 | my_number.what_is_this
| ^^^^^^^^^^^^
These reveal the type, which in this case is actually not fully resolved. It’s called “floating-point variable” in the first example, and “{float}” in all three examples; this is a partially resolved type which could end up f32 or f64, depending on how you use it. “{float}” is not a legal type name, it’s a placeholder meaning “I’m not completely sure what this is”, but it is a floating-point number. In the case of floating-point variables, if you don't constrain it, it will default to f64¹. (An unqualified integer literal will default to i32.)
See also:
What is the {integer} or {float} in a compiler error message?
¹ There may still be ways of baffling the compiler so that it can’t decide between f32 and f64; I’m not sure. It used to be as simple as 32.90.eq(&32.90), but that treats both as f64 now and chugs along happily, so I don’t know.
There is an unstable function std::intrinsics::type_name that can get you the name of a type, though you have to use a nightly build of Rust (this is unlikely to ever work in stable Rust). Here’s an example:
#![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"
}
If you know all the types beforehand, you can use traits to add a type_of method:
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"
}
}
//...
No intrisics or nothin', so although more limited this is the only solution here that gets you a string and is stable. (see Boiethios's answer) However, it's very laborious and doesn't account for type parameters, so we could...
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<'a, T: TypeInfo + ?Sized> TypeInfo for &'a T {
fn type_name() -> String {
let mut res = String::from("&");
res.push_str(&T::type_name());
res
}
fn type_of(&self) -> String {
<&T>::type_name()
}
}
impl<'a, T: TypeInfo + ?Sized> TypeInfo for &'a mut T {
fn type_name() -> String {
let mut res = String::from("&mut ");
res.push_str(&T::type_name());
res
}
fn type_of(&self) -> String {
<&mut T>::type_name()
}
}
macro_rules! type_of {
($x:expr) => { (&$x).type_of() };
}
Let's use it:
impl_type_info!(i32, i64, f32, f64, str, String, Vec<T>, Result<T,S>)
fn main() {
println!("{}", type_of!(1));
println!("{}", type_of!(&1));
println!("{}", type_of!(&&1));
println!("{}", type_of!(&mut 1));
println!("{}", type_of!(&&mut 1));
println!("{}", type_of!(&mut &1));
println!("{}", type_of!(1.0));
println!("{}", type_of!("abc"));
println!("{}", type_of!(&"abc"));
println!("{}", type_of!(String::from("abc")));
println!("{}", type_of!(vec![1,2,3]));
println!("{}", <Result<String,i64>>::type_name());
println!("{}", <&i32>::type_name());
println!("{}", <&str>::type_name());
}
output:
i32
&i32
&&i32
&mut i32
&&mut i32
&mut &i32
f64
&str
&&str
String
Vec<i32>
Result<String,i64>
&i32
&str
Rust Playground
UPD The following does not work anymore. Check Shubham's answer for correction.
Check out std::intrinsics::get_tydesc<T>(). It is in "experimental" state right now, but it's OK if you are just hacking around the type system.
Check out the following example:
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>"
}
This is what is used internally to implement the famous {:?} formatter.
Update, original answer below
How about trait function type_name, which is useful to get type name quickly.
pub trait AnyExt {
fn type_name(&self) -> &'static str;
}
impl<T> AnyExt for T {
fn type_name(&self) -> &'static str {
std::any::type_name::<T>()
}
}
fn main(){
let my_number = 32.90;
println!("{}",my_number.type_name());
}
Output:
f64
Original answer
I write a macro type_of!() to debug, which is original from std dbg!().
pub fn type_of2<T>(v: T) -> (&'static str, T) {
(std::any::type_name::<T>(), v)
}
#[macro_export]
macro_rules! type_of {
// NOTE: We cannot use `concat!` to make a static string as a format argument
// of `eprintln!` because `file!` could contain a `{` or
// `$val` expression could be a block (`{ .. }`), in which case the `eprintln!`
// will be malformed.
() => {
eprintln!("[{}:{}]", file!(), line!());
};
($val:expr $(,)?) => {
// Use of `match` here is intentional because it affects the lifetimes
// of temporaries - https://stackoverflow.com/a/48732525/1063961
match $val {
tmp => {
let (type_,tmp) = $crate::type_of2(tmp);
eprintln!("[{}:{}] {}: {}",
file!(), line!(), stringify!($val), type_);
tmp
}
}
};
($($val:expr),+ $(,)?) => {
($($crate::type_of!($val)),+,)
};
}
fn main(){
let my_number = type_of!(32.90);
type_of!(my_number);
}
Output:
[src/main.rs:32] 32.90: f64
[src/main.rs:33] my_number: f64
** UPDATE ** This has not been verified to work any time recently.
I put together a little crate to do this based off vbo's answer. It gives you a macro to return or print out the type.
Put this in your Cargo.toml file:
[dependencies]
t_bang = "0.1.2"
Then you can use it like so:
#[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"
}
You can also use the simple approach of using the variable in println!("{:?}", var). If Debug is not implemented for the type, you can see the type in the compiler's error message:
mod some {
pub struct SomeType;
}
fn main() {
let unknown_var = some::SomeType;
println!("{:?}", unknown_var);
}
(playpen)
It's dirty but it works.
There's a #ChrisMorgan answer to get approximate type ("float") in stable rust and there's a #ShubhamJain answer to get precise type ("f64") through unstable function in nightly rust.
Now here's a way one can get precise type (ie decide between f32 and f64) in stable rust:
fn main() {
let a = 5.;
let _: () = unsafe { std::mem::transmute(a) };
}
results in
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> main.rs:3:27
|
3 | let _: () = unsafe { std::mem::transmute(a) };
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `f64` (64 bits)
= note: target type: `()` (0 bits)
Update
The turbofish variation
fn main() {
let a = 5.;
unsafe { std::mem::transmute::<_, ()>(a) }
}
is slightly shorter but somewhat less readable.
Some other answers don't work, but I find that the typename crate works.
Create a new project:
cargo new test_typename
Modify the Cargo.toml
[dependencies]
typename = "0.1.1"
Modify your source code
use typename::TypeName;
fn main() {
assert_eq!(String::type_name(), "std::string::String");
assert_eq!(Vec::<i32>::type_name(), "std::vec::Vec<i32>");
assert_eq!([0, 1, 2].type_name_of(), "[i32; 3]");
let a = 65u8;
let b = b'A';
let c = 65;
let d = 65i8;
let e = 65i32;
let f = 65u32;
let arr = [1,2,3,4,5];
let first = arr[0];
println!("type of a 65u8 {} is {}", a, a.type_name_of());
println!("type of b b'A' {} is {}", b, b.type_name_of());
println!("type of c 65 {} is {}", c, c.type_name_of());
println!("type of d 65i8 {} is {}", d, d.type_name_of());
println!("type of e 65i32 {} is {}", e, e.type_name_of());
println!("type of f 65u32 {} is {}", f, f.type_name_of());
println!("type of arr {:?} is {}", arr, arr.type_name_of());
println!("type of first {} is {}", first, first.type_name_of());
}
The output is:
type of a 65u8 65 is u8
type of b b'A' 65 is u8
type of c 65 65 is i32
type of d 65i8 65 is i8
type of e 65i32 65 is i32
type of f 65u32 65 is u32
type of arr [1, 2, 3, 4, 5] is [i32; 5]
type of first 1 is i32
If your just wanting to know the type of your variable during interactive development, I would highly recommend using rls (rust language server) inside of your editor or ide. You can then simply permanently enable or toggle the hover ability and just put your cursor over the variable. A little dialog should come up with information about the variable including the type.
This is simplified version of #Boiethios answer. I have removed some '&' symbols from original solution.
fn print_type_of<T>(_: T) {
println!("{}", std::any::type_name::<T>())
}
fn main() {
let s = "Hello";
let i = 42;
print_type_of(s); // &str
print_type_of(i); // i32
print_type_of(main); // playground::main
print_type_of(print_type_of::<i32>); // playground::print_type_of<i32>
print_type_of(|| "Hi!" ); // playground::main::{{closure}}
}
View in Rust Playground
Newly added in version 1.38 std::any::type_name
use std::any::type_name;
fn type_of<T>(_: T) -> &'static str {
type_name::<T>()
}
fn main() {
let x = 21;
let y = 2.5;
println!("{}", type_of(&y));
println!("{}", type_of(x));
}
short story;
fn tyof<T>(_: &T) -> String {
std::any::type_name::<T>().into()
}
long story;
trait Type {
fn type_of(&self) -> String;
}
macro_rules! Type {
($($ty:ty),*) => {
$(
impl Type for $ty {
fn type_of(&self) -> String {
stringify!($ty).into()
}
}
)*
}
}
#[rustfmt::skip]
Type!(
u8, i8, u16, i16, u32, i32, i64, u64, i128, String, [()], (), Vec<()>, &u8, &i8, &u16, &i16, &u32, &i32, &i64, &u64, &i128, &str, &[()], &Vec<()>, &()
// add any struct, enum or type you want
);
macro_rules! tyof {
($var: expr) => {{
$var.type_of()
}};
}
fn main() {
let x = "Hello world!";
println!("{}", tyof!(x));
// or
println!("{}", x.type_of());
let x = 5;
println!("{}", tyof!(x));
// or
println!("{}", x.type_of());
}
Macro form permits an usage "everywhere" while the function need an object to be parse.
Macro form (one liner):
macro_rules! ty {($type:ty) => {std::any::type_name::<$type>()}}
Macro form formated:
macro_rules! ty {
($type:ty) => {
std::any::type_name::<$type>()
};
}
Function form (borrowing is to not destroy the parsed var):
fn type_of<T>(_: &T) -> &'static str {std::any::type_name::<T>()}
fn type_of<T>(_: &T) -> &'static str {
std::any::type_name::<T>()
}
Example:
macro_rules! ty {($type:ty) => {std::any::type_name::<$type>()}}
fn type_of<T>(_: &T) -> &'static str {std::any::type_name::<T>()}
struct DontMater<T>(T);
impl<T: std::fmt::Debug> std::fmt::Debug for DontMater<T> {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fmt.write_fmt(format_args!("DontMater<{}>({:?})", ty!(T), self.0))
}
}
fn main() {
type µ = [Vec<String>; 7];
println!("{:?}", DontMater(5_usize));
println!("{:?}", DontMater("¤"));
println!("{}", ty!(char));
println!("{:?}", ty!(µ));
println!("{}", type_of(&DontMater(72_i8)));
println!("{:?}", type_of(&15_f64));
}
Returns:
DontMater<usize>(5)
DontMater<&str>("¤")
char
"[alloc::vec::Vec<alloc::string::String>; 7]"
env_vars::DontMater<i8>
"f64"
I like previous answer by #Coautose very much, but in case anyone wants just the type name without the namespace, for example C instead of a::b::C, here is a modified version of the macro that appears to work as intended:
macro_rules! ty {
($type:ty) => {{
let result = std::any::type_name::<$type>();
match result.rsplit_once(':') {
Some((_, s)) => s,
None => result,
}
}};
}
Usage:
debug!("Testing type name: {}", ty!(A));
Better to use this:
fn print_type_of<T>(_: &T) -> String {
format!("{}", std::any::type_name::<T>())
}
fn main() {
let s = &"hello world".to_string();
let cloned_s = s.clone();
println!("{:?}", print_type_of(&s));
println!("{:?}", print_type_of(&cloned_s));
}
Taken inference from https://stackoverflow.com/a/29168659/6774636
I have the following:
let mut my_number = 32.90;
How do I print the type of my_number?
Using type and type_of did not work. Is there another way I can print the number's type?
You can use the std::any::type_name function. This doesn't need a nightly compiler or an external crate, and the results are quite correct:
fn print_type_of<T>(_: &T) {
println!("{}", std::any::type_name::<T>())
}
fn main() {
let s = "Hello";
let i = 42;
print_type_of(&s); // &str
print_type_of(&i); // i32
print_type_of(&main); // playground::main
print_type_of(&print_type_of::<i32>); // playground::print_type_of<i32>
print_type_of(&{ || "Hi!" }); // playground::main::{{closure}}
}
Be warned: as said in the documentation, this information must be used for a debug purpose only:
This is intended for diagnostic use. The exact contents and format of the string are not specified, other than being a best-effort description of the type.
If you want your type representation to stay the same between compiler versions, you should use a trait, like in the phicr's answer.
If you merely wish to find out the type of a variable and are willing to do it at compile time, you can cause an error and get the compiler to pick it up.
For example, set the variable to a type which doesn't work:
let mut my_number: () = 32.90;
// let () = x; would work too
error[E0308]: mismatched types
--> src/main.rs:2:29
|
2 | let mut my_number: () = 32.90;
| ^^^^^ expected (), found floating-point number
|
= note: expected type `()`
found type `{float}`
Or call an invalid method:
let mut my_number = 32.90;
my_number.what_is_this();
error[E0599]: no method named `what_is_this` found for type `{float}` in the current scope
--> src/main.rs:3:15
|
3 | my_number.what_is_this();
| ^^^^^^^^^^^^
Or access an invalid field:
let mut my_number = 32.90;
my_number.what_is_this
error[E0610]: `{float}` is a primitive type and therefore doesn't have fields
--> src/main.rs:3:15
|
3 | my_number.what_is_this
| ^^^^^^^^^^^^
These reveal the type, which in this case is actually not fully resolved. It’s called “floating-point variable” in the first example, and “{float}” in all three examples; this is a partially resolved type which could end up f32 or f64, depending on how you use it. “{float}” is not a legal type name, it’s a placeholder meaning “I’m not completely sure what this is”, but it is a floating-point number. In the case of floating-point variables, if you don't constrain it, it will default to f64¹. (An unqualified integer literal will default to i32.)
See also:
What is the {integer} or {float} in a compiler error message?
¹ There may still be ways of baffling the compiler so that it can’t decide between f32 and f64; I’m not sure. It used to be as simple as 32.90.eq(&32.90), but that treats both as f64 now and chugs along happily, so I don’t know.
There is an unstable function std::intrinsics::type_name that can get you the name of a type, though you have to use a nightly build of Rust (this is unlikely to ever work in stable Rust). Here’s an example:
#![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"
}
If you know all the types beforehand, you can use traits to add a type_of method:
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"
}
}
//...
No intrisics or nothin', so although more limited this is the only solution here that gets you a string and is stable. (see Boiethios's answer) However, it's very laborious and doesn't account for type parameters, so we could...
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<'a, T: TypeInfo + ?Sized> TypeInfo for &'a T {
fn type_name() -> String {
let mut res = String::from("&");
res.push_str(&T::type_name());
res
}
fn type_of(&self) -> String {
<&T>::type_name()
}
}
impl<'a, T: TypeInfo + ?Sized> TypeInfo for &'a mut T {
fn type_name() -> String {
let mut res = String::from("&mut ");
res.push_str(&T::type_name());
res
}
fn type_of(&self) -> String {
<&mut T>::type_name()
}
}
macro_rules! type_of {
($x:expr) => { (&$x).type_of() };
}
Let's use it:
impl_type_info!(i32, i64, f32, f64, str, String, Vec<T>, Result<T,S>)
fn main() {
println!("{}", type_of!(1));
println!("{}", type_of!(&1));
println!("{}", type_of!(&&1));
println!("{}", type_of!(&mut 1));
println!("{}", type_of!(&&mut 1));
println!("{}", type_of!(&mut &1));
println!("{}", type_of!(1.0));
println!("{}", type_of!("abc"));
println!("{}", type_of!(&"abc"));
println!("{}", type_of!(String::from("abc")));
println!("{}", type_of!(vec![1,2,3]));
println!("{}", <Result<String,i64>>::type_name());
println!("{}", <&i32>::type_name());
println!("{}", <&str>::type_name());
}
output:
i32
&i32
&&i32
&mut i32
&&mut i32
&mut &i32
f64
&str
&&str
String
Vec<i32>
Result<String,i64>
&i32
&str
Rust Playground
UPD The following does not work anymore. Check Shubham's answer for correction.
Check out std::intrinsics::get_tydesc<T>(). It is in "experimental" state right now, but it's OK if you are just hacking around the type system.
Check out the following example:
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>"
}
This is what is used internally to implement the famous {:?} formatter.
Update, original answer below
How about trait function type_name, which is useful to get type name quickly.
pub trait AnyExt {
fn type_name(&self) -> &'static str;
}
impl<T> AnyExt for T {
fn type_name(&self) -> &'static str {
std::any::type_name::<T>()
}
}
fn main(){
let my_number = 32.90;
println!("{}",my_number.type_name());
}
Output:
f64
Original answer
I write a macro type_of!() to debug, which is original from std dbg!().
pub fn type_of2<T>(v: T) -> (&'static str, T) {
(std::any::type_name::<T>(), v)
}
#[macro_export]
macro_rules! type_of {
// NOTE: We cannot use `concat!` to make a static string as a format argument
// of `eprintln!` because `file!` could contain a `{` or
// `$val` expression could be a block (`{ .. }`), in which case the `eprintln!`
// will be malformed.
() => {
eprintln!("[{}:{}]", file!(), line!());
};
($val:expr $(,)?) => {
// Use of `match` here is intentional because it affects the lifetimes
// of temporaries - https://stackoverflow.com/a/48732525/1063961
match $val {
tmp => {
let (type_,tmp) = $crate::type_of2(tmp);
eprintln!("[{}:{}] {}: {}",
file!(), line!(), stringify!($val), type_);
tmp
}
}
};
($($val:expr),+ $(,)?) => {
($($crate::type_of!($val)),+,)
};
}
fn main(){
let my_number = type_of!(32.90);
type_of!(my_number);
}
Output:
[src/main.rs:32] 32.90: f64
[src/main.rs:33] my_number: f64
** UPDATE ** This has not been verified to work any time recently.
I put together a little crate to do this based off vbo's answer. It gives you a macro to return or print out the type.
Put this in your Cargo.toml file:
[dependencies]
t_bang = "0.1.2"
Then you can use it like so:
#[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"
}
You can also use the simple approach of using the variable in println!("{:?}", var). If Debug is not implemented for the type, you can see the type in the compiler's error message:
mod some {
pub struct SomeType;
}
fn main() {
let unknown_var = some::SomeType;
println!("{:?}", unknown_var);
}
(playpen)
It's dirty but it works.
There's a #ChrisMorgan answer to get approximate type ("float") in stable rust and there's a #ShubhamJain answer to get precise type ("f64") through unstable function in nightly rust.
Now here's a way one can get precise type (ie decide between f32 and f64) in stable rust:
fn main() {
let a = 5.;
let _: () = unsafe { std::mem::transmute(a) };
}
results in
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> main.rs:3:27
|
3 | let _: () = unsafe { std::mem::transmute(a) };
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `f64` (64 bits)
= note: target type: `()` (0 bits)
Update
The turbofish variation
fn main() {
let a = 5.;
unsafe { std::mem::transmute::<_, ()>(a) }
}
is slightly shorter but somewhat less readable.
Some other answers don't work, but I find that the typename crate works.
Create a new project:
cargo new test_typename
Modify the Cargo.toml
[dependencies]
typename = "0.1.1"
Modify your source code
use typename::TypeName;
fn main() {
assert_eq!(String::type_name(), "std::string::String");
assert_eq!(Vec::<i32>::type_name(), "std::vec::Vec<i32>");
assert_eq!([0, 1, 2].type_name_of(), "[i32; 3]");
let a = 65u8;
let b = b'A';
let c = 65;
let d = 65i8;
let e = 65i32;
let f = 65u32;
let arr = [1,2,3,4,5];
let first = arr[0];
println!("type of a 65u8 {} is {}", a, a.type_name_of());
println!("type of b b'A' {} is {}", b, b.type_name_of());
println!("type of c 65 {} is {}", c, c.type_name_of());
println!("type of d 65i8 {} is {}", d, d.type_name_of());
println!("type of e 65i32 {} is {}", e, e.type_name_of());
println!("type of f 65u32 {} is {}", f, f.type_name_of());
println!("type of arr {:?} is {}", arr, arr.type_name_of());
println!("type of first {} is {}", first, first.type_name_of());
}
The output is:
type of a 65u8 65 is u8
type of b b'A' 65 is u8
type of c 65 65 is i32
type of d 65i8 65 is i8
type of e 65i32 65 is i32
type of f 65u32 65 is u32
type of arr [1, 2, 3, 4, 5] is [i32; 5]
type of first 1 is i32
If your just wanting to know the type of your variable during interactive development, I would highly recommend using rls (rust language server) inside of your editor or ide. You can then simply permanently enable or toggle the hover ability and just put your cursor over the variable. A little dialog should come up with information about the variable including the type.
This is simplified version of #Boiethios answer. I have removed some '&' symbols from original solution.
fn print_type_of<T>(_: T) {
println!("{}", std::any::type_name::<T>())
}
fn main() {
let s = "Hello";
let i = 42;
print_type_of(s); // &str
print_type_of(i); // i32
print_type_of(main); // playground::main
print_type_of(print_type_of::<i32>); // playground::print_type_of<i32>
print_type_of(|| "Hi!" ); // playground::main::{{closure}}
}
View in Rust Playground
Newly added in version 1.38 std::any::type_name
use std::any::type_name;
fn type_of<T>(_: T) -> &'static str {
type_name::<T>()
}
fn main() {
let x = 21;
let y = 2.5;
println!("{}", type_of(&y));
println!("{}", type_of(x));
}
short story;
fn tyof<T>(_: &T) -> String {
std::any::type_name::<T>().into()
}
long story;
trait Type {
fn type_of(&self) -> String;
}
macro_rules! Type {
($($ty:ty),*) => {
$(
impl Type for $ty {
fn type_of(&self) -> String {
stringify!($ty).into()
}
}
)*
}
}
#[rustfmt::skip]
Type!(
u8, i8, u16, i16, u32, i32, i64, u64, i128, String, [()], (), Vec<()>, &u8, &i8, &u16, &i16, &u32, &i32, &i64, &u64, &i128, &str, &[()], &Vec<()>, &()
// add any struct, enum or type you want
);
macro_rules! tyof {
($var: expr) => {{
$var.type_of()
}};
}
fn main() {
let x = "Hello world!";
println!("{}", tyof!(x));
// or
println!("{}", x.type_of());
let x = 5;
println!("{}", tyof!(x));
// or
println!("{}", x.type_of());
}
Macro form permits an usage "everywhere" while the function need an object to be parse.
Macro form (one liner):
macro_rules! ty {($type:ty) => {std::any::type_name::<$type>()}}
Macro form formated:
macro_rules! ty {
($type:ty) => {
std::any::type_name::<$type>()
};
}
Function form (borrowing is to not destroy the parsed var):
fn type_of<T>(_: &T) -> &'static str {std::any::type_name::<T>()}
fn type_of<T>(_: &T) -> &'static str {
std::any::type_name::<T>()
}
Example:
macro_rules! ty {($type:ty) => {std::any::type_name::<$type>()}}
fn type_of<T>(_: &T) -> &'static str {std::any::type_name::<T>()}
struct DontMater<T>(T);
impl<T: std::fmt::Debug> std::fmt::Debug for DontMater<T> {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fmt.write_fmt(format_args!("DontMater<{}>({:?})", ty!(T), self.0))
}
}
fn main() {
type µ = [Vec<String>; 7];
println!("{:?}", DontMater(5_usize));
println!("{:?}", DontMater("¤"));
println!("{}", ty!(char));
println!("{:?}", ty!(µ));
println!("{}", type_of(&DontMater(72_i8)));
println!("{:?}", type_of(&15_f64));
}
Returns:
DontMater<usize>(5)
DontMater<&str>("¤")
char
"[alloc::vec::Vec<alloc::string::String>; 7]"
env_vars::DontMater<i8>
"f64"
I like previous answer by #Coautose very much, but in case anyone wants just the type name without the namespace, for example C instead of a::b::C, here is a modified version of the macro that appears to work as intended:
macro_rules! ty {
($type:ty) => {{
let result = std::any::type_name::<$type>();
match result.rsplit_once(':') {
Some((_, s)) => s,
None => result,
}
}};
}
Usage:
debug!("Testing type name: {}", ty!(A));
Better to use this:
fn print_type_of<T>(_: &T) -> String {
format!("{}", std::any::type_name::<T>())
}
fn main() {
let s = &"hello world".to_string();
let cloned_s = s.clone();
println!("{:?}", print_type_of(&s));
println!("{:?}", print_type_of(&cloned_s));
}
Taken inference from https://stackoverflow.com/a/29168659/6774636
EDIT: This question isn't relevant on versions of Rust >= 1.47 because "const generics" has started being implemented.
I'm trying to implement a sudoku solver in Rust for learning purposes. I'm trying to create a board with a fixed size (81) array of Cells (which is Copy) but I can't seem to get it to work. I can create a line of 9 Cells so I guess I'm running into the problem where there are only generics for TryFrom for up 32 for this kind of conversion.
Cell looks like this for now:
#[derive(Debug, Default, Clone, Copy)]
struct Cell {
row: u8,
column: u8,
}
This works:
use std::convert::TryInto;
fn main() {
let cells: Vec<Cell> = std::iter::repeat(0)
.zip(0..9u8)
.map(|(row, column)| Cell { row, column} )
.collect();
let c: Box<[Cell; 9]> = cells.into_boxed_slice().try_into().unwrap();
println!("{:#?}", c);
}
But this doesn't:
use std::convert::TryInto;
fn main() {
let cells: Vec<Cell> = (0..9u8).into_iter()
.flat_map(|x| {
std::iter::repeat(x)
.zip(0..9u8)
})
.map(|(row, column)| Cell { row, column} )
.collect();
let c: Box<[Cell; 81]> = cells.into_boxed_slice().try_into().unwrap();
println!("{:#?}", c);
}
I tried to use the code from std as a guide like this:
impl TryFrom<Box<[Cell]>> for Box<[Cell; 81]> {
type Error = Box<[Cell]>;
fn try_from(boxed_slice: Box<[Cell]>) -> Result<Self, Self::Error> {
if boxed_slice.len() == 81 {
Ok(unsafe { Box::from_raw(Box::into_raw(boxed_slice) as *mut [Cell; 91]) })
} else {
Err(boxed_slice)
}
}
}
but that runs into an error about conflicting implementations of trait which I guess makes sense.
I know I could just use a Vec or do something like [[Cell; 9]; 9] but I'd really like to understand what's going on. While trying to figure this out I've seen a number of similar questions where people were trying to use types that didn't implement Copy and that was the problem but that's not the case here and I can't figure out how to make this work.
The trait FromIterator is not implemented for slices, you can wrap it in a type and implement it yourself:
use core::iter::FromIterator;
#[derive(Debug, Default, Clone, Copy)]
struct Cell {
row: u8,
column: u8,
}
#[derive(Debug)]
struct Sudoku(Box<[Cell]>);
impl FromIterator<Cell> for Sudoku {
fn from_iter<I: IntoIterator<Item=Cell>>(iter: I) -> Self {
let mut v = Vec::new();
for cell in iter {
v.push(cell)
}
Sudoku(v.into_boxed_slice())
}
}
fn main() {
let cells: Sudoku = (0..9u8).into_iter()
.flat_map(|x| {
std::iter::repeat(x)
.zip(0..9u8)
})
.map(|(row, column)| Cell { row, column} )
.collect();
println!("{:#?}", cells);
}
Playground
Edit:
You can also implement it for the specific size of the array. Which for the sudoku case should be ok, but in general you would like things to work in a more general way. Instead of the fixated size, you could write a macro that would write the implementation for any given size too.
Example:
use core::iter::FromIterator;
use std::fmt;
#[derive(Clone, Copy)]
struct Cell {
row: u8,
column: u8,
}
impl fmt::Display for Cell {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Cell: ({}, {})", self.row, self.column)
}
}
struct Sudoku([Cell; 81]);
impl fmt::Display for Sudoku {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for cell in self.0.iter() {
write!(f, "{}\n", cell)?;
}
Ok(())
}
}
impl FromIterator<Cell> for Sudoku {
fn from_iter<I: IntoIterator<Item=Cell>>(iter: I) -> Self {
let mut v = [Cell {row: 0, column: 0}; 81];
for (i, cell) in (0..81).zip(iter) {
v[i] = cell;
}
Sudoku(v)
}
}
fn main() {
let cells: Sudoku = (0..9u8).into_iter()
.flat_map(|x| {
std::iter::repeat(x)
.zip(0..9u8)
})
.map(|(row, column)| Cell { row, column} )
.collect();
println!("{}", cells);
}
Playground
I have a problem when I use macro_rules!.
I defined a enum Test and impl fmt for the enum.
use core::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Test {
Foo(String),
Bar,
}
impl fmt::Display for Test {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Test::Foo(id) => write!(f, "Foo({})", id),
Test::Bar => write!(f, "Bar"),
}
}
}
Then I defined a macro print_test!.
macro_rules! print_test {
($test:pat) => {
println!("the Test is {}", $test);
};
}
However I got an error .
error: expected expression, found `Bar`
--> src/main.rs:53:36
|
53 | println!("the Test is {}", $test);
| ^^^^^ expected expression
...
57 | print_test!(Bar);
| ----------------- in this macro invocation
I'm a new Rustacean. And I really don't know why this happened.
update
I have already import the enum variants in a global scope.And following is the complete code
mod test {
use core::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Test {
Foo(String),
Bar,
}
impl fmt::Display for Test {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Test::Foo(id) => write!(f, "Foo({})", id),
Test::Bar => write!(f, "Bar"),
}
}
}
}
use test::Test::*;
macro_rules! print_test {
($test:pat) => {
println!("the Test is {}", $test);
};
}
fn main() {
let a=String::from ("test");
print_test!(Bar);
}
Just change the pat to expr can resolve the problem.
macro_rules! print_test {
($test:expr) => {
println!("{}",$test);
};
}