How to Print the Type of a Variable in Rust
1. Overview
Data types are essential components of virtually every programming language. Rust is a strongly typed language with various built-in types. While modern IDEs often help preview variable types, there may be cases where we need to programmatically determine a variable’s type, particularly for debugging purposes.
In this tutorial, we’ll learn how to use Rust’s built-in library to print the type of a variable.
2. Using type_name()
The type_name() function provided by the Rust standard library can be used to print the type of a variable. First, we need to import the necessary function:
use std::any::type_name;
To demonstrate its usage, let’s define a helper function named print_type_of(). This function accepts a generic parameter T and uses type_name() to print its type. The underscore parameter name indicates we don’t use the actual value:
fn print_type_of<T>(_: &T) { println!("{}", type_name::<T>()); }
Let’s define some variables and use print_type_of() to display their types:
let number = 32.90;
let greeting = "Hello World!";
let publishers = vec!["Springer", "Healthline"];
print_type_of(&number);
print_type_of(&greeting);
print_type_of(&publishers);
When we ran this code, we saw the following output:
f64 &str alloc::vec::Vec<&str>
In the output above, we saw the float, string, and Vec<> type.
3. Using Compiler Errors to Determine Types
Another way to determine types is to cause a compile-time type mismatch intentionally. For example, we can try assigning values to variables explicitly typed as the unit type ():
let number: () = 32.90; let greeting: () = "Hello World!"; let publishers: () = vec!["Springer", "Healthline"];
When we attempt to compile this code, the compiler will produce errors that reveal the actual types:
error[E0308]: mismatched types | | let number: () = 32.90; | ^^^^^ expected `()`, found floating-point number | error[E0308]: mismatched types | | let greeting: () = "Hello World!"; | ^^^^^^^^^^^^^^ expected `()`, found `&str` | error[E0308]: mismatched types | | let publishers: () = vec!["Springer", "Healthline"]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Vec<&str>`
This compile-time error approach can be particularly useful during development when we’re working with complex types or trying to understand type inference in our code.
4. Best Practices
- We should use type_name() when we need type information at runtime, such as in logging or debugging scenarios
- We should consider using compiler errors during development when we’re trying to understand type inference
- Notably, print_type_of function takes references to avoid taking ownership of the values
5. Conclusion
In this article, we’ve explored two effective methods for determining variable types in Rust:
- Using the std::any::type_name function for runtime type information
- Leveraging compiler error messages during development
Both approaches serve different purposes and can be valuable tools in our Rust debugging toolkit. The type_name approach is more suitable for production code when type information is needed at runtime, while the compiler error method is helpful during the development and learning phases.