Why does storing &str in a Box<dyn Any> and downcasting it to a &Box<&str> always result in None? - struct

I want to create a vector of structs each of which contains a field that can have any (multiple) type, being able to extract those values too. I've tried this:
use std::any::Any;
fn main() {
let mut v: Vec<Box<dyn Any>> = Vec::new();
v.push(Box::new("test"));
v.push(Box::new(3i32));
let string: &Box<&str> = &v[0].downcast_ref().unwrap(); // erroneous line
println!("{}", string);
let int: &Box<&i32> = &v[1].downcast_ref().unwrap(); // probably gives an error too
println!("{}", int);
}
It should print out
test
3
Instead, it panics:
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:8:51
From what I understand, it downcasts to &str and unwraps to give &Box<&str>, except it returns a None value.
I've tried other stuff such as structs with generics but that's limited to only 1 type:
struct Item<T> {
item: T,
}
fn main() {
let mut v: Vec<Item<&str>> = Vec::new();
v.push(Item { item: "hi" });
v.push(Item { item: 3i32 }); // error because it can only be &str, not i32
}
How would I do this?

You do not hold Box<&str> in Any. You hold &str in Any.
let string: &str = v[0]
.downcast_ref::<&str>()
.unwrap();
println!("{}", string);
let int: &i32 = v[1]
.downcast_ref() // Rust infers ::<i32>
.unwrap();
println!("{}", int);

Related

How to drop a MaybeUninit of vector or array which is partially initialized?

I'm looking for information and good practices for using MaybeUninit
to directly initialize collections (typically arrays or vectors) and
drop them properly if initialization failed.
Thanks to the API examples, I was able to get by fairly quickly with
arrays but it was much trickier with vectors. On the example that
follows (which is a toy simplification of what I did in my project),
generic function, try_new<T: TryFrom<()>, A:ArrayUninit<T>>(len: usize), tries to create an array or a vector of objects T by means
of a fallible data generator TryFrom::try_from(_:()) implemented by
T. The order in which the array is generated is random
(asynchronism); this is simulated by function indices(len:usize).
Function, try_new<A:ArrayUninit>(len: usize), uses method
ArrayUninit::try_uninit(len: usize), implemented by Vec<Data> and
[Data;N], for building uninitialized array or vector.
In our main, we use data type, Data, as example, for which
generator, TryFrom<()> is implemented.
The following code seems to work, but I'm wondering
how to drop uninitialized data:
(playground)
use core::{ time::Duration, mem::MaybeUninit, };
use std::thread;
use rand::prelude::*;
// trait with method for building uninited array/vector
// implementations for Vec<T> and [T;N] after the main()
trait ArrayUninit<T>: AsMut<[T]> + Sized {
fn try_uninit(len: usize) -> Result<MaybeUninit<Self>,String>;
}
// generate shuffled indices
fn indices(len: usize) -> Box<dyn Iterator<Item = usize>> {
let mut vec: Vec<usize> = (0..len).collect();
vec.shuffle(&mut thread_rng());
Box::new(vec.into_iter())
}
// try to build an array or a vector of objects T
fn try_new<T: TryFrom<()>, A:ArrayUninit<T>>(len: usize) -> Result<A,String> {
// build uninitialized collection
let mut uninited = A::try_uninit(len)?;
// simulate initialization in random order
let indices = indices(len);
// build a mutable ref to the array/vector
let ra: &mut A = unsafe {(uninited.as_mut_ptr() as *mut A).as_mut() }.unwrap();
let mut failed = false;
for i in indices {
// get ptr at i
let ptr_arr: * mut T = unsafe{AsMut::<[T]>::as_mut(ra).as_mut_ptr().add(i)};
// get object and break if failed
let data = match T::try_from(()) {
Ok(data) => data, Err(_) => { failed = true; break; },
};
// set object
unsafe { *ptr_arr = data };
}
if !failed {
Ok(unsafe{ uninited.assume_init() }) // return array, if successful
} else {
// if failed, then
for i in 0..len { // drop all objects within array/vector
let ptr_arr: * mut T = unsafe{AsMut::<[T]>::as_mut(ra).as_mut_ptr().add(i)};
drop(unsafe { ptr_arr.read() });
}
drop(uninited); // and drop uninited array/vector
Err(format!("failed to init"))
}
}
// Object Data
#[derive(Debug)]
struct Data(f64);
impl TryFrom<()> for Data {
type Error = ();
// generate a float with errors; time consuming
fn try_from(_:()) -> Result<Self,()> {
thread::sleep(Duration::from_millis(10));
let f = rand::random();
if f <= 0.99 { Ok(Data(f)) } else { Err(()) }
}
}
fn main() {
let result: Result<Vec<Data>,_> = try_new(3);
println!("result: {:?}",result);
let result: Result<[Data;3],_> = try_new(3);
println!("result: {:?}",result);
let result: Result<Vec<Data>,_> = try_new(1000);
println!("result: {:?}",result);
let result: Result<[Data;1000],_> = try_new(1000);
println!("result: {:?}",result);
}
impl<T> ArrayUninit<T> for Vec<T> {
fn try_uninit(len: usize) -> Result<MaybeUninit<Self>,String> {
let mut v: MaybeUninit<Vec<T>> = MaybeUninit::uninit();
let mut vv = Vec::with_capacity(len);
unsafe { vv.set_len(len) };
v.write(vv);
Ok(v)
}
}
impl<T,const N: usize> ArrayUninit<T> for [T;N] {
fn try_uninit(len: usize) -> Result<MaybeUninit<Self>,String> {
if len == N {
Ok(MaybeUninit::uninit())
} else { Err(format!("len differs from array size")) }
}
}
Here is an example of run (results are random):
Standard Error
Compiling playground v0.0.1 (/playground)
Finished dev [unoptimized + debuginfo] target(s) in 0.84s
Running `target/debug/playground`
Standard Output
result: Ok([Data(0.9778296353515407), Data(0.9319034033060891), Data(0.11046580243682291)])
result: Ok([Data(0.749182522350767), Data(0.5432451150541627), Data(0.6840763419767837)])
result: Err("failed to init")
result: Err("failed to init")
For now, in case of failure, I drop all the addresses within the
array/vector, both initialized and uninitialized, then I drop the
array/vector. It seems to work, but I'm surprised that one can also
drop uninitialized data.
Can anyone confirm if this is a right approach to drop the
uninitialized data? If not, what are the rules to follow?
[EDIT:]
Thanks to the remarks of isaactfa and Chayim, I updated the code as follows (playgroud):
use core::{ time::Duration, mem::MaybeUninit, };
use std::thread;
use rand::prelude::*;
// trait with method for building uninited array/vector
// implementations for Vec<T> and [T;N] after the main()
trait ArrayUninit<T>: AsMut<[T]> + Sized {
type Uninited: Sized;
fn try_uninit(len: usize) -> Result<Self::Uninited,String>;
unsafe fn set(uninit: &mut Self::Uninited, i: usize, t: T);
unsafe fn destructor(uninit: &mut Self::Uninited,);
unsafe fn finalize(uninit: Self::Uninited) -> Self;
}
// generate shuffled indices
fn indices(len: usize) -> Box<dyn Iterator<Item = usize>> {
let mut vec: Vec<usize> = (0..len).collect();
vec.shuffle(&mut thread_rng());
Box::new(vec.into_iter())
}
// try to build an array or a vector of objects T
fn try_new<T: TryFrom<()>, A:ArrayUninit<T>>(len: usize) -> Result<A,String> {
// build uninitialized collection
let mut uninited = A::try_uninit(len)?;
// simulate initialization in random order
let indices = indices(len);
let mut failed = false;
for i in indices {
// get object and break if failed
let data = match T::try_from(()) {
Ok(data) => { data }, Err(_) => { failed = true; break; },
};
// set object
unsafe { A::set(&mut uninited,i,data) };
}
if !failed {
Ok(unsafe{ A::finalize(uninited) }) // return array, if successful
} else {
unsafe { A::destructor(&mut uninited) };
Err(format!("failed to init"))
}
}
// Object Data
#[derive(Debug)]
struct Data(String);
impl TryFrom<()> for Data {
type Error = ();
// generate a float with errors; time consuming
fn try_from(_:()) -> Result<Self,()> {
thread::sleep(Duration::from_millis(10));
let f:f32 = rand::random();
if f <= 0.99 { Ok(Data(format!("Value = {}",f))) } else { Err(()) }
}
}
fn main() {
let result: Result<Vec<Data>,_> = try_new(3);
println!("result: {:?}",result);
let result: Result<[Data;3],_> = try_new(3);
println!("result: {:?}",result);
let result: Result<Vec<Data>,_> = try_new(3);
println!("result: {:?}",result);
let result: Result<[Data;3],_> = try_new(3);
println!("result: {:?}",result);
let result: Result<Vec<Data>,_> = try_new(1000);
println!("result: {:?}",result);
let result: Result<[Data;1000],_> = try_new(1000);
println!("result: {:?}",result);
let result: Result<Vec<Data>,_> = try_new(1000);
println!("result: {:?}",result);
let result: Result<[Data;1000],_> = try_new(1000);
println!("result: {:?}",result);
}
impl<T> ArrayUninit<T> for Vec<T> {
type Uninited = (Vec<T>,Vec<bool>);
fn try_uninit(len: usize) -> Result<Self::Uninited,String> {
Ok((Vec::with_capacity(len),vec![false;len]))
}
unsafe fn set((uninit,flag): &mut Self::Uninited, i: usize, t: T) {
uninit.as_mut_ptr().offset(i as isize).write(t); flag[i] = true;
}
unsafe fn destructor((uninit,flag): &mut Self::Uninited,) {
for i in 0..flag.len() {
if flag[i] { std::ptr::drop_in_place(uninit.as_mut_ptr().offset(i as isize)); }
}
}
unsafe fn finalize((mut uninit,flag): Self::Uninited) -> Self {
uninit.set_len(flag.len());
uninit
}
}
impl<T,const N: usize> ArrayUninit<T> for [T;N] {
type Uninited = ([MaybeUninit<T>;N],[bool;N]);
fn try_uninit(len: usize) -> Result<Self::Uninited,String> {
if len == N {
let uninit = unsafe{ MaybeUninit::uninit().assume_init() };
Ok((uninit,[false;N]))
} else { Err(format!("len differs from array size")) }
}
unsafe fn set((uninit,flag): &mut Self::Uninited, i: usize, t: T) {
uninit[i].write(t); flag[i] = true;
}
unsafe fn destructor((uninit,flag): &mut Self::Uninited,) {
for i in 0..N {
if flag[i] { std::ptr::drop_in_place(uninit[i].as_mut_ptr()); }
}
}
unsafe fn finalize((uninit,_): Self::Uninited) -> Self {
(&uninit as *const _ as *const Self).read()
}
}
The idea here is to use specific approaches for arrays and vecs, which are encoded within trait ArrayUninit. MaybeUninit is used only for arrays, while it is not needed for vecs.
Your code contains multiple points of UB:
Calling set_len() when the elements in range are uninitialized (you're doing that in try_uninit() for Vec<T>) is UB (see set_len()'s docs).
When initializing arrays, you create uninitialized storage for the array in try_uninit() and then turns that into a reference to an initialized array in try_new(). This may be undefined behavior (but not necessarily), see https://github.com/rust-lang/unsafe-code-guidelines/issues/84.
When setting the value at the index (unsafe { *ptr_arr = data } in try_new()), you drop the old value. If the value has no drop glue this is likely fine, but if it has this is undefined behavior since your drop uninitialized data. You need to use std::ptr::write() instead.
You're doing a typed copy of the values by drop(unsafe { ptr_arr.read() }). Doing a typed copy of uninitialized values is definitely UB (Miri is even flagging this one).

How can a Rust developer get an inferred data type? [duplicate]

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

In Rust, is it possible to have a mutable copy-able string allocated on the stack?

I need something that will make this work:
#[derive(Copy)]
struct TestData {
val : MutableString
}
Presumably, the MutableString will have to be of fixed size, and I am okay with that.
We can use const generics for this!
#[derive(Copy, Clone)]
struct TestData<const SIZE1: usize> {
val : MutableString<SIZE1>
}
#[derive(Copy, Clone)]
struct MutableString<const SIZE: usize> {
inner : [u8; SIZE],
len: usize
}
(note: these are both Copy, but Clone must also be present due to trait bounds)
The SIZE parameter must be a value that is computable at compile time so you are right about needing fixed length strings.
We need a len field here because we need to know how long the actual string itself is. The alternative would be using a null-terminator like C does.
I defined a couple methods to make one of these from an &str and turn one back into a &str:
impl<'a, const SIZE: usize> MutableString<SIZE> {
fn from_str(s: &str) -> Result<Self, &'static str> {
let slice = s.as_bytes();
if slice.len() > SIZE {
Err("String is too big")
} else {
let mut inner = [0; SIZE];
for (i, byte) in slice.iter().enumerate() { inner[i] = *byte; }
Ok(Self {
inner,
len: slice.len()
})
}
}
fn to_str(&'a self) -> &'a str {
std::str::from_utf8(&self.inner).unwrap()
}
}
In the real world you'd want more error handling around this and also offer methods that guard mutation to ensure it doesn't expand beyond SIZE or require len to be updated.
We can verify that the string is being copied:
fn main() {
let mut_str = MutableString::from_str("Hello, world!").unwrap();
let mut data: TestData<256> = TestData { val: mut_str };
let copy = data;
data.val.inner[12] = b'?'; // irl guard this around a method that updates len, etc.
println!("{}", data.val.to_str());
println!("{}", copy.val.to_str());
}

How to print out type of variable in Rust? [duplicate]

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

How do I modify the content of a `RefCell<Option<T>>`?

I have an Option<T> that is shared by several structures and that must be mutable. I'm using a RefCell since, as I understand, it is the tool for that job. How do I access (and alter) the content of that Option<T> ?
I tried the following:
use std::cell::RefCell;
#[derive(Debug)]
struct S {
val: i32
}
fn main() {
let rc: RefCell<Option<S>> = RefCell::new(Some(S{val: 0}));
if let Some(ref mut s2) = rc.borrow_mut() {
s2.val += 1;
}
println!("{:?}", rc);
}
But the compiler won't let me do it:
error[E0308]: mismatched types
--> <anon>:10:12
|
10 | if let Some(ref mut s2) = rc.borrow_mut() {
| ^^^^^^^^^^^^^^^^ expected struct `std::cell::RefMut`, found enum `std::option::Option`
|
= note: expected type `std::cell::RefMut<'_, std::option::Option<S>, >`
found type `std::option::Option<_>`
When you borrow_mut the RefCell, you get a RefMut, as the compiler says. To get the value inside it, just use the operator deref_mut:
use std::cell::RefCell;
#[derive(Debug)]
struct S {
val: i32
}
fn main() {
let rc: RefCell<Option<S>> = RefCell::new(Some(S{val: 0}));
if let Some(ref mut s2) = *rc.borrow_mut() { // deref_mut
s2.val += 1;
}
println!("{:?}", rc);
}

Resources